diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index f09c71ed79cafa5174110c958a1a933d7edbddd2..eb7022b8c42ef8d8772f3d3f9c0f60497743aa6a 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -8,7 +8,7 @@ import { FirstTimeComponent } from './page/first-time/first-time.component'; import { authGuard } from './guard/auth.guard'; import { WeightDetailsComponent } from './page/details/weight-details/weight-details.component'; import { FoodDetailsComponent } from './page/details/food-details/food-details.component'; -import { MealDetailsComponent } from './page/details/meal-details/meal-details.component'; +import { MealDetailsComponent } from './page/details/meal/meal-details/meal-details.component'; import { DietDetailsComponent } from './page/details/diet-details/diet-details.component'; import { TrainingComponent } from './page/training/training/training.component'; import { AddTrainingComponent } from './page/training/add-training/add-training.component'; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 3fe9d6d1bde090524282f0089e97c7c0c053afc6..d6a520b8b51143ba0e747dfb7a6c4ff9ed94f62d 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -33,7 +33,7 @@ import {MatIconModule} from '@angular/material/icon'; import {MatInputModule} from '@angular/material/input'; import {MatCheckboxModule} from '@angular/material/checkbox'; import { SortPipe } from "./pipe/sort.pipe"; -import { MealDetailsComponent } from './page/details/meal-details/meal-details.component'; +import { MealDetailsComponent } from './page/details/meal/meal-details/meal-details.component'; import {MatAutocompleteModule} from '@angular/material/autocomplete'; import { DietDetailsComponent } from './page/details/diet-details/diet-details.component'; import { TrainingComponent } from './page/training/training/training.component'; @@ -41,6 +41,7 @@ import { TrainingDetailsComponent } from './page/training/training-details/train import { AddTrainingComponent } from './page/training/add-training/add-training.component'; import { MenuDialogComponent } from './component/menu/menu-dialog/menu-dialog.component'; import { MatDialogActions, MatDialogClose, MatDialogContent, MatDialogTitle } from '@angular/material/dialog'; +import { FoodDetailsDialogComponent } from './page/details/food-details/food-details-dialog/food-details-dialog.component'; @NgModule({ declarations: [ @@ -51,7 +52,7 @@ import { MatDialogActions, MatDialogClose, MatDialogContent, MatDialogTitle } fr TwentyFourWeatherComponent, LocalTimePipe, WeightDetailsComponent, FoodDetailsComponent, GoBackComponent, MealDetailsComponent, DietDetailsComponent, TrainingComponent, MenuDialogComponent, - TrainingDetailsComponent, AddTrainingComponent + TrainingDetailsComponent, AddTrainingComponent, FoodDetailsDialogComponent ], imports: [ HttpClientModule, diff --git a/src/app/component/menu/menu-dialog/menu-dialog.component.ts b/src/app/component/menu/menu-dialog/menu-dialog.component.ts index 0f6c4931e24313d60d1ecb3d2dfea10567fa0e87..b6af1fa4a79df7857ec9c2746fa1cbea2ebeac4c 100644 --- a/src/app/component/menu/menu-dialog/menu-dialog.component.ts +++ b/src/app/component/menu/menu-dialog/menu-dialog.component.ts @@ -11,7 +11,7 @@ import { LoginService } from 'src/app/service/login.service'; }) export class MenuDialogComponent { readonly dialogRef = inject(MatDialogRef); - private login = inject(LoginService); + private login = inject(LoginService); private router = inject(Router); public async logout(){ diff --git a/src/app/component/menu/menu.component.html b/src/app/component/menu/menu.component.html index e5488d2988b9e9bb93abda37c8ae7c4458135ae1..45b9f17d76767460621d25b2955bbdf71dee62d7 100644 --- a/src/app/component/menu/menu.component.html +++ b/src/app/component/menu/menu.component.html @@ -2,13 +2,25 @@ @if(mobile.isMobile){ } @else { diff --git a/src/app/component/menu/menu.component.ts b/src/app/component/menu/menu.component.ts index 3ab34aee442c135bffbf625f558eaadca1c7cea0..746ffb3a4ee9c79771b512a4d3574827aa18be41 100644 --- a/src/app/component/menu/menu.component.ts +++ b/src/app/component/menu/menu.component.ts @@ -1,10 +1,10 @@ import { Component, inject } from '@angular/core'; import { Router } from '@angular/router'; -import { AccountService } from 'src/app/service/database/account.service'; import { LoginService } from 'src/app/service/login.service'; import { MobileService } from 'src/app/service/mobile.service'; import { MatDialog } from '@angular/material/dialog'; import { MenuDialogComponent } from './menu-dialog/menu-dialog.component'; +import { map, Observable } from 'rxjs'; @Component({ selector: 'app-menu', @@ -13,27 +13,17 @@ import { MenuDialogComponent } from './menu-dialog/menu-dialog.component'; standalone: false }) export class MenuComponent { - private login = inject(LoginService); private router = inject(Router); - private account = inject(AccountService); + private loginService = inject(LoginService); public mobile = inject(MobileService); private dialog = inject(MatDialog); public async logout(){ - await this.login.logout(); + await this.loginService.logout(); this.router.navigate(['/login']); } - getPhoto() { - if(this.account.current){ - const currentPhoto = this.account.current.photo; - if(!currentPhoto){ - return '../assets/account.png' - } - return currentPhoto; - } - return ''; - } + get Account() { return this.loginService.Account} openDialog(): void { const dialogRef = this.dialog.open(MenuDialogComponent); diff --git a/src/app/enumeration/Calculation/Bmi-enum.ts b/src/app/enum/Calculation/Bmi-enum.ts similarity index 100% rename from src/app/enumeration/Calculation/Bmi-enum.ts rename to src/app/enum/Calculation/Bmi-enum.ts diff --git a/src/app/enumeration/Calculation/corpulence-index-enum.ts b/src/app/enum/Calculation/corpulence-index-enum.ts similarity index 100% rename from src/app/enumeration/Calculation/corpulence-index-enum.ts rename to src/app/enum/Calculation/corpulence-index-enum.ts diff --git a/src/app/enumeration/morpho-enum.ts b/src/app/enum/morpho-enum.ts similarity index 100% rename from src/app/enumeration/morpho-enum.ts rename to src/app/enum/morpho-enum.ts diff --git a/src/app/enumeration/periodicity-enum.ts b/src/app/enum/periodicity-enum.ts similarity index 100% rename from src/app/enumeration/periodicity-enum.ts rename to src/app/enum/periodicity-enum.ts diff --git a/src/app/enumeration/sex-enum.ts b/src/app/enum/sex-enum.ts similarity index 100% rename from src/app/enumeration/sex-enum.ts rename to src/app/enum/sex-enum.ts diff --git a/src/app/guard/auth.guard.ts b/src/app/guard/auth.guard.ts index 9150af1a1f45afb0bcbdbf7c815fe6bb9cce7def..d55b89d6cf506f2db70dbd486075dfa3b8ad9269 100644 --- a/src/app/guard/auth.guard.ts +++ b/src/app/guard/auth.guard.ts @@ -1,21 +1,21 @@ import { inject } from '@angular/core'; import { CanActivateFn, Router } from '@angular/router'; -import { AccountService } from '../service/database/account.service'; import { LoginService } from '../service/login.service'; import { from, map, of, switchMap, take } from 'rxjs'; import { ProfilService } from '../service/database/profil.service'; export const authGuard: CanActivateFn = (route, state) => { const router = inject(Router); - const account = inject(AccountService); + const account = inject(LoginService); const login = inject(LoginService); const profile = inject(ProfilService); const currentUrl = route.routeConfig?.path; console.log('Current route : ' + route.routeConfig?.path); - return login.user$.pipe( + return login.User.pipe( switchMap(user => { if(user){ console.log('User connecté'); + console.log(user.email); return from(profile.checkProfil(user.email)).pipe( map(canAccess => { if(canAccess){ @@ -25,6 +25,7 @@ export const authGuard: CanActivateFn = (route, state) => { } return true; } + console.log(canAccess); console.log('User has no profile available'); if(currentUrl !== 'login/first-connection'){ router.navigate(['/login/first-connection']); diff --git a/src/app/interface/common/cloud-save.ts b/src/app/interface/common/cloud-save.ts index a16d5eceba9dec7a81d33732c837298731cea95d..07aaa3e42b137aab9bc6466dcd99088045189d82 100644 --- a/src/app/interface/common/cloud-save.ts +++ b/src/app/interface/common/cloud-save.ts @@ -1,4 +1,4 @@ -import { PeriodicityEnum } from "src/app/enumeration/periodicity-enum"; +import { PeriodicityEnum } from "src/app/enum/periodicity-enum"; /** * @author Aurélien A. diff --git a/src/app/interface/database/account.ts b/src/app/interface/database/account.ts index d22f136660793c5af2813579e9ee8d99eccd1ff3..f527328439434c0c5979e9c613608f4626beb731 100644 --- a/src/app/interface/database/account.ts +++ b/src/app/interface/database/account.ts @@ -8,6 +8,16 @@ export interface Account { id: string } +export function getDefaultAccount(): Account{ + return { + createAt: new Date().toString(), + id: '', + mail: '', + photo: null, + username: '' + } +} + export const accountConverter: FirestoreDataConverter = { toFirestore: (account: Account) => ({ id: account.id, diff --git a/src/app/interface/database/calories.ts b/src/app/interface/database/calories.ts index 21630e1d0e1d0f35437c7146964c3f4e5fbb7e35..f025038538579865dc4765f2dc4db7e589344c56 100644 --- a/src/app/interface/database/calories.ts +++ b/src/app/interface/database/calories.ts @@ -14,6 +14,12 @@ export interface CaloriesDetails extends Calories { meals: MealData[] } +export function isDefault(calories: CaloriesDetails): boolean{ + return calories.total === 0 && calories.foods.length === 0 + && calories.meals.length === 0 && calories.macros.carbohydrates === 0 + && calories.macros.fats === 0 && calories.macros.proteins === 0; +} + export function getDefaultCalories(): CaloriesDetails{ return { date: getDefaultNumberDate(), @@ -43,8 +49,8 @@ export const caloriesConverter: FirestoreDataConverter = { fromFirestore: (snapshot, options) => { const data = snapshot.data(options); return { - date: data['id'], - total: data['id'], + date: data['date'], + total: data['total'], macros: data['macros'], foods: data['foods'], meals: data['meals'] diff --git a/src/app/interface/database/common/meal-data.ts b/src/app/interface/database/common/meal-data.ts index f25eff8d9b64a7fde847bad333fab6d3de230cb1..b25fe4a7e51e60283350844950c94d43c998d8ff 100644 --- a/src/app/interface/database/common/meal-data.ts +++ b/src/app/interface/database/common/meal-data.ts @@ -2,4 +2,10 @@ export interface MealData { id: string, name: string, quantity: number +} + +export interface Meal { + id: string, + name: string, + } \ No newline at end of file diff --git a/src/app/interface/database/profil.ts b/src/app/interface/database/profil.ts index e31a1d3d2108b985fdba5a2322e91ab6a35cea62..0c5f5ee71960c57aed12c3521e34ba1bcb6bbe4c 100644 --- a/src/app/interface/database/profil.ts +++ b/src/app/interface/database/profil.ts @@ -1,8 +1,8 @@ import { FirestoreDataConverter } from "@angular/fire/firestore"; import { CloudSaveOptions } from "../common/cloud-save"; import { Physical } from "../common/physical"; -import { MorphoTypeEnum } from "src/app/enumeration/morpho-enum"; -import { SexEnum } from "src/app/enumeration/sex-enum"; +import { MorphoTypeEnum } from "src/app/enum/morpho-enum"; +import { SexEnum } from "src/app/enum/sex-enum"; /** * @author Aurélien A. diff --git a/src/app/page/account/account.component.html b/src/app/page/account/account.component.html index d8b2a7c8f6f9dab355c2e3cd48d61136cebffd64..23b5b46d6d291873d68c97b6a5542f28bc0dbe1c 100644 --- a/src/app/page/account/account.component.html +++ b/src/app/page/account/account.component.html @@ -1,5 +1,5 @@ -
+

Mon compte

@@ -26,8 +26,10 @@
  • Poids : 92.9 kg
  • -
    +
    +
    +

    Cloud Save Options

    - +
    diff --git a/src/app/page/account/account.component.scss b/src/app/page/account/account.component.scss index 2b93a92d15073b84f7879e134f1787191642a895..24b48b9c24d9d74b851b6085555688bf806b73e0 100644 --- a/src/app/page/account/account.component.scss +++ b/src/app/page/account/account.component.scss @@ -58,3 +58,11 @@ width: 1.25rem; height: 1.25rem; } + +.card { + background-color: white; + width: 95%; + margin-right: auto; + margin-left: auto; + margin-bottom: 10px; +} \ No newline at end of file diff --git a/src/app/page/account/account.component.ts b/src/app/page/account/account.component.ts index aca363a1d90f6f06d4abf1f191ccb37fd95db305..e72c892d99b6ae749fcc6a110d9a5069990754d7 100644 --- a/src/app/page/account/account.component.ts +++ b/src/app/page/account/account.component.ts @@ -1,14 +1,15 @@ import { Component, inject } from '@angular/core'; -import { AccountService } from 'src/app/service/database/account.service'; +import { map, Observable, of } from 'rxjs'; +import { LoginService } from 'src/app/service/login.service'; @Component({ selector: 'app-account', templateUrl: './account.component.html', - styleUrl: './account.component.scss', + styleUrls: ['./account.component.scss', '../../styles/infobulle.scss'], standalone: false }) export class AccountComponent { - private account = inject(AccountService); + private loginService = inject(LoginService); selectedFile: File | null = null; //currentPhoto: string | ArrayBuffer | null; @@ -19,22 +20,22 @@ export class AccountComponent { } this.selectedFile = input.files[0]; const reader = new FileReader(); - reader.onload = () => { + /*reader.onload = () => { if(this.account.current){ this.account.current.photo = reader.result; // Contient le base64 (data:image/png;base64,...) } }; - reader.readAsDataURL(this.selectedFile); + reader.readAsDataURL(this.selectedFile);*/ } - getPhoto() { - if(this.account.current){ - const currentPhoto = this.account.current.photo; - if(!currentPhoto){ + getPhoto(): Observable { + return this.loginService.Account.pipe( + map(account => { + if(account && account.photo){ + return account.photo + } return '../assets/account.png' - } - return currentPhoto; - } - return ''; + }) + ); } } diff --git a/src/app/page/details/food-details/food-details-dialog/food-details-dialog.component.html b/src/app/page/details/food-details/food-details-dialog/food-details-dialog.component.html new file mode 100644 index 0000000000000000000000000000000000000000..8c5abbd3495100620a084bfcbac06eddb0fc4cea --- /dev/null +++ b/src/app/page/details/food-details/food-details-dialog/food-details-dialog.component.html @@ -0,0 +1,38 @@ +

    {{getName()}}

    + +

    Informations pour 100g de l'aliment

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    MacronutrimentsTotal%
    Calories{{getCalories()}} Kcal100%
    Protéines{{data.nutriments.proteins_100g}} g{{getEnergies(data.nutriments.proteins_100g, 4)}} %
    Lipides{{data.nutriments.fat_100g}} g{{getEnergies(data.nutriments.fat_100g, 9)}} %
    Glucides{{data.nutriments.carbohydrates_100g}} g{{getEnergies(data.nutriments.carbohydrates_100g, 4)}} %
    +
    + + + \ No newline at end of file diff --git a/src/app/page/details/food-details/food-details-dialog/food-details-dialog.component.scss b/src/app/page/details/food-details/food-details-dialog/food-details-dialog.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..7227b39d82142228c94a070df42b995220e69d46 --- /dev/null +++ b/src/app/page/details/food-details/food-details-dialog/food-details-dialog.component.scss @@ -0,0 +1,14 @@ +table { + border-collapse: separate; /* ⚠️ PAS collapse sinon bug avec sticky */ + border-spacing: 0; /* remet les bordures collées */ + width: 100%; +} +th { + font-size: large; + background: #f2f2f2; +} + +th, td { + border: 1px solid #ccc; + padding: 8px; +} \ No newline at end of file diff --git a/src/app/page/details/food-details/food-details-dialog/food-details-dialog.component.ts b/src/app/page/details/food-details/food-details-dialog/food-details-dialog.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..b8c061afc59573da4eb15c8979f5426bcd548839 --- /dev/null +++ b/src/app/page/details/food-details/food-details-dialog/food-details-dialog.component.ts @@ -0,0 +1,34 @@ +import { Component, Inject, inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { MenuDialogComponent } from 'src/app/component/menu/menu-dialog/menu-dialog.component'; +import { Product } from 'src/app/interface/api/openFood/search/search-result'; + +@Component({ + selector: 'app-food-details-dialog', + templateUrl: './food-details-dialog.component.html', + styleUrl: './food-details-dialog.component.scss', + standalone: false +}) +export class FoodDetailsDialogComponent { + readonly dialogRef = inject(MatDialogRef); + + constructor(@Inject(MAT_DIALOG_DATA) public data: Product){ } + + onNoClick(): void { + this.dialogRef.close(); + } + + getCalories(): number | undefined { + return this.data.nutriments['energy-kcal_100g']; + } + + getName(){ return this.data.product_name ?? this.data.generic_name; } + + getEnergies(value: number, energyNutriments: number): string { + if(!this.data.nutriments['energy-kcal_100g']){ + return '0'; + } + const energy = this.data.nutriments['energy-kcal_100g']; + return (((value*energyNutriments)/energy)*100).toFixed(2); + } +} diff --git a/src/app/page/details/food-details/food-details.component.html b/src/app/page/details/food-details/food-details.component.html index 411ba3cab6a5f4a3fb0ebcd5498034561a8486ae..b65dcbb8d05499dabf3d5efdcb97b5638d945176 100644 --- a/src/app/page/details/food-details/food-details.component.html +++ b/src/app/page/details/food-details/food-details.component.html @@ -1,6 +1,6 @@ -
    -
    diff --git a/src/app/page/details/food-details/food-details.component.scss b/src/app/page/details/food-details/food-details.component.scss index 352d31a1bbe8ff2b62b8d1f4b81b7653f97660a3..910b759a4147c28cf96ae3d1a6481a9b786497cf 100644 --- a/src/app/page/details/food-details/food-details.component.scss +++ b/src/app/page/details/food-details/food-details.component.scss @@ -1,5 +1,5 @@ .page { - width: 85%; + width: 95%; margin-left: auto; margin-right: auto; display: flex; @@ -113,4 +113,11 @@ color: rgba(0, 0, 0, 0.65); box-shadow: inset 4px 4px 12px #c5c5c5, inset -4px -4px 12px #ffffff; } +} + +.macros { + display: inline-flex; + img{ max-width: 20%; max-height: 40px; } + ul { list-style: none; display: inline-flex; } + li { margin-right: 15px; } } \ No newline at end of file diff --git a/src/app/page/details/food-details/food-details.component.ts b/src/app/page/details/food-details/food-details.component.ts index 0469ead89404eaa476b060d5721e66baeea5b08b..0fd4d423695ca41f3588d2c937b7ace1c833060d 100644 --- a/src/app/page/details/food-details/food-details.component.ts +++ b/src/app/page/details/food-details/food-details.component.ts @@ -1,5 +1,6 @@ import { Component, ElementRef, inject, ViewChild } from '@angular/core'; import { FormControl } from '@angular/forms'; +import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; import { Router } from '@angular/router'; import { Observable } from 'rxjs'; @@ -8,6 +9,8 @@ import { Product, SearchResult } from 'src/app/interface/api/openFood/search/sea import { OpenFoodFactsService } from 'src/app/service/api/open-food-facts.service'; import { CalorieService } from 'src/app/service/database/calorie.service'; import { MobileService } from 'src/app/service/mobile.service'; +import { FoodDetailsDialogComponent } from './food-details-dialog/food-details-dialog.component'; +import { LoginService } from 'src/app/service/login.service'; @Component({ selector: 'app-food-details', @@ -21,6 +24,8 @@ export class FoodDetailsComponent { private openFood = inject(OpenFoodFactsService); private calories = inject(CalorieService); public mobile = inject(MobileService); + private dialog = inject(MatDialog); + private loginService = inject(LoginService); addMultiple: boolean = false; @ViewChild('input') input: ElementRef| undefined; @@ -30,6 +35,7 @@ export class FoodDetailsComponent { resultSearch: Observable | undefined; currentFood: Product | undefined; foodCache: Product[] = []; + quantity: number = 0; constructor() { this.filteredOptions = []; @@ -60,10 +66,21 @@ export class FoodDetailsComponent { } addFood(){ - if(!this.addMultiple){ - this.router.navigateByUrl('/home'); - } - this.snackBar.open('Pesée ajoutée avec succès', 'Ok', {duration: 3000}); + this.loginService.Account.subscribe((data) => { + if(data){ + let energy: number; + if(!this.currentFood || !this.currentFood.nutriments['energy-kcal_100g']){ + energy = 0; + } else { + energy = (this.quantity * this.currentFood.nutriments['energy-kcal_100g']) / 100; + } + this.calories.saveFood(data.id, this.currentFood!, this.quantity, energy) + if(!this.addMultiple){ + this.router.navigateByUrl('/home'); + } + this.snackBar.open('Pesée ajoutée avec succès', 'Ok', {duration: 3000}); + } + }); } chooseFood(id: string){ @@ -96,5 +113,25 @@ export class FoodDetailsComponent { getKcal(product: Product){ return product.nutriments['energy-kcal_100g']; } getName(product: Product){ return product.product_name ?? product.generic_name; } + + openDialog(food: Product): void { + const dialogRef = this.dialog.open(FoodDetailsDialogComponent, + {width: '99%', height: '500px', data: food} + ); + dialogRef.afterClosed().subscribe(result => { }); + } + + //#region MACROS MANAGEMENT + getProportionEnergy(): string{ + if(!this.currentFood || !this.currentFood.nutriments['energy-kcal_100g']){ + return '0'; + } + return this.getProportion(this.currentFood.nutriments['energy-kcal_100g']); + } + + getProportion(valuePer100g: number): string { + return ((this.quantity * valuePer100g) / 100).toFixed(2); + } + //#endregion //#endregion } diff --git a/src/app/page/details/meal/add-meal/add-meal.component.html b/src/app/page/details/meal/add-meal/add-meal.component.html new file mode 100644 index 0000000000000000000000000000000000000000..e9890fbd185221f5d44b1847e9918ad7bf42a515 --- /dev/null +++ b/src/app/page/details/meal/add-meal/add-meal.component.html @@ -0,0 +1 @@ +

    add-meal works!

    diff --git a/src/app/page/details/meal-details/meal-details.component.scss b/src/app/page/details/meal/add-meal/add-meal.component.scss similarity index 100% rename from src/app/page/details/meal-details/meal-details.component.scss rename to src/app/page/details/meal/add-meal/add-meal.component.scss diff --git a/src/app/page/details/meal/add-meal/add-meal.component.ts b/src/app/page/details/meal/add-meal/add-meal.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..bf7a94517fd9d1e7a03b5b6153b6ae694ad1ee33 --- /dev/null +++ b/src/app/page/details/meal/add-meal/add-meal.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-add-meal', + imports: [], + templateUrl: './add-meal.component.html', + styleUrl: './add-meal.component.scss' +}) +export class AddMealComponent { + +} diff --git a/src/app/page/details/meal-details/meal-details.component.html b/src/app/page/details/meal/meal-details/meal-details.component.html similarity index 100% rename from src/app/page/details/meal-details/meal-details.component.html rename to src/app/page/details/meal/meal-details/meal-details.component.html diff --git a/src/app/page/details/meal/meal-details/meal-details.component.scss b/src/app/page/details/meal/meal-details/meal-details.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/app/page/details/meal-details/meal-details.component.ts b/src/app/page/details/meal/meal-details/meal-details.component.ts similarity index 100% rename from src/app/page/details/meal-details/meal-details.component.ts rename to src/app/page/details/meal/meal-details/meal-details.component.ts diff --git a/src/app/page/details/meal/meal-dialog/meal-dialog.component.html b/src/app/page/details/meal/meal-dialog/meal-dialog.component.html new file mode 100644 index 0000000000000000000000000000000000000000..a801ce42e0462b3636b3ca1189e92582d8d96ab1 --- /dev/null +++ b/src/app/page/details/meal/meal-dialog/meal-dialog.component.html @@ -0,0 +1 @@ +

    meal-dialog works!

    diff --git a/src/app/page/details/meal/meal-dialog/meal-dialog.component.scss b/src/app/page/details/meal/meal-dialog/meal-dialog.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/app/page/details/meal/meal-dialog/meal-dialog.component.ts b/src/app/page/details/meal/meal-dialog/meal-dialog.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..296c8e370bf02a1c493fe30e89124767631f3b46 --- /dev/null +++ b/src/app/page/details/meal/meal-dialog/meal-dialog.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-meal-dialog', + imports: [], + templateUrl: './meal-dialog.component.html', + styleUrl: './meal-dialog.component.scss' +}) +export class MealDialogComponent { + +} diff --git a/src/app/page/details/weight-details/weight-details.component.ts b/src/app/page/details/weight-details/weight-details.component.ts index 8695ed3ab6bb77fcdf556040dc6f50cc29980d90..d37ad9a6592d4359554e4dec219c31601d558480 100644 --- a/src/app/page/details/weight-details/weight-details.component.ts +++ b/src/app/page/details/weight-details/weight-details.component.ts @@ -2,11 +2,11 @@ import { Component, inject, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; import { Router } from '@angular/router'; import { DataDate, ToDate, YearHistory } from 'src/app/interface/database/grap-data'; -import { AccountService } from 'src/app/service/database/account.service'; import { WeightService } from 'src/app/service/database/weight.service'; import {MatSnackBar} from '@angular/material/snack-bar'; import { Observable } from 'rxjs'; import { NumberDate } from 'src/app/interface/database/common/number-date'; +import { LoginService } from 'src/app/service/login.service'; @Component({ selector: 'app-weight-details', @@ -18,7 +18,7 @@ export class WeightDetailsComponent implements OnInit{ //SERVICES private snackBar = inject(MatSnackBar); private weightService = inject(WeightService); - private accountService = inject(AccountService); + private loginService = inject(LoginService); private router = inject(Router); //DATA date = new FormControl(new Date()); @@ -28,14 +28,11 @@ export class WeightDetailsComponent implements OnInit{ $currentYear: Observable | undefined; ngOnInit(): void { - /*if(this.weightService.current){ - if(this.weightService.current.current){ - this.filledWeight = this.weightService.current.current.data; - this.date.setValue(ToDate(this.weightService.current.current.date)); - } - }*/ - this.$yearHistory = this.weightService.getYearHistory(this.accountService.current?.mail ?? null); - this.$currentYear = this.weightService.getHistory(this.accountService.current?.mail ?? null); + this.$yearHistory = this.weightService.getYearHistory(); + this.$currentYear = this.weightService.getHistory(); + this.$currentYear.subscribe(data => { + console.log(data); + }) } //#region SAVE MANAGEMENT @@ -47,25 +44,23 @@ export class WeightDetailsComponent implements OnInit{ if(this.addMultiple){ this.snackBar.dismiss(); } - const currentAccount = this.accountService.current; - if(currentAccount){ - console.log(currentAccount); - this.weightService.saveWeight(currentAccount.id, this.date.value ?? new Date(), this.filledWeight) - .then(docRef => { - console.log('coucou'); - if(!this.addMultiple){ - this.router.navigateByUrl('home'); - } - this.snackBar.open('Pesée ajoutée avec succès', 'Ok', {duration: 3000}); - console.log(docRef); - }) - .catch(err => { - console.error(err); - this.snackBar.open('Sauvegarde non réussi de la pesée', 'Ok', {duration: 3000}); - }); - } - - + this.loginService.Account.subscribe((data) => { + if(data){ + console.log(data); + this.weightService.saveWeight(data.id, this.date.value ?? new Date(), this.filledWeight) + .then(docRef => { + if(!this.addMultiple){ + this.router.navigateByUrl('home'); + } + this.snackBar.open('Pesée ajoutée avec succès', 'Ok', {duration: 3000}); + console.log(docRef); + }) + .catch(err => { + console.error(err); + this.snackBar.open('Sauvegarde non réussi de la pesée', 'Ok', {duration: 3000}); + }); + } + }); } //#endregion diff --git a/src/app/page/home/home.component.html b/src/app/page/home/home.component.html index 3d05de563f71a75d291e25da3bb135dd948db193..4ad12478a40745146b637bb9a241fc7e8e45a0af 100644 --- a/src/app/page/home/home.component.html +++ b/src/app/page/home/home.component.html @@ -1,6 +1,6 @@
    -
    +

    Meteo du jour

    @if(vm$ | async; as vm){ @@ -22,14 +22,16 @@
    } + } @else if(errorLocalisation){ +

    Service de géolocalisation est actuellement indisponible

    } @else { -
    +
    }
    -
    +

    Repas de la journée

    🥕
    @@ -48,7 +50,7 @@
    }
    -
    +

    Courbe de poids

    @if(currentWeight$ | async; as current){
    diff --git a/src/app/page/home/home.component.scss b/src/app/page/home/home.component.scss index 9724ab71be2850ec8a151d7d9c309cab7eff555f..390ec722e4e00c03d862bdf7213fa4ceb489a0cc 100644 --- a/src/app/page/home/home.component.scss +++ b/src/app/page/home/home.component.scss @@ -47,7 +47,6 @@ twentyfourweather { flex-direction: column; align-items: center; margin-bottom: 10px; - border-radius: 10px; } .card > * { width: 95%; } diff --git a/src/app/page/home/home.component.ts b/src/app/page/home/home.component.ts index 67ae14ea3a8d8705232855ce3fe0ccc8ba114b1f..0d8f2388107a527c6f48f29f2744545996be984d 100644 --- a/src/app/page/home/home.component.ts +++ b/src/app/page/home/home.component.ts @@ -1,14 +1,14 @@ import { Component, inject, OnInit } from '@angular/core'; -import { forkJoin, map, Observable } from 'rxjs'; +import { forkJoin, map, Observable, of, switchMap } from 'rxjs'; import { CurrentWeather } from 'src/app/interface/api/weather/current-weather'; import { Forecast } from 'src/app/interface/api/weather/forecast'; -import { CaloriesDetails } from 'src/app/interface/database/calories'; +import { CaloriesDetails, getDefaultCalories } from 'src/app/interface/database/calories'; import { DataDate, ToDate } from 'src/app/interface/database/grap-data'; import { UiForecast } from 'src/app/interface/ui/ui-forecast'; import { LocalisationService } from 'src/app/service/api/localisation.service'; -import { AccountService } from 'src/app/service/database/account.service'; import { CalorieService } from 'src/app/service/database/calorie.service'; import { WeightService } from 'src/app/service/database/weight.service'; +import { LoginService } from 'src/app/service/login.service'; @Component({ selector: 'app-home', @@ -20,7 +20,7 @@ export class HomeComponent implements OnInit{ //Services private localisation = inject(LocalisationService); private weightService = inject(WeightService); - private account = inject(AccountService); + private loginService = inject(LoginService); private calories = inject(CalorieService); //Observables errorLocalisation: boolean = false; @@ -38,7 +38,7 @@ export class HomeComponent implements OnInit{ async ngOnInit(): Promise { this.getLocalisationData(); this.getWeight(); - await this.getCalories(); + this.getCalories(); } getLocalisationData() : void { @@ -60,26 +60,20 @@ export class HomeComponent implements OnInit{ ); } - async getCalories(){ - const currentAccount = this.account.current; - if(currentAccount){ - this.currentCalories$ = await this.calories.checkCurrentCalories(currentAccount.id); - } + getCalories(){ + this.currentCalories$ = this.calories.checkCurrentCalories(); } //#region WEIGHT MANAGEMENT getWeight(): void { - const currentAccount = this.account.current; - if(currentAccount){ - this.currentWeight$ = this.weightService.checkWeight(currentAccount.id); - this.historyWeight$ = this.weightService.getHistory(currentAccount.id); - this.vm2$ = forkJoin({ - current: this.currentWeight$, - history: this.historyWeight$ - }).pipe( - map(({ current, history }) => ({ current, history, condition: !!current && !!history })) - ); - } + this.currentWeight$ = this.weightService.checkWeight(); + this.historyWeight$ = this.weightService.getHistory(); + this.vm2$ = forkJoin({ + current: this.currentWeight$, + history: this.historyWeight$ + }).pipe( + map(({ current, history }) => ({ current, history, condition: !!current && !!history })) + ); } getSortedHistory(history: DataDate[]){ diff --git a/src/app/service/calculation.service.ts b/src/app/service/calculation.service.ts index bb3caa869fece398afb26ddedea0bb049aee446c..115327abfd196a9904d8adc4eacbf11a6f87083f 100644 --- a/src/app/service/calculation.service.ts +++ b/src/app/service/calculation.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { SexEnum } from '../enumeration/sex-enum'; +import { SexEnum } from '../enum/sex-enum'; /** * @author Aurélien A. diff --git a/src/app/service/database/account.service.ts b/src/app/service/database/account.service.ts deleted file mode 100644 index 3c41b119fe9d228447d7ef4622427e8ff893fee0..0000000000000000000000000000000000000000 --- a/src/app/service/database/account.service.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { inject, Injectable } from '@angular/core'; -import { doc, Firestore, getDoc, setDoc } from '@angular/fire/firestore'; -import { Account, accountConverter } from 'src/app/interface/database/account'; - -/** - * Gives the access to the information about the account of the user - * @author Aurélien A. - */ -@Injectable({ - providedIn: 'root' -}) -export class AccountService { - /***/ - private firestore = inject(Firestore); - private currentAccount: Account | undefined; - - /** Retrieves the current information about the account of the user*/ - get current(): Account | undefined { - return this.currentAccount; - } - - async checkAccount(mail: string | null): Promise { - if(this.currentAccount){ - return true; - } - if(!mail){ - return false; - } - try{ - const docRef = doc(this.firestore, `Account/${mail}`).withConverter(accountConverter); - const docSnap = await getDoc(docRef); - const docExists = docSnap.exists(); - if(docExists){ - this.currentAccount = docSnap.data(); - } - return docExists; - } catch(error){ - console.error(error); - return false; - } - } - - /** - * Create a new account in the application - * @param account The account to create - */ - async createAccount(account: Account){ - const docRef = doc(this.firestore, `Account/${account.id}`); - await setDoc(docRef, account); - this.currentAccount = account; - console.log("Account ajouté avec succès"); - } - - async updateAccount(account: Account){ - - } -} diff --git a/src/app/service/database/calorie.service.ts b/src/app/service/database/calorie.service.ts index 2892d1c99bbd663b8fd9c53ff224e08c21fdfd88..85e307be4af6a0ef6265c1941b24a2f6d1a09c03 100644 --- a/src/app/service/database/calorie.service.ts +++ b/src/app/service/database/calorie.service.ts @@ -1,9 +1,16 @@ import { inject, Injectable } from '@angular/core'; -import { doc, docData, Firestore, getDoc } from '@angular/fire/firestore'; -import { Observable, of } from 'rxjs'; -import { caloriesConverter, CaloriesDetails, getDefaultCalories } from 'src/app/interface/database/calories'; +import { addDoc, collection, doc, docData, DocumentData, DocumentReference, Firestore, getDoc, setDoc } from '@angular/fire/firestore'; +import { from, map, Observable, of, switchMap } from 'rxjs'; +import { Product } from 'src/app/interface/api/openFood/search/search-result'; +import { caloriesConverter, CaloriesDetails, getDefaultCalories, isDefault } from 'src/app/interface/database/calories'; import { dateEquals, getDefaultNumberDate } from 'src/app/interface/database/common/number-date'; +import { LoginService } from '../login.service'; +import { Account } from 'src/app/interface/database/account'; +/** + * Gives access to the calories collection in database + * @author Aurélien A. + */ /** * Gives access to the calories collection in database * @author Aurélien A. @@ -12,33 +19,86 @@ import { dateEquals, getDefaultNumberDate } from 'src/app/interface/database/com providedIn: 'root' }) export class CalorieService{ + /**Access to the database*/ /**Access to the database*/ private firestore = inject(Firestore); + private loginService = inject(LoginService); /** * Check if the collection exists in the database for the current user * @param mail Identifier of the user * @returns {Promise>} */ - async checkCurrentCalories(mail: string | null): Promise> { - if(!mail){ - return of(getDefaultCalories()); + checkCurrentCalories(): Observable { + return this.loginService.Account.pipe( + switchMap(account => { + return from(this.getCalories(account!)); + }) + ) + } + + private async getCalories(account: Account | null): Promise{ + if(account){ + const docRef = doc(this.firestore, `Calories/${account.id}`).withConverter(caloriesConverter); + const docSnap = await getDoc(docRef); + if(docSnap.exists()){ + var data = docSnap.data(); + console.log(data); + if(dateEquals(data.date, getDefaultNumberDate())){ + console.log('Date identique on garde le même'); + return data; + } + if(!isDefault(data)){ + console.log('Date différente on enregistre le précédent dans historique'); + this.save(data); + return getDefaultCalories(); + } + data.date = getDefaultNumberDate(); + return data; + } + return getDefaultCalories(); } - const docRef = doc(this.firestore, `Calories/${mail}`).withConverter(caloriesConverter); + return getDefaultCalories(); + } + + /** + * Register a new weight into the database + * @param id Identifier of the user + * @param data Information about the weight to save + * @returns {Promise>} A reference to the new document created in the database + */ + save(data: CaloriesDetails) : void { + this.loginService.Account.subscribe(async (account) => { + const docRef = doc(this.firestore, `Calories/${account?.id}`); + const currentYearRef = collection(docRef, 'current-year'); + console.log("Ajout de l'historique"); + await addDoc(currentYearRef, data); + console.log("suvegarde de nouveau"); + await setDoc(docRef, getDefaultCalories()); + }); + } + + async saveFood(userId: string | null, food: Product, quantity: number, energy: number){ + if(!userId){ + + } + const docRef = doc(this.firestore, `Calories/${userId}`).withConverter(caloriesConverter); const docSnap = await getDoc(docRef); + let macros: CaloriesDetails; if(docSnap.exists()){ - var data = docSnap.data(); - if(dateEquals(data.date, getDefaultNumberDate())){ - console.log('Date identique on garde le même'); - return docData(docRef) as Observable; - } - console.log('Date différente on enrgistre le précédent dans historique'); - return of(getDefaultCalories()); - } - return of(getDefaultCalories()); + macros = docSnap.data(); + } else { + macros = getDefaultCalories(); + } + macros.foods.push({id: food.id, name: food.product_name, quantity: quantity}); + macros.total += energy; + macros.macros.carbohydrates += this.getProportion(food.nutriments.carbohydrates_100g, quantity); + macros.macros.fats += this.getProportion(food.nutriments.fat_100g, quantity); + macros.macros.proteins += this.getProportion(food.nutriments.proteins_100g, quantity); + return await setDoc(docRef, macros); } - saveFood(){ - + getProportion(valuePer100g: number, quantity: number): number { + return ((quantity * valuePer100g) / 100); } } diff --git a/src/app/service/database/profil.service.ts b/src/app/service/database/profil.service.ts index 334aadd8e806f0acd04476e9d93a104bd78ba13e..9524dfb26f9ec635d5745b14f60f1fc9f7f30149 100644 --- a/src/app/service/database/profil.service.ts +++ b/src/app/service/database/profil.service.ts @@ -1,9 +1,14 @@ import { inject, Injectable } from '@angular/core'; import { doc, getDoc, setDoc } from '@angular/fire/firestore'; import { Profil, profilConverter } from 'src/app/interface/database/profil'; -import { AccountService } from './account.service'; import { DbServiceBase } from 'src/app/class/dbServiceBase'; +import { Observable } from 'rxjs'; +import { LoginService } from '../login.service'; +/** + * Give access to the profil of the user in database + * @author Aurélien A. + */ /** * Give access to the profil of the user in database * @author Aurélien A. @@ -13,10 +18,16 @@ import { DbServiceBase } from 'src/app/class/dbServiceBase'; }) export class ProfilService extends DbServiceBase { /**Access to the service that manages the connection*/ - private account = inject(AccountService); + private loginService = inject(LoginService); + private profil$ = Observable; + + /**Profil of the user*/ private currentProfil: Profil | undefined; + /** + * Retrieves the current profil of the user + */ /** * Retrieves the current profil of the user */ @@ -24,6 +35,11 @@ export class ProfilService extends DbServiceBase { return this.currentProfil; } + /** + * Check if the user has a profil in database or not + * @param id Identifier of the user + * @returns {boolean} Indicates if the user has a profil or not + */ /** * Check if the user has a profil in database or not * @param id Identifier of the user @@ -51,18 +67,23 @@ export class ProfilService extends DbServiceBase { } } + /** + * Update the information of the profil + * @param profil The current profil of the user + */ /** * Update the information of the profil * @param profil The current profil of the user */ async save(profil: Profil){ - console.log(this.account.current); - if(this.account.current){ - profil.id = this.account.current.id; - const docRef = doc(this.firestore, `Profil/${profil.id}`); - await setDoc(docRef, profil); - this.currentProfil = profil; - console.log("Profil ajouté avec succès"); - } + this.loginService.Account.subscribe(async (data) => { + if(data){ + profil.id = data.id; + const docRef = doc(this.firestore, `Profil/${profil.id}`); + await setDoc(docRef, profil); + this.currentProfil = profil; + console.log("Profil ajouté avec succès"); + } + }); } } diff --git a/src/app/service/database/weight.service.ts b/src/app/service/database/weight.service.ts index 3296510d51c87adaf6398917e0e752461ea47a70..722c2e112bd909c01f632d01df7dde75adbaaa51 100644 --- a/src/app/service/database/weight.service.ts +++ b/src/app/service/database/weight.service.ts @@ -1,9 +1,14 @@ import { inject, Injectable } from '@angular/core'; -import { addDoc, collection, collectionData, doc, docData, DocumentData, DocumentReference, Firestore, getDoc } from '@angular/fire/firestore'; -import { Observable, of } from 'rxjs'; +import { addDoc, collection, collectionData, doc, docData, DocumentData, DocumentReference, Firestore } from '@angular/fire/firestore'; +import { Observable, of, switchMap } from 'rxjs'; import { ToNumberDate } from 'src/app/interface/database/common/number-date'; import { DataDate, getDataDateDefault, YearHistory } from 'src/app/interface/database/grap-data'; +import { LoginService } from '../login.service'; +/** + * Manages the interaction with the Weight collection in database + * @author Aurélien A. + */ /** * Manages the interaction with the Weight collection in database * @author Aurélien A. @@ -12,48 +17,63 @@ import { DataDate, getDataDateDefault, YearHistory } from 'src/app/interface/dat providedIn: 'root' }) export class WeightService { + /**Access to the database*/ /**Access to the database*/ private firestore = inject(Firestore); + private loginService = inject(LoginService); /** * Check if the collection for the specific user exists and retrieve the current weight * @param mail Identifier of the user * @returns {Observable} */ - checkWeight(mail: string | null): Observable { - if(!mail){ - return of(getDataDateDefault()); - } - const docRef = doc(this.firestore, `Weight/${mail}`); - return docData(docRef) as Observable; + checkWeight(): Observable { + return this.loginService.Account.pipe( + switchMap(account => { + if(account){ + const docRef = doc(this.firestore, `Weight/${account.id}`); + return docData(docRef) as Observable; + } + return of(getDataDateDefault()); + }) + ); } /** * Retrieves the weight history for the previous years - * @param mail Identifier of the user * @returns {Observable} An observable of a collection that contains the history */ - getYearHistory(mail: string | null): Observable{ - if(!mail){ - return of([]); - } - const docRef = doc(this.firestore, `Weight/${mail}`); - const yearHistoryRef = collection(docRef, 'year-history'); - return collectionData(yearHistoryRef) as Observable; + getYearHistory(): Observable{ + return this.loginService.Account.pipe( + switchMap(account => { + console.log('Weight Service : ' + account); + if(account){ + + const docRef = doc(this.firestore, `Weight/${account.id}`); + const yearHistoryRef = collection(docRef, 'year-history'); + return collectionData(yearHistoryRef) as Observable; + } + return of([]) as Observable + }) + ) } /** * Retrieves the weight history for the current year - * @param mail Identifier of the user * @returns {Observable} An observable of a collection that contains the history */ - getHistory(mail: string | null): Observable{ - if(!mail){ - return of([]); - } - const docRef = doc(this.firestore, `Weight/${mail}`); - const currentYearRef = collection(docRef, 'current-year'); - return collectionData(currentYearRef) as Observable; + getHistory(): Observable{ + return this.loginService.Account.pipe( + switchMap(account => { + if(account){ + console.log(account); + const docRef = doc(this.firestore, `Weight/${account.id}`); + const currentYearRef = collection(docRef, 'current-year'); + return collectionData(currentYearRef) as Observable; + } + return of([]) as Observable; + }) + ); } /** @@ -80,3 +100,4 @@ export class WeightService { return this.save(id, newData); } } + diff --git a/src/app/service/login.service.ts b/src/app/service/login.service.ts index 25bec2f8a5849b620be26b2be1e947144178ca87..53285da5d62c18ef4e80f354d8f7fb58965dcb72 100644 --- a/src/app/service/login.service.ts +++ b/src/app/service/login.service.ts @@ -1,8 +1,15 @@ import { inject, Injectable } from '@angular/core'; import { Auth, ConfirmationResult, createUserWithEmailAndPassword, GoogleAuthProvider, RecaptchaVerifier, - signInWithEmailAndPassword, signInWithPhoneNumber, signInWithPopup, signOut, user } from '@angular/fire/auth'; -import { AccountService } from './database/account.service'; + signInWithEmailAndPassword, signInWithPhoneNumber, signInWithPopup, signOut, User, user } from '@angular/fire/auth'; +import { Observable, of, switchMap } from 'rxjs'; +import { doc, docData, Firestore, getDoc, setDoc } from '@angular/fire/firestore'; +import { Account, accountConverter } from '../interface/database/account'; +/** + * Allows the management of the authentication using the provider + * displayed by the firebase project + * @author Aurélien A. + */ /** * Allows the management of the authentication using the provider * displayed by the firebase project @@ -12,40 +19,31 @@ import { AccountService } from './database/account.service'; providedIn: 'root' }) export class LoginService { + //#region SERVICE INJECTED /**Auth services displayed by Firebase*/ private auth = inject(Auth); - /**Service that gives the access to the account Firebase collection*/ - private account = inject(AccountService); - /**An observable that containes the information about the current user*/ - public user$ = user(this.auth); - - constructor(){ - this.user$.subscribe(async (user) => { - if(user){ - await this.account.checkAccount(user.email); - } - }); - } + /**Access to the database of firebase*/ + private firestore = inject(Firestore); + //#endregion + + /**An observable that contains the information about the current user*/ + private user$ = user(this.auth); + /**An observable that contains the information of the account*/ + private account$ = this.getAccount(); - //#region Authentification avec email + password /** - * Allows to register a new account into the application with the couple (mail/password) - * @param username Username of the user when using the application - * @param mail The mail of the current user - * @param password The password set by the user to login - * @returns {Promise} Indicates if the registration suceeded or not + * Gives access to the user information + * @returns {User} An object containing information about the user */ - public async registerMail(username: string, mail: string, password: string): Promise { - if(await this.account.checkAccount(mail)){ - throw new Error('An account already exists for the mail ' + mail); - } - await createUserWithEmailAndPassword(this.auth, mail, password); - const user = { id: mail, mail: mail, - username: username, createAt: new Date().toDateString(), photo: null }; - await this.account.createAccount(user); - return true; - } + public get User() : Observable { return this.user$; } + /** + * Gives access to the account information + * @returns {Account} An object containing information about the account + */ + public get Account(): Observable { return this.account$; } + + //#region LOGIN MANAGEMENT /** * Allows to register a new account into the application by using the Google Auth provider * @param mail The mail of the current user @@ -53,25 +51,69 @@ export class LoginService { * @returns {Promise} Indicates if the registration suceeded or not */ public async loginWithMail(mail: string, password: string): Promise { - if(!await this.account.checkAccount(mail)){ - throw new Error('No account found for the mail ' + mail); - } - const cred = await signInWithEmailAndPassword(this.auth, mail, password); - return true; + if(!await this.checkAccount(mail)){ + throw new Error('No account found for the mail ' + mail); + } + const cred = await signInWithEmailAndPassword(this.auth, mail, password); + return true; } /** - * Allows a user to modify it password if it forget it - * @param mail The mail of the user + * Disconnects the user to the application */ - public async forgotPassword(mail: string){ - if(!await this.account.checkAccount(mail)){ - throw new Error('No account found for the mail ' + mail); + public async logout() { + await signOut(this.auth); + } + //#endregion + + //#region ACCOUNT MANAGEMENT + private getAccount() : Observable{ + return this.user$.pipe( + switchMap(user => { + if(user){ + const docRef = doc(this.firestore, `Account/${user.email}`); + return docData(docRef) as Observable; + } + return of(null) + }) + ); + } + + private async checkAccount(mail: string | null): Promise { + if(!mail){ + return false; + } + try{ + const docRef = doc(this.firestore, `Account/${mail}`).withConverter(accountConverter); + const docSnap = await getDoc(docRef); + const docExists = docSnap.exists(); + if(docExists){ + this.account$ = of(docSnap.data()); + } + return docExists; + } catch(error){ + console.error(error); + return false; } - throw new Error('Not implemented yet !'); } //#endregion + //#region NOT USED YET + async updateAccount(account: Account){ + + } + + /** + * Create a new account in the application + * @param account The account to create + */ + async createAccount(account: Account){ + const docRef = doc(this.firestore, `Account/${account.id}`); + await setDoc(docRef, account); + this.account$ = of(account); + console.log("Account ajouté avec succès"); + } + /** * Allows a connection to the application by using the Google Auth Provider * @param isSignIn @@ -81,7 +123,7 @@ export class LoginService { const provider = new GoogleAuthProvider(); var credential = await signInWithPopup(this.auth, provider); if(isSignIn){ - if(!await this.account.checkAccount(credential.user.email)){ + if(!await this.checkAccount(credential.user.email)){ throw new Error('No account found for the google account ' + credential.user.email); } return {success: true, id: credential.user.email}; @@ -90,23 +132,7 @@ export class LoginService { } } - //#region Authentification avec numéro de téléphone NOT WORKIN CURRENTLY - private recaptchaVerifier!: RecaptchaVerifier; - - /** - * - * @returns - */ - public getCaptcha(): RecaptchaVerifier{ - return new RecaptchaVerifier(this.auth, 'recaptcha-container', - { - size: 'normal', - callback: (response: any) => console.log('reCAPTCHA OK', response) - } - ); - } - - /** + /** * Allows to register a new account into the application by using the phone number of the user * @param username The name to use for the user in the account * @param phoneNumber The phone number of the user linked to the account @@ -122,18 +148,63 @@ export class LoginService { * @returns {Promise} A promise that contains the information about the success of the login */ public async loginWithPhoneNumber(phoneNumber: string): Promise { - if(!await this.account.checkAccount(phoneNumber)){ + if(!await this.checkAccount(phoneNumber)){ throw new Error('No account found for the google account ' + phoneNumber); } this.recaptchaVerifier = this.getCaptcha(); return await signInWithPhoneNumber(this.auth, phoneNumber, this.recaptchaVerifier); } - //#endregion + + private recaptchaVerifier!: RecaptchaVerifier; /** - * Disconnects the user to the application + * + * @returns */ - public async logout() { - await signOut(this.auth); + /** + * + * @returns + */ + public getCaptcha(): RecaptchaVerifier{ + return new RecaptchaVerifier(this.auth, 'recaptcha-container', + { + size: 'normal', + callback: (response: any) => console.log('reCAPTCHA OK', response) + } + ); + } + + //#region Authentification avec email + password + /** + * Allows to register a new account into the application with the couple (mail/password) + * @param username Username of the user when using the application + * @param mail The mail of the current user + * @param password The password set by the user to login + * @returns {Promise} Indicates if the registration suceeded or not + */ + public async registerMail(username: string, mail: string, password: string): Promise { + if(await this.checkAccount(mail)){ + throw new Error('An account already exists for the mail ' + mail); + } + await createUserWithEmailAndPassword(this.auth, mail, password); + const user = { id: mail, mail: mail, + username: username, createAt: new Date().toDateString(), photo: null }; + await this.createAccount(user); + return true; + } + + + + /** + * Allows a user to modify it password if it forget it + * @param mail The mail of the user + */ + public async forgotPassword(mail: string){ + if(!await this.checkAccount(mail)){ + throw new Error('No account found for the mail ' + mail); + } + throw new Error('Not implemented yet !'); } + //#endregion + //#endregion } diff --git a/src/styles.scss b/src/styles.scss index 948398979a125397e2e58101aa88d5fe277ed053..dbf4d904a0e551feedf24be4ce30806c4719e4f7 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -28,3 +28,7 @@ body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } + +.border { + border-radius: 10px; +} \ No newline at end of file