Compare commits
9 Commits
main
...
WORK_COMMU
Author | SHA1 | Date |
---|---|---|
![]() |
57dc8d5d18 | 51 minutes ago |
|
1887022681 | 1 week ago |
|
7dd7b2a482 | 1 week ago |
|
019b67cce0 | 1 week ago |
![]() |
c8696f223d | 3 weeks ago |
![]() |
2c8db06f32 | 3 weeks ago |
![]() |
90b1e450e1 | 3 weeks ago |
![]() |
a3e567f291 | 4 weeks ago |
![]() |
4cba2025cf | 4 weeks ago |
@ -1,13 +0,0 @@
|
||||
import axios from 'axios';
|
||||
|
||||
const apiClient = axios.create({
|
||||
baseURL: 'https://codefirst.iut.uca.fr/containers/Optifit-optifit-ef-api/api/v1/',
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
// ajoute ici les headers supplémentaires, ex. Auth
|
||||
},
|
||||
});
|
||||
|
||||
export default apiClient;
|
@ -1,5 +0,0 @@
|
||||
|
||||
|
||||
export const EXERCICES = {
|
||||
GETALL: '/exercices',
|
||||
}
|
@ -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<string, string>;
|
||||
};
|
||||
|
||||
export abstract class AbstractServiceApi {
|
||||
protected async request(path: string, options?: RequestOption): Promise<any> {
|
||||
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<string, string>
|
||||
): Record<string, string> {
|
||||
return {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
...(headers || {}),
|
||||
};
|
||||
}
|
||||
|
||||
private async checkStatus(
|
||||
path: string,
|
||||
res: Response,
|
||||
options?: RequestOption
|
||||
): Promise<any> {
|
||||
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<boolean> {
|
||||
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<Response> {
|
||||
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 }),
|
||||
});
|
||||
}
|
||||
}
|
@ -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<ExerciceDTO[]> {
|
||||
const data = await this.request(ENDPOINTS.CATALOG);
|
||||
return data as ExerciceDTO[];
|
||||
}
|
||||
|
||||
async getExercices(spec: ESearchExerciceFilter): Promise<ExerciceDTO[]> {
|
||||
const param = new URLSearchParams({ spec: spec });
|
||||
const data = await this.request(`${ENDPOINTS.CATALOG}?${param}`);
|
||||
return data as ExerciceDTO[];
|
||||
}
|
||||
|
||||
async getExercice(id: string): Promise<ExerciceDTO | undefined> {
|
||||
const param = new URLSearchParams({ id });
|
||||
const data = await this.request(`${ENDPOINTS.CATALOG}?${param}`);
|
||||
return data as ExerciceDTO;
|
||||
}
|
||||
|
||||
async addExercice(exercice: ExerciceDTO): Promise<ExerciceDTO> {
|
||||
const data = await this.request(ENDPOINTS.CATALOG, {
|
||||
method: "POST",
|
||||
body: exercice,
|
||||
});
|
||||
return data as ExerciceDTO;
|
||||
}
|
||||
|
||||
async editExercice(
|
||||
id: string,
|
||||
exercice: UpdateExerciceDTO
|
||||
): Promise<UpdateExerciceDTO | undefined> {
|
||||
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<DeleteDTO> {
|
||||
const param = new URLSearchParams({ id: id });
|
||||
const data = await this.request(`${ENDPOINTS.CATALOG}?${param}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
return data as DeleteDTO;
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import axios from "axios";
|
||||
|
||||
const apiClient = axios.create({
|
||||
baseURL:
|
||||
"https://codefirst.iut.uca.fr/containers/Optifit-optifit-ef-api/api/v1/",
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
export default apiClient;
|
@ -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;
|
@ -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<TrainingDTO[]> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getTrainings(spec: ESearchTrainingFilter): Promise<TrainingDTO[]> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getTraining(id: string): Promise<TrainingDTO | undefined> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getSession(id: string): Promise<SessionDTO | undefined> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getExercice(id: string): Promise<ExerciceDTO | undefined> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
createTraining(training: TrainingDTO): Promise<TrainingDTO | undefined> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
editTraining(
|
||||
training: UpdateTrainingDTO
|
||||
): Promise<UpdateTrainingDTO> | undefined {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
duplicateTraining(id: string): Promise<TrainingDTO | undefined> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
deleteTraining(id: string): Promise<TrainingDTO | undefined> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
import { User } from "@/model/User";
|
||||
import { setItemAsync } from "expo-secure-store";
|
||||
import { IUserService } from "../interface/service.interface.user";
|
||||
import { AbstractServiceApi } from "./service.api.abstract";
|
||||
|
||||
export class UserServiceApi extends AbstractServiceApi implements IUserService {
|
||||
async login(email: string, password: string): Promise<User> {
|
||||
const body = new URLSearchParams({
|
||||
grant_type: "password",
|
||||
client_id: email,
|
||||
client_secret: this.CLIENT_SECRET,
|
||||
email,
|
||||
password,
|
||||
scope: this.SCOPES,
|
||||
});
|
||||
|
||||
const res = await fetch(`${this.IDP_URL}/connect/token`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
body: body.toString(),
|
||||
});
|
||||
|
||||
if (!res.ok) throw new Error(`Auth failed: ${res.status}`);
|
||||
const json = await res.json();
|
||||
|
||||
await setItemAsync(this.ACCESS_TOKEN_PATH, json.access_token);
|
||||
await setItemAsync(this.REFRESH_TOKEN_PATH, json.refresh_token);
|
||||
|
||||
return json;
|
||||
}
|
||||
}
|
@ -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;
|
||||
};
|
@ -0,0 +1,3 @@
|
||||
export type DeleteDTO = {
|
||||
Id: string;
|
||||
};
|
@ -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[];
|
||||
};
|
@ -0,0 +1,35 @@
|
||||
import { EHealthProblem } from "@/enum/enum.health-problem";
|
||||
import { ESleepLevel } from "@/enum/enum.sleep-level";
|
||||
import { ESport } from "@/enum/enum.sport";
|
||||
import { ESportLevel } from "@/enum/enum.sport-level";
|
||||
|
||||
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[];
|
||||
};
|
@ -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<ExerciceDTO[]>;
|
||||
getExercices(spec: ESearchExerciceFilter): Promise<ExerciceDTO[]>;
|
||||
getExercice(id: string): Promise<ExerciceDTO | undefined>;
|
||||
addExercice(exercice: ExerciceDTO): Promise<ExerciceDTO>;
|
||||
editExercice(
|
||||
id: string,
|
||||
exercice: UpdateExerciceDTO
|
||||
): Promise<UpdateExerciceDTO | undefined>;
|
||||
deleteExercice(id: string): Promise<DeleteDTO>;
|
||||
}
|
@ -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<TrainingDTO[]>;
|
||||
getTrainings(spec: ESearchTrainingFilter): Promise<TrainingDTO[]>;
|
||||
getTraining(id: string): Promise<TrainingDTO | undefined>;
|
||||
getSession(id: string): Promise<SessionDTO | undefined>;
|
||||
getExercice(id: string): Promise<ExerciceDTO | undefined>;
|
||||
createTraining(training: TrainingDTO): Promise<TrainingDTO | undefined>;
|
||||
editTraining(
|
||||
training: UpdateTrainingDTO
|
||||
): Promise<UpdateTrainingDTO> | undefined;
|
||||
duplicateTraining(id: string): Promise<TrainingDTO | undefined>;
|
||||
deleteTraining(id: string): Promise<TrainingDTO | undefined>;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { User } from "@/model/User";
|
||||
|
||||
export interface IUserService {
|
||||
login(email: string, password: string): User | undefined;
|
||||
login(email: string, password: string): Promise<User>;
|
||||
}
|
@ -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();
|
@ -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<ExerciceDTO[]> {
|
||||
return Promise.resolve(this.exercices);
|
||||
}
|
||||
|
||||
getExercices(spec: ESearchExerciceFilter): Promise<ExerciceDTO[]> {
|
||||
return Promise.resolve(this.exercices);
|
||||
}
|
||||
|
||||
getExercice(id: string): Promise<ExerciceDTO | undefined> {
|
||||
return Promise.resolve(this.exercices.find((x) => x.Id === id));
|
||||
}
|
||||
|
||||
addExercice(exercice: ExerciceDTO): Promise<ExerciceDTO> {
|
||||
this.exercices.push(exercice);
|
||||
return Promise.resolve(exercice);
|
||||
}
|
||||
|
||||
editExercice(
|
||||
id: string,
|
||||
exercice: UpdateExerciceDTO
|
||||
): Promise<UpdateExerciceDTO | undefined> {
|
||||
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<DeleteDTO> {
|
||||
const dto: DeleteDTO = {
|
||||
Id: id,
|
||||
};
|
||||
return Promise.resolve(dto);
|
||||
}
|
||||
}
|
@ -0,0 +1,284 @@
|
||||
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 {
|
||||
private readonly trainings: TrainingDTO[] = [
|
||||
{
|
||||
Id: "t1",
|
||||
Name: "Full Body Starter",
|
||||
Description: "Programme d'initiation complet pour débutants.",
|
||||
Sessions: [
|
||||
{
|
||||
Id: "s1",
|
||||
Name: "Jour 1 - Haut du corps",
|
||||
Description: "Focus sur les bras, épaules et poitrine.",
|
||||
Category: "WARM_UP",
|
||||
Exercices: [
|
||||
{
|
||||
Id: "e1",
|
||||
Name: "Pompes",
|
||||
Description: "Renforce les pectoraux et les triceps.",
|
||||
Target: "CHEST",
|
||||
Image: "pompes.jpg",
|
||||
Video: "pompes.mp4",
|
||||
Duration: 10,
|
||||
NbSet: 3,
|
||||
RestTime: 60,
|
||||
NbRep: 12,
|
||||
Passed: false,
|
||||
},
|
||||
{
|
||||
Id: "e2",
|
||||
Name: "Curl haltère",
|
||||
Description: "Travail des biceps.",
|
||||
Target: "ARM",
|
||||
Image: "curl.jpg",
|
||||
Video: "curl.mp4",
|
||||
Duration: 15,
|
||||
NbSet: 3,
|
||||
RestTime: 45,
|
||||
NbRep: 10,
|
||||
Weight: 8,
|
||||
Passed: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
Id: "s2",
|
||||
Name: "Jour 2 - Bas du corps",
|
||||
Description: "Travail des jambes et fessiers.",
|
||||
Category: "TRAINING",
|
||||
Exercices: [
|
||||
{
|
||||
Id: "e3",
|
||||
Name: "Squats",
|
||||
Description: "Renforce les jambes et fessiers.",
|
||||
Target: "LEG",
|
||||
Image: "squat.jpg",
|
||||
Video: "squat.mp4",
|
||||
Duration: 0,
|
||||
NbSet: 4,
|
||||
RestTime: 60,
|
||||
NbRep: 15,
|
||||
Passed: false,
|
||||
},
|
||||
{
|
||||
Id: "e4",
|
||||
Name: "Fentes",
|
||||
Description: "Développe les quadriceps et ischio-jambiers.",
|
||||
Target: "LEG",
|
||||
Image: "fente.jpg",
|
||||
Video: "fente.mp4",
|
||||
Duration: 0,
|
||||
NbSet: 3,
|
||||
RestTime: 45,
|
||||
NbRep: 12,
|
||||
Passed: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
Id: "t2",
|
||||
Name: "Cardio Express",
|
||||
Description: "Séances courtes et intenses pour brûler des calories.",
|
||||
Sessions: [
|
||||
{
|
||||
Id: "s3",
|
||||
Name: "HIIT 20 min",
|
||||
Description: "Enchaînement rapide d'exercices.",
|
||||
Category: "WARM_UP",
|
||||
Exercices: [
|
||||
{
|
||||
Id: "e5",
|
||||
Name: "Burpees",
|
||||
Description: "Exercice complet pour le cardio.",
|
||||
Target: "CARDIO",
|
||||
Image: "burpee.jpg",
|
||||
Video: "burpee.mp4",
|
||||
Duration: 30,
|
||||
NbSet: 4,
|
||||
RestTime: 30,
|
||||
NbRep: 0,
|
||||
Passed: false,
|
||||
},
|
||||
{
|
||||
Id: "e6",
|
||||
Name: "Jumping Jacks",
|
||||
Description: "Échauffement et endurance.",
|
||||
Target: "CARDIO",
|
||||
Image: "jumpingjack.jpg",
|
||||
Video: "jumpingjack.mp4",
|
||||
Duration: 60,
|
||||
NbSet: 3,
|
||||
RestTime: 20,
|
||||
NbRep: 0,
|
||||
Passed: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
Id: "t3",
|
||||
Name: "Renforcement Core",
|
||||
Description: "Travail spécifique du gainage et des abdos.",
|
||||
Sessions: [
|
||||
{
|
||||
Id: "s4",
|
||||
Name: "Abdos explosifs",
|
||||
Description: "Séance abdos intense.",
|
||||
Category: "TRAINING",
|
||||
Exercices: [
|
||||
{
|
||||
Id: "e7",
|
||||
Name: "Crunchs",
|
||||
Description: "Renforcement du grand droit abdominal.",
|
||||
Target: "CHEST",
|
||||
Image: "crunch.jpg",
|
||||
Video: "crunch.mp4",
|
||||
Duration: 0,
|
||||
NbSet: 4,
|
||||
RestTime: 30,
|
||||
NbRep: 20,
|
||||
Passed: false,
|
||||
},
|
||||
{
|
||||
Id: "e8",
|
||||
Name: "Planche",
|
||||
Description: "Gainage isométrique.",
|
||||
Target: "CHEST",
|
||||
Image: "plank.jpg",
|
||||
Video: "plank.mp4",
|
||||
Duration: 60,
|
||||
NbSet: 3,
|
||||
RestTime: 30,
|
||||
NbRep: 0,
|
||||
Passed: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
Id: "t4",
|
||||
Name: "Force & Masse",
|
||||
Description: "Programme orienté prise de muscle.",
|
||||
Sessions: [
|
||||
{
|
||||
Id: "s5",
|
||||
Name: "Pecs & Triceps",
|
||||
Description: "Travail des muscles du haut du torse.",
|
||||
Category: "TRAINING",
|
||||
Exercices: [
|
||||
{
|
||||
Id: "e9",
|
||||
Name: "Développé couché",
|
||||
Description: "Exercice principal pour les pectoraux.",
|
||||
Target: "CHEST",
|
||||
Image: "benchpress.jpg",
|
||||
Video: "benchpress.mp4",
|
||||
Duration: 0,
|
||||
NbSet: 4,
|
||||
RestTime: 90,
|
||||
NbRep: 8,
|
||||
Weight: 40,
|
||||
Passed: false,
|
||||
},
|
||||
{
|
||||
Id: "e10",
|
||||
Name: "Dips",
|
||||
Description: "Renforcement des triceps.",
|
||||
Target: "ARM",
|
||||
Image: "dips.jpg",
|
||||
Video: "dips.mp4",
|
||||
Duration: 0,
|
||||
NbSet: 3,
|
||||
RestTime: 60,
|
||||
NbRep: 10,
|
||||
Passed: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
Id: "t5",
|
||||
Name: "Mobilité & Étirements",
|
||||
Description: "Programme doux pour améliorer la souplesse.",
|
||||
Sessions: [
|
||||
{
|
||||
Id: "s6",
|
||||
Name: "Étirements du matin",
|
||||
Description: "Routine pour bien démarrer la journée.",
|
||||
Category: "STRETCHING",
|
||||
Exercices: [
|
||||
{
|
||||
Id: "e11",
|
||||
Name: "Étirement dos",
|
||||
Description: "Soulage le bas du dos.",
|
||||
Target: "BACK",
|
||||
Image: "stretch_back.jpg",
|
||||
Video: "stretch_back.mp4",
|
||||
Duration: 45,
|
||||
NbSet: 2,
|
||||
RestTime: 30,
|
||||
NbRep: 0,
|
||||
Passed: false,
|
||||
},
|
||||
{
|
||||
Id: "e12",
|
||||
Name: "Étirement ischio-jambiers",
|
||||
Description: "Améliore la flexibilité des jambes.",
|
||||
Target: "LEG",
|
||||
Image: "stretch_hamstrings.jpg",
|
||||
Video: "stretch_hamstrings.mp4",
|
||||
Duration: 60,
|
||||
NbSet: 2,
|
||||
RestTime: 30,
|
||||
NbRep: 0,
|
||||
Passed: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
getAllTrainings(): Promise<TrainingDTO[]> {
|
||||
return Promise.resolve(this.trainings);
|
||||
}
|
||||
getTrainings(spec: ESearchTrainingFilter): Promise<TrainingDTO[]> {
|
||||
return Promise.resolve(this.trainings);
|
||||
}
|
||||
getTraining(id: string): Promise<TrainingDTO | undefined> {
|
||||
return Promise.resolve(this.trainings.find((x) => x.Id === id));
|
||||
}
|
||||
getSession(id: string): Promise<SessionDTO | undefined> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getExercice(id: string): Promise<ExerciceDTO | undefined> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
createTraining(training: TrainingDTO): Promise<TrainingDTO | undefined> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
editTraining(
|
||||
training: UpdateTrainingDTO
|
||||
): Promise<UpdateTrainingDTO> | undefined {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
duplicateTraining(id: string): Promise<TrainingDTO | undefined> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
deleteTraining(id: string): Promise<TrainingDTO | undefined> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
import { User } from "@/model/User";
|
||||
import { IUserService } from "../interface/service.interface.user";
|
||||
|
||||
export class UserServiceStub implements IUserService {
|
||||
private readonly users: User[] = [
|
||||
new User({
|
||||
name: "Alice",
|
||||
age: 28,
|
||||
height: 165,
|
||||
weight: 58,
|
||||
sexe: false,
|
||||
logo: "alice.png",
|
||||
nbSessionPerWeek: 3,
|
||||
goal: "Perdre du poids",
|
||||
healthProblems: [],
|
||||
sport: "YOGA",
|
||||
sleepLevel: "GOOD",
|
||||
sportLevel: "BEGINNER",
|
||||
email: "test@1.com",
|
||||
password: "password1",
|
||||
}),
|
||||
new User({
|
||||
email: "test@2.com",
|
||||
password: "password2",
|
||||
}),
|
||||
new User({
|
||||
name: "Charlie",
|
||||
age: 22,
|
||||
height: 172,
|
||||
weight: 70,
|
||||
sexe: true,
|
||||
logo: "charlie.png",
|
||||
nbSessionPerWeek: 2,
|
||||
goal: "Se remettre en forme",
|
||||
healthProblems: [],
|
||||
sport: "BIKING",
|
||||
sleepLevel: "GOOD",
|
||||
sportLevel: "BEGINNER",
|
||||
email: "test@3.com",
|
||||
password: "password3",
|
||||
}),
|
||||
new User({
|
||||
name: "Diana",
|
||||
age: 31,
|
||||
height: 160,
|
||||
weight: 55,
|
||||
sexe: false,
|
||||
logo: "diana.png",
|
||||
nbSessionPerWeek: 5,
|
||||
goal: "Préparer un marathon",
|
||||
healthProblems: [],
|
||||
sport: "RUNNING",
|
||||
sleepLevel: "GOOD",
|
||||
sportLevel: "VERY_SPORTY",
|
||||
email: "test@4.com",
|
||||
password: "password4",
|
||||
}),
|
||||
new User({
|
||||
name: "Ethan",
|
||||
age: 40,
|
||||
height: 180,
|
||||
weight: 88,
|
||||
sexe: true,
|
||||
logo: "ethan.png",
|
||||
nbSessionPerWeek: 1,
|
||||
goal: "Maintenir sa forme",
|
||||
healthProblems: ["MIGRAINE"],
|
||||
sport: "WALKING",
|
||||
sleepLevel: "BAD",
|
||||
sportLevel: "SPORTY",
|
||||
email: "test@5.com",
|
||||
password: "password5",
|
||||
}),
|
||||
new User({
|
||||
name: "Fiona",
|
||||
age: 26,
|
||||
height: 167,
|
||||
weight: 62,
|
||||
sexe: false,
|
||||
logo: "fiona.png",
|
||||
nbSessionPerWeek: 3,
|
||||
goal: "Renforcer le dos",
|
||||
healthProblems: ["MIGRAINE"],
|
||||
sport: "FOOTBALL",
|
||||
sleepLevel: "BAD",
|
||||
sportLevel: "BEGINNER",
|
||||
email: "test@6.com",
|
||||
password: "password6",
|
||||
}),
|
||||
new User({
|
||||
name: "George",
|
||||
age: 30,
|
||||
height: 185,
|
||||
weight: 90,
|
||||
sexe: true,
|
||||
logo: "george.png",
|
||||
nbSessionPerWeek: 4,
|
||||
goal: "Perdre du gras",
|
||||
healthProblems: [],
|
||||
sport: "BIKING",
|
||||
sleepLevel: "TERRIBLE",
|
||||
sportLevel: "SPORTY",
|
||||
email: "test@7.com",
|
||||
password: "password7",
|
||||
}),
|
||||
new User({
|
||||
name: "Hanna",
|
||||
age: 24,
|
||||
height: 158,
|
||||
weight: 54,
|
||||
sexe: false,
|
||||
logo: "hanna.png",
|
||||
nbSessionPerWeek: 2,
|
||||
goal: "Se tonifier",
|
||||
healthProblems: [],
|
||||
sport: "HANDBALL",
|
||||
sleepLevel: "GOOD",
|
||||
sportLevel: "BEGINNER",
|
||||
email: "test@8.com",
|
||||
password: "password8",
|
||||
}),
|
||||
new User({
|
||||
name: "Ivan",
|
||||
age: 50,
|
||||
height: 175,
|
||||
weight: 95,
|
||||
sexe: true,
|
||||
logo: "ivan.png",
|
||||
nbSessionPerWeek: 1,
|
||||
goal: "Rééducation",
|
||||
healthProblems: ["ARTHROSE"],
|
||||
sport: "WALKING",
|
||||
sleepLevel: "BAD",
|
||||
sportLevel: "BEGINNER",
|
||||
email: "test@9.com",
|
||||
password: "password9",
|
||||
}),
|
||||
new User({
|
||||
name: "Julia",
|
||||
age: 29,
|
||||
height: 170,
|
||||
weight: 60,
|
||||
sexe: false,
|
||||
logo: "julia.png",
|
||||
nbSessionPerWeek: 3,
|
||||
goal: "Rester active",
|
||||
healthProblems: [],
|
||||
sport: "ELSE",
|
||||
sleepLevel: "GOOD",
|
||||
sportLevel: "SPORTY",
|
||||
email: "test@10.com",
|
||||
password: "password10",
|
||||
}),
|
||||
];
|
||||
|
||||
async login(email: string, password: string): Promise<User> {
|
||||
const user = this.users.find(
|
||||
(x) => x.email === email && x.password === password
|
||||
);
|
||||
|
||||
if (!user) {
|
||||
throw new Error("User not found.");
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
import apiClient from "../client";
|
||||
import {EXERCICES} from "../endpoints";
|
||||
|
||||
export const getExercices = async () => {
|
||||
try {
|
||||
const response = await apiClient.get(EXERCICES.GETALL);
|
||||
return response.data.data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
import Error from "@/components/Error";
|
||||
//@ts-ignore
|
||||
import blockedPict from "@/assets/images/Blocked.png";
|
||||
import { FEATURE_LOCKED } from "@/components/Errors";
|
||||
import React from "react";
|
||||
|
||||
export default function Blocked() {
|
||||
return (
|
||||
<Error
|
||||
picture={blockedPict}
|
||||
problem="Fonctionnalité bloquée"
|
||||
description={FEATURE_LOCKED}
|
||||
information="Devenez PREMIUM pour débloquer"
|
||||
/>
|
||||
);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import Error from "@/components/Error";
|
||||
//@ts-ignore
|
||||
import internalErrorPict from "@/assets/images/InternalError.png";
|
||||
import { INTERNAL_ERROR } from "@/components/Errors";
|
||||
import React from "react";
|
||||
|
||||
export default function InternalError() {
|
||||
return (
|
||||
<Error
|
||||
picture={internalErrorPict}
|
||||
problem="Problème interne"
|
||||
description={INTERNAL_ERROR}
|
||||
information="Contactez le support"
|
||||
/>
|
||||
);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import Error from "@/components/Error";
|
||||
//@ts-ignore
|
||||
import maintenancePict from "@/assets/images/Maintenance.png";
|
||||
import { MAINTENANCE } from "@/components/Errors";
|
||||
import React from "react";
|
||||
|
||||
export default function Maintenance() {
|
||||
return (
|
||||
<Error
|
||||
picture={maintenancePict}
|
||||
problem="Maintenance"
|
||||
description={MAINTENANCE}
|
||||
information="Revenez plus tard"
|
||||
/>
|
||||
);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import Error from "@/components/Error";
|
||||
//@ts-ignore
|
||||
import noInternetPict from "@/assets/images/NoInternet.png";
|
||||
import { NO_INTERNET } from "@/components/Errors";
|
||||
import React from "react";
|
||||
|
||||
export default function NoInternet() {
|
||||
return (
|
||||
<Error
|
||||
picture={noInternetPict}
|
||||
problem="Pas d'internet"
|
||||
description={NO_INTERNET}
|
||||
information="Réessayez plus tard"
|
||||
/>
|
||||
);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import Error from "@/components/Error";
|
||||
//@ts-ignore
|
||||
import notAllowedPict from "@/assets/images/NotAllowed.png";
|
||||
import { NOT_AUTHORIZED } from "@/components/Errors";
|
||||
import React from "react";
|
||||
|
||||
export default function NotAllowedProblem() {
|
||||
return (
|
||||
<Error
|
||||
picture={notAllowedPict}
|
||||
problem="Pas autorisé"
|
||||
description={NOT_AUTHORIZED}
|
||||
information="Connectez vous avec plus de privilèges"
|
||||
/>
|
||||
);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import Error from "@/components/Error";
|
||||
//@ts-ignore
|
||||
import notFoundPict from "@/assets/images/NotFound.png";
|
||||
import { NOT_FOUND } from "@/components/Errors";
|
||||
import React from "react";
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<Error
|
||||
picture={notFoundPict}
|
||||
problem="Introuvable"
|
||||
description={NOT_FOUND}
|
||||
information="Status Code : 404"
|
||||
/>
|
||||
);
|
||||
}
|
@ -1,16 +1,33 @@
|
||||
import {SafeAreaView, View, Text} from "react-native";
|
||||
import React from "react";
|
||||
import InternalError from "@/components/error/InternalErrorProblem";
|
||||
import {
|
||||
ImageBackground,
|
||||
SafeAreaView,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from "react-native";
|
||||
|
||||
export default function AddScreen() {
|
||||
return (
|
||||
<ImageBackground
|
||||
className="h-full w-full"
|
||||
source={require("assets/images/TrainingPresentation.png")}
|
||||
>
|
||||
<SafeAreaView>
|
||||
<View>
|
||||
<InternalError/>
|
||||
<View className="flex-row justify-between items-center mb-4">
|
||||
<TouchableOpacity className="bg-blue-500 px-4 py-2 rounded"></TouchableOpacity>
|
||||
|
||||
<TouchableOpacity className="bg-green-500 px-4 py-2 rounded">
|
||||
<Text className="text-white font-bold">Action</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<View className="flex-1 items-center justify-center">
|
||||
<Text className="text-xl font-semibold">
|
||||
Contenu de l'entraînement
|
||||
</Text>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
</ImageBackground>
|
||||
);
|
||||
}
|
||||
|
||||
//<Text className="m-7 font-extrabold">Welcome to Add Screen </Text>
|
||||
// <Text>We will do it soon</Text>
|
@ -1,97 +0,0 @@
|
||||
// import { SafeAreaView, StyleSheet, View } from "react-native";
|
||||
// import React from "react";
|
||||
// import {
|
||||
// Avatar,
|
||||
// AvatarFallbackText,
|
||||
// AvatarImage,
|
||||
// } from "@/components/ui/avatar";
|
||||
// import { AntDesign } from "@expo/vector-icons";
|
||||
// import { Text } from "@/components/ui/text";
|
||||
// import ExerciceOverview from "@/components/ExerciceOverview";
|
||||
|
||||
// export default function HomeScreen() {
|
||||
// const date = new Date();
|
||||
// const formattedDate = date.toLocaleDateString("fr-FR", {
|
||||
// year: "numeric",
|
||||
// month: "long",
|
||||
// day: "numeric",
|
||||
// });
|
||||
|
||||
// return (
|
||||
// <SafeAreaView style={styles.container}>
|
||||
// <View style={styles.headerStyle}>
|
||||
// <View style={styles.dateContainer}>
|
||||
// <AntDesign name="calendar" size={24} color="white" />
|
||||
// <Text style={styles.dateText}>{formattedDate}</Text>
|
||||
// </View>
|
||||
|
||||
// <View style={styles.avatarContainer}>
|
||||
// <Avatar size="xl">
|
||||
// <AvatarFallbackText>Jane Doe</AvatarFallbackText>
|
||||
// <AvatarImage
|
||||
// source={{
|
||||
// uri: "https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80",
|
||||
// }}
|
||||
// />
|
||||
// </Avatar>
|
||||
// <Text style={styles.titleNameUser}>Hello, Tata Monique</Text>
|
||||
// </View>
|
||||
// </View>
|
||||
|
||||
// <View>
|
||||
// <ExerciceOverview />
|
||||
// </View>
|
||||
// </SafeAreaView>
|
||||
// );
|
||||
// }
|
||||
|
||||
// const styles = StyleSheet.create({
|
||||
// container: {
|
||||
// flex: 1,
|
||||
// backgroundColor: "#f9f9f9", // Fond de l'écran avec une couleur claire
|
||||
// },
|
||||
// headerStyle: {
|
||||
// height: 200,
|
||||
// backgroundColor: "#333333", // Gris foncé pour l'arrière-plan du header
|
||||
// borderBottomEndRadius: 25,
|
||||
// borderBottomStartRadius: 25,
|
||||
// padding: 20,
|
||||
// alignItems: "flex-start",
|
||||
// justifyContent: "flex-start",
|
||||
// },
|
||||
// dateContainer: {
|
||||
// flexDirection: "row",
|
||||
// alignItems: "flex-start",
|
||||
// marginBottom: 20,
|
||||
// },
|
||||
// dateText: {
|
||||
// fontSize: 18,
|
||||
// fontWeight: "bold",
|
||||
// marginLeft: 10,
|
||||
// color: "#ffffff",
|
||||
// },
|
||||
// avatarContainer: {
|
||||
// marginBottom: 15,
|
||||
// flexDirection: "row",
|
||||
// alignItems: "center",
|
||||
// },
|
||||
|
||||
// titleNameUser: {
|
||||
// fontSize: 24,
|
||||
// color: "#ffffff",
|
||||
// fontWeight: "bold",
|
||||
// marginLeft: 10,
|
||||
// },
|
||||
// contentContainer: {
|
||||
// marginTop: 20,
|
||||
// padding: 15,
|
||||
// alignItems: "flex-start",
|
||||
// },
|
||||
// contentText: {
|
||||
// fontSize: 16,
|
||||
// color: "#333333", // Texte en gris foncé pour une bonne lisibilité
|
||||
// textAlign: "center",
|
||||
// },
|
||||
|
||||
// fitness: {},
|
||||
// });
|
@ -1,19 +0,0 @@
|
||||
import React from "react";
|
||||
import {Stack} from "expo-router";
|
||||
|
||||
export default function RootoLayout() {
|
||||
return (
|
||||
<Stack screenOptions={{
|
||||
headerShown: false,
|
||||
}}
|
||||
initialRouteName={"ExercicesScreen"}
|
||||
>
|
||||
<Stack.Screen name="ExercicesScreen" />
|
||||
|
||||
<Stack.Screen name="WorkoutScreen"/>
|
||||
|
||||
</Stack>
|
||||
|
||||
);
|
||||
|
||||
}
|
@ -1,15 +1,14 @@
|
||||
import React from "react";
|
||||
import { Stack } from "expo-router";
|
||||
import HelpsScreen from "@/app/(tabs)/(help)/HelpsScreen";
|
||||
import React from "react";
|
||||
|
||||
export default function RootoLayout() {
|
||||
return (
|
||||
<Stack screenOptions={{
|
||||
<Stack
|
||||
screenOptions={{
|
||||
headerShown: false,
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<Stack.Screen name="HelpsScreen" />
|
||||
</Stack>
|
||||
|
||||
);
|
||||
|
||||
}
|
@ -1,10 +1,6 @@
|
||||
import {SafeAreaView, Text, View} from "react-native";
|
||||
import React from "react";
|
||||
import HomeScreen from "@/app/(tabs)/(home)/HomeScreen";
|
||||
import React from "react";
|
||||
|
||||
export default function App() {
|
||||
|
||||
return (
|
||||
<HomeScreen/>
|
||||
);
|
||||
return <HomeScreen />;
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
import { ExerciceDTO } from "@/api/service/dto/dto.training";
|
||||
import { TrainingServiceRef } from "@/api/service/service.ref";
|
||||
import { useWorkoutStore } from "@/store/workoutStore";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
Dimensions,
|
||||
Image,
|
||||
ImageBackground,
|
||||
ScrollView,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from "react-native";
|
||||
import Modal from "react-native-modal";
|
||||
|
||||
const screenHeight = Dimensions.get("window").height;
|
||||
|
||||
export default function WorkoutScreen() {
|
||||
let session = useWorkoutStore((s) => s.selectedWorkout);
|
||||
const [isModalVisible, setModalVisible] = useState(false);
|
||||
const [totalDuration, setTotalDuration] = useState(0);
|
||||
const [totalReps, setTotalReps] = useState(0);
|
||||
const [exercices, setExercices] = useState<ExerciceDTO[] | undefined>();
|
||||
const trainingService = TrainingServiceRef;
|
||||
|
||||
useEffect(() => {
|
||||
trainingService.getTraining("t1").then((x) => {
|
||||
if (x) {
|
||||
const sessionData = x.Sessions[0];
|
||||
if (!sessionData) return;
|
||||
|
||||
let duration = 0;
|
||||
let reps = 0;
|
||||
|
||||
setExercices(sessionData.Exercices);
|
||||
|
||||
sessionData?.Exercices.forEach((ex) => {
|
||||
duration += ex.Duration;
|
||||
reps += ex.NbRep;
|
||||
});
|
||||
|
||||
setTotalDuration(duration);
|
||||
setTotalReps(reps);
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View className="flex-1 bg-black">
|
||||
<ImageBackground
|
||||
source={require("assets/images/TrainingPresentation.png")}
|
||||
className="flex-1 justify-between px-6 pb-10 pt-14"
|
||||
imageStyle={{ resizeMode: "cover" }}
|
||||
>
|
||||
<View className="flex-row justify-between">
|
||||
<TouchableOpacity className="bg-black/50 p-2 rounded-full">
|
||||
<Ionicons name="chevron-back" size={20} color="white" />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity className="bg-black/50 p-2 rounded-full">
|
||||
<Ionicons name="settings-outline" size={20} color="white" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<View className="flex-1 justify-end">
|
||||
<View className="items-center">
|
||||
<Text className="text-white text-4xl font-bold">
|
||||
{session?.Name}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View className="flex-row justify-between mb-16 mt-16">
|
||||
<View className="items-center flex-1">
|
||||
<Ionicons name="time-outline" size={36} color="white" />
|
||||
<Text className="text-white font-bold text-xl mt-2">
|
||||
{totalDuration + " min"}
|
||||
</Text>
|
||||
<Text className="text-gray-300 text-lg">Time</Text>
|
||||
</View>
|
||||
|
||||
<View className="h-20 w-1 bg-white mx-2" />
|
||||
|
||||
<View className="items-center flex-1">
|
||||
<Ionicons name="flame-outline" size={36} color="white" />
|
||||
<Text className="text-white font-bold text-xl mt-2">240kcal</Text>
|
||||
<Text className="text-gray-300 text-lg">Calories</Text>
|
||||
</View>
|
||||
|
||||
<View className="h-20 w-1 bg-white mx-2" />
|
||||
|
||||
<View className="items-center flex-1">
|
||||
<Ionicons name="barbell-outline" size={36} color="white" />
|
||||
<Text className="text-white font-bold text-xl mt-2">
|
||||
{totalReps}
|
||||
</Text>
|
||||
<Text className="text-gray-300 text-lg">Sets</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className="flex-row">
|
||||
<TouchableOpacity
|
||||
className="flex-1 bg-black/50 p-4 rounded-xl flex-row justify-center items-center"
|
||||
onPress={() => setModalVisible(true)}
|
||||
>
|
||||
<Text className="text-white mr-2">Details</Text>
|
||||
<Ionicons name="document-text-outline" size={18} color="white" />
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity className="flex-1 bg-orange-500 p-4 rounded-xl flex-row justify-center items-center">
|
||||
<Text className="text-white font-bold mr-2">Start</Text>
|
||||
<Ionicons name="timer-outline" size={18} color="white" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</ImageBackground>
|
||||
|
||||
<Modal
|
||||
isVisible={isModalVisible}
|
||||
onBackdropPress={() => setModalVisible(false)}
|
||||
swipeDirection="down"
|
||||
onSwipeComplete={() => setModalVisible(false)}
|
||||
style={{
|
||||
justifyContent: "flex-end",
|
||||
margin: 0,
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
height: screenHeight * 0.65,
|
||||
backgroundColor: "white",
|
||||
borderTopLeftRadius: 20,
|
||||
borderTopRightRadius: 20,
|
||||
padding: 20,
|
||||
}}
|
||||
>
|
||||
<ScrollView>
|
||||
<Text className="text-center text-gray-700 mb-4">
|
||||
Liste des exercices
|
||||
</Text>
|
||||
|
||||
{exercices?.map((ex, index) => (
|
||||
<View
|
||||
key={ex.Id}
|
||||
className="flex-row bg-gray-100 rounded-xl items-center p-3 mb-4"
|
||||
>
|
||||
<Image
|
||||
source={require("assets/images/TrainingPresentation.png")}
|
||||
className="w-16 h-16 rounded-md mr-3"
|
||||
/>
|
||||
<View className="flex-1">
|
||||
<Text className="font-semibold text-black">
|
||||
{index + 1}. {ex.Name}
|
||||
</Text>
|
||||
<View className="flex-row items-center mt-1">
|
||||
<Ionicons name="time-outline" size={14} color="gray" />
|
||||
<Text className="text-gray-500 text-xs ml-1">
|
||||
{ex.Duration}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
// router.push("/(tabs)/(exercice)/ExercicesScreen")
|
||||
}}
|
||||
>
|
||||
<Ionicons name="play-circle" size={30} color="#ff7a00" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</Modal>
|
||||
</View>
|
||||
);
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
import { ExerciceDTO } from "@/api/service/dto/dto.training";
|
||||
import WorkoutPresentationComponent from "@/components/WorkoutPresentationComponent";
|
||||
import { useLocalSearchParams } from "expo-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Text, View } from "react-native";
|
||||
|
||||
export default function WorkoutScreen() {
|
||||
const params = useLocalSearchParams();
|
||||
const [workout, setWorkout] = useState<ExerciceDTO | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof params.workout === "string") {
|
||||
try {
|
||||
const parsed = JSON.parse(params.workout);
|
||||
setWorkout(parsed);
|
||||
} catch (error) {}
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (!workout) {
|
||||
return (
|
||||
<Text style={{ padding: 20, margin: 30 }}>Aucune donnée reçue.</Text>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View>
|
||||
<WorkoutPresentationComponent workout={workout} />r
|
||||
</View>
|
||||
);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import React from "react";
|
||||
import {Stack} from "expo-router";
|
||||
|
||||
export default function RootoLayout() {
|
||||
return (
|
||||
<Stack
|
||||
screenOptions={{
|
||||
headerShown: false,
|
||||
}}
|
||||
initialRouteName="ExercicesScreen"
|
||||
>
|
||||
<Stack.Screen name="ExercicesScreen" />
|
||||
<Stack.Screen name="WorkoutScreen" />
|
||||
</Stack>
|
||||
);
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
import Text from "@/components/ui/Text";
|
||||
import React, {forwardRef} from "react";
|
||||
import {Image, View, ViewProps} from "react-native";
|
||||
import BackButton from "@/components/BackButton";
|
||||
|
||||
import {Entypo} from "@expo/vector-icons";
|
||||
|
||||
export interface ProblemProps extends ViewProps{
|
||||
picture: string;
|
||||
problem: string;
|
||||
description: string;
|
||||
information: string;
|
||||
isVisible?: boolean;
|
||||
}
|
||||
|
||||
export default forwardRef<any, ProblemProps> (({className, ...Props}, ref) => {
|
||||
return (
|
||||
<View className={"gap-4 justify-between h-3/4" + " " + className} {...Props} ref={ref}>
|
||||
<View className="flex-row justify-between items-center p-4">
|
||||
<BackButton/>
|
||||
</View>
|
||||
|
||||
<View className="flex-row justify-center">
|
||||
<Image className="aspect-square w-3/5 h-3/5" source={Props.picture}/>
|
||||
</View>
|
||||
|
||||
<Text position="center" weight="bold" size="3xl"> {Props.problem} </Text>
|
||||
<Text size="lg" position="center" className="text-gray-400"> {Props.description} </Text>
|
||||
<View className="flex-row justify-center">
|
||||
<View className="flex-row items-center border-2 rounded-2xl bg-red-300 border-red-600 p-4">
|
||||
<Entypo name="warning" size={30} color="red"/>
|
||||
<Text size="lg" position="center"> {Props.information} </Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
});
|
Binary file not shown.
After Width: | Height: | Size: 354 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 278 KiB |
Before Width: | Height: | Size: 278 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,50 @@
|
||||
import BackButton from "@/components/BackButton";
|
||||
import Text from "@/components/ui/Text";
|
||||
import React, { forwardRef } from "react";
|
||||
import { Image, View, ViewProps } from "react-native";
|
||||
|
||||
import { Entypo } from "@expo/vector-icons";
|
||||
|
||||
export interface ProblemProps extends ViewProps {
|
||||
picture: string;
|
||||
problem: string;
|
||||
description: string;
|
||||
information: string;
|
||||
isVisible?: boolean;
|
||||
}
|
||||
|
||||
export default forwardRef<any, ProblemProps>(({ className, ...Props }, ref) => {
|
||||
return (
|
||||
<View
|
||||
className={"gap-4 justify-between h-3/4" + " " + className}
|
||||
{...Props}
|
||||
ref={ref}
|
||||
>
|
||||
<View className="flex-row justify-between items-center p-4">
|
||||
<BackButton />
|
||||
</View>
|
||||
|
||||
<View className="flex-row justify-center">
|
||||
<Image className="aspect-square w-3/5 h-3/5" source={Props.picture} />
|
||||
</View>
|
||||
|
||||
<Text position="center" weight="bold" size="3xl">
|
||||
{" "}
|
||||
{Props.problem}{" "}
|
||||
</Text>
|
||||
<Text size="lg" position="center" className="text-gray-400">
|
||||
{" "}
|
||||
{Props.description}{" "}
|
||||
</Text>
|
||||
<View className="flex-row justify-center">
|
||||
<View className="flex-row items-center border-2 rounded-2xl bg-red-300 border-red-600 p-4">
|
||||
<Entypo name="warning" size={30} color="red" />
|
||||
<Text size="lg" position="center">
|
||||
{" "}
|
||||
{Props.information}{" "}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
});
|
@ -1,28 +1,29 @@
|
||||
import {Image, Text, TouchableOpacity, View} from "react-native";
|
||||
import {Ionicons} from "@expo/vector-icons";
|
||||
import React from "react";
|
||||
import { useSession } from "@/ctx";
|
||||
import React from "react";
|
||||
import { Image, Text, View } from "react-native";
|
||||
|
||||
export default function HeaderProfileComponent() {
|
||||
const { session } = useSession();
|
||||
|
||||
|
||||
return (
|
||||
<View className="rounded-2xl overflow-hidden shadow-lg h-auto p-4">
|
||||
|
||||
<View className="flex-row items-center justify-between">
|
||||
<View className="flex-row items-center w-full">
|
||||
<Image className="h-16 w-16 rounded-2xl"
|
||||
<Image
|
||||
className="h-16 w-16 rounded-2xl"
|
||||
source={require("assets/images/sigma-profile.jpeg")}
|
||||
/>
|
||||
|
||||
<View>
|
||||
<Text className="text-gray-500 font-semibold ml-4">Prêt pour t'entrainer ?</Text>
|
||||
<Text className="text-black text-4xl ml-4 mt-0.5">{session}</Text>
|
||||
<Text className="text-gray-500 font-semibold ml-4">
|
||||
Prêt pour t'entrainer ?
|
||||
</Text>
|
||||
<Text className="text-black text-4xl ml-4 mt-0.5">
|
||||
{session?.name}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
</View>
|
||||
);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import React from "react";
|
||||
import {FEATURE_LOCKED} from "@/components/Errors";
|
||||
import Error from "@/app/(utility)/Error";
|
||||
import blockedPict from "@/assets/images/Blocked.png";
|
||||
|
||||
export default function Blocked() {
|
||||
return (
|
||||
<Error
|
||||
picture={blockedPict}
|
||||
problem="Fonctionnalité bloquée"
|
||||
description={FEATURE_LOCKED}
|
||||
information="Devenez PREMIUM pour débloquer"
|
||||
/>
|
||||
);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import React from "react";
|
||||
import {INTERNAL_ERROR} from "@/components/Errors";
|
||||
import Error from "@/app/(utility)/Error";
|
||||
import internalErrorPict from "@/assets/images/InternalError.png";
|
||||
|
||||
export default function InternalError() {
|
||||
return (
|
||||
<Error
|
||||
picture={internalErrorPict}
|
||||
problem="Problème interne"
|
||||
description={INTERNAL_ERROR}
|
||||
information="Contactez le support"
|
||||
/>
|
||||
);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import React from "react";
|
||||
import {MAINTENANCE} from "@/components/Errors";
|
||||
import Error from "@/app/(utility)/Error";
|
||||
import maintenancePict from "@/assets/images/Maintenance.png";
|
||||
|
||||
export default function Maintenance() {
|
||||
return (
|
||||
<Error
|
||||
picture={maintenancePict}
|
||||
problem="Maintenance"
|
||||
description={MAINTENANCE}
|
||||
information="Revenez plus tard"
|
||||
/>
|
||||
);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import React from "react";
|
||||
import {NO_INTERNET} from "@/components/Errors";
|
||||
import Error from "@/app/(utility)/Error";
|
||||
import noInternetPict from "@/assets/images/NoInternet.png";
|
||||
|
||||
export default function NoInternet() {
|
||||
return (
|
||||
<Error
|
||||
picture={noInternetPict}
|
||||
problem="Pas d'internet"
|
||||
description={NO_INTERNET}
|
||||
information="Réessayez plus tard"
|
||||
/>
|
||||
);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import React from "react";
|
||||
import {NOT_AUTHORIZED} from "@/components/Errors";
|
||||
import Error from "@/app/(utility)/Error";
|
||||
import notAllowedPict from "@/assets/images/NotAllowed.png";
|
||||
|
||||
export default function NotAllowedProblem() {
|
||||
return (
|
||||
<Error
|
||||
picture={notAllowedPict}
|
||||
problem="Pas autorisé"
|
||||
description={NOT_AUTHORIZED}
|
||||
information="Connectez vous avec plus de privilèges"
|
||||
/>
|
||||
);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import React from "react";
|
||||
import {NOT_FOUND} from "@/components/Errors";
|
||||
import Error from "@/app/(utility)/Error";
|
||||
import notFoundPict from "@/assets/images/NotFound.png";
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<Error
|
||||
picture={notFoundPict}
|
||||
problem="Introuvable"
|
||||
description={NOT_FOUND}
|
||||
information="Status Code : 404"
|
||||
/>
|
||||
);
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
import { StringUtils } from "@/utils/string.utils";
|
||||
import React, { forwardRef, useImperativeHandle, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import FormInput from "../form/FormInput";
|
||||
import Question, { QuestionChildProps } from "./Question";
|
||||
|
||||
export interface NameQuestionRef {
|
||||
getAnswer: () => string;
|
||||
isOk: () => boolean;
|
||||
}
|
||||
|
||||
export default forwardRef<any, QuestionChildProps>(({ ...props }, ref) => {
|
||||
const [answer, setAnswer] = useState<string>();
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
getAnswer: () => answer,
|
||||
isOk: () => !StringUtils.IsNullOrEnptyWhiteSpace(answer ?? ""),
|
||||
}));
|
||||
|
||||
return (
|
||||
<Question question="Quel est votre nom ?" {...props} {...ref}>
|
||||
<View className="gap-4">
|
||||
<FormInput
|
||||
beforeIcon="user"
|
||||
placeholder="Ex: Michel"
|
||||
label={"Prénom"}
|
||||
value={answer}
|
||||
onChangeText={setAnswer}
|
||||
/>
|
||||
</View>
|
||||
</Question>
|
||||
);
|
||||
});
|
@ -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);
|
@ -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);
|
@ -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);
|
@ -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
|
||||
);
|
@ -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
|
||||
);
|
@ -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);
|
@ -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);
|
@ -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);
|
@ -0,0 +1,12 @@
|
||||
export const ETarget = {
|
||||
CHEST: "CHEST",
|
||||
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);
|
@ -1,19 +0,0 @@
|
||||
export const useExercices = () => {
|
||||
const [exercices, setExercices] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
useEffect(() => {
|
||||
const fetchExercices = async () => {
|
||||
try {
|
||||
const response = await apiClient.get(EXERCICES.GETALL);
|
||||
setExercices(response.data);
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
setError(error);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
fetchExercices();
|
||||
}, []);
|
||||
return { exercices, loading, error };
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
export interface Workout {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
duration: number;
|
||||
image: string;
|
||||
video: string;
|
||||
nbSeries: number;
|
||||
nbRepetitions: number;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
export enum CategoryEnum {
|
||||
NONE = 'none',
|
||||
TRAINING = 'training',
|
||||
STRETCHING = 'stretching',
|
||||
WARMUP = 'warmup'
|
||||
}
|
@ -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";
|
@ -0,0 +1,8 @@
|
||||
export enum TargetEnum {
|
||||
NONE = 'none',
|
||||
ARM= 'arms',
|
||||
BACK = 'back',
|
||||
CARDIO = 'cardio',
|
||||
CHEST = 'chest',
|
||||
LEG = 'legs'
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue