diff --git a/api/endpoints.jsx b/api/endpoints.jsx deleted file mode 100644 index cc7aff0..0000000 --- a/api/endpoints.jsx +++ /dev/null @@ -1,8 +0,0 @@ -export const AUTH = { - LOGIN: "/login", - REFRESH_TOKEN: "/refresh-token", -}; - -export const EXERCICES = { - GETALL: "/exercices", -}; diff --git a/api/service/api/service.api.abstract.tsx b/api/service/api/service.api.abstract.tsx new file mode 100644 index 0000000..8ce17f0 --- /dev/null +++ b/api/service/api/service.api.abstract.tsx @@ -0,0 +1,111 @@ +import AsyncStorage from "@react-native-async-storage/async-storage"; +import { router } from "expo-router"; +import { getItemAsync } from "expo-secure-store"; +import apiClient from "./service.api.client"; +import { + ACCESS_TOKEN_PATH, + API_URL, + CLIENT_ID, + CLIENT_SECRET, + ENDPOINTS, + REFRESH_TOKEN_PATH, +} from "./service.api.constant"; + +type RequestOption = { + method?: string; + body?: any; + headers?: Record; +}; + +export abstract class AbstractServiceApi { + protected async request(path: string, options?: RequestOption): Promise { + const token = await getItemAsync(ACCESS_TOKEN_PATH); + const headers = this.buildHeaders(token, options?.headers); + + const fetchOptions: RequestInit = { + method: options?.method ?? "GET", + headers, + }; + + if (options?.body && fetchOptions.method !== "GET") { + fetchOptions.body = JSON.stringify(options.body); + } + + const res = await fetch(`${API_URL}${path}`, fetchOptions); + + return await this.checkStatus(path, res, options); + } + + private buildHeaders( + token?: string | null, + headers?: Record + ): Record { + return { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + ...(headers || {}), + }; + } + + private async checkStatus( + path: string, + res: Response, + options?: RequestOption + ): Promise { + switch (res.status) { + case 401: + await this.tryRefreshToken(); + return this.request(path, options); + case 403: + router.replace("/(error)/NotAllowedProblem"); + return; + case 500: + router.replace("/(error)/InternalErrorProblem"); + return; + case 503: + router.replace("/(error)/BlockedProblem"); + return; + default: + return await res.json(); + } + } + + private async tryRefreshToken(): Promise { + try { + const refreshToken = await AsyncStorage.getItem(REFRESH_TOKEN_PATH); + + if (!refreshToken) return false; + + const response = await this.getRefreshTokenResponse(refreshToken); + + if (!response.ok) return false; + + const { accessToken, refreshToken: newRefreshToken } = + await response.json(); + + await AsyncStorage.setItem(ACCESS_TOKEN_PATH, accessToken); + await AsyncStorage.setItem(REFRESH_TOKEN_PATH, newRefreshToken); + + apiClient.defaults.headers.common[ + "Authorization" + ] = `Bearer ${accessToken}`; + + return true; + } catch (e) { + return false; + } + } + + private async getRefreshTokenResponse( + refreshToken: string + ): Promise { + return await fetch(`${API_URL}/${ENDPOINTS.REFRESH_TOKEN}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Basic ${btoa(`${CLIENT_ID}:${CLIENT_SECRET}`)}`, + }, + body: JSON.stringify({ refresh_token: refreshToken }), + }); + } +} diff --git a/api/service/api/service.api.catalog.tsx b/api/service/api/service.api.catalog.tsx new file mode 100644 index 0000000..8ea831c --- /dev/null +++ b/api/service/api/service.api.catalog.tsx @@ -0,0 +1,57 @@ +import { ESearchExerciceFilter } from "@/enum/enum.search-filter.exercice"; +import { UpdateExerciceDTO } from "../dto/dto.catalog"; +import { DeleteDTO } from "../dto/dto.generic"; +import { ExerciceDTO } from "../dto/dto.training"; +import { ICatalogService } from "../interface/service.interface.catalog"; +import { AbstractServiceApi } from "./service.api.abstract"; +import { ENDPOINTS } from "./service.api.constant"; + +export class CatalogServiceApi + extends AbstractServiceApi + implements ICatalogService +{ + async getAllExercices(): Promise { + const data = await this.request(ENDPOINTS.CATALOG); + return data as ExerciceDTO[]; + } + + async getExercices(spec: ESearchExerciceFilter): Promise { + const param = new URLSearchParams({ spec: spec }); + const data = await this.request(`${ENDPOINTS.CATALOG}?${param}`); + return data as ExerciceDTO[]; + } + + async getExercice(id: string): Promise { + const param = new URLSearchParams({ id }); + const data = await this.request(`${ENDPOINTS.CATALOG}?${param}`); + return data as ExerciceDTO; + } + + async addExercice(exercice: ExerciceDTO): Promise { + const data = await this.request(ENDPOINTS.CATALOG, { + method: "POST", + body: exercice, + }); + return data as ExerciceDTO; + } + + async editExercice( + id: string, + exercice: UpdateExerciceDTO + ): Promise { + const param = new URLSearchParams({ id: id }); + const data = await this.request(`${ENDPOINTS.CATALOG}?${param}`, { + method: "PUT", + body: exercice, + }); + return data as UpdateExerciceDTO; + } + + async deleteExercice(id: string): Promise { + const param = new URLSearchParams({ id: id }); + const data = await this.request(`${ENDPOINTS.CATALOG}?${param}`, { + method: "DELETE", + }); + return data as DeleteDTO; + } +} diff --git a/api/client.jsx b/api/service/api/service.api.client.tsx similarity index 100% rename from api/client.jsx rename to api/service/api/service.api.client.tsx diff --git a/api/service/api/service.api.constant.tsx b/api/service/api/service.api.constant.tsx new file mode 100644 index 0000000..f0dbd8b --- /dev/null +++ b/api/service/api/service.api.constant.tsx @@ -0,0 +1,27 @@ +export const IDP_URL = + "https://codefirst.iut.uca.fr/containers/Optifit-optifit-ef-api/api/v1"; +export const API_URL = + "https://codefirst.iut.uca.fr/containers/Optifit-optifit-ef-api/api/v1"; + +export const CLIENT_ID = "mobile-app"; +export const CLIENT_SECRET = "super-secret"; + +export const SCOPES = + "openid profile training.generate training.read offline_access"; + +export const ACCESS_TOKEN_PATH = "access-token"; +export const REFRESH_TOKEN_PATH = "refresh-token"; + +export const ENDPOINTS = { + // User + LOGIN: "/login", + REFRESH_TOKEN: "/refresh-token", + + // Exercice + CATALOG: "/exercices", + + // Training + TRAINING: "/trainings", +}; + +export type EndpointType = keyof typeof ENDPOINTS; diff --git a/api/service/api/service.api.training.tsx b/api/service/api/service.api.training.tsx new file mode 100644 index 0000000..4114692 --- /dev/null +++ b/api/service/api/service.api.training.tsx @@ -0,0 +1,44 @@ +import { ESearchTrainingFilter } from "@/enum/enum.search-filter.training"; +import { + ExerciceDTO, + SessionDTO, + TrainingDTO, + UpdateTrainingDTO, +} from "../dto/dto.training"; +import { ITrainingService } from "../interface/service.interface.training"; +import { AbstractServiceApi } from "./service.api.abstract"; + +export class TrainingServiceApi + extends AbstractServiceApi + implements ITrainingService +{ + getAllTrainings(): Promise { + throw new Error("Method not implemented."); + } + getTrainings(spec: ESearchTrainingFilter): Promise { + throw new Error("Method not implemented."); + } + getTraining(id: string): Promise { + throw new Error("Method not implemented."); + } + getSession(id: string): Promise { + throw new Error("Method not implemented."); + } + getExercice(id: string): Promise { + throw new Error("Method not implemented."); + } + createTraining(training: TrainingDTO): Promise { + throw new Error("Method not implemented."); + } + editTraining( + training: UpdateTrainingDTO + ): Promise | undefined { + throw new Error("Method not implemented."); + } + duplicateTraining(id: string): Promise { + throw new Error("Method not implemented."); + } + deleteTraining(id: string): Promise { + throw new Error("Method not implemented."); + } +} diff --git a/api/services/user/user.service.api.tsx b/api/service/api/service.api.user.tsx similarity index 80% rename from api/services/user/user.service.api.tsx rename to api/service/api/service.api.user.tsx index b9b55d5..bd8ba45 100644 --- a/api/services/user/user.service.api.tsx +++ b/api/service/api/service.api.user.tsx @@ -1,9 +1,9 @@ import { User } from "@/model/User"; import { setItemAsync } from "expo-secure-store"; -import { AbstractService as AbstractAPIService } from "../abstract.service"; -import { IUserService } from "./user.service.interface"; +import { IUserService } from "../interface/service.interface.user"; +import { AbstractServiceApi } from "./service.api.abstract"; -export class UserAPIService extends AbstractAPIService implements IUserService { +export class UserServiceApi extends AbstractServiceApi implements IUserService { async login(email: string, password: string): Promise { const body = new URLSearchParams({ grant_type: "password", diff --git a/api/service/dto/dto.catalog.tsx b/api/service/dto/dto.catalog.tsx new file mode 100644 index 0000000..158ecdb --- /dev/null +++ b/api/service/dto/dto.catalog.tsx @@ -0,0 +1,19 @@ +import { ETarget } from "@/enum/enum.target"; + +export type ExerciceTemplateDTO = { + Id: string; + Name: string; + Description: string; + Target: ETarget; + Image: string; + Video: string; +}; + +export type UpdateExerciceDTO = { + Id: string; + Name?: string; + Description?: string; + Target?: ETarget; + Image?: string; + Video?: string; +}; diff --git a/api/service/dto/dto.generic.tsx b/api/service/dto/dto.generic.tsx new file mode 100644 index 0000000..f6b1686 --- /dev/null +++ b/api/service/dto/dto.generic.tsx @@ -0,0 +1,3 @@ +export type DeleteDTO = { + Id: string; +}; diff --git a/api/service/dto/dto.training.tsx b/api/service/dto/dto.training.tsx new file mode 100644 index 0000000..75764fc --- /dev/null +++ b/api/service/dto/dto.training.tsx @@ -0,0 +1,54 @@ +import { ECategory } from "@/enum/enum.category"; +import { ETarget } from "@/enum/enum.target"; + +export type ExerciceDTO = { + Id: string; + Name: string; + Description: string; + Target: ETarget; + Image: string; + Video: string; + Duration: number; + NbSet: number; + RestTime: number; + NbRep: number; + Weight?: number; + Passed: boolean; +}; + +export type SessionDTO = { + Id: string; + Name: string; + Description: string; + Category: ECategory; + Exercices: ExerciceDTO[]; +}; + +export type TrainingDTO = { + Id: string; + Name: string; + Description: string; + Sessions: SessionDTO[]; +}; + +export type CreateSessionDTO = { + Name: string; + Description: string; + Category: ECategory; + Exercices: ExerciceDTO[]; +}; + +export type CreateTrainingDTO = { + Name: string; + description: string; + Category: ECategory; + Exercices: ExerciceDTO[]; +}; + +export type UpdateTrainingDTO = { + Id: string; + Name?: string; + description?: string; + Category?: ECategory; + Exercices?: ExerciceDTO[]; +}; diff --git a/api/service/dto/dto.user.tsx b/api/service/dto/dto.user.tsx new file mode 100644 index 0000000..34d8293 --- /dev/null +++ b/api/service/dto/dto.user.tsx @@ -0,0 +1,37 @@ +import { + EHealthProblem, + ESleepLevel, + ESport, + ESportLevel, +} from "@/model/enums/Enums"; + +export type UserDTO = { + Name: string; + Age: number; + Weight: number; + Height: number; + Sexe: boolean; // true = Male, false = Female + ProfilePict: string; + NbSessionPerWeek: number; + Goal: string; + SleepLevel: ESleepLevel; + SportLevel: ESportLevel; + Sport: ESport[]; + HealthProblems: EHealthProblem[]; +}; + +export type UpdateUserDTO = { + Id?: string; + Name?: string; + Age?: number; + Weight?: number; + Height?: number; + Sexe?: boolean; // true = Male, false = Female + ProfilePict?: string; + NbSessionPerWeek?: number; + Goal?: string; + SleepLevel?: ESleepLevel; + SportLevel?: ESportLevel; + Sport?: ESport[]; + HealthProblems?: EHealthProblem[]; +}; diff --git a/api/service/interface/service.interface.catalog.tsx b/api/service/interface/service.interface.catalog.tsx new file mode 100644 index 0000000..aace319 --- /dev/null +++ b/api/service/interface/service.interface.catalog.tsx @@ -0,0 +1,16 @@ +import { ESearchExerciceFilter } from "@/enum/enum.search-filter.exercice"; +import { UpdateExerciceDTO } from "../dto/dto.catalog"; +import { DeleteDTO } from "../dto/dto.generic"; +import { ExerciceDTO } from "../dto/dto.training"; + +export interface ICatalogService { + getAllExercices(): Promise; + getExercices(spec: ESearchExerciceFilter): Promise; + getExercice(id: string): Promise; + addExercice(exercice: ExerciceDTO): Promise; + editExercice( + id: string, + exercice: UpdateExerciceDTO + ): Promise; + deleteExercice(id: string): Promise; +} diff --git a/api/service/interface/service.interface.training.tsx b/api/service/interface/service.interface.training.tsx new file mode 100644 index 0000000..f7a0ae2 --- /dev/null +++ b/api/service/interface/service.interface.training.tsx @@ -0,0 +1,21 @@ +import { ESearchTrainingFilter } from "@/enum/enum.search-filter.training"; +import { + ExerciceDTO, + SessionDTO, + TrainingDTO, + UpdateTrainingDTO, +} from "../dto/dto.training"; + +export interface ITrainingService { + getAllTrainings(): Promise; + getTrainings(spec: ESearchTrainingFilter): Promise; + getTraining(id: string): Promise; + getSession(id: string): Promise; + getExercice(id: string): Promise; + createTraining(training: TrainingDTO): Promise; + editTraining( + training: UpdateTrainingDTO + ): Promise | undefined; + duplicateTraining(id: string): Promise; + deleteTraining(id: string): Promise; +} diff --git a/api/services/user/user.service.interface.tsx b/api/service/interface/service.interface.user.tsx similarity index 100% rename from api/services/user/user.service.interface.tsx rename to api/service/interface/service.interface.user.tsx diff --git a/api/service/service.ref.tsx b/api/service/service.ref.tsx new file mode 100644 index 0000000..6960c73 --- /dev/null +++ b/api/service/service.ref.tsx @@ -0,0 +1,10 @@ +import { ICatalogService } from "./interface/service.interface.catalog"; +import { ITrainingService } from "./interface/service.interface.training"; +import { IUserService } from "./interface/service.interface.user"; +import { CatalogServiceStub } from "./stub/service.stub.catalog"; +import { TrainingServiceStub } from "./stub/service.stub.training"; +import { UserServiceStub } from "./stub/service.stub.user"; + +export const CatalogServiceRef: ICatalogService = new CatalogServiceStub(); +export const UserServiceRef: IUserService = new UserServiceStub(); +export const TrainingServiceRef: ITrainingService = new TrainingServiceStub(); diff --git a/api/service/stub/service.stub.catalog.tsx b/api/service/stub/service.stub.catalog.tsx new file mode 100644 index 0000000..ecce33c --- /dev/null +++ b/api/service/stub/service.stub.catalog.tsx @@ -0,0 +1,120 @@ +import { ESearchExerciceFilter } from "@/enum/enum.search-filter.exercice"; +import { AbstractServiceApi } from "../api/service.api.abstract"; +import { UpdateExerciceDTO } from "../dto/dto.catalog"; +import { DeleteDTO } from "../dto/dto.generic"; +import { ExerciceDTO } from "../dto/dto.training"; +import { ICatalogService } from "../interface/service.interface.catalog"; + +export class CatalogServiceStub + extends AbstractServiceApi + implements ICatalogService +{ + exercices: ExerciceDTO[] = [ + { + Id: "1", + Name: "Pompes", + Description: + "Exercice classique de renforcement des pectoraux et triceps.", + Duration: 60, + Image: "https://example.com/images/pompes.jpg", + Video: "https://example.com/videos/pompes.mp4", + NbSet: 3, + NbRep: 15, + Target: "ARM", + RestTime: 0, + Passed: false, + }, + { + Id: "2", + Name: "Squats", + Description: "Travail les jambes, les fessiers et le tronc.", + Duration: 90, + Image: "https://example.com/images/squats.jpg", + Video: "https://example.com/videos/squats.mp4", + NbSet: 4, + NbRep: 20, + Target: "LEG", + RestTime: 0, + Passed: false, + }, + { + Id: "3", + Name: "Gainage", + Description: "Renforcement du tronc, gainage statique.", + Duration: 45, + Image: "https://example.com/images/gainage.jpg", + Video: "https://example.com/videos/gainage.mp4", + NbSet: 3, + NbRep: 1, + Target: "CARDIO", + RestTime: 0, + Passed: false, + }, + { + Id: "4", + Name: "Fentes", + Description: "Renforcement des jambes, bon pour l'équilibre.", + Duration: 80, + Image: "https://example.com/images/fentes.jpg", + Video: "https://example.com/videos/fentes.mp4", + NbSet: 3, + NbRep: 12, + Target: "LEG", + RestTime: 0, + Passed: false, + }, + { + Id: "5", + Name: "Abdominaux", + Description: "Travail des muscles abdominaux avec crunchs.", + Duration: 60, + Image: "https://example.com/images/abdos.jpg", + Video: "https://example.com/videos/abdos.mp4", + NbSet: 4, + NbRep: 20, + Target: "ARM", + RestTime: 0, + Passed: false, + }, + ]; + + getAllExercices(): Promise { + return Promise.resolve(this.exercices); + } + + getExercices(spec: ESearchExerciceFilter): Promise { + return Promise.resolve(this.exercices); + } + + getExercice(id: string): Promise { + return Promise.resolve(this.exercices.find((x) => x.Id === id)); + } + + addExercice(exercice: ExerciceDTO): Promise { + this.exercices.push(exercice); + return Promise.resolve(exercice); + } + + editExercice( + id: string, + exercice: UpdateExerciceDTO + ): Promise { + const ex = this.exercices.find((x) => x.Id === id); + if (ex != null) { + Object.entries(exercice).forEach(([key, value]) => { + if (value !== undefined) { + // @ts-ignore : typage des clés non dynamique + ex[key] = value; + } + }); + } + return Promise.resolve(ex); + } + + deleteExercice(id: string): Promise { + const dto: DeleteDTO = { + Id: id, + }; + return Promise.resolve(dto); + } +} diff --git a/api/service/stub/service.stub.training.tsx b/api/service/stub/service.stub.training.tsx new file mode 100644 index 0000000..2f89587 --- /dev/null +++ b/api/service/stub/service.stub.training.tsx @@ -0,0 +1,40 @@ +import { ESearchTrainingFilter } from "@/enum/enum.search-filter.training"; +import { + ExerciceDTO, + SessionDTO, + TrainingDTO, + UpdateTrainingDTO, +} from "../dto/dto.training"; +import { ITrainingService } from "../interface/service.interface.training"; + +export class TrainingServiceStub implements ITrainingService { + getAllTrainings(): Promise { + throw new Error("Method not implemented."); + } + getTrainings(spec: ESearchTrainingFilter): Promise { + throw new Error("Method not implemented."); + } + getTraining(id: string): Promise { + throw new Error("Method not implemented."); + } + getSession(id: string): Promise { + throw new Error("Method not implemented."); + } + getExercice(id: string): Promise { + throw new Error("Method not implemented."); + } + createTraining(training: TrainingDTO): Promise { + throw new Error("Method not implemented."); + } + editTraining( + training: UpdateTrainingDTO + ): Promise | undefined { + throw new Error("Method not implemented."); + } + duplicateTraining(id: string): Promise { + throw new Error("Method not implemented."); + } + deleteTraining(id: string): Promise { + throw new Error("Method not implemented."); + } +} diff --git a/api/services/user/user.service.stub.tsx b/api/service/stub/service.stub.user.tsx similarity index 95% rename from api/services/user/user.service.stub.tsx rename to api/service/stub/service.stub.user.tsx index f3de839..f59f6d0 100644 --- a/api/services/user/user.service.stub.tsx +++ b/api/service/stub/service.stub.user.tsx @@ -1,7 +1,7 @@ import { User } from "@/model/User"; -import { IUserService } from "./user.service.interface"; +import { IUserService } from "../interface/service.interface.user"; -export class UserStubService implements IUserService { +export class UserServiceStub implements IUserService { private readonly users: User[] = [ new User({ name: "Alice", @@ -81,7 +81,7 @@ export class UserStubService implements IUserService { nbSessionPerWeek: 3, goal: "Renforcer le dos", healthProblems: ["MIGRAINE"], - sport: "CARDIO", + sport: "FOOTBALL", sleepLevel: "BAD", sportLevel: "BEGINNER", email: "test@6.com", @@ -113,7 +113,7 @@ export class UserStubService implements IUserService { nbSessionPerWeek: 2, goal: "Se tonifier", healthProblems: [], - sport: "RANDO", + sport: "HANDBALL", sleepLevel: "GOOD", sportLevel: "BEGINNER", email: "test@8.com", diff --git a/api/services/abstract.service.tsx b/api/services/abstract.service.tsx deleted file mode 100644 index 2ae031e..0000000 --- a/api/services/abstract.service.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import AsyncStorage from "@react-native-async-storage/async-storage"; -import { router } from "expo-router"; -import { getItemAsync } from "expo-secure-store"; -import apiClient from "../client"; -import { AUTH } from "../endpoints"; - -export abstract class AbstractService { - protected IDP_URL = - "https://codefirst.iut.uca.fr/containers/Optifit-optifit-ef-api/api/v1"; - protected URL = - "https://codefirst.iut.uca.fr/containers/Optifit-optifit-ef-api/api/v1"; - - protected CLIENT_ID = "mobile-app"; - protected CLIENT_SECRET = "super-secret"; - - protected SCOPES = - "openid profile training.generate training.read offline_access"; - - protected ACCESS_TOKEN_PATH = "access-token"; - protected REFRESH_TOKEN_PATH = "refresh-token"; - - protected async request( - path: string, - options: RequestInit = {} - ): Promise { - const token = await getItemAsync(this.ACCESS_TOKEN_PATH); - const res = await fetch(`${this.URL}${path}`, { - ...options, - headers: { - ...(options.headers || {}), - Authorization: `Bearer ${token}`, - }, - }); - - switch (res.status) { - case 401: - await this.tryRefreshToken(); - return this.request(path, options); - case 403: - router.replace("/(error)/NotAllowedProblem"); - return; - case 500: - router.replace("/(error)/InternalErrorProblem"); - return; - case 503: - router.replace("/(error)/BlockedProblem"); - return; - default: - return await res.json(); - } - } - - private async tryRefreshToken(): Promise { - try { - const refreshToken = await AsyncStorage.getItem(this.REFRESH_TOKEN_PATH); - - if (!refreshToken) return false; - - const response = await apiClient.post(AUTH.REFRESH_TOKEN, { - refreshToken, - }); - - const { accessToken, refreshToken: newRefreshToken } = response.data; - - await AsyncStorage.setItem(this.ACCESS_TOKEN_PATH, accessToken); - await AsyncStorage.setItem(this.REFRESH_TOKEN_PATH, newRefreshToken); - - apiClient.defaults.headers.common[ - "Authorization" - ] = `Bearer ${accessToken}`; - - return true; - } catch (e) { - return false; - } - } -} diff --git a/api/services/exercice/exercice.service.api.tsx b/api/services/exercice/exercice.service.api.tsx deleted file mode 100644 index 7311444..0000000 --- a/api/services/exercice/exercice.service.api.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { EXERCICES } from "@/api/endpoints"; -import { Workout } from "@/model/Workout"; -import { AbstractService } from "../abstract.service"; -import { IExerciceService } from "./exercice.service.interface"; - -export class ExerciceAPIService - extends AbstractService - implements IExerciceService -{ - async getExercices(): Promise { - const data = await this.request(EXERCICES.GETALL); - return data.data.map((item: any) => Workout.fromJson(item)); - } -} diff --git a/api/services/exercice/exercice.service.interface.tsx b/api/services/exercice/exercice.service.interface.tsx deleted file mode 100644 index e9704e6..0000000 --- a/api/services/exercice/exercice.service.interface.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export interface IExerciceService { - getExercices(): Promise; -} diff --git a/api/services/exercice/exercice.service.stub.tsx b/api/services/exercice/exercice.service.stub.tsx deleted file mode 100644 index d7469cb..0000000 --- a/api/services/exercice/exercice.service.stub.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { Workout } from "@/model/Workout"; -import { AbstractService } from "../abstract.service"; -import { IExerciceService } from "./exercice.service.interface"; - -export class ExerciceStubService - extends AbstractService - implements IExerciceService -{ - async getExercices() { - return [ - new Workout({ - id: "1", - name: "Pompes", - description: - "Exercice classique de renforcement des pectoraux et triceps.", - duration: 60, - image: "https://example.com/images/pompes.jpg", - video: "https://example.com/videos/pompes.mp4", - nbSeries: 3, - nbRepetitions: 15, - }), - new Workout({ - id: "2", - name: "Squats", - description: "Travail les jambes, les fessiers et le tronc.", - duration: 90, - image: "https://example.com/images/squats.jpg", - video: "https://example.com/videos/squats.mp4", - nbSeries: 4, - nbRepetitions: 20, - }), - new Workout({ - id: "3", - name: "Gainage", - description: "Renforcement du tronc, gainage statique.", - duration: 45, - image: "https://example.com/images/gainage.jpg", - video: "https://example.com/videos/gainage.mp4", - nbSeries: 3, - nbRepetitions: 1, // pour les exercices isométriques, 1 répétition de 45s par exemple - }), - new Workout({ - id: "4", - name: "Fentes", - description: "Renforcement des jambes, bon pour l’équilibre.", - duration: 80, - image: "https://example.com/images/fentes.jpg", - video: "https://example.com/videos/fentes.mp4", - nbSeries: 3, - nbRepetitions: 12, - }), - new Workout({ - id: "5", - name: "Abdominaux", - description: "Travail des muscles abdominaux avec crunchs.", - duration: 60, - image: "https://example.com/images/abdos.jpg", - video: "https://example.com/videos/abdos.mp4", - nbSeries: 4, - nbRepetitions: 20, - }), - ]; - } -} diff --git a/api/services/service.ref.tsx b/api/services/service.ref.tsx deleted file mode 100644 index b5fbb2e..0000000 --- a/api/services/service.ref.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { IExerciceService } from "./exercice/exercice.service.interface"; -import { ExerciceStubService } from "./exercice/exercice.service.stub"; -import { IUserService } from "./user/user.service.interface"; -import { UserStubService } from "./user/user.service.stub"; - -export const ExerciceServiceRef: IExerciceService = new ExerciceStubService(); -export const UserServiceRef: IUserService = new UserStubService(); diff --git a/app/(quiz)/quiz.tsx b/app/(quiz)/quiz.tsx index 10f911a..c60a14b 100644 --- a/app/(quiz)/quiz.tsx +++ b/app/(quiz)/quiz.tsx @@ -103,7 +103,6 @@ export default function Quiz() { session.sleepLevel = sleepRef.current?.getAnswer(); signIn(session); } - router.replace("/(tabs)/(home)/HomeScreen"); } @@ -134,7 +133,7 @@ export default function Quiz() { {questions.map((question, index) => React.createElement(question.component, { isVisible: index === currentQuestionIndex, - key: index, + key: question.component.name, ...question.props, }) )} diff --git a/app/(tabs)/(exercice)/ExercicesScreen.tsx b/app/(tabs)/(exercice)/ExercicesScreen.tsx index cc8e97d..ed8ef59 100644 --- a/app/(tabs)/(exercice)/ExercicesScreen.tsx +++ b/app/(tabs)/(exercice)/ExercicesScreen.tsx @@ -1,4 +1,4 @@ -import { ExerciceServiceRef } from "@/api/services/service.ref"; +import { CatalogServiceRef } from "@/api/service/service.ref"; import WorkoutCardComponent from "@/components/WorkoutCardComponent"; import { Workout } from "@/model/Workout"; import { useRouter } from "expo-router"; @@ -11,12 +11,12 @@ export default function ExercicesScreen() { const [error, setError] = useState(null); const router = useRouter(); - const exerciceService = ExerciceServiceRef; + const exerciceService = CatalogServiceRef; useEffect(() => { const fetchData = async () => { try { - const data = await exerciceService.getExercices(); + const data = await exerciceService.getAllExercices(); setExercices(data); } catch (err: any) { setError(err.message); diff --git a/app/(tabs)/(exercice)/WorkoutScreen.tsx b/app/(tabs)/(exercice)/WorkoutScreen.tsx index d40eec2..cf07c77 100644 --- a/app/(tabs)/(exercice)/WorkoutScreen.tsx +++ b/app/(tabs)/(exercice)/WorkoutScreen.tsx @@ -1,4 +1,4 @@ -import { ExerciceServiceRef } from "@/api/services/service.ref"; +import { CatalogServiceRef } from "@/api/service/service.ref"; import WorkoutPresentationComponent from "@/components/WorkoutPresentationComponent"; import { Workout } from "@/model/Workout"; import { useRouter } from "expo-router"; @@ -11,12 +11,12 @@ export default function WorkoutScreen() { const [exercices, setExercices] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const exerciceService = ExerciceServiceRef; + const exerciceService = CatalogServiceRef; useEffect(() => { const loadExercices = async () => { try { - const data = await exerciceService.getExercices(); + const data = await exerciceService.getAllExercices(); setExercices(data); } catch (err: any) { setError(err.message); diff --git a/app/(tabs)/(home)/HomeScreen.tsx b/app/(tabs)/(home)/HomeScreen.tsx index 378c1e4..eed4fbf 100644 --- a/app/(tabs)/(home)/HomeScreen.tsx +++ b/app/(tabs)/(home)/HomeScreen.tsx @@ -1,16 +1,16 @@ -import { ExerciceServiceRef } from "@/api/services/service.ref"; +import { ExerciceDTO } from "@/api/service/dto/dto.training"; +import { CatalogServiceRef } from "@/api/service/service.ref"; import ActivitiesComponent from "@/components/ActivitiesComponent"; import CalendarComponent from "@/components/CalendarComponent"; import WelcomeComponent from "@/components/WelcomeComponent"; import WorkoutCardComponent from "@/components/WorkoutCardComponent"; import Screen from "@/components/ui/Screen"; -import { Workout } from "@/model/Workout"; import React, { useEffect, useState } from "react"; import { ScrollView, Text, View } from "react-native"; export default function HomeScreen() { - const [exercices, setExercices] = useState([]); - const exerciceService = ExerciceServiceRef; + const [exercices, setExercices] = useState([]); + const exerciceService = CatalogServiceRef; const getRandomNumber = (min: number, max: number) => { return Math.floor(Math.random() * (max - min + 1)) + min; @@ -18,7 +18,7 @@ export default function HomeScreen() { useEffect(() => { const fetchData = async () => { try { - const data = await exerciceService.getExercices(); + const data = await exerciceService.getAllExercices(); setExercices(data); } catch (err: any) {} }; diff --git a/components/ActivitiesComponent.tsx b/components/ActivitiesComponent.tsx index 0a5725d..c578e91 100644 --- a/components/ActivitiesComponent.tsx +++ b/components/ActivitiesComponent.tsx @@ -85,7 +85,7 @@ export default function ActivitiesComponent() { {months.map((item, index) => { return ( - {exercise?.duration} min + {exercise?.Duration} min @@ -38,20 +38,18 @@ export default function WorkoutCardComponent({ - {exercise?.name} kcal + {exercise?.Name} kcal - {exercise?.name} - - {exercise?.nbRepetitions} - + {exercise?.Name} + {exercise?.NbRep} - {exercise?.name} + {exercise?.Name} diff --git a/components/WorkoutPresentationComponent.tsx b/components/WorkoutPresentationComponent.tsx index eaad6af..d154384 100644 --- a/components/WorkoutPresentationComponent.tsx +++ b/components/WorkoutPresentationComponent.tsx @@ -1,14 +1,14 @@ +import { ExerciceDTO } from "@/api/service/dto/dto.training"; import LinearProgressBar from "@/components/LinearProgressBar"; import Screen from "@/components/ui/Screen"; -import { Workout } from "@/model/Workout"; import { Ionicons } from "@expo/vector-icons"; import { router, Router } from "expo-router"; import * as React from "react"; import { ImageBackground, Text, TouchableOpacity, View } from "react-native"; type WorkoutPresentationComponentProps = { - workout: Workout; - dataExercise: Workout[]; + workout: ExerciceDTO; + dataExercise: ExerciceDTO[]; router: Router; }; @@ -40,16 +40,16 @@ export default function WorkoutPresentationComponent({ - {workout.nbSeries} x {workout.nbRepetitions} + {workout.NbSet} x {workout.NbRep} - {workout.name} + {workout.Name} - + diff --git a/components/form/LoginForm.tsx b/components/form/LoginForm.tsx index 6c62e61..5891fac 100644 --- a/components/form/LoginForm.tsx +++ b/components/form/LoginForm.tsx @@ -1,4 +1,4 @@ -import { UserServiceRef } from "@/api/services/service.ref"; +import { UserServiceRef } from "@/api/service/service.ref"; import { useSession } from "@/ctx"; import { router } from "expo-router"; import React from "react"; diff --git a/components/quiz/ActivityQuestion.tsx b/components/quiz/ActivityQuestion.tsx index e17f51d..ab9406e 100644 --- a/components/quiz/ActivityQuestion.tsx +++ b/components/quiz/ActivityQuestion.tsx @@ -1,4 +1,4 @@ -import { ESportLevel, SportLevels } from "@/model/enums/Enums"; +import { ESportLevel, SportLevels } from "@/enum/enum.sport-level"; import React, { useImperativeHandle, useState } from "react"; import { View } from "react-native"; import Checkbox from "../CheckBox"; @@ -34,7 +34,7 @@ export default React.forwardRef( selected = index; } }); - return SportLevels[SportLevels.length - 1 - selected]; + return SportLevels[selected]; }, })); @@ -47,11 +47,10 @@ export default React.forwardRef( } const data: IData[] = [ - { label: "Athlète", antIcon: "smile-circle" }, { label: "Très sportif", antIcon: "smileo" }, - { label: "Un peu sportif", antIcon: "meh" }, - { label: "Peu sportif", antIcon: "frowno" }, - { label: "Pas du tout sportif", antIcon: "frown" }, + { label: "Sportif", antIcon: "meh" }, + { label: "Débutant", antIcon: "frowno" }, + { label: "Pas sportif", antIcon: "frown" }, ]; return ( @@ -63,7 +62,7 @@ export default React.forwardRef( {data.map((item, index) => ( handleChange(index)} diff --git a/components/quiz/GoalQuestion.tsx b/components/quiz/GoalQuestion.tsx index 0e55627..a0df7c5 100644 --- a/components/quiz/GoalQuestion.tsx +++ b/components/quiz/GoalQuestion.tsx @@ -1,4 +1,4 @@ -import { EGoal, Goals } from "@/model/enums/Enums"; +import { EGoal, Goals } from "@/enum/enum.goal"; import React, { forwardRef, ReactElement, @@ -70,7 +70,7 @@ export default forwardRef( {data.map((item, index) => ( handleChange(index)} diff --git a/components/quiz/SleepQuestion.tsx b/components/quiz/SleepQuestion.tsx index 916b13b..c3be277 100644 --- a/components/quiz/SleepQuestion.tsx +++ b/components/quiz/SleepQuestion.tsx @@ -1,4 +1,4 @@ -import { ESleepLevel, SleepLevels } from "@/model/enums/Enums"; +import { ESleepLevel, SleepLevels } from "@/enum/enum.sleep-level"; import React, { useImperativeHandle, useState } from "react"; import { View } from "react-native"; import Checkbox from "../CheckBox"; @@ -29,7 +29,7 @@ export default React.forwardRef( selected = index; } }); - return SleepLevels[SleepLevels.length - 1 - selected]; + return SleepLevels[selected]; }, })); @@ -41,12 +41,12 @@ export default React.forwardRef( const data: IData[] = [ { - label: "Excellent", + label: "Excellente", icon: "smile-circle", endText: ">8 heures", }, { - label: "Bien", + label: "Bonne", icon: "smileo", endText: "7-8 heures", }, @@ -61,7 +61,7 @@ export default React.forwardRef( endText: "3-4 heures", }, { - label: "Insomniaque", + label: "Terrible", icon: "frown", endText: "<2 heures", }, @@ -76,7 +76,7 @@ export default React.forwardRef( {data.map((item, index) => ( handleChange(index)} diff --git a/components/quiz/SportQuestion.tsx b/components/quiz/SportQuestion.tsx index 05d7d29..d6c0fff 100644 --- a/components/quiz/SportQuestion.tsx +++ b/components/quiz/SportQuestion.tsx @@ -1,4 +1,4 @@ -import { ESport, Sports } from "@/model/enums/Enums"; +import { ESport, Sports } from "@/enum/enum.sport"; import React, { forwardRef, ReactElement, @@ -68,7 +68,7 @@ export default forwardRef( {data.map((item, index) => ( handleChange(index)} diff --git a/enum/enum.category.tsx b/enum/enum.category.tsx new file mode 100644 index 0000000..58da953 --- /dev/null +++ b/enum/enum.category.tsx @@ -0,0 +1,10 @@ +export const ECategory = { + WARM_UP: "WARM_UP", + TRAINING: "TRAINING", + STRETCHING: "STRETCHING", + NONE: "NONE", +} as const; + +export type ECategory = keyof typeof ECategory; + +export const Categories: ECategory[] = Object.values(ECategory); diff --git a/enum/enum.goal.tsx b/enum/enum.goal.tsx new file mode 100644 index 0000000..d389c67 --- /dev/null +++ b/enum/enum.goal.tsx @@ -0,0 +1,12 @@ +export const EGoal = { + WEIGHT_LOSS: "WEIGHT_LOSS", + MASS_GAIN: "MASS_GAIN", + FITNESS: "FITNESS", + IMPROVE_STAMINA: "IMPROVE_STAMINA", + KEEP_FIT: "KEEP_FIT", + NONE: "NONE", +} as const; + +export type EGoal = keyof typeof EGoal; + +export const Goals: EGoal[] = Object.values(EGoal); diff --git a/enum/enum.health-problem.tsx b/enum/enum.health-problem.tsx new file mode 100644 index 0000000..2aa97f4 --- /dev/null +++ b/enum/enum.health-problem.tsx @@ -0,0 +1,9 @@ +export const EHealthProblem = { + ARTHROSE: "ARTHROSE", + MIGRAINE: "MIGRAINE", + NONE: "NONE", +} as const; + +export type EHealthProblem = keyof typeof EHealthProblem; + +export const HealthProblems: EHealthProblem[] = Object.values(EHealthProblem); diff --git a/enum/enum.search-filter.exercice.tsx b/enum/enum.search-filter.exercice.tsx new file mode 100644 index 0000000..54ca94c --- /dev/null +++ b/enum/enum.search-filter.exercice.tsx @@ -0,0 +1,11 @@ +export const ESearchExerciceFilter = { + NAME: "NAME", + TARGET: "TARGET", + NONE: "NONE", +} as const; + +export type ESearchExerciceFilter = keyof typeof ESearchExerciceFilter; + +export const searchExerciceFilters: ESearchExerciceFilter[] = Object.values( + ESearchExerciceFilter +); diff --git a/enum/enum.search-filter.training.tsx b/enum/enum.search-filter.training.tsx new file mode 100644 index 0000000..8c2cd03 --- /dev/null +++ b/enum/enum.search-filter.training.tsx @@ -0,0 +1,12 @@ +export const ESearchTrainingFilter = { + NAME: "NAME", + DATE: "DATE", + DESCRIPTION: "DESCRIPTION", + NONE: "NONE", +} as const; + +export type ESearchTrainingFilter = keyof typeof ESearchTrainingFilter; + +export const SearchTrainingFilters: ESearchTrainingFilter[] = Object.values( + ESearchTrainingFilter +); diff --git a/enum/enum.sleep-level.tsx b/enum/enum.sleep-level.tsx new file mode 100644 index 0000000..104794d --- /dev/null +++ b/enum/enum.sleep-level.tsx @@ -0,0 +1,12 @@ +export const ESleepLevel = { + EXCELLENT: "EXCELLENT", + GOOD: "GOOD", + BAD: "BAD", + VERY_BAD: "VERY_BAD", + TERRIBLE: "TERRIBLE", + NONE: "NONE", +} as const; + +export type ESleepLevel = keyof typeof ESleepLevel; + +export const SleepLevels: ESleepLevel[] = Object.values(ESleepLevel); diff --git a/enum/enum.sport-level.tsx b/enum/enum.sport-level.tsx new file mode 100644 index 0000000..d408fa0 --- /dev/null +++ b/enum/enum.sport-level.tsx @@ -0,0 +1,11 @@ +export const ESportLevel = { + VERY_SPORTY: "VERY_SPORTY", + SPORTY: "SPORTY", + BEGINNER: "BEGINNER", + NOT_SPORTY: "NOT_SPORTY", + NONE: "NONE", +} as const; + +export type ESportLevel = keyof typeof ESportLevel; + +export const SportLevels: ESportLevel[] = Object.values(ESportLevel); diff --git a/enum/enum.sport.tsx b/enum/enum.sport.tsx new file mode 100644 index 0000000..4e530db --- /dev/null +++ b/enum/enum.sport.tsx @@ -0,0 +1,17 @@ +export const Esport = { + FOOTBALL: "FOOTBALL", + BASKETBALL: "BASKETBALL", + HANDBALL: "HANDBALL", + TENNIS: "TENNIS", + WALKING: "WALKING", + RUNNING: "RUNNING", + SKATEBOARD: "SKATEBOARD", + BIKING: "BIKING", + YOGA: "YOGA", + ELSE: "ELSE", + NONE: "NONE", +} as const; + +export type ESport = keyof typeof Esport; + +export const Sports: ESport[] = Object.values(Esport); diff --git a/enum/enum.target.tsx b/enum/enum.target.tsx new file mode 100644 index 0000000..735e27d --- /dev/null +++ b/enum/enum.target.tsx @@ -0,0 +1,11 @@ +export const ETarget = { + LEG: "LEG", + ARM: "ARM", + CARDIO: "CARDIO", + BACK: "BACK", + NONE: "NONE", +} as const; + +export type ETarget = keyof typeof ETarget; + +export const Target: ETarget[] = Object.values(ETarget); diff --git a/model/User.ts b/model/User.ts index 25be84a..160f567 100644 --- a/model/User.ts +++ b/model/User.ts @@ -3,7 +3,7 @@ import { ESleepLevel, ESport, ESportLevel, -} from "./enums/Enums"; +} from "../enum/Enums.js"; export class User { private _name?: string; diff --git a/model/Workout.ts b/model/Workout.ts deleted file mode 100644 index 605119c..0000000 --- a/model/Workout.ts +++ /dev/null @@ -1,118 +0,0 @@ -export class Workout { - private _id?: string; - private _name?: string; - private _description?: string; - private _duration?: number; - private _image?: string; - private _video?: string; - private _nbSeries?: number; - private _nbRepetitions?: number; - - constructor({ - id, - name, - description, - duration, - image, - video, - nbSeries, - nbRepetitions, - }: { - id?: string; - name?: string; - description?: string; - duration?: number; - image?: string; - video?: string; - nbSeries?: number; - nbRepetitions?: number; - } = {}) { - this._id = id; - this._name = name; - this._description = description; - this._duration = duration; - this._image = image; - this._video = video; - this._nbSeries = nbSeries; - this._nbRepetitions = nbRepetitions; - } - - // Getters - get id(): string | undefined { - return this._id; - } - - get name(): string | undefined { - return this._name; - } - - get description(): string | undefined { - return this._description; - } - - get duration(): number | undefined { - return this._duration; - } - - get image(): string | undefined { - return this._image; - } - - get video(): string | undefined { - return this._video; - } - - get nbSeries(): number | undefined { - return this._nbSeries; - } - - get nbRepetitions(): number | undefined { - return this._nbRepetitions; - } - - // Setters - set id(value: string | undefined) { - this._id = value; - } - - set name(value: string | undefined) { - this._name = value; - } - - set description(value: string | undefined) { - this._description = value; - } - - set duration(value: number | undefined) { - this._duration = value; - } - - set image(value: string | undefined) { - this._image = value; - } - - set video(value: string | undefined) { - this._video = value; - } - - set nbSeries(value: number | undefined) { - this._nbSeries = value; - } - - set nbRepetitions(value: number | undefined) { - this._nbRepetitions = value; - } - - static fromJson(json: any): Workout { - return new Workout({ - id: json.id, - name: json.name, - description: json.description, - duration: json.duration, - image: json.image, - video: json.video, - nbSeries: json.nbSeries, - nbRepetitions: json.nbRepetitions, - }); - } -} diff --git a/model/component.ts b/model/component.ts deleted file mode 100644 index e69de29..0000000 diff --git a/model/enums/Enums.ts b/model/enums/Enums.ts deleted file mode 100644 index f147943..0000000 --- a/model/enums/Enums.ts +++ /dev/null @@ -1,42 +0,0 @@ -export const Goals = [ - "WEIGHT_LOSE", - "IMPROVE_MUSCLE", - "WEIGHT_GAIN", - "IMPROVE_STAMINA", - "KEEP_FIT", -] as const; - -export const SportLevels = [ - "NOT_SPORTY", - "BEGINNER", - "SPORTY", - "VERY_SPORTY", - "PERFORMER", -] as const; - -export const Sports = [ - "RUNNING", - "WALKING", - "RANDO", - "SKATEBOARD", - "BIKING", - "BASKETBALL", - "CARDIO", - "YOGA", - "ELSE", -] as const; - -export const SleepLevels = [ - "TERRIBLE", - "VERY_BAD", - "BAD", - "GOOD", - "EXCELLENT", -] as const; - -export type EGoal = (typeof Goals)[number]; -export type ESportLevel = (typeof SportLevels)[number]; -export type ESport = (typeof Sports)[number]; -export type ESleepLevel = (typeof SleepLevels)[number]; - -export type EHealthProblem = "ARTHROSE" | "MIGRAINE"; diff --git a/tsconfig.json b/tsconfig.json index cadd0ba..92beb97 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,5 +13,6 @@ ".expo/types/**/*.ts", "expo-env.d.ts", "nativewind-env.d.ts", + "enum/Enums.tsx" ] }