Setup for API

Setup_For_API
Anthony RICHARD 2 weeks ago
parent c8696f223d
commit 9625c01ef3

@ -1,8 +0,0 @@
export const AUTH = {
LOGIN: "/login",
REFRESH_TOKEN: "/refresh-token",
};
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,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.");
}
}

@ -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<User> {
const body = new URLSearchParams({
grant_type: "password",

@ -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,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[];
};

@ -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>;
}

@ -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,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<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.");
}
}

@ -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",

@ -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<any> {
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<boolean> {
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;
}
}
}

@ -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<Workout[]> {
const data = await this.request(EXERCICES.GETALL);
return data.data.map((item: any) => Workout.fromJson(item));
}
}

@ -1,3 +0,0 @@
export interface IExerciceService {
getExercices(): Promise<any>;
}

@ -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,
}),
];
}
}

@ -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();

@ -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,
})
)}

@ -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);

@ -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<Workout[]>([]);
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);

@ -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<Workout[]>([]);
const exerciceService = ExerciceServiceRef;
const [exercices, setExercices] = useState<ExerciceDTO[]>([]);
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) {}
};

@ -85,7 +85,7 @@ export default function ActivitiesComponent() {
{months.map((item, index) => {
return (
<TouchableOpacity
key={index}
key={item}
className={`w-16 h-10 flex items-center justify-center rounded-xl ${
dateSelected === item
? "bg-orange-500 border-2 border-orange-300"

@ -1,12 +1,12 @@
import { ExerciceDTO } from "@/api/service/dto/dto.training";
import Text from "@/components/ui/Text";
import { Workout } from "@/model/Workout";
import { AntDesign, MaterialCommunityIcons } from "@expo/vector-icons";
import { useRouter } from "expo-router";
import React from "react";
import { ImageBackground, TouchableOpacity, View } from "react-native";
interface WorkoutCardComponentProps {
exercise?: Workout;
exercise?: ExerciceDTO;
background?: string;
height?: number;
}
@ -26,7 +26,7 @@ export default function WorkoutCardComponent({
<View className="flex-row space-x-4 h-44 items-top justify-center ">
<View className="flex-row items-top">
<Text className="text-white text-sm ml-1">
{exercise?.duration} min
{exercise?.Duration} min
</Text>
</View>
<View className="flex-row justify-center">
@ -38,20 +38,18 @@ export default function WorkoutCardComponent({
</View>
<View className="flex-row">
<Text className="text-white text-sm ml-1">
{exercise?.name} kcal
{exercise?.Name} kcal
</Text>
</View>
</View>
</View>
<View className="absolute bottom-0 left-0 right-0 p-4 bg-opacity-50">
<Text className="text-white text-lg font-bold">{exercise?.name}</Text>
<Text className="text-gray-300 text-sm">
{exercise?.nbRepetitions}
</Text>
<Text className="text-white text-lg font-bold">{exercise?.Name}</Text>
<Text className="text-gray-300 text-sm">{exercise?.NbRep}</Text>
<View className="flex-row items-center mt-2">
<Text className="text-white text-xs bg-gray-800 py-1 px-3 rounded-full">
{exercise?.name}
{exercise?.Name}
</Text>
</View>
</View>

@ -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({
<View className="items-center mb-10">
<Text className="text-white bg-transparent border-2 border-white px-3 py-1 rounded-full text-2xl font-bold">
{workout.nbSeries} x {workout.nbRepetitions}
{workout.NbSet} x {workout.NbRep}
</Text>
<Text className="text-white text-4xl font-bold mt-2">
{workout.name}
{workout.Name}
</Text>
</View>
<View className="mb-5">
<LinearProgressBar duration={workout.duration} />
<LinearProgressBar duration={workout.Duration} />
</View>
</View>
</Screen>

@ -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";

@ -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<ActivityQuestionRef, QuestionChildProps>(
selected = index;
}
});
return SportLevels[SportLevels.length - 1 - selected];
return SportLevels[selected];
},
}));
@ -47,11 +47,10 @@ export default React.forwardRef<ActivityQuestionRef, QuestionChildProps>(
}
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<ActivityQuestionRef, QuestionChildProps>(
<View className="gap-2">
{data.map((item, index) => (
<Checkbox
key={index}
key={item.label}
label={item.label}
value={checkedItems[index]}
onChange={() => handleChange(index)}

@ -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<GoalQuestionRef, QuestionChildProps>(
<View className="gap-2">
{data.map((item, index) => (
<CheckBox
key={index}
key={item.label}
label={item.label}
value={checkedItems[index]}
onChange={() => handleChange(index)}

@ -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<SleepQuestionRef, QuestionChildProps>(
selected = index;
}
});
return SleepLevels[SleepLevels.length - 1 - selected];
return SleepLevels[selected];
},
}));
@ -41,12 +41,12 @@ export default React.forwardRef<SleepQuestionRef, QuestionChildProps>(
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<SleepQuestionRef, QuestionChildProps>(
endText: "3-4 heures",
},
{
label: "Insomniaque",
label: "Terrible",
icon: "frown",
endText: "<2 heures",
},
@ -76,7 +76,7 @@ export default React.forwardRef<SleepQuestionRef, QuestionChildProps>(
<View className="gap-2">
{data.map((item, index) => (
<Checkbox
key={index}
key={item.label}
label={item.label}
value={checkedItems[index]}
onChange={() => handleChange(index)}

@ -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<SportQuestionRef, QuestionChildProps>(
<View className="flex-row justify-center flex-wrap gap-2">
{data.map((item, index) => (
<CheckBox
key={index}
key={item.label}
label={item.label}
value={checkedItems[index]}
onChange={() => handleChange(index)}

@ -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,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);

@ -3,7 +3,7 @@ import {
ESleepLevel,
ESport,
ESportLevel,
} from "./enums/Enums";
} from "../enum/Enums.js";
export class User {
private _name?: string;

@ -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,
});
}
}

@ -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";

@ -13,5 +13,6 @@
".expo/types/**/*.ts",
"expo-env.d.ts",
"nativewind-env.d.ts",
"enum/Enums.tsx"
]
}

Loading…
Cancel
Save