chore: fix
This commit is contained in:
@@ -130,7 +130,6 @@ func (d *Database) GetAllClients() ([]*models.Client, error) {
|
|||||||
func (d *Database) UpdateClient(client *models.Client) error {
|
func (d *Database) UpdateClient(client *models.Client) error {
|
||||||
result := d.GDB.Model(&models.Client{}).Where("id = ?", client.ID).Updates(map[string]any{
|
result := d.GDB.Model(&models.Client{}).Where("id = ?", client.ID).Updates(map[string]any{
|
||||||
"username": client.Username,
|
"username": client.Username,
|
||||||
"password": client.Password,
|
|
||||||
"nom": client.Nom,
|
"nom": client.Nom,
|
||||||
"prenom": client.Prenom,
|
"prenom": client.Prenom,
|
||||||
"telephone": client.Telephone,
|
"telephone": client.Telephone,
|
||||||
|
|||||||
@@ -1047,7 +1047,8 @@ func DeleteCommandItem(c *gin.Context) {
|
|||||||
func UpdateCommandStatusAdmin(c *gin.Context) {
|
func UpdateCommandStatusAdmin(c *gin.Context) {
|
||||||
database := c.MustGet("database").(*db.Database)
|
database := c.MustGet("database").(*db.Database)
|
||||||
|
|
||||||
if c.GetString("role") != "admin" {
|
role := c.GetString("role")
|
||||||
|
if role != "admin" && role != "cabine" {
|
||||||
c.JSON(http.StatusForbidden, gin.H{"error": "Accès refusé"})
|
c.JSON(http.StatusForbidden, gin.H{"error": "Accès refusé"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1068,7 +1069,7 @@ func UpdateCommandStatusAdmin(c *gin.Context) {
|
|||||||
|
|
||||||
allowed := map[string]bool{
|
allowed := map[string]bool{
|
||||||
"pending": true, "assigned": true, "en_route": true,
|
"pending": true, "assigned": true, "en_route": true,
|
||||||
"livre": true, "approved": true, "cancelled": true,
|
"arrived": true, "livre": true, "approved": true, "cancelled": true,
|
||||||
}
|
}
|
||||||
if !allowed[req.Status] {
|
if !allowed[req.Status] {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Statut invalide: " + req.Status})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Statut invalide: " + req.Status})
|
||||||
@@ -1080,7 +1081,7 @@ func UpdateCommandStatusAdmin(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("✅ [STATUS_ADMIN] Cmd %d → %s", commandID, req.Status)
|
log.Printf("✅ [STATUS_ADMIN] Cmd %d → %s (par %s)", commandID, req.Status, role)
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": "Statut mis à jour",
|
"message": "Statut mis à jour",
|
||||||
|
|||||||
@@ -345,18 +345,28 @@ func UpdateDeliveryStatus(c *gin.Context) {
|
|||||||
var clientMsg string
|
var clientMsg string
|
||||||
switch req.Status {
|
switch req.Status {
|
||||||
case "en_route":
|
case "en_route":
|
||||||
if etaMinutes > 0 {
|
notifETA := etaMinutes
|
||||||
|
if notifETA == 0 {
|
||||||
|
if etaData, err := database.GetCommandETA(commandID); err == nil {
|
||||||
|
if v, ok := etaData["total_eta_minutes"]; ok {
|
||||||
|
if n, err2 := strconv.Atoi(v); err2 == nil && n > 0 {
|
||||||
|
notifETA = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if notifETA > 0 {
|
||||||
var etaStr string
|
var etaStr string
|
||||||
if etaMinutes >= 60 {
|
if notifETA >= 60 {
|
||||||
h := etaMinutes / 60
|
h := notifETA / 60
|
||||||
m := etaMinutes % 60
|
m := notifETA % 60
|
||||||
if m > 0 {
|
if m > 0 {
|
||||||
etaStr = fmt.Sprintf("%dh%02d", h, m)
|
etaStr = fmt.Sprintf("%dh%02d", h, m)
|
||||||
} else {
|
} else {
|
||||||
etaStr = fmt.Sprintf("%dh", h)
|
etaStr = fmt.Sprintf("%dh", h)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
etaStr = fmt.Sprintf("%d min", etaMinutes)
|
etaStr = fmt.Sprintf("%d min", notifETA)
|
||||||
}
|
}
|
||||||
clientMsg = fmt.Sprintf("Un livreur vient de prendre en charge ta commande #%d, il est en route (~%s)", database.GetClientOrderID(commandID), etaStr)
|
clientMsg = fmt.Sprintf("Un livreur vient de prendre en charge ta commande #%d, il est en route (~%s)", database.GetClientOrderID(commandID), etaStr)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -236,7 +236,8 @@ func UpdateClientByAdmin(c *gin.Context) {
|
|||||||
log.Printf("✏️ [UPDATE_CLIENT_ADMIN] Username modifié: %s", req.Username)
|
log.Printf("✏️ [UPDATE_CLIENT_ADMIN] Username modifié: %s", req.Username)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mise à jour du mot de passe
|
// Mise à jour du mot de passe (opération séparée pour garantir l'écriture)
|
||||||
|
var newHashedPassword string
|
||||||
if req.Password != "" {
|
if req.Password != "" {
|
||||||
if len(req.Password) < 8 {
|
if len(req.Password) < 8 {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Le mot de passe doit contenir au moins 8 caractères"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Le mot de passe doit contenir au moins 8 caractères"})
|
||||||
@@ -248,7 +249,7 @@ func UpdateClientByAdmin(c *gin.Context) {
|
|||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur traitement mot de passe"})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur traitement mot de passe"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
client.Password = string(hashed)
|
newHashedPassword = string(hashed)
|
||||||
hasChanges = true
|
hasChanges = true
|
||||||
log.Printf("✏️ [UPDATE_CLIENT_ADMIN] Mot de passe modifié")
|
log.Printf("✏️ [UPDATE_CLIENT_ADMIN] Mot de passe modifié")
|
||||||
}
|
}
|
||||||
@@ -323,13 +324,23 @@ func UpdateClientByAdmin(c *gin.Context) {
|
|||||||
log.Printf("📊 [UPDATE_CLIENT_ADMIN] État avant save - Command: %d, Amende: %.2f",
|
log.Printf("📊 [UPDATE_CLIENT_ADMIN] État avant save - Command: %d, Amende: %.2f",
|
||||||
client.Command, client.Amende)
|
client.Command, client.Amende)
|
||||||
|
|
||||||
// Sauvegarder les modifications
|
// Sauvegarder les modifications de profil (hors mot de passe)
|
||||||
if err := database.UpdateClient(client); err != nil {
|
if err := database.UpdateClient(client); err != nil {
|
||||||
log.Printf("❌ [UPDATE_CLIENT_ADMIN] Erreur mise à jour: %v", err)
|
log.Printf("❌ [UPDATE_CLIENT_ADMIN] Erreur mise à jour profil: %v", err)
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur lors de la mise à jour"})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur lors de la mise à jour"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mettre à jour le mot de passe séparément si demandé
|
||||||
|
if newHashedPassword != "" {
|
||||||
|
if err := database.UpdateClientPasswordAndClearFlag(clientID, newHashedPassword); err != nil {
|
||||||
|
log.Printf("❌ [UPDATE_CLIENT_ADMIN] Erreur mise à jour mot de passe: %v", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur lors de la mise à jour du mot de passe"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Printf("✅ [UPDATE_CLIENT_ADMIN] Mot de passe mis à jour pour client ID=%d", clientID)
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("✅ [UPDATE_CLIENT_ADMIN] Client mis à jour par admin: %s (ID=%d)", client.Username, client.ID)
|
log.Printf("✅ [UPDATE_CLIENT_ADMIN] Client mis à jour par admin: %s (ID=%d)", client.Username, client.ID)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
|||||||
@@ -352,7 +352,14 @@ func StartDelivery(c *gin.Context) {
|
|||||||
if clientUsername, _ := command["username"].(string); clientUsername != "" {
|
if clientUsername, _ := command["username"].(string); clientUsername != "" {
|
||||||
var msg string
|
var msg string
|
||||||
etaMinutes := 0
|
etaMinutes := 0
|
||||||
if req.Latitude != 0 && req.Longitude != 0 {
|
if etaData, err := database.GetCommandETA(commandID); err == nil {
|
||||||
|
if v, ok := etaData["total_eta_minutes"]; ok {
|
||||||
|
if n, err2 := strconv.Atoi(v); err2 == nil && n > 0 {
|
||||||
|
etaMinutes = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if etaMinutes == 0 && req.Latitude != 0 && req.Longitude != 0 {
|
||||||
destLat, _ := command["dest_latitude"].(float64)
|
destLat, _ := command["dest_latitude"].(float64)
|
||||||
destLon, _ := command["dest_longitude"].(float64)
|
destLon, _ := command["dest_longitude"].(float64)
|
||||||
if destLat != 0 && destLon != 0 {
|
if destLat != 0 && destLon != 0 {
|
||||||
|
|||||||
@@ -302,6 +302,7 @@ func SetupRoutes(router *gin.Engine, database *db.Database, geoService *services
|
|||||||
cabineGroupV1.POST("/commands/:id/confirm-reception", handlers.StaffApproveDelivery)
|
cabineGroupV1.POST("/commands/:id/confirm-reception", handlers.StaffApproveDelivery)
|
||||||
cabineGroupV1.POST("/commands/:id/assign", handlers.AssignDeliveryPerson)
|
cabineGroupV1.POST("/commands/:id/assign", handlers.AssignDeliveryPerson)
|
||||||
cabineGroupV1.POST("/commands/:id/notify-client", handlers.NotifyClientToDescend)
|
cabineGroupV1.POST("/commands/:id/notify-client", handlers.NotifyClientToDescend)
|
||||||
|
cabineGroupV1.PUT("/commands/:id/status", handlers.UpdateCommandStatusAdmin)
|
||||||
cabineGroupV1.PUT("/items/:item_id/status", handlers.UpdateItemStatus)
|
cabineGroupV1.PUT("/items/:item_id/status", handlers.UpdateItemStatus)
|
||||||
cabineGroupV1.GET("/commands/:id/deliveryman/location", handlers.GetDeliverymanLocationForCommand)
|
cabineGroupV1.GET("/commands/:id/deliveryman/location", handlers.GetDeliverymanLocationForCommand)
|
||||||
cabineGroupV1.GET("/all/deliveryman", handlers.GetAllDeliveryMen)
|
cabineGroupV1.GET("/all/deliveryman", handlers.GetAllDeliveryMen)
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// Surchargé par le ConfigMap Helm en production
|
||||||
|
window.__APP_CONFIG__ = {
|
||||||
|
apiUrl: "",
|
||||||
|
};
|
||||||
@@ -7,10 +7,6 @@ html, body, #root {
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ne pas forcer de backgroundColor global pour permettre à login d'avoir son propre style */
|
|
||||||
body, html {
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#root {
|
#root {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -2010,7 +2010,10 @@ export const updateMyProfile = async (fields: {
|
|||||||
// 🤖 TELEGRAM
|
// 🤖 TELEGRAM
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
export const getTelegramStatus = async (): Promise<{ linked: boolean; enabled: boolean }> => {
|
export const getTelegramStatus = async (): Promise<{
|
||||||
|
linked: boolean;
|
||||||
|
enabled: boolean;
|
||||||
|
}> => {
|
||||||
const token = getAuthToken();
|
const token = getAuthToken();
|
||||||
if (!token) return { linked: false, enabled: false };
|
if (!token) return { linked: false, enabled: false };
|
||||||
try {
|
try {
|
||||||
@@ -2048,5 +2051,7 @@ export const unlinkTelegram = async (): Promise<void> => {
|
|||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers: { Authorization: `Bearer ${token}` },
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
});
|
});
|
||||||
} catch { /* silencieux */ }
|
} catch {
|
||||||
|
/* silencieux */
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,12 +16,38 @@
|
|||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
/* Empêcher le zoom sur les inputs pour iOS */
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|
||||||
|
--bg: #09090b;
|
||||||
|
--surface: #111115;
|
||||||
|
--surface-2: #1c1c22;
|
||||||
|
--border: rgba(255, 255, 255, 0.07);
|
||||||
|
--primary: #8b5cf6;
|
||||||
|
--primary-soft: rgba(139, 92, 246, 0.12);
|
||||||
|
--primary-glow: rgba(139, 92, 246, 0.25);
|
||||||
|
--cyan: #22d3ee;
|
||||||
|
--cyan-soft: rgba(34, 211, 238, 0.1);
|
||||||
|
--red: #ef4444;
|
||||||
|
--text: #f4f4f5;
|
||||||
|
--text-muted: #71717a;
|
||||||
|
--radius: 10px;
|
||||||
|
--transition: 0.22s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="light"] {
|
[data-theme="light"] {
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
|
--bg: #f4f4f8;
|
||||||
|
--surface: #ffffff;
|
||||||
|
--surface-2: #ebebf2;
|
||||||
|
--border: rgba(0, 0, 0, 0.08);
|
||||||
|
--primary: #7c3aed;
|
||||||
|
--primary-soft: rgba(124, 58, 237, 0.08);
|
||||||
|
--primary-glow: rgba(124, 58, 237, 0.18);
|
||||||
|
--cyan: #0891b2;
|
||||||
|
--cyan-soft: rgba(8, 145, 178, 0.1);
|
||||||
|
--red: #dc2626;
|
||||||
|
--text: #18181b;
|
||||||
|
--text-muted: #52525b;
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
|
|||||||
@@ -122,10 +122,11 @@ function Checkout() {
|
|||||||
if (savedAddress) setAddress(savedAddress);
|
if (savedAddress) setAddress(savedAddress);
|
||||||
if (savedPhone) setPhone(savedPhone);
|
if (savedPhone) setPhone(savedPhone);
|
||||||
|
|
||||||
// Pré-remplir nom depuis le backend
|
// Pré-remplir nom/prénom depuis le backend
|
||||||
getMyProfile().then((res) => {
|
getMyProfile().then((res) => {
|
||||||
if (res.success && res.client) {
|
if (res.success && res.client) {
|
||||||
if (res.client.nom) setLastName(res.client.nom);
|
if (res.client.nom) setLastName(res.client.nom);
|
||||||
|
if (res.client.prenom) setFirstName(res.client.prenom);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import react from "@vitejs/plugin-react";
|
import react from "@vitejs/plugin-react";
|
||||||
|
|
||||||
|
const DEV_API_TARGET = "http://localhost:8080";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
build: {
|
build: {
|
||||||
@@ -9,11 +11,11 @@ export default defineConfig({
|
|||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
"/api": {
|
"/api": {
|
||||||
target: "https://5.181.0.112.nip.io",
|
target: DEV_API_TARGET,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
"/uploads": {
|
"/uploads": {
|
||||||
target: "https://5.181.0.112.nip.io",
|
target: DEV_API_TARGET,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user