@@ -28,6 +28,7 @@ import { useNavigate } from 'react-router-dom'
|
||||
import { api, ApiError, type Demo, type DemoDetails } from '../../lib/api'
|
||||
import { statusColor, statusLabel } from '../../lib/format'
|
||||
import { ChevronIcon, PodStatusPanel } from '../../components/PodStatusPanel'
|
||||
import { ConfirmDialog } from '../../components/ConfirmDialog'
|
||||
import { CreateDemoModal } from '../../components/CreateDemoModal'
|
||||
import { EditDomainModal } from '../../components/EditDomainModal'
|
||||
import { DemoCard } from '../../components/DemoCard'
|
||||
@@ -42,6 +43,8 @@ export function PremiumDemos() {
|
||||
const navigate = useNavigate()
|
||||
const [demos, setDemos] = useState<Demo[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [busy, setBusy] = useState<string | null>(null)
|
||||
const [toDelete, setToDelete] = useState<Demo | null>(null)
|
||||
const [createModalOpen, setCreateModalOpen] = useState(false)
|
||||
const [editingDomain, setEditingDomain] = useState<Demo | null>(null)
|
||||
|
||||
@@ -68,6 +71,23 @@ export function PremiumDemos() {
|
||||
return () => clearInterval(id)
|
||||
}, [load])
|
||||
|
||||
const confirmDestroy = async () => {
|
||||
if (!toDelete) return
|
||||
const d = toDelete
|
||||
setBusy(d.id)
|
||||
try {
|
||||
await api.deleteDemo(d.id)
|
||||
toast({ status: 'success', title: 'Plateforme détruite' })
|
||||
setToDelete(null)
|
||||
await load()
|
||||
} catch (err) {
|
||||
const msg = err instanceof ApiError ? err.message : 'Erreur'
|
||||
toast({ status: 'error', title: 'Destruction impossible', description: msg })
|
||||
} finally {
|
||||
setBusy(null)
|
||||
}
|
||||
}
|
||||
|
||||
const toggleRow = async (d: Demo) => {
|
||||
if (expandedId === d.id) {
|
||||
setExpandedId(null)
|
||||
@@ -107,6 +127,21 @@ export function PremiumDemos() {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [expandedId])
|
||||
|
||||
const renderActions = (d: Demo) => (
|
||||
<Button
|
||||
size="sm"
|
||||
colorScheme="red"
|
||||
variant="outline"
|
||||
isDisabled={busy === d.id}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setToDelete(d)
|
||||
}}
|
||||
>
|
||||
Détruire
|
||||
</Button>
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex mb={2} align="center" gap={4} wrap="wrap">
|
||||
@@ -143,6 +178,7 @@ export function PremiumDemos() {
|
||||
<Th>Client</Th>
|
||||
<Th>Statut</Th>
|
||||
<Th>URL</Th>
|
||||
<Th></Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
@@ -198,9 +234,12 @@ export function PremiumDemos() {
|
||||
/>
|
||||
</HStack>
|
||||
</Td>
|
||||
<Td textAlign="right">
|
||||
<HStack justify="flex-end">{renderActions(d)}</HStack>
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td p={0} border={isOpen ? undefined : 'none'} colSpan={4}>
|
||||
<Td p={0} border={isOpen ? undefined : 'none'} colSpan={5}>
|
||||
<Collapse in={isOpen} unmountOnExit animateOpacity>
|
||||
<Box p={4} bg="chakra-subtle-bg" borderTopWidth="1px">
|
||||
{detailsLoading && !details ? (
|
||||
@@ -234,12 +273,29 @@ export function PremiumDemos() {
|
||||
detailsLoading={detailsLoading}
|
||||
details={expandedId === d.id ? details : null}
|
||||
onEditDomain={() => setEditingDomain(d)}
|
||||
actions={renderActions(d)}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</>
|
||||
)}
|
||||
|
||||
<ConfirmDialog
|
||||
isOpen={!!toDelete}
|
||||
title="Détruire la plateforme premium ?"
|
||||
confirmLabel="Détruire"
|
||||
isLoading={!!toDelete && busy === toDelete.id}
|
||||
onConfirm={confirmDestroy}
|
||||
onClose={() => setToDelete(null)}
|
||||
>
|
||||
La plateforme{' '}
|
||||
<Text as="span" fontFamily="mono" fontWeight="semibold">
|
||||
{toDelete?.namespace}
|
||||
</Text>{' '}
|
||||
et toutes ses données (client payant) seront supprimées définitivement. Cette action est
|
||||
irréversible.
|
||||
</ConfirmDialog>
|
||||
|
||||
<EditDomainModal
|
||||
demo={editingDomain}
|
||||
onClose={() => setEditingDomain(null)}
|
||||
|
||||
Reference in New Issue
Block a user