@viridial/shared 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -0
- package/USER-MODULE.md +268 -0
- package/dist/api/auth.service.d.ts +35 -0
- package/dist/api/auth.service.d.ts.map +1 -0
- package/dist/api/auth.service.js +63 -0
- package/dist/api/http.client.d.ts +19 -0
- package/dist/api/http.client.d.ts.map +1 -0
- package/dist/api/http.client.js +97 -0
- package/dist/api/property.service.d.ts +31 -0
- package/dist/api/property.service.d.ts.map +1 -0
- package/dist/api/property.service.js +47 -0
- package/dist/api/user.service.d.ts +86 -0
- package/dist/api/user.service.d.ts.map +1 -0
- package/dist/api/user.service.js +145 -0
- package/dist/composables/useAuth.d.ts +21 -0
- package/dist/composables/useAuth.d.ts.map +1 -0
- package/dist/composables/useAuth.js +43 -0
- package/dist/composables/useUser.d.ts +173 -0
- package/dist/composables/useUser.d.ts.map +1 -0
- package/dist/composables/useUser.js +132 -0
- package/dist/constants/api.constants.d.ts +32 -0
- package/dist/constants/api.constants.d.ts.map +1 -0
- package/dist/constants/api.constants.js +35 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/stores/auth.store.d.ts +75 -0
- package/dist/stores/auth.store.d.ts.map +1 -0
- package/dist/stores/auth.store.js +71 -0
- package/dist/stores/user.store.d.ts +748 -0
- package/dist/stores/user.store.d.ts.map +1 -0
- package/dist/stores/user.store.js +264 -0
- package/dist/types/api.types.d.ts +27 -0
- package/dist/types/api.types.d.ts.map +1 -0
- package/dist/types/api.types.js +4 -0
- package/dist/types/auth.types.d.ts +38 -0
- package/dist/types/auth.types.d.ts.map +1 -0
- package/dist/types/auth.types.js +4 -0
- package/dist/types/property.types.d.ts +66 -0
- package/dist/types/property.types.d.ts.map +1 -0
- package/dist/types/property.types.js +20 -0
- package/dist/types/user.types.d.ts +103 -0
- package/dist/types/user.types.d.ts.map +1 -0
- package/dist/types/user.types.js +21 -0
- package/dist/utils/token.utils.d.ts +30 -0
- package/dist/utils/token.utils.d.ts.map +1 -0
- package/dist/utils/token.utils.js +56 -0
- package/package.json +96 -0
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# 📦 Shared Modules - Architecture Modulaire
|
|
2
|
+
|
|
3
|
+
Ce répertoire contient les modules partagés entre les trois applications frontend (admin, agent, public).
|
|
4
|
+
|
|
5
|
+
## 🏗️ Structure Modulaire
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
shared/
|
|
9
|
+
├── api/ # Services API réutilisables
|
|
10
|
+
├── stores/ # Stores Pinia partagés
|
|
11
|
+
├── composables/ # Composables Vue réutilisables
|
|
12
|
+
├── types/ # Types TypeScript partagés
|
|
13
|
+
├── utils/ # Utilitaires communs
|
|
14
|
+
├── constants/ # Constantes partagées
|
|
15
|
+
└── components/ # Composants UI réutilisables
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 📦 Modules Disponibles
|
|
19
|
+
|
|
20
|
+
### 1. API Module (`api/`)
|
|
21
|
+
Services API pour communiquer avec le backend :
|
|
22
|
+
- `auth.service.ts` - Authentification
|
|
23
|
+
- `property.service.ts` - Gestion des propriétés
|
|
24
|
+
- `user.service.ts` - Gestion des utilisateurs
|
|
25
|
+
- `organization.service.ts` - Gestion des organisations
|
|
26
|
+
- `http.client.ts` - Client HTTP configuré (axios)
|
|
27
|
+
|
|
28
|
+
### 2. Stores Module (`stores/`)
|
|
29
|
+
Stores Pinia pour la gestion d'état :
|
|
30
|
+
- `auth.store.ts` - État d'authentification
|
|
31
|
+
- `user.store.ts` - Données utilisateur
|
|
32
|
+
- `property.store.ts` - Propriétés
|
|
33
|
+
- `organization.store.ts` - Organisations
|
|
34
|
+
|
|
35
|
+
### 3. Composables Module (`composables/`)
|
|
36
|
+
Composables Vue réutilisables :
|
|
37
|
+
- `useAuth.ts` - Hook d'authentification
|
|
38
|
+
- `useApi.ts` - Hook pour appels API
|
|
39
|
+
- `useToast.ts` - Hook pour notifications
|
|
40
|
+
- `useForm.ts` - Hook pour formulaires
|
|
41
|
+
|
|
42
|
+
### 4. Types Module (`types/`)
|
|
43
|
+
Types TypeScript partagés :
|
|
44
|
+
- `auth.types.ts` - Types d'authentification
|
|
45
|
+
- `property.types.ts` - Types de propriétés
|
|
46
|
+
- `user.types.ts` - Types utilisateurs
|
|
47
|
+
- `api.types.ts` - Types API génériques
|
|
48
|
+
|
|
49
|
+
### 5. Utils Module (`utils/`)
|
|
50
|
+
Utilitaires communs :
|
|
51
|
+
- `token.utils.ts` - Gestion des tokens JWT
|
|
52
|
+
- `date.utils.ts` - Formatage de dates
|
|
53
|
+
- `validation.utils.ts` - Validation
|
|
54
|
+
- `format.utils.ts` - Formatage
|
|
55
|
+
|
|
56
|
+
### 6. Constants Module (`constants/`)
|
|
57
|
+
Constantes partagées :
|
|
58
|
+
- `api.constants.ts` - URLs API, endpoints
|
|
59
|
+
- `routes.constants.ts` - Routes
|
|
60
|
+
- `config.constants.ts` - Configuration
|
|
61
|
+
|
|
62
|
+
### 7. Components Module (`components/`)
|
|
63
|
+
Composants UI réutilisables :
|
|
64
|
+
- `Layout/` - Layouts communs
|
|
65
|
+
- `Forms/` - Formulaires réutilisables
|
|
66
|
+
- `Cards/` - Cartes spécialisées
|
|
67
|
+
|
|
68
|
+
## 🔧 Utilisation
|
|
69
|
+
|
|
70
|
+
### Dans un projet frontend (admin/agent/public)
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// Importer un service API
|
|
74
|
+
import { authService } from '@/shared/api/auth.service'
|
|
75
|
+
|
|
76
|
+
// Importer un store
|
|
77
|
+
import { useAuthStore } from '@/shared/stores/auth.store'
|
|
78
|
+
|
|
79
|
+
// Importer un composable
|
|
80
|
+
import { useAuth } from '@/shared/composables/useAuth'
|
|
81
|
+
|
|
82
|
+
// Importer un type
|
|
83
|
+
import type { User } from '@/shared/types/user.types'
|
|
84
|
+
|
|
85
|
+
// Importer une constante
|
|
86
|
+
import { API_ENDPOINTS } from '@/shared/constants/api.constants'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 📝 Configuration
|
|
90
|
+
|
|
91
|
+
Chaque projet doit configurer le chemin `@/shared` dans son `tsconfig.json` :
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"compilerOptions": {
|
|
96
|
+
"paths": {
|
|
97
|
+
"@/*": ["./src/*"],
|
|
98
|
+
"@/shared/*": ["../shared/*"]
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Et dans `vite.config.ts` :
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
resolve: {
|
|
108
|
+
alias: {
|
|
109
|
+
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
|
110
|
+
'@/shared': fileURLToPath(new URL('../shared', import.meta.url))
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
package/USER-MODULE.md
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# 👥 Module de Gestion des Utilisateurs SaaS
|
|
2
|
+
|
|
3
|
+
Module complet pour la gestion des utilisateurs de la plateforme SaaS.
|
|
4
|
+
|
|
5
|
+
## 📦 Composants du Module
|
|
6
|
+
|
|
7
|
+
### 1. Service API (`api/user.service.ts`)
|
|
8
|
+
|
|
9
|
+
Service complet pour toutes les opérations sur les utilisateurs :
|
|
10
|
+
|
|
11
|
+
- **Gestion de base** : `getAll`, `getById`, `create`, `update`, `delete`
|
|
12
|
+
- **Profil utilisateur** : `getProfile`, `updateProfile`, `changePassword`
|
|
13
|
+
- **Statut** : `activate`, `deactivate`, `suspend`
|
|
14
|
+
- **Recherche** : `search`, `getStats`, `getActivity`
|
|
15
|
+
- **Rôles** : `assignRoles`, `removeRoles`
|
|
16
|
+
- **Email** : `verifyEmail`, `resendVerificationEmail`
|
|
17
|
+
|
|
18
|
+
### 2. Store Pinia (`stores/user.store.ts`)
|
|
19
|
+
|
|
20
|
+
Gestion d'état centralisée :
|
|
21
|
+
|
|
22
|
+
- **State** : `users`, `currentUser`, `selectedUser`, `stats`, `loading`
|
|
23
|
+
- **Getters** : `activeUsers`, `inactiveUsers`, `suspendedUsers`, `usersByRole`
|
|
24
|
+
- **Actions** : Toutes les opérations CRUD + gestion de statut
|
|
25
|
+
|
|
26
|
+
### 3. Composable (`composables/useUser.ts`)
|
|
27
|
+
|
|
28
|
+
Hook réutilisable avec permissions :
|
|
29
|
+
|
|
30
|
+
- **State & Getters** : Accès à tous les états et données
|
|
31
|
+
- **Actions** : Toutes les opérations sur les utilisateurs
|
|
32
|
+
- **Permissions** : `canEditUser`, `canDeleteUser`, `canManageRoles`
|
|
33
|
+
|
|
34
|
+
### 4. Types TypeScript (`types/user.types.ts`)
|
|
35
|
+
|
|
36
|
+
Types complets pour les utilisateurs :
|
|
37
|
+
|
|
38
|
+
- `User`, `UserCreate`, `UserUpdate`
|
|
39
|
+
- `UserProfile`, `UserPreferences`, `NotificationSettings`
|
|
40
|
+
- `UserStatus`, `UserRole` (enums)
|
|
41
|
+
- `UserStats`, `UserActivity`
|
|
42
|
+
|
|
43
|
+
## 🚀 Utilisation
|
|
44
|
+
|
|
45
|
+
### Dans un composant Vue
|
|
46
|
+
|
|
47
|
+
```vue
|
|
48
|
+
<script setup lang="ts">
|
|
49
|
+
import { useUser } from '@/shared'
|
|
50
|
+
import { UserStatus, UserRole } from '@/shared'
|
|
51
|
+
|
|
52
|
+
const {
|
|
53
|
+
users,
|
|
54
|
+
loading,
|
|
55
|
+
loadUsers,
|
|
56
|
+
createUser,
|
|
57
|
+
updateUser,
|
|
58
|
+
deleteUser,
|
|
59
|
+
canEditUser,
|
|
60
|
+
canDeleteUser
|
|
61
|
+
} = useUser()
|
|
62
|
+
|
|
63
|
+
// Charger les utilisateurs
|
|
64
|
+
await loadUsers({ status: UserStatus.ACTIVE })
|
|
65
|
+
|
|
66
|
+
// Créer un utilisateur
|
|
67
|
+
const newUser = await createUser({
|
|
68
|
+
email: 'user@example.com',
|
|
69
|
+
name: 'John Doe',
|
|
70
|
+
password: 'password123',
|
|
71
|
+
roles: [UserRole.AGENT]
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
// Vérifier les permissions
|
|
75
|
+
if (canEditUser(userId)) {
|
|
76
|
+
await updateUser(userId, { name: 'New Name' })
|
|
77
|
+
}
|
|
78
|
+
</script>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Utiliser le service directement
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { userService } from '@/shared'
|
|
85
|
+
import type { UserCreate } from '@/shared'
|
|
86
|
+
|
|
87
|
+
// Créer un utilisateur
|
|
88
|
+
const user = await userService.create({
|
|
89
|
+
email: 'user@example.com',
|
|
90
|
+
name: 'John Doe',
|
|
91
|
+
password: 'password123',
|
|
92
|
+
roles: ['AGENT']
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
// Récupérer les statistiques
|
|
96
|
+
const stats = await userService.getStats()
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Utiliser le store directement
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { useUserStore } from '@/shared'
|
|
103
|
+
|
|
104
|
+
const userStore = useUserStore()
|
|
105
|
+
|
|
106
|
+
// Charger les utilisateurs
|
|
107
|
+
await userStore.fetchUsers()
|
|
108
|
+
|
|
109
|
+
// Accéder aux données
|
|
110
|
+
const activeUsers = userStore.activeUsers
|
|
111
|
+
const stats = userStore.stats
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## 🔐 Gestion des Permissions
|
|
115
|
+
|
|
116
|
+
Le composable `useUser` inclut des helpers de permissions :
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
const { canEditUser, canDeleteUser, canManageRoles } = useUser()
|
|
120
|
+
|
|
121
|
+
// Vérifier si on peut éditer un utilisateur
|
|
122
|
+
if (canEditUser(userId)) {
|
|
123
|
+
// Éditer l'utilisateur
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Vérifier si on peut supprimer
|
|
127
|
+
if (canDeleteUser(userId)) {
|
|
128
|
+
// Supprimer l'utilisateur
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Vérifier si on peut gérer les rôles
|
|
132
|
+
if (canManageRoles(userId)) {
|
|
133
|
+
// Assigner/retirer des rôles
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## 📊 Types de Rôles
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
enum UserRole {
|
|
141
|
+
SUPER_ADMIN = 'SUPER_ADMIN', // Super administrateur
|
|
142
|
+
ADMIN = 'ADMIN', // Administrateur
|
|
143
|
+
AGENT = 'AGENT', // Agent immobilier
|
|
144
|
+
FREELANCE = 'FREELANCE', // Freelance
|
|
145
|
+
AUTO_ENTREPRENEUR = 'AUTO_ENTREPRENEUR', // Auto-entrepreneur
|
|
146
|
+
PARTICULAR = 'PARTICULAR', // Particulier
|
|
147
|
+
USER = 'USER' // Utilisateur standard
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## 📈 Statuts Utilisateur
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
enum UserStatus {
|
|
155
|
+
ACTIVE = 'ACTIVE', // Actif
|
|
156
|
+
INACTIVE = 'INACTIVE', // Inactif
|
|
157
|
+
SUSPENDED = 'SUSPENDED', // Suspendu
|
|
158
|
+
PENDING = 'PENDING', // En attente
|
|
159
|
+
DELETED = 'DELETED' // Supprimé
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## 🔍 Recherche et Filtres
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
const { loadUsers } = useUser()
|
|
167
|
+
|
|
168
|
+
// Recherche avec filtres
|
|
169
|
+
await loadUsers({
|
|
170
|
+
search: 'john',
|
|
171
|
+
status: UserStatus.ACTIVE,
|
|
172
|
+
role: UserRole.AGENT,
|
|
173
|
+
organizationId: 1,
|
|
174
|
+
page: 0,
|
|
175
|
+
size: 20
|
|
176
|
+
})
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## 📝 Exemple Complet
|
|
180
|
+
|
|
181
|
+
```vue
|
|
182
|
+
<template>
|
|
183
|
+
<div>
|
|
184
|
+
<Button @click="loadUsers">Charger les utilisateurs</Button>
|
|
185
|
+
|
|
186
|
+
<Table v-if="!loading">
|
|
187
|
+
<TableHeader>
|
|
188
|
+
<TableRow>
|
|
189
|
+
<TableHead>Nom</TableHead>
|
|
190
|
+
<TableHead>Email</TableHead>
|
|
191
|
+
<TableHead>Rôles</TableHead>
|
|
192
|
+
<TableHead>Statut</TableHead>
|
|
193
|
+
<TableHead>Actions</TableHead>
|
|
194
|
+
</TableRow>
|
|
195
|
+
</TableHeader>
|
|
196
|
+
<TableBody>
|
|
197
|
+
<TableRow v-for="user in users" :key="user.id">
|
|
198
|
+
<TableCell>{{ user.name }}</TableCell>
|
|
199
|
+
<TableCell>{{ user.email }}</TableCell>
|
|
200
|
+
<TableCell>{{ user.roles.join(', ') }}</TableCell>
|
|
201
|
+
<TableCell>{{ user.status }}</TableCell>
|
|
202
|
+
<TableCell>
|
|
203
|
+
<Button
|
|
204
|
+
v-if="canEditUser(user.id)"
|
|
205
|
+
@click="editUser(user.id)"
|
|
206
|
+
>
|
|
207
|
+
Éditer
|
|
208
|
+
</Button>
|
|
209
|
+
<Button
|
|
210
|
+
v-if="canDeleteUser(user.id)"
|
|
211
|
+
@click="deleteUser(user.id)"
|
|
212
|
+
variant="destructive"
|
|
213
|
+
>
|
|
214
|
+
Supprimer
|
|
215
|
+
</Button>
|
|
216
|
+
</TableCell>
|
|
217
|
+
</TableRow>
|
|
218
|
+
</TableBody>
|
|
219
|
+
</Table>
|
|
220
|
+
</div>
|
|
221
|
+
</template>
|
|
222
|
+
|
|
223
|
+
<script setup lang="ts">
|
|
224
|
+
import { onMounted } from 'vue'
|
|
225
|
+
import { useUser } from '@/shared'
|
|
226
|
+
import { Button } from '@/components/ui/button'
|
|
227
|
+
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from '@/components/ui/table'
|
|
228
|
+
|
|
229
|
+
const {
|
|
230
|
+
users,
|
|
231
|
+
loading,
|
|
232
|
+
loadUsers,
|
|
233
|
+
deleteUser: removeUser,
|
|
234
|
+
canEditUser,
|
|
235
|
+
canDeleteUser
|
|
236
|
+
} = useUser()
|
|
237
|
+
|
|
238
|
+
onMounted(() => {
|
|
239
|
+
loadUsers()
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
const editUser = (id: number) => {
|
|
243
|
+
// Navigation vers la page d'édition
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const deleteUser = async (id: number) => {
|
|
247
|
+
if (confirm('Êtes-vous sûr de vouloir supprimer cet utilisateur ?')) {
|
|
248
|
+
await removeUser(id)
|
|
249
|
+
await loadUsers() // Recharger la liste
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
</script>
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## 🎯 Fonctionnalités
|
|
256
|
+
|
|
257
|
+
- ✅ CRUD complet des utilisateurs
|
|
258
|
+
- ✅ Gestion des rôles et permissions
|
|
259
|
+
- ✅ Gestion des statuts (actif, inactif, suspendu)
|
|
260
|
+
- ✅ Recherche et filtres avancés
|
|
261
|
+
- ✅ Statistiques des utilisateurs
|
|
262
|
+
- ✅ Historique d'activité
|
|
263
|
+
- ✅ Gestion du profil utilisateur
|
|
264
|
+
- ✅ Changement de mot de passe
|
|
265
|
+
- ✅ Vérification d'email
|
|
266
|
+
- ✅ Pagination
|
|
267
|
+
- ✅ Permissions intégrées
|
|
268
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { LoginRequest, LoginResponse, SignupRequest, SignupResponse, ForgotPasswordRequest, ResetPasswordRequest } from '../types/auth.types';
|
|
2
|
+
/**
|
|
3
|
+
* Service d'authentification
|
|
4
|
+
*/
|
|
5
|
+
export declare const authService: {
|
|
6
|
+
/**
|
|
7
|
+
* Connexion
|
|
8
|
+
*/
|
|
9
|
+
login(credentials: LoginRequest): Promise<LoginResponse>;
|
|
10
|
+
/**
|
|
11
|
+
* Inscription
|
|
12
|
+
*/
|
|
13
|
+
signup(data: SignupRequest): Promise<SignupResponse>;
|
|
14
|
+
/**
|
|
15
|
+
* Déconnexion
|
|
16
|
+
*/
|
|
17
|
+
logout(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Demande de réinitialisation de mot de passe
|
|
20
|
+
*/
|
|
21
|
+
forgotPassword(data: ForgotPasswordRequest): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Réinitialisation de mot de passe
|
|
24
|
+
*/
|
|
25
|
+
resetPassword(data: ResetPasswordRequest): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Rafraîchir le token
|
|
28
|
+
*/
|
|
29
|
+
refreshToken(): Promise<LoginResponse>;
|
|
30
|
+
/**
|
|
31
|
+
* Vérifier si l'utilisateur est authentifié
|
|
32
|
+
*/
|
|
33
|
+
isAuthenticated(): boolean;
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=auth.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.service.d.ts","sourceRoot":"","sources":["../../api/auth.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAGlJ;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB;;OAEG;uBACsB,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAQ9D;;OAEG;iBACgB,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAK1D;;OAEG;cACa,OAAO,CAAC,IAAI,CAAC;IAQ7B;;OAEG;yBACwB,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE;;OAEG;wBACuB,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9D;;OAEG;oBACmB,OAAO,CAAC,aAAa,CAAC;IAQ5C;;OAEG;uBACgB,OAAO;CAG3B,CAAA"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { httpClient } from './http.client';
|
|
2
|
+
import { tokenUtils } from '../utils/token.utils';
|
|
3
|
+
/**
|
|
4
|
+
* Service d'authentification
|
|
5
|
+
*/
|
|
6
|
+
export const authService = {
|
|
7
|
+
/**
|
|
8
|
+
* Connexion
|
|
9
|
+
*/
|
|
10
|
+
async login(credentials) {
|
|
11
|
+
const response = await httpClient.post('/identity/auth/login', credentials);
|
|
12
|
+
if (response.data?.token) {
|
|
13
|
+
tokenUtils.setToken(response.data.token);
|
|
14
|
+
}
|
|
15
|
+
return response.data;
|
|
16
|
+
},
|
|
17
|
+
/**
|
|
18
|
+
* Inscription
|
|
19
|
+
*/
|
|
20
|
+
async signup(data) {
|
|
21
|
+
const response = await httpClient.post('/identity/auth/register', data);
|
|
22
|
+
return response.data;
|
|
23
|
+
},
|
|
24
|
+
/**
|
|
25
|
+
* Déconnexion
|
|
26
|
+
*/
|
|
27
|
+
async logout() {
|
|
28
|
+
try {
|
|
29
|
+
await httpClient.post('/identity/auth/logout');
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
tokenUtils.removeToken();
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
/**
|
|
36
|
+
* Demande de réinitialisation de mot de passe
|
|
37
|
+
*/
|
|
38
|
+
async forgotPassword(data) {
|
|
39
|
+
await httpClient.post('/identity/auth/forgot-password', data);
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
* Réinitialisation de mot de passe
|
|
43
|
+
*/
|
|
44
|
+
async resetPassword(data) {
|
|
45
|
+
await httpClient.post('/identity/auth/reset-password', data);
|
|
46
|
+
},
|
|
47
|
+
/**
|
|
48
|
+
* Rafraîchir le token
|
|
49
|
+
*/
|
|
50
|
+
async refreshToken() {
|
|
51
|
+
const response = await httpClient.post('/identity/auth/refresh');
|
|
52
|
+
if (response.data?.token) {
|
|
53
|
+
tokenUtils.setToken(response.data.token);
|
|
54
|
+
}
|
|
55
|
+
return response.data;
|
|
56
|
+
},
|
|
57
|
+
/**
|
|
58
|
+
* Vérifier si l'utilisateur est authentifié
|
|
59
|
+
*/
|
|
60
|
+
isAuthenticated() {
|
|
61
|
+
return tokenUtils.hasToken();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type AxiosRequestConfig } from 'axios';
|
|
2
|
+
import type { ApiResponse } from '../types/api.types';
|
|
3
|
+
/**
|
|
4
|
+
* Client HTTP configuré avec intercepteurs pour l'authentification
|
|
5
|
+
*/
|
|
6
|
+
declare class HttpClient {
|
|
7
|
+
private client;
|
|
8
|
+
constructor(baseURL?: string);
|
|
9
|
+
private setupInterceptors;
|
|
10
|
+
private handleError;
|
|
11
|
+
get<T>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>>;
|
|
12
|
+
post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<ApiResponse<T>>;
|
|
13
|
+
put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<ApiResponse<T>>;
|
|
14
|
+
patch<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<ApiResponse<T>>;
|
|
15
|
+
delete<T>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>>;
|
|
16
|
+
}
|
|
17
|
+
export declare const httpClient: HttpClient;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=http.client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.client.d.ts","sourceRoot":"","sources":["../../api/http.client.ts"],"names":[],"mappings":"AAAA,OAAc,EAAsB,KAAK,kBAAkB,EAAsB,MAAM,OAAO,CAAA;AAC9F,OAAO,KAAK,EAAE,WAAW,EAAY,MAAM,oBAAoB,CAAA;AAG/D;;GAEG;AACH,cAAM,UAAU;IACd,OAAO,CAAC,MAAM,CAAe;gBAEjB,OAAO,GAAE,MAAe;IAYpC,OAAO,CAAC,iBAAiB;IAkCzB,OAAO,CAAC,WAAW;IAcb,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IASzE,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAStF,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IASrF,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IASvF,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;CAQnF;AAED,eAAO,MAAM,UAAU,YAAmB,CAAA"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { tokenUtils } from '../utils/token.utils';
|
|
3
|
+
/**
|
|
4
|
+
* Client HTTP configuré avec intercepteurs pour l'authentification
|
|
5
|
+
*/
|
|
6
|
+
class HttpClient {
|
|
7
|
+
constructor(baseURL = '/api') {
|
|
8
|
+
this.client = axios.create({
|
|
9
|
+
baseURL,
|
|
10
|
+
timeout: 30000,
|
|
11
|
+
headers: {
|
|
12
|
+
'Content-Type': 'application/json'
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
this.setupInterceptors();
|
|
16
|
+
}
|
|
17
|
+
setupInterceptors() {
|
|
18
|
+
// Request interceptor - Ajouter le token
|
|
19
|
+
this.client.interceptors.request.use((config) => {
|
|
20
|
+
const token = tokenUtils.getToken();
|
|
21
|
+
if (token) {
|
|
22
|
+
config.headers.Authorization = `Bearer ${token}`;
|
|
23
|
+
}
|
|
24
|
+
return config;
|
|
25
|
+
}, (error) => {
|
|
26
|
+
return Promise.reject(error);
|
|
27
|
+
});
|
|
28
|
+
// Response interceptor - Gérer les erreurs
|
|
29
|
+
this.client.interceptors.response.use((response) => {
|
|
30
|
+
return response;
|
|
31
|
+
}, async (error) => {
|
|
32
|
+
if (error.response?.status === 401) {
|
|
33
|
+
// Token expiré ou invalide
|
|
34
|
+
tokenUtils.removeToken();
|
|
35
|
+
// Rediriger vers login
|
|
36
|
+
if (typeof window !== 'undefined') {
|
|
37
|
+
window.location.href = '/login';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return Promise.reject(this.handleError(error));
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
handleError(error) {
|
|
44
|
+
if (error.response) {
|
|
45
|
+
return {
|
|
46
|
+
message: error.response.data?.message || 'Une erreur est survenue',
|
|
47
|
+
status: error.response.status,
|
|
48
|
+
data: error.response.data
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
message: error.message || 'Erreur de connexion',
|
|
53
|
+
status: 0
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
async get(url, config) {
|
|
57
|
+
const response = await this.client.get(url, config);
|
|
58
|
+
return {
|
|
59
|
+
data: response.data,
|
|
60
|
+
status: response.status,
|
|
61
|
+
message: 'Success'
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async post(url, data, config) {
|
|
65
|
+
const response = await this.client.post(url, data, config);
|
|
66
|
+
return {
|
|
67
|
+
data: response.data,
|
|
68
|
+
status: response.status,
|
|
69
|
+
message: 'Success'
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async put(url, data, config) {
|
|
73
|
+
const response = await this.client.put(url, data, config);
|
|
74
|
+
return {
|
|
75
|
+
data: response.data,
|
|
76
|
+
status: response.status,
|
|
77
|
+
message: 'Success'
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async patch(url, data, config) {
|
|
81
|
+
const response = await this.client.patch(url, data, config);
|
|
82
|
+
return {
|
|
83
|
+
data: response.data,
|
|
84
|
+
status: response.status,
|
|
85
|
+
message: 'Success'
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async delete(url, config) {
|
|
89
|
+
const response = await this.client.delete(url, config);
|
|
90
|
+
return {
|
|
91
|
+
data: response.data,
|
|
92
|
+
status: response.status,
|
|
93
|
+
message: 'Success'
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export const httpClient = new HttpClient();
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Property, PropertyCreate, PropertyUpdate, PropertySearchParams } from '../types/property.types';
|
|
2
|
+
/**
|
|
3
|
+
* Service de gestion des propriétés
|
|
4
|
+
*/
|
|
5
|
+
export declare const propertyService: {
|
|
6
|
+
/**
|
|
7
|
+
* Récupérer toutes les propriétés
|
|
8
|
+
*/
|
|
9
|
+
getAll(params?: PropertySearchParams): Promise<Property[]>;
|
|
10
|
+
/**
|
|
11
|
+
* Récupérer une propriété par ID
|
|
12
|
+
*/
|
|
13
|
+
getById(id: number): Promise<Property>;
|
|
14
|
+
/**
|
|
15
|
+
* Créer une propriété
|
|
16
|
+
*/
|
|
17
|
+
create(data: PropertyCreate): Promise<Property>;
|
|
18
|
+
/**
|
|
19
|
+
* Mettre à jour une propriété
|
|
20
|
+
*/
|
|
21
|
+
update(id: number, data: PropertyUpdate): Promise<Property>;
|
|
22
|
+
/**
|
|
23
|
+
* Supprimer une propriété
|
|
24
|
+
*/
|
|
25
|
+
delete(id: number): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Rechercher des propriétés
|
|
28
|
+
*/
|
|
29
|
+
search(params: PropertySearchParams): Promise<Property[]>;
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=property.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"property.service.d.ts","sourceRoot":"","sources":["../../api/property.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAE7G;;GAEG;AACH,eAAO,MAAM,eAAe;IAC1B;;OAEG;oBACmB,oBAAoB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAKhE;;OAEG;gBACe,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAK5C;;OAEG;iBACgB,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC;IAKrD;;OAEG;eACc,MAAM,QAAQ,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC;IAKjE;;OAEG;eACc,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC;;OAEG;mBACkB,oBAAoB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;CAIhE,CAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { httpClient } from './http.client';
|
|
2
|
+
/**
|
|
3
|
+
* Service de gestion des propriétés
|
|
4
|
+
*/
|
|
5
|
+
export const propertyService = {
|
|
6
|
+
/**
|
|
7
|
+
* Récupérer toutes les propriétés
|
|
8
|
+
*/
|
|
9
|
+
async getAll(params) {
|
|
10
|
+
const response = await httpClient.get('/property-service/api/properties', { params });
|
|
11
|
+
return response.data || [];
|
|
12
|
+
},
|
|
13
|
+
/**
|
|
14
|
+
* Récupérer une propriété par ID
|
|
15
|
+
*/
|
|
16
|
+
async getById(id) {
|
|
17
|
+
const response = await httpClient.get(`/property-service/api/properties/${id}`);
|
|
18
|
+
return response.data;
|
|
19
|
+
},
|
|
20
|
+
/**
|
|
21
|
+
* Créer une propriété
|
|
22
|
+
*/
|
|
23
|
+
async create(data) {
|
|
24
|
+
const response = await httpClient.post('/property-service/api/properties', data);
|
|
25
|
+
return response.data;
|
|
26
|
+
},
|
|
27
|
+
/**
|
|
28
|
+
* Mettre à jour une propriété
|
|
29
|
+
*/
|
|
30
|
+
async update(id, data) {
|
|
31
|
+
const response = await httpClient.put(`/property-service/api/properties/${id}`, data);
|
|
32
|
+
return response.data;
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* Supprimer une propriété
|
|
36
|
+
*/
|
|
37
|
+
async delete(id) {
|
|
38
|
+
await httpClient.delete(`/property-service/api/properties/${id}`);
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* Rechercher des propriétés
|
|
42
|
+
*/
|
|
43
|
+
async search(params) {
|
|
44
|
+
const response = await httpClient.get('/property-service/api/properties/search', { params });
|
|
45
|
+
return response.data || [];
|
|
46
|
+
}
|
|
47
|
+
};
|