diff --git a/.gitignore b/.gitignore
index 3f3a096..4802c92 100644
--- a/.gitignore
+++ b/.gitignore
@@ -135,3 +135,6 @@ logs/
*.secrets
.act.secrets
.env
+
+.vscode
+
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
deleted file mode 100644
index 77b3745..0000000
--- a/.vscode/extensions.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
- "recommendations": ["angular.ng-template"]
-}
diff --git a/.vscode/launch.json b/.vscode/launch.json
deleted file mode 100644
index 925af83..0000000
--- a/.vscode/launch.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
- "version": "0.2.0",
- "configurations": [
- {
- "name": "ng serve",
- "type": "chrome",
- "request": "launch",
- "preLaunchTask": "npm: start",
- "url": "http://localhost:4200/"
- },
- {
- "name": "ng test",
- "type": "chrome",
- "request": "launch",
- "preLaunchTask": "npm: test",
- "url": "http://localhost:9876/debug.html"
- }
- ]
-}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
deleted file mode 100644
index a298b5b..0000000
--- a/.vscode/tasks.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
- "version": "2.0.0",
- "tasks": [
- {
- "type": "npm",
- "script": "start",
- "isBackground": true,
- "problemMatcher": {
- "owner": "typescript",
- "pattern": "$tsc",
- "background": {
- "activeOnStart": true,
- "beginsPattern": {
- "regexp": "(.*?)"
- },
- "endsPattern": {
- "regexp": "bundle generation complete"
- }
- }
- }
- },
- {
- "type": "npm",
- "script": "test",
- "isBackground": true,
- "problemMatcher": {
- "owner": "typescript",
- "pattern": "$tsc",
- "background": {
- "activeOnStart": true,
- "beginsPattern": {
- "regexp": "(.*?)"
- },
- "endsPattern": {
- "regexp": "bundle generation complete"
- }
- }
- }
- }
- ]
-}
diff --git a/package.json b/package.json
index abcf445..dc1b2e7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "trouve-ton-profile",
- "version": "1.3.1",
+ "version": "1.3.2",
"scripts": {
"ng": "ng",
"start": "bash replace-prod-env.sh src/environments/environment.development.ts $ENV_URL && ng serve",
diff --git a/src/app/adapters/profiles/profile.presenter.model.ts b/src/app/adapters/profiles/profile.presenter.model.ts
index 8e01e55..da66e50 100644
--- a/src/app/adapters/profiles/profile.presenter.model.ts
+++ b/src/app/adapters/profiles/profile.presenter.model.ts
@@ -23,6 +23,8 @@ export interface ProfileViewModel {
settings?: SettingsProfileDto;
slug?: string;
userViewModel?: UserViewModel;
+ mail?: string;
+ phone?: string;
}
export interface ProfileViewModelPaginated {
diff --git a/src/app/adapters/profiles/profile.presenter.ts b/src/app/adapters/profiles/profile.presenter.ts
index 3e1d0a9..73d4d2e 100644
--- a/src/app/adapters/profiles/profile.presenter.ts
+++ b/src/app/adapters/profiles/profile.presenter.ts
@@ -46,6 +46,7 @@ export class ProfilePresenter {
settings,
isProfileVisible,
missingFields,
+ phone: this.formatPhoneNumberForDisplay(profile.phone ? `${profile.phone.toString()}` : ''),
};
const profileExpand = (profile as any) ? (profile as any).expand : { utilisateur: {} as User };
@@ -58,7 +59,7 @@ export class ProfilePresenter {
const slug = userSlug === '' ? profileId : userSlug.concat('-', profileId);
const avatarUrl = userExpand.avatar
? `${environment.baseUrl}/api/files/users/${profile.utilisateur}/${userExpand.avatar}?thumb=320x240`
- : `https://api.dicebear.com/9.x/initials/svg?seed=${userExpand.name}}`;
+ : `https://api.dicebear.com/9.x/initials/svg?seed=${userExpand.name}`;
profileViewModel = {
...profileViewModel,
@@ -66,6 +67,7 @@ export class ProfilePresenter {
slug,
fullName: userExpand.name,
avatarUrl,
+ mail: userExpand.email,
};
}
@@ -104,4 +106,31 @@ export class ProfilePresenter {
return missing;
}
+
+ private cleanPhoneNumber(phone: string): string {
+ if (!phone) return '';
+ return phone.replace(/\D/g, '');
+ }
+
+ private formatPhoneNumberForDisplay(phone: string): string {
+ if (!phone) return '';
+
+ const cleaned = this.cleanPhoneNumber(`0${phone}`);
+
+ // 9 chiffres : 06 xxx xx xx (3 + 2 + 2 + 2)
+ if (cleaned.length === 9) {
+ return `${cleaned.slice(0, 2)} ${cleaned.slice(2, 5)} ${cleaned.slice(5, 7)} ${cleaned.slice(7, 9)}`;
+ }
+
+ // 10 chiffres : 06 xx xx xx xx (5 groupes de 2)
+ if (cleaned.length === 10) {
+ const groups: string[] = [];
+ for (let i = 0; i < cleaned.length; i += 2) {
+ groups.push(cleaned.slice(i, i + 2));
+ }
+ return groups.join(' ');
+ }
+
+ return cleaned;
+ }
}
diff --git a/src/app/domain/profiles/profile.model.ts b/src/app/domain/profiles/profile.model.ts
index f8b7df6..2728b21 100644
--- a/src/app/domain/profiles/profile.model.ts
+++ b/src/app/domain/profiles/profile.model.ts
@@ -16,6 +16,7 @@ export interface Profile {
estGeolocaliser?: boolean;
partageMail?: boolean;
partagePhone?: boolean;
+ phone?: number;
}
export interface ProfilePaginated {
diff --git a/src/app/infrastructure/profiles/pb-profile.repository.ts b/src/app/infrastructure/profiles/pb-profile.repository.ts
index 22e14be..77d8263 100644
--- a/src/app/infrastructure/profiles/pb-profile.repository.ts
+++ b/src/app/infrastructure/profiles/pb-profile.repository.ts
@@ -1,8 +1,8 @@
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
-import { from, map, Observable } from 'rxjs';
+import { from, Observable } from 'rxjs';
import { Profile, ProfilePaginated } from '@app/domain/profiles/profile.model';
import { Injectable } from '@angular/core';
-import PocketBase, { ListResult } from 'pocketbase';
+import PocketBase from 'pocketbase';
import { environment } from '@env/environment';
import { ProfileDTO } from '@app/domain/profiles/dto/create-profile.dto';
import { SearchFilters } from '@app/domain/search/search-filters';
diff --git a/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.html b/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.html
index 8898e80..ba25023 100644
--- a/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.html
+++ b/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.html
@@ -42,6 +42,135 @@
+
+
+
+
+
+
+
+
+
+ @if (isEmailInvalid) {
+
+
+ {{ emailErrorMessage }}
+
+ }
+
+
+
+
+
+
+ @if (isPhoneInvalid) {
+
+
+ {{ phoneErrorMessage }}
+
+ }
+
+
+
+
{
bio: '',
apropos: '',
reseaux: { facebook: '', github: '', instagram: '', linkedIn: '', web: '', x: '', youTube: '' },
+ phone: '123',
+ mail: 'test@mail.com',
};
beforeEach(async () => {
@@ -69,6 +71,8 @@ describe('MyProfileUpdateFormComponent', () => {
mockProfileData.secteur = 'technology';
mockProfileData.bio = 'A passionate developer';
mockProfileData.apropos = 'About me';
+ mockProfileData.mail = 'test@mail.com';
+ mockProfileData.phone = '123';
component.profileForm.setValue(mockProfileData);
const spyUpdateProfile = jest.spyOn(component, 'onSubmit');
diff --git a/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.ts b/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.ts
index e73a55b..8463301 100644
--- a/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.ts
+++ b/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.ts
@@ -78,6 +78,11 @@ export class MyProfileUpdateFormComponent implements OnInit {
),
bio: new FormControl(this.profile.bio ? this.profile.bio.toLowerCase() : ''),
apropos: new FormControl(this.profile.apropos ? this.profile.apropos.toLowerCase() : ''),
+ mail: new FormControl(
+ { value: this.profile.mail ? this.profile.mail.toLowerCase() : '', disabled: true },
+ [Validators.email]
+ ),
+ phone: new FormControl(this.profile.phone ? this.profile.phone.toString().toLowerCase() : ''),
reseaux: new FormGroup({
facebook: new FormControl(
this.profile.reseaux ? (this.profile.reseaux as any)['facebook'] : ''
@@ -111,14 +116,36 @@ export class MyProfileUpdateFormComponent implements OnInit {
return;
}
- const data: Profile = {
+ const data: Partial
= {
profession: this.profileForm.getRawValue().profession,
secteur: this.profileForm.getRawValue().secteur,
apropos: this.profileForm.getRawValue().apropos,
bio: this.profileForm.getRawValue().bio,
+ phone: parseInt(this.profileForm.getRawValue().phone.replace(/\D/g, '')),
reseaux: this.profileForm.getRawValue().reseaux,
- } as Profile;
+ } as Partial;
this.profileFacade.update(this.profile.id, data);
}
+
+ get isEmailInvalid(): boolean {
+ const mailControl = this.profileForm.get('mail');
+ return !!(mailControl?.invalid && mailControl?.touched && mailControl?.value);
+ }
+
+ get isPhoneInvalid(): boolean {
+ const phoneControl = this.profileForm.get('phone');
+ if (!phoneControl?.value) return false;
+ const phone = phoneControl.value.replace(/\D/g, '');
+
+ return phoneControl.touched && (phone.length < 9 || !phone.startsWith('0'));
+ }
+
+ get emailErrorMessage(): string {
+ return 'Veuillez entrer une adresse email valide';
+ }
+
+ get phoneErrorMessage(): string {
+ return 'Le numéro doit contenir minimum 9 chiffres (ex: 06 xxx xx xx)';
+ }
}
diff --git a/src/app/testing/adapters/profiles/profile.presenter.spec.ts b/src/app/testing/adapters/profiles/profile.presenter.spec.ts
index f5cc9a1..acbfb4f 100644
--- a/src/app/testing/adapters/profiles/profile.presenter.spec.ts
+++ b/src/app/testing/adapters/profiles/profile.presenter.spec.ts
@@ -1,56 +1,332 @@
import { ProfilePresenter } from '@app/adapters/profiles/profile.presenter';
-import { Profile } from '@app/domain/profiles/profile.model';
+import { Profile, ProfilePaginated } from '@app/domain/profiles/profile.model';
import { mockProfiles } from '@app/testing/profile.mock';
-import { Coordinates } from '@app/domain/localisation/coordinates.model';
+import { UserViewModel } from '@app/adapters/users/user.presenter.model';
+import { mockUsers } from '@app/testing/user.mock';
describe('ProfilePresenter', () => {
- it('devrait transformer un Profile en ProfileViewModel', () => {
- const profile: Profile = mockProfiles[0];
+ let presenter: ProfilePresenter;
- const profilePresenter = new ProfilePresenter();
- const viewModel = profilePresenter.toViewModel(profile);
+ const mockProfile: Profile = mockProfiles[0] as Profile;
- expect(viewModel).toEqual({
- id: profile.id,
- fullName: '', // transformation OK
- isVerifiedLabel: '✅ Vérifié',
- estVerifier: true,
- coordonnees: { latitude: 0, longitude: 0 } as Coordinates,
- profession: 'Développeur Web'.toUpperCase(),
- reseaux: { linkedin: 'https://linkedin.com/in/test' },
- secteur: 'Informatique',
- utilisateur: 'user_abc',
- createdAtFormatted: new Date(profile.created).toLocaleDateString(),
- avatarUrl: '',
- apropos: 'Développeur Angular & Node.js',
- bio: 'Passionné de code.',
- cv: 'http://localhost:8090/api/files/profiles/1/cv.pdf',
- isProfileVisible: true,
- missingFields: [],
- projets: ['p1', 'p2'],
- settings: {
- showEmail: false,
- showPhone: false,
- allowGeolocation: false,
- isProfilePublic: false,
- },
+ const mockUser: UserViewModel = mockUsers[0];
+
+ beforeEach(() => {
+ presenter = new ProfilePresenter();
+ });
+
+ describe('toViewModel', () => {
+ it('devrait convertir un profil en ProfileViewModel', () => {
+ const viewModel = presenter.toViewModel(mockProfile);
+
+ expect(viewModel).toBeDefined();
+ expect(viewModel.id).toBe('1');
+ expect(viewModel.profession).toBe('DÉVELOPPEUR WEB');
+ expect(viewModel.secteur).toBe('Informatique');
+ expect(viewModel.bio).toBe('Passionné de code.');
+ expect(viewModel.apropos).toBe('Développeur Angular & Node.js');
+ expect(viewModel.estVerifier).toBe(true);
+ expect(viewModel.isVerifiedLabel).toBe('✅ Vérifié');
+ });
+
+ it('devrait formater le numéro de téléphone à 10 chiffres', () => {
+ const profileWithPhone = {
+ ...mockProfile,
+ phone: 612345678,
+ } as Profile;
+
+ const viewModel = presenter.toViewModel(profileWithPhone);
+
+ expect(viewModel.phone).toBe('06 12 34 56 78');
+ });
+
+ it('devrait formater le numéro de téléphone à 9 chiffres', () => {
+ const profileWithPhone = {
+ ...mockProfile,
+ phone: 123456789,
+ } as Profile;
+
+ const viewModel = presenter.toViewModel(profileWithPhone);
+
+ expect(viewModel.phone).toBe('01 23 45 67 89');
+ });
+
+ it('devrait gérer un téléphone vide', () => {
+ const profileWithoutPhone = {
+ ...mockProfile,
+ phone: undefined,
+ } as Profile;
+
+ const viewModel = presenter.toViewModel(profileWithoutPhone);
+
+ expect(viewModel.phone).toBe('');
+ });
+
+ it('devrait utiliser la bio par défaut si non fournie', () => {
+ const profileWithoutBio = {
+ ...mockProfile,
+ bio: '',
+ } as Profile;
+
+ const viewModel = presenter.toViewModel(profileWithoutBio);
+
+ expect(viewModel.bio).toContain('Trouve Ton Profil');
+ expect(viewModel.bio).toContain('expertise');
+ });
+
+ it("devrait générer l'URL du CV correctement", () => {
+ const viewModel = presenter.toViewModel(mockProfile);
+
+ expect(viewModel.cv).toContain('/api/files/profiles/1/cv.pdf');
+ });
+
+ it('devrait retourner une chaîne vide si pas de CV', () => {
+ const profileWithoutCv = {
+ ...mockProfile,
+ cv: '',
+ } as Profile;
+
+ const viewModel = presenter.toViewModel(profileWithoutCv);
+
+ expect(viewModel.cv).toBe('');
+ });
+
+ it('devrait définir les settings correctement', () => {
+ const viewModel = presenter.toViewModel(mockProfile);
+
+ expect(viewModel.settings).toBeDefined();
+ expect(viewModel.settings?.showEmail).toBe(false);
+ expect(viewModel.settings?.showPhone).toBe(false);
+ expect(viewModel.settings?.allowGeolocation).toBe(false);
+ expect(viewModel.settings?.isProfilePublic).toBe(false);
+ });
+
+ it('devrait définir les coordonnées correctement', () => {
+ const viewModel = presenter.toViewModel(mockProfile);
+
+ expect(viewModel.coordonnees).toBeDefined();
+ expect(viewModel.coordonnees?.latitude).toBe(0);
+ expect(viewModel.coordonnees?.longitude).toBe(0);
+ });
+
+ it("devrait gérer l'absence de coordonnées", () => {
+ const profileWithoutCoords = {
+ ...mockProfile,
+ coordonnees: undefined,
+ } as Profile;
+
+ const viewModel = presenter.toViewModel(profileWithoutCoords);
+
+ expect(viewModel.coordonnees).toBeUndefined();
+ });
+
+ it('devrait formater la date de création', () => {
+ const viewModel = presenter.toViewModel(mockProfile);
+
+ expect(viewModel.createdAtFormatted).toBeDefined();
+ expect(typeof viewModel.createdAtFormatted).toBe('string');
+ });
+
+ it('devrait définir le label de vérification pour un profil non vérifié', () => {
+ const unverifiedProfile = {
+ ...mockProfile,
+ estVerifier: false,
+ } as Profile;
+
+ const viewModel = presenter.toViewModel(unverifiedProfile);
+
+ expect(viewModel.isVerifiedLabel).toBe('❌ Non vérifié');
+ });
+
+ describe('avec données utilisateur (expand)', () => {
+ it('devrait inclure les informations utilisateur si disponibles', () => {
+ const profileWithExpand = {
+ ...mockProfile,
+ expand: {
+ utilisateur: mockUser,
+ },
+ } as any;
+
+ const viewModel = presenter.toViewModel(profileWithExpand);
+
+ expect(viewModel.fullName).toBe('foo');
+ expect(viewModel.mail).toBe('foo@bar.com');
+ expect(viewModel.avatarUrl).toContain(
+ 'http://localhost:8090/api/files/users/user_abc/foo.png?thumb=320x240'
+ );
+ expect(viewModel.userViewModel).toBeDefined();
+ });
+
+ it("devrait générer un slug à partir du username et de l'ID", () => {
+ const profileWithExpand = {
+ ...mockProfile,
+ expand: {
+ utilisateur: {
+ ...mockUser,
+ slug: 'test-user',
+ },
+ },
+ } as any;
+
+ const viewModel = presenter.toViewModel(profileWithExpand);
+
+ expect(viewModel.slug).toBe('foo-user001-1');
+ });
+
+ it("devrait utiliser l'ID du profil si pas de slug utilisateur", () => {
+ const profileWithExpand = {
+ ...mockProfile,
+ expand: {
+ utilisateur: {
+ ...mockUser,
+ slug: undefined,
+ },
+ },
+ } as any;
+
+ const viewModel = presenter.toViewModel(profileWithExpand);
+
+ expect(viewModel.slug).toBe('foo-user001-1');
+ });
+
+ it("devrait générer une URL Dicebear si pas d'avatar", () => {
+ const profileWithExpand = {
+ ...mockProfile,
+ expand: {
+ utilisateur: {
+ ...mockUser,
+ avatar: undefined,
+ },
+ },
+ } as any;
+
+ const viewModel = presenter.toViewModel(profileWithExpand);
+
+ expect(viewModel.avatarUrl).toContain('dicebear.com');
+ expect(viewModel.avatarUrl).toContain('foo');
+ });
});
});
- it('devrait retourner ❌ Non vérifié si estVerifier = false', () => {
- const profile = { ...mockProfiles[1], estVerifier: false };
+ describe('toViewModels', () => {
+ it('devrait convertir un tableau de profils', () => {
+ const profiles = [mockProfile, { ...mockProfile, id: '456' }];
+ const viewModels = presenter.toViewModels(profiles);
- const profilePresenter = new ProfilePresenter();
- const viewModel = profilePresenter.toViewModel(profile);
+ expect(viewModels).toHaveLength(2);
+ expect(viewModels[0].id).toBe('1');
+ expect(viewModels[1].id).toBe('456');
+ });
- expect(viewModel.isVerifiedLabel).toBe('❌ Non vérifié');
+ it('devrait gérer un tableau vide', () => {
+ const viewModels = presenter.toViewModels([]);
+
+ expect(viewModels).toEqual([]);
+ });
});
- it('devrait transformer un tableau complet', () => {
- const profilePresenter = new ProfilePresenter();
- const result = profilePresenter.toViewModels(mockProfiles);
+ describe('toViewModelPaginated', () => {
+ it('devrait convertir un ProfilePaginated en ProfileViewModelPaginated', () => {
+ const paginatedProfiles: ProfilePaginated = {
+ page: 1,
+ perPage: 10,
+ totalPages: 5,
+ totalItems: 50,
+ items: [mockProfile],
+ };
- expect(result.length).toBe(2);
- expect(result[0].fullName).toBe('');
+ const viewModel = presenter.toViewModelPaginated(paginatedProfiles);
+
+ expect(viewModel.page).toBe(1);
+ expect(viewModel.perPage).toBe(10);
+ expect(viewModel.totalPages).toBe(5);
+ expect(viewModel.totalItems).toBe(50);
+ expect(viewModel.items).toHaveLength(1);
+ expect(viewModel.items[0].id).toBe('1');
+ });
+ });
+
+ describe('isProfileVisible (méthode privée via toViewModel)', () => {
+ it('devrait marquer le profil comme visible si profession et secteur sont renseignés', () => {
+ const viewModel = presenter.toViewModel(mockProfile);
+
+ expect(viewModel.isProfileVisible).toBe(true);
+ expect(viewModel.missingFields).toEqual([]);
+ });
+
+ it("devrait marquer le profil comme non visible si la profession n'est pas renseignée", () => {
+ const profileWithoutProfession = {
+ ...mockProfile,
+ profession: 'profession non renseignée',
+ } as Profile;
+
+ const viewModel = presenter.toViewModel(profileWithoutProfession);
+
+ expect(viewModel.isProfileVisible).toBe(false);
+ expect(viewModel.missingFields).toContain('profession');
+ });
+
+ it("devrait marquer le profil comme non visible si le secteur n'est pas renseigné", () => {
+ const profileWithoutSector = {
+ ...mockProfile,
+ secteur: '',
+ } as Profile;
+
+ const viewModel = presenter.toViewModel(profileWithoutSector);
+
+ expect(viewModel.isProfileVisible).toBe(false);
+ expect(viewModel.missingFields).toContain("secteur d'activité");
+ });
+
+ it('devrait lister tous les champs manquants', () => {
+ const incompleteProfile = {
+ ...mockProfile,
+ profession: 'profession non renseignée',
+ secteur: '',
+ } as Profile;
+
+ const viewModel = presenter.toViewModel(incompleteProfile);
+
+ expect(viewModel.isProfileVisible).toBe(false);
+ expect(viewModel.missingFields).toContain('profession');
+ expect(viewModel.missingFields).toContain("secteur d'activité");
+ });
+ });
+
+ describe('formatPhoneNumberForDisplay (méthode privée)', () => {
+ it('devrait formater un numéro à 10 chiffres', () => {
+ const profile = { ...mockProfile, phone: 612345678 } as Profile;
+ const viewModel = presenter.toViewModel(profile);
+
+ expect(viewModel.phone).toBe('06 12 34 56 78');
+ });
+
+ it('devrait formater un numéro à 9 chiffres', () => {
+ const profile = { ...mockProfile, phone: 123456789 } as Profile;
+ const viewModel = presenter.toViewModel(profile);
+
+ expect(viewModel.phone).toBe('01 23 45 67 89');
+ });
+
+ it('devrait retourner le numéro tel quel si moins de 9 chiffres', () => {
+ const profile = { ...mockProfile, phone: 1234567 } as Profile;
+ const viewModel = presenter.toViewModel(profile);
+
+ expect(viewModel.phone).toBe('01234567');
+ });
+
+ it('devrait retourner le numéro tel quel si plus de 10 chiffres', () => {
+ const profile = { ...mockProfile, phone: 12345678901 } as Profile;
+ const viewModel = presenter.toViewModel(profile);
+
+ expect(viewModel.phone).toBe('012345678901');
+ });
+
+ it('devrait retourner une chaîne vide pour un téléphone null', () => {
+ const profile = { ...mockProfile, phone: null } as any;
+ const viewModel = presenter.toViewModel(profile);
+
+ expect(viewModel.phone).toBe('');
+ });
});
});
diff --git a/src/app/testing/profile.mock.ts b/src/app/testing/profile.mock.ts
index 6720ae9..df5cec2 100644
--- a/src/app/testing/profile.mock.ts
+++ b/src/app/testing/profile.mock.ts
@@ -14,6 +14,7 @@ export const mockProfiles: Profile[] = [
reseaux: JSON.parse('{"linkedin": "https://linkedin.com/in/test"}'),
bio: 'Passionné de code.',
cv: 'cv.pdf',
+ phone: 123,
projets: ['p1', 'p2'],
apropos: 'Développeur Angular & Node.js',
},