feat: TFS Sync

This commit is contained in:
Julien Froidefond
2025-09-22 21:51:12 +02:00
parent 472135a97f
commit 723a44df32
27 changed files with 3309 additions and 364 deletions

View File

@@ -0,0 +1,100 @@
'use client';
import { useState, useTransition } from 'react';
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
import { syncTfsPullRequests } from '@/actions/tfs';
export function TfsSync() {
const [isPending, startTransition] = useTransition();
const [lastSync, setLastSync] = useState<{
success: boolean;
message: string;
stats?: {
created: number;
updated: number;
skipped: number;
deleted: number;
}
} | null>(null);
const handleSync = () => {
startTransition(async () => {
setLastSync(null);
const result = await syncTfsPullRequests();
if (result.success) {
setLastSync({
success: true,
message: result.message || 'Synchronisation réussie',
stats: result.data ? {
created: result.data.pullRequestsCreated,
updated: result.data.pullRequestsUpdated,
skipped: result.data.pullRequestsSkipped,
deleted: result.data.pullRequestsDeleted
} : undefined
});
} else {
setLastSync({
success: false,
message: result.error || 'Erreur lors de la synchronisation'
});
}
});
};
return (
<Card>
<CardHeader>
<h3 className="text-lg font-semibold flex items-center gap-2">
<span className="text-blue-600">🔄</span>
Synchronisation TFS
</h3>
</CardHeader>
<CardContent className="space-y-4">
<p className="text-sm text-[var(--muted-foreground)]">
Synchronise manuellement les Pull Requests depuis Azure DevOps
</p>
{/* Résultat de la dernière synchronisation */}
{lastSync && (
<div className={`p-3 rounded-lg text-sm ${
lastSync.success
? 'bg-green-50 text-green-800 border border-green-200'
: 'bg-red-50 text-red-800 border border-red-200'
}`}>
<div className="font-medium mb-1">
{lastSync.success ? '✅' : '❌'} {lastSync.message}
</div>
{lastSync.stats && (
<div className="text-xs opacity-80">
Créées: {lastSync.stats.created} |
Mises à jour: {lastSync.stats.updated} |
Ignorées: {lastSync.stats.skipped} |
Supprimées: {lastSync.stats.deleted}
</div>
)}
</div>
)}
<button
onClick={handleSync}
disabled={isPending}
className="w-full px-4 py-2 bg-[var(--primary)] text-[var(--primary-foreground)] rounded-lg hover:bg-[var(--primary)]/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
>
{isPending && (
<svg className="animate-spin h-4 w-4" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 0 1 8-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 0 1 4 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
</svg>
)}
{isPending ? 'Synchronisation en cours...' : 'Synchroniser maintenant'}
</button>
<div className="text-xs text-[var(--muted-foreground)] text-center">
Les Pull Requests seront importées comme tâches dans le tableau Kanban
</div>
</CardContent>
</Card>
);
}