'use client'; import { useState } from 'react'; import { Button } from '@/components/ui/Button'; import { Card, CardHeader, CardContent } from '@/components/ui/Card'; import { Badge } from '@/components/ui/Badge'; import { Modal } from '@/components/ui/Modal'; import { jiraClient } from '@/clients/jira-client'; import { JiraSyncResult, JiraSyncAction } from '@/services/jira'; interface JiraSyncProps { onSyncComplete?: () => void; className?: string; } export function JiraSync({ onSyncComplete, className = "" }: JiraSyncProps) { const [isConnected, setIsConnected] = useState(null); const [isLoading, setIsLoading] = useState(false); const [isSyncing, setIsSyncing] = useState(false); const [lastSyncResult, setLastSyncResult] = useState(null); const [error, setError] = useState(null); const [showDetails, setShowDetails] = useState(false); const testConnection = async () => { setIsLoading(true); setError(null); try { const status = await jiraClient.testConnection(); setIsConnected(status.connected); if (!status.connected) { setError(status.message); } } catch (err) { setIsConnected(false); setError(err instanceof Error ? err.message : 'Erreur de connexion'); } finally { setIsLoading(false); } }; const startSync = async () => { setIsSyncing(true); setError(null); try { const result = await jiraClient.syncTasks(); setLastSyncResult(result); if (result.success) { onSyncComplete?.(); } } catch (err) { setError(err instanceof Error ? err.message : 'Erreur de synchronisation'); } finally { setIsSyncing(false); } }; const getConnectionStatus = () => { if (isConnected === null) return null; return isConnected ? ( ✓ Connecté ) : ( ✗ Déconnecté ); }; const getSyncStatus = () => { if (!lastSyncResult) return null; const { success, tasksFound, tasksCreated, tasksUpdated, tasksSkipped, tasksDeleted = 0, errors, actions = [] } = lastSyncResult; return (
{success ? "✓ Succès" : "⚠ Erreurs"} {new Date().toLocaleTimeString()}
{tasksFound} trouvé{tasksFound > 1 ? 's' : ''} dans Jira
{tasksCreated}
Créées
{tasksUpdated}
Mises à jour
{tasksSkipped}
Ignorées
{tasksDeleted}
Supprimées
{/* Résumé textuel avec bouton détails */}
Résumé:
{actions.length > 0 && ( )}
{tasksCreated > 0 && `${tasksCreated} nouvelle${tasksCreated > 1 ? 's' : ''} • `} {tasksUpdated > 0 && `${tasksUpdated} mise${tasksUpdated > 1 ? 's' : ''} à jour • `} {tasksDeleted > 0 && `${tasksDeleted} supprimée${tasksDeleted > 1 ? 's' : ''} (réassignées) • `} {tasksSkipped > 0 && `${tasksSkipped} ignorée${tasksSkipped > 1 ? 's' : ''} • `} {(tasksCreated + tasksUpdated + tasksDeleted + tasksSkipped) === 0 && 'Aucune modification'}
{errors.length > 0 && (
Erreurs ({errors.length}):
{errors.map((err, i) => (
{err}
))}
)}
); }; return (

JIRA SYNC

{getConnectionStatus()}
{/* Test de connexion */}
{/* Messages d'erreur */} {error && (
{error}
)} {/* Résultats de sync */} {getSyncStatus()} {/* Info */}
• Synchronisation unidirectionnelle (Jira → TowerControl)
• Les modifications locales sont préservées
• Seuls les tickets assignés sont synchronisés
• Les tickets réassignés sont automatiquement supprimés
{/* Modal détails de synchronisation */} {lastSyncResult && ( setShowDetails(false)} title="📋 DÉTAILS DE SYNCHRONISATION" size="xl" >

{(lastSyncResult.actions || []).length} action{(lastSyncResult.actions || []).length > 1 ? 's' : ''} effectuée{(lastSyncResult.actions || []).length > 1 ? 's' : ''}

{(lastSyncResult.actions || []).length > 0 ? ( ) : (
📝
Aucun détail disponible pour cette synchronisation
Les détails sont disponibles pour les nouvelles synchronisations
)}
)}
); } // Composant pour afficher la liste des actions function SyncActionsList({ actions }: { actions: JiraSyncAction[] }) { const getActionIcon = (type: JiraSyncAction['type']) => { switch (type) { case 'created': return '➕'; case 'updated': return '🔄'; case 'skipped': return '⏭️'; case 'deleted': return '🗑️'; default: return '❓'; } }; const getActionColor = (type: JiraSyncAction['type']) => { switch (type) { case 'created': return 'text-emerald-400'; case 'updated': return 'text-blue-400'; case 'skipped': return 'text-orange-400'; case 'deleted': return 'text-red-400'; default: return 'text-gray-400'; } }; const getActionLabel = (type: JiraSyncAction['type']) => { switch (type) { case 'created': return 'Créée'; case 'updated': return 'Mise à jour'; case 'skipped': return 'Ignorée'; case 'deleted': return 'Supprimée'; default: return 'Inconnue'; } }; // Grouper les actions par type const groupedActions = actions.reduce((acc, action) => { if (!acc[action.type]) acc[action.type] = []; acc[action.type].push(action); return acc; }, {} as Record); return (
{Object.entries(groupedActions).map(([type, typeActions]) => (

{getActionIcon(type as JiraSyncAction['type'])} {getActionLabel(type as JiraSyncAction['type'])} ({typeActions.length})

{typeActions.map((action, index) => (
{action.taskKey} {action.taskTitle}
{getActionLabel(action.type)}
{action.reason && (
💡 {action.reason}
)} {action.changes && action.changes.length > 0 && (
Modifications:
{action.changes.map((change, changeIndex) => (
{change}
))}
)}
))}
))}
); }