From 65ca24b6eba2feff3004977ee789fe3a8600f7d7 Mon Sep 17 00:00:00 2001 From: Nuxgrid Date: Tue, 28 Jul 2026 14:19:57 +0200 Subject: [PATCH] feat: add details demo --- web/src/lib/api.ts | 17 +++++ web/src/pages/backoffice/Demos.tsx | 107 +++++++++++++++++++++++++++-- 2 files changed, 119 insertions(+), 5 deletions(-) diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts index 8d79c62..59d5725 100644 --- a/web/src/lib/api.ts +++ b/web/src/lib/api.ts @@ -63,6 +63,7 @@ export type DemoStatus = export interface Demo { id: string + username: string lead_id?: string status: DemoStatus namespace: string @@ -87,6 +88,20 @@ export interface Contact { created_at: string } +export interface DemoState { + APIState: string + WebState: string + DBState: string + DBMemoryState: string +} + +export interface DemoDetails { + username: string + namespace: string + state: DemoState +} + + // --- Endpoints --- export const api = { @@ -130,4 +145,6 @@ export const api = { sendMessage: (username: string, telegram: string, sujet: string, message: string) => request<{ success: string }>('POST', '/send/message', { username, telegram, sujet, message }), getMessage: () => request<{ messages: Contact[] }>('GET', '/messages'), + getDemoDetails: (username: string) => + request('POST', '/demos/details', { username }), } diff --git a/web/src/pages/backoffice/Demos.tsx b/web/src/pages/backoffice/Demos.tsx index c91e622..a5bbb16 100644 --- a/web/src/pages/backoffice/Demos.tsx +++ b/web/src/pages/backoffice/Demos.tsx @@ -6,8 +6,19 @@ import { Heading, HStack, Link, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + SimpleGrid, Spacer, Spinner, + Stat, + StatLabel, + StatNumber, Table, TableContainer, Tbody, @@ -19,7 +30,7 @@ import { useToast, } from '@chakra-ui/react' import { useNavigate } from 'react-router-dom' -import { api, ApiError, type Demo } from '../../lib/api' +import { api, ApiError, type Demo, type DemoDetails } from '../../lib/api' import { statusColor, statusLabel, timeRemaining } from '../../lib/format' import { ConfirmDialog } from '../../components/ConfirmDialog' @@ -34,6 +45,11 @@ export function Demos() { const [busy, setBusy] = useState(null) const [toDelete, setToDelete] = useState(null) + // --- Détails d'une démo (modale) --- + const [detailsFor, setDetailsFor] = useState(null) + const [details, setDetails] = useState(null) + const [detailsLoading, setDetailsLoading] = useState(false) + const load = useCallback(async () => { try { const res = await api.listDemos() @@ -97,6 +113,27 @@ export function Demos() { } } + const openDetails = async (d: Demo) => { + setDetailsFor(d) + setDetails(null) + setDetailsLoading(true) + try { + const res = await api.getDemoDetails(d.username) + setDetails(res) + } catch (err) { + const msg = err instanceof ApiError ? err.message : 'Erreur' + toast({ status: 'error', title: 'Détails indisponibles', description: msg }) + setDetailsFor(null) + } finally { + setDetailsLoading(false) + } + } + + const closeDetails = () => { + setDetailsFor(null) + setDetails(null) + } + const isAlive = (s: Demo['status']) => s !== 'expired' && s !== 'failed' return ( @@ -127,14 +164,24 @@ export function Demos() { {demos.map((d) => ( - + openDetails(d)} + > {d.namespace} {statusLabel(d.status)} {d.status === 'ready' ? ( - + e.stopPropagation()} + > {d.url} ) : ( @@ -148,7 +195,10 @@ export function Demos() { size="sm" variant="outline" isDisabled={!isAlive(d.status) || busy === d.id} - onClick={() => extend(d)} + onClick={(e) => { + e.stopPropagation() + extend(d) + }} > +30 j @@ -157,7 +207,10 @@ export function Demos() { colorScheme="red" variant="outline" isDisabled={!isAlive(d.status)} - onClick={() => setToDelete(d)} + onClick={(e) => { + e.stopPropagation() + setToDelete(d) + }} > Détruire @@ -185,6 +238,50 @@ export function Demos() { et toutes ses données seront supprimées définitivement. Les ressources du pool seront libérées. Cette action est irréversible. + + + + + + Détails de{' '} + + {detailsFor?.namespace} + + + + + {detailsLoading ? ( + + + + ) : details ? ( + + + Backend + {details.state.APIState || '—'} + + + Frontend + {details.state.WebState || '—'} + + + PostgreSQL + {details.state.DBState || '—'} + + + Redis + {details.state.DBMemoryState || '—'} + + + ) : ( + Aucune donnée. + )} + + + + + + ) }