@ -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,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,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();
|
@ -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);
|
@ -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";
|
Loading…
Reference in new issue