change and add into components, widgets and pages
This commit is contained in:
+20
-143
@@ -1,153 +1,30 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { pb } from '@services/pocketbase';
|
||||
import NewTicket from './NewTicket';
|
||||
import TicketDetail from './TicketDetail';
|
||||
|
||||
interface Ticket {
|
||||
id: string;
|
||||
subject: string;
|
||||
category: string;
|
||||
status: 'Ouvert' | 'En analyse' | 'Résolu';
|
||||
created: string;
|
||||
}
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { PageHeader } from '@/components/ui/PageHeader';
|
||||
import { TicketsWidget } from '@/components/widgets/TicketsWidget';
|
||||
|
||||
export default function ServiceDesk() {
|
||||
const [tickets, setTickets] = useState<Ticket[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
// États de navigation interne au module Service Desk
|
||||
const [currentView, setCurrentView] = useState<'list' | 'new' | 'detail'>('list');
|
||||
const [selectedTicketId, setSelectedTicketId] = useState<string | null>(null);
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Récupération des tickets de l'entreprise connectée
|
||||
const fetchTickets = async () => {
|
||||
try {
|
||||
const records = await pb.collection('aegis_tickets').getFullList<Ticket>({
|
||||
sort: '-created', // Du plus récent au plus ancien
|
||||
});
|
||||
setTickets(records);
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la récupération des tickets :", error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchTickets();
|
||||
}, []);
|
||||
|
||||
// Gestion du clic sur un ticket pour ouvrir la discussion
|
||||
const handleSelectTicket = (id: string) => {
|
||||
setSelectedTicketId(id);
|
||||
setCurrentView('detail');
|
||||
};
|
||||
|
||||
// Styles visuels pour les statuts
|
||||
const getStatusStyle = (status: Ticket['status']) => {
|
||||
switch (status) {
|
||||
case 'Ouvert': return 'bg-blue-50 text-blue-700 border-blue-100';
|
||||
case 'En analyse': return 'bg-amber-50 text-amber-700 border-amber-100';
|
||||
case 'Résolu': return 'bg-emerald-50 text-emerald-700 border-emerald-100';
|
||||
default: return 'bg-slate-50 text-slate-700 border-slate-100';
|
||||
}
|
||||
};
|
||||
|
||||
// Rendu conditionnel selon la vue active
|
||||
if (currentView === 'new') {
|
||||
return (
|
||||
<NewTicket
|
||||
onCancel={() => setCurrentView('list')}
|
||||
onTicketCreated={() => {
|
||||
setCurrentView('list');
|
||||
fetchTickets(); // On recharge la liste pour afficher le nouveau ticket
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (currentView === 'detail' && selectedTicketId) {
|
||||
return (
|
||||
<TicketDetail
|
||||
ticketId={selectedTicketId}
|
||||
onBack={() => {
|
||||
setCurrentView('list');
|
||||
setSelectedTicketId(null);
|
||||
fetchTickets();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Vue par défaut : La liste des tickets
|
||||
return (
|
||||
<div className="min-h-screen bg-slate-50 font-sans text-slate-900 relative">
|
||||
|
||||
{/* Header */}
|
||||
<header className="bg-white border-b border-slate-200 px-8 py-6">
|
||||
<div className="max-w-7xl mx-auto flex justify-between items-center">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-slate-900 tracking-tight">Centre de Support (Service Desk)</h1>
|
||||
<p className="text-sm text-slate-500 mt-1">Canal de communication sécurisé avec vos experts GISE.</p>
|
||||
</div>
|
||||
<div className="flex items-center space-x-3">
|
||||
<button
|
||||
onClick={() => setCurrentView('new')}
|
||||
className="bg-blue-900 hover:bg-blue-800 text-white px-4 py-2.5 rounded-lg text-sm font-medium transition-colors shadow-sm"
|
||||
<div className="bg-slate-50 font-sans text-slate-900 relative min-h-[calc(100vh-4rem)]">
|
||||
<main className="max-w-7xl mx-auto px-4 sm:px-8 py-8 space-y-6">
|
||||
|
||||
{/* HEADER EXTRAIT */}
|
||||
<PageHeader
|
||||
title="Centre de Support (Service Desk)"
|
||||
description="Canal de communication sécurisé avec vos experts GISE."
|
||||
>
|
||||
Ouvrir un ticket sécurisé
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<Button onClick={() => navigate('/support/new')}>
|
||||
Ouvrir un ticket sécurisé
|
||||
</Button>
|
||||
</PageHeader>
|
||||
|
||||
<main className="max-w-7xl mx-auto px-8 py-8">
|
||||
{/* WIDGET DES TICKETS */}
|
||||
<TicketsWidget
|
||||
onSelectTicket={(ticketId) => navigate(`/support/tickets/${ticketId}`)}
|
||||
/>
|
||||
|
||||
{/* Liste des tickets */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden">
|
||||
<div className="p-6 border-b border-slate-100">
|
||||
<h2 className="text-lg font-semibold text-slate-900">Requêtes en cours et historiques</h2>
|
||||
</div>
|
||||
|
||||
{isLoading ? (
|
||||
<div className="flex justify-center items-center py-12">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-900"></div>
|
||||
</div>
|
||||
) : tickets.length === 0 ? (
|
||||
<div className="text-center py-12 text-sm text-slate-500 italic">
|
||||
Aucun ticket enregistré pour le moment.
|
||||
</div>
|
||||
) : (
|
||||
<div className="divide-y divide-slate-100">
|
||||
{tickets.map((ticket) => (
|
||||
<div
|
||||
key={ticket.id}
|
||||
onClick={() => handleSelectTicket(ticket.id)}
|
||||
className="p-6 flex items-center justify-between hover:bg-slate-50 transition-colors cursor-pointer group"
|
||||
>
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center space-x-3">
|
||||
<span className="text-xs font-semibold px-2 py-0.5 bg-slate-100 text-slate-700 rounded border border-slate-200">
|
||||
{ticket.category}
|
||||
</span>
|
||||
<span className="text-xs text-slate-400">
|
||||
Ouvert le {new Date(ticket.created).toLocaleDateString('fr-FR')}
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="text-sm font-semibold text-slate-900 group-hover:text-blue-900 transition-colors">
|
||||
{ticket.subject}
|
||||
</h3>
|
||||
</div>
|
||||
<div>
|
||||
<span className={`px-3 py-1 rounded-full text-xs font-medium border ${getStatusStyle(ticket.status)}`}>
|
||||
{ticket.status}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user