package handlers import ( "gestion/db" "log" "net/http" "strconv" "github.com/gin-gonic/gin" ) // GetCommandStatus - Statut temps réel d'une commande func GetCommandStatus(c *gin.Context) { database := c.MustGet("database").(*db.Database) username, exists := c.Get("username") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentification requise"}) return } usernameStr := username.(string) commandID, err := strconv.Atoi(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "ID invalide"}) return } command, err := database.GetCommandByID(commandID) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Commande non trouvée"}) return } cmdUsername, _ := command["username"].(string) if cmdUsername != usernameStr { log.Printf("❌ [STATUS] Accès refusé - cmd de %s demandée par %s", cmdUsername, usernameStr) c.JSON(http.StatusForbidden, gin.H{ "error": "Cette commande ne vous appartient pas", }) return } etaData, _ := database.GetCommandETA(commandID) livreurInfo := gin.H{ "assigned": false, } if livreurAssign, ok := command["livreur_assign"].(string); ok && livreurAssign != "" { queueInfo, _ := database.GetDeliverymanQueueInfo(livreurAssign) livreurInfo = gin.H{ "assigned": true, "livreur_name": livreurAssign, "queue_position": queueInfo["queue_size"], } } statusMessage := getStatusMessage(command["status"].(string)) c.JSON(http.StatusOK, gin.H{ "success": true, "command_id": commandID, "status": command["status"], "status_message": statusMessage, "adresse": command["adresse"], "total_prix": command["total_prix"], "created_at": command["created_at"], "livreur": livreurInfo, "eta": etaData, }) } // GetMyCommandsWithTracking - Liste des commandes avec suivi func GetMyCommandsWithTracking(c *gin.Context) { database := c.MustGet("database").(*db.Database) username, exists := c.Get("username") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentification requise"}) return } usernameStr := username.(string) status := c.Query("status") log.Printf("📋 [MY_CMDS] Client %s demande ses commandes (status=%s)", usernameStr, status) commands, err := database.GetAllCommands(status, usernameStr) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Erreur récupération", "details": err.Error(), }) return } // Enrichir avec tracking enrichedCommands := make([]gin.H, len(commands)) for i, cmd := range commands { commandID, _ := cmd["id"].(int) // ETA etaData, _ := database.GetCommandETA(commandID) // Infos livreur livreurInfo := gin.H{ "assigned": false, } if livreurAssign, ok := cmd["livreur_assign"].(string); ok && livreurAssign != "" { queueInfo, _ := database.GetDeliverymanQueueInfo(livreurAssign) livreurInfo = gin.H{ "assigned": true, "livreur_name": livreurAssign, "queue_position": queueInfo["queue_size"], } } enrichedCommands[i] = gin.H{ "id": cmd["id"], "status": cmd["status"], "status_message": getStatusMessage(cmd["status"].(string)), "adresse": cmd["adresse"], "total_prix": cmd["total_prix"], "created_at": cmd["created_at"], "livreur": livreurInfo, "eta": etaData, "proposed_address": cmd["proposed_address"], "address_proposal_status": cmd["address_proposal_status"], } } c.JSON(http.StatusOK, gin.H{ "success": true, "commands": enrichedCommands, "count": len(enrichedCommands), }) } // GetCommandTracking - Suivi détaillé d'une commande func GetCommandTracking(c *gin.Context) { database := c.MustGet("database").(*db.Database) username := c.GetString("username") commandID, err := strconv.Atoi(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "ID invalide"}) return } // Récupérer commande command, err := database.GetCommandByID(commandID) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Commande non trouvée"}) return } // Vérifier propriété cmdUsername, _ := command["username"].(string) if cmdUsername != username { c.JSON(http.StatusForbidden, gin.H{ "error": "Cette commande ne vous appartient pas", }) return } logs, _ := database.GetCommandLogs(commandID) etaData, _ := database.GetCommandETA(commandID) timeline := buildTimeline(logs) c.JSON(http.StatusOK, gin.H{ "success": true, "command_id": commandID, "status": command["status"], "status_message": getStatusMessage(command["status"].(string)), "eta": etaData, "timeline": timeline, "logs": logs, }) } func getStatusMessage(status string) string { messages := map[string]string{ "pending": "⏳ En attente d'assignation", "assigned": "✅ Livreur assigné", "en_route": "🚗 En cours de livraison", "arrived": "📍 Livreur arrivé", "livre": "📦 Livré - En attente de confirmation", "delivered": "✅ Livré", "approved": "🎉 Livraison confirmée", "cancelled": "🚫 Annulée", "disabled": "⚠️ Désactivée", } if msg, ok := messages[status]; ok { return msg } return "📋 " + status } // buildTimeline construit une timeline depuis les logs func buildTimeline(logs []map[string]any) []gin.H { timeline := make([]gin.H, 0) for _, logEntry := range logs { status, _ := logEntry["status"].(string) message, _ := logEntry["message"].(string) createdAt, _ := logEntry["created_at"] timeline = append(timeline, gin.H{ "status": status, "message": message, "icon": getStatusIcon(status), "created_at": createdAt, }) } return timeline } // getStatusIcon retourne une icône pour la timeline func getStatusIcon(status string) string { icons := map[string]string{ "created": "🛒", "assigned": "👤", "en_route": "🚗", "arrived": "📍", "livre": "✅", "approved": "🎉", "cancelled": "🚫", } if icon, ok := icons[status]; ok { return icon } return "📋" }