feat: aligner le dashboard production sur recette

This commit is contained in:
Santinova Deploy
2026-09-05 02:23:30 +00:00
parent 79240dd914
commit e352c46fd2
101 changed files with 11870 additions and 196 deletions

View File

@@ -0,0 +1,108 @@
import React, { useState, useEffect } from 'react';
import { Box, RefreshCw, Plus } from 'lucide-react';
import AppCard from '../components/AppCard';
import AddAppModal from '../components/AddAppModal';
import { getApps, getGiteaCommits } from '../utils/api';
export default function AppsPage({ apps, onRefresh }) {
const [commitsMap, setCommitsMap] = useState({});
const [showAddModal, setShowAddModal] = useState(false);
useEffect(() => {
// Charger les commits pour chaque app
apps.forEach((app) => {
const owner = app.giteaOwner || 'manus-admin';
const repo = app.giteaRepo || app.id;
getGiteaCommits(owner, repo)
.then((res) => {
setCommitsMap((prev) => ({
...prev,
[app.id]: res.data,
}));
})
.catch(() => {
// Ignorer les erreurs Gitea pour les apps sans dépôt
});
});
}, [apps]);
const handleAddSuccess = () => {
setShowAddModal(false);
// Rafraîchir la liste après un délai pour laisser le temps au health check
setTimeout(() => {
if (onRefresh) onRefresh();
}, 5000);
// Rafraîchir encore après 15s
setTimeout(() => {
if (onRefresh) onRefresh();
}, 15000);
};
return (
<div className="space-y-6">
{/* Header */}
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-bold text-white flex items-center gap-3">
<Box className="w-7 h-7 text-primary-400" />
Applications
</h2>
<p className="text-gray-400 mt-1">
Gérez et surveillez vos applications déployées
</p>
</div>
<div className="flex items-center gap-3">
<button onClick={onRefresh} className="btn-secondary flex items-center gap-2">
<RefreshCw className="w-4 h-4" />
Rafraîchir
</button>
<button
onClick={() => setShowAddModal(true)}
className="btn-primary flex items-center gap-2"
>
<Plus className="w-4 h-4" />
Ajouter une application
</button>
</div>
</div>
{/* Apps List */}
{apps.length === 0 ? (
<div className="card p-12 text-center">
<Box className="w-12 h-12 text-gray-600 mx-auto mb-4" />
<h3 className="text-lg font-medium text-gray-400">
Aucune application
</h3>
<p className="text-gray-600 mt-2">
Les applications déployées apparaîtront ici
</p>
<button
onClick={() => setShowAddModal(true)}
className="btn-primary mt-4 inline-flex items-center gap-2"
>
<Plus className="w-4 h-4" />
Ajouter votre première application
</button>
</div>
) : (
<div className="space-y-4">
{apps.map((app) => (
<AppCard
key={app.id}
app={app}
commits={commitsMap[app.id] || []}
onRefresh={onRefresh}
/>
))}
</div>
)}
{/* Add App Modal */}
<AddAppModal
isOpen={showAddModal}
onClose={() => setShowAddModal(false)}
onSuccess={handleAddSuccess}
/>
</div>
);
}