chore: add createclientbyadmin
This commit is contained in:
@@ -274,6 +274,67 @@ func RegisterClient(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AdminCreateClient crée un client depuis l'interface admin (sans session ni token)
|
||||||
|
// POST /api/v2/admin/protected/clients
|
||||||
|
func AdminCreateClient(c *gin.Context) {
|
||||||
|
var req RegisterClientRequest
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Données invalides"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !validatePhoneNumber(req.Telephone) {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Numéro de téléphone invalide"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizedPhone := normalizePhoneNumber(req.Telephone)
|
||||||
|
database := c.MustGet("database").(*db.Database)
|
||||||
|
|
||||||
|
if existing, _ := database.GetClientByUsername(req.Username); existing != nil {
|
||||||
|
c.JSON(http.StatusConflict, gin.H{"error": "Nom d'utilisateur déjà utilisé"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if existing, _ := database.GetClientByTelephone(normalizedPhone); existing != nil {
|
||||||
|
c.JSON(http.StatusConflict, gin.H{"error": "Ce numéro de téléphone est déjà utilisé"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hashed, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur traitement mot de passe"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &models.Client{
|
||||||
|
Username: req.Username,
|
||||||
|
Password: string(hashed),
|
||||||
|
Nom: strings.TrimSpace(req.Nom),
|
||||||
|
Prenom: strings.TrimSpace(req.Prenom),
|
||||||
|
Telephone: normalizedPhone,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := database.CreateClient(client); err != nil {
|
||||||
|
log.Printf("❌ [ADMIN_CREATE_CLIENT] Erreur création: %v", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur création client"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("✅ [ADMIN_CREATE_CLIENT] Client créé par admin: %s (ID=%d)", client.Username, client.ID)
|
||||||
|
|
||||||
|
c.JSON(http.StatusCreated, gin.H{
|
||||||
|
"message": "Client créé avec succès",
|
||||||
|
"client": gin.H{
|
||||||
|
"id": client.ID,
|
||||||
|
"username": client.Username,
|
||||||
|
"nom": client.Nom,
|
||||||
|
"prenom": client.Prenom,
|
||||||
|
"telephone": client.Telephone,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// LoginClient authentifie un client
|
// LoginClient authentifie un client
|
||||||
// POST /api/v1/auth/login
|
// POST /api/v1/auth/login
|
||||||
func LoginClient(c *gin.Context) {
|
func LoginClient(c *gin.Context) {
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ func SetupRoutes(router *gin.Engine, database *db.Database, geoService *services
|
|||||||
// ============================================
|
// ============================================
|
||||||
authGroupV1 := router.Group("/api/v1/auth")
|
authGroupV1 := router.Group("/api/v1/auth")
|
||||||
{
|
{
|
||||||
authGroupV1.POST("/register", handlers.RegisterClient)
|
|
||||||
authGroupV1.POST("/login", handlers.LoginClient)
|
authGroupV1.POST("/login", handlers.LoginClient)
|
||||||
authGroupV1.POST("/logout", handlers.LogoutClient)
|
authGroupV1.POST("/logout", handlers.LogoutClient)
|
||||||
}
|
}
|
||||||
@@ -154,6 +153,7 @@ func SetupRoutes(router *gin.Engine, database *db.Database, geoService *services
|
|||||||
// ⭐⭐ MODIFICATION DE PROFILS PAR ADMIN
|
// ⭐⭐ MODIFICATION DE PROFILS PAR ADMIN
|
||||||
adminGroupV2.PUT("/clients/:id", handlers.UpdateClientByAdmin) // ✅ Modifier un client
|
adminGroupV2.PUT("/clients/:id", handlers.UpdateClientByAdmin) // ✅ Modifier un client
|
||||||
adminGroupV2.PUT("/users/:id", handlers.UpdateUserByAdmin) // ✅ Modifier un user
|
adminGroupV2.PUT("/users/:id", handlers.UpdateUserByAdmin) // ✅ Modifier un user
|
||||||
|
adminGroupV2.POST("/clients", handlers.AdminCreateClient)
|
||||||
adminGroupV2.DELETE("/clients/:id", handlers.DeleteClient)
|
adminGroupV2.DELETE("/clients/:id", handlers.DeleteClient)
|
||||||
adminGroupV2.DELETE("/users/:id", handlers.DeleteUser)
|
adminGroupV2.DELETE("/users/:id", handlers.DeleteUser)
|
||||||
adminGroupV2.POST("/users", handlers.CreateUser)
|
adminGroupV2.POST("/users", handlers.CreateUser)
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
const { getDefaultConfig } = require('expo/metro-config');
|
||||||
|
|
||||||
|
const IS_PROD = process.env.NODE_ENV === 'production';
|
||||||
|
|
||||||
|
const config = getDefaultConfig(__dirname);
|
||||||
|
|
||||||
|
if (IS_PROD) {
|
||||||
|
config.transformer = {
|
||||||
|
...config.transformer,
|
||||||
|
babelTransformerPath: require.resolve('react-native-obfuscating-transformer'),
|
||||||
|
obfuscatorOptions: {
|
||||||
|
compact: true,
|
||||||
|
identifierNamesGenerator: 'hexadecimal',
|
||||||
|
renameGlobals: false,
|
||||||
|
rotateStringArray: true,
|
||||||
|
stringArray: true,
|
||||||
|
stringArrayEncoding: ['base64'],
|
||||||
|
stringArrayThreshold: 0.75,
|
||||||
|
// Disabled: incompatible with Hermes
|
||||||
|
selfDefending: false,
|
||||||
|
controlFlowFlattening: false,
|
||||||
|
deadCodeInjection: false,
|
||||||
|
transformObjectKeys: false,
|
||||||
|
debugProtection: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = config;
|
||||||
+1639
File diff suppressed because it is too large
Load Diff
Generated
+1641
File diff suppressed because it is too large
Load Diff
@@ -40,6 +40,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@expo/ngrok": "^4.1.3",
|
"@expo/ngrok": "^4.1.3",
|
||||||
"@types/react": "~19.1.0",
|
"@types/react": "~19.1.0",
|
||||||
|
"javascript-obfuscator": "^4.1.1",
|
||||||
|
"react-native-obfuscating-transformer": "^1.0.0",
|
||||||
"typescript": "~5.9.2"
|
"typescript": "~5.9.2"
|
||||||
},
|
},
|
||||||
"private": true
|
"private": true
|
||||||
|
|||||||
@@ -427,13 +427,13 @@ export const createClientByAdmin = async (data: {
|
|||||||
telephone: string;
|
telephone: string;
|
||||||
}) => {
|
}) => {
|
||||||
const { data: res } = await apiClient.post(
|
const { data: res } = await apiClient.post(
|
||||||
`https://uber-stup.club/api/v1/auth/register`,
|
`${V2}/admin/protected/clients`,
|
||||||
data,
|
data,
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: res.message || "Client créé",
|
message: res.message || "Client créé",
|
||||||
user: res.user,
|
client: res.client,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
const { getDefaultConfig } = require('expo/metro-config');
|
||||||
|
|
||||||
|
const IS_PROD = process.env.NODE_ENV === 'production';
|
||||||
|
|
||||||
|
const config = getDefaultConfig(__dirname);
|
||||||
|
|
||||||
|
if (IS_PROD) {
|
||||||
|
config.transformer = {
|
||||||
|
...config.transformer,
|
||||||
|
babelTransformerPath: require.resolve('react-native-obfuscating-transformer'),
|
||||||
|
obfuscatorOptions: {
|
||||||
|
compact: true,
|
||||||
|
identifierNamesGenerator: 'hexadecimal',
|
||||||
|
renameGlobals: false,
|
||||||
|
rotateStringArray: true,
|
||||||
|
stringArray: true,
|
||||||
|
stringArrayEncoding: ['base64'],
|
||||||
|
stringArrayThreshold: 0.75,
|
||||||
|
// Disabled: incompatible with Hermes
|
||||||
|
selfDefending: false,
|
||||||
|
controlFlowFlattening: false,
|
||||||
|
deadCodeInjection: false,
|
||||||
|
transformObjectKeys: false,
|
||||||
|
debugProtection: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = config;
|
||||||
Generated
+1630
File diff suppressed because it is too large
Load Diff
@@ -42,6 +42,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@expo/ngrok": "^4.1.3",
|
"@expo/ngrok": "^4.1.3",
|
||||||
"@types/react": "~19.1.0",
|
"@types/react": "~19.1.0",
|
||||||
|
"javascript-obfuscator": "^4.1.1",
|
||||||
|
"react-native-obfuscating-transformer": "^1.0.0",
|
||||||
"typescript": "~5.9.2"
|
"typescript": "~5.9.2"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -545,16 +545,16 @@ export default function CheckoutScreen() {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{confirmationData?.assigned_to && (
|
<View style={styles.confirmInfo}>
|
||||||
<View style={styles.confirmInfo}>
|
<Ionicons
|
||||||
<Ionicons
|
name="location-outline"
|
||||||
name="bicycle-outline"
|
size={16}
|
||||||
size={16}
|
color={colors.info}
|
||||||
color={colors.info}
|
/>
|
||||||
/>
|
<Text style={styles.confirmInfoText}>
|
||||||
<Text style={styles.confirmInfoText}>Livreur</Text>
|
Suivez votre livraison en temps réel depuis la page Suivi
|
||||||
</View>
|
</Text>
|
||||||
)}
|
</View>
|
||||||
<Button
|
<Button
|
||||||
title="Voir mes commandes"
|
title="Voir mes commandes"
|
||||||
onPress={handleConfirmClose}
|
onPress={handleConfirmClose}
|
||||||
|
|||||||
Reference in New Issue
Block a user