@@ -28,6 +28,7 @@ import { useNavigate } from 'react-router-dom'
|
|||||||
import { api, ApiError, type Demo, type DemoDetails } from '../../lib/api'
|
import { api, ApiError, type Demo, type DemoDetails } from '../../lib/api'
|
||||||
import { statusColor, statusLabel } from '../../lib/format'
|
import { statusColor, statusLabel } from '../../lib/format'
|
||||||
import { ChevronIcon, PodStatusPanel } from '../../components/PodStatusPanel'
|
import { ChevronIcon, PodStatusPanel } from '../../components/PodStatusPanel'
|
||||||
|
import { ConfirmDialog } from '../../components/ConfirmDialog'
|
||||||
import { CreateDemoModal } from '../../components/CreateDemoModal'
|
import { CreateDemoModal } from '../../components/CreateDemoModal'
|
||||||
import { EditDomainModal } from '../../components/EditDomainModal'
|
import { EditDomainModal } from '../../components/EditDomainModal'
|
||||||
import { DemoCard } from '../../components/DemoCard'
|
import { DemoCard } from '../../components/DemoCard'
|
||||||
@@ -42,6 +43,8 @@ export function PremiumDemos() {
|
|||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const [demos, setDemos] = useState<Demo[]>([])
|
const [demos, setDemos] = useState<Demo[]>([])
|
||||||
const [loading, setLoading] = useState(true)
|
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 [createModalOpen, setCreateModalOpen] = useState(false)
|
||||||
const [editingDomain, setEditingDomain] = useState<Demo | null>(null)
|
const [editingDomain, setEditingDomain] = useState<Demo | null>(null)
|
||||||
|
|
||||||
@@ -68,6 +71,23 @@ export function PremiumDemos() {
|
|||||||
return () => clearInterval(id)
|
return () => clearInterval(id)
|
||||||
}, [load])
|
}, [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) => {
|
const toggleRow = async (d: Demo) => {
|
||||||
if (expandedId === d.id) {
|
if (expandedId === d.id) {
|
||||||
setExpandedId(null)
|
setExpandedId(null)
|
||||||
@@ -107,6 +127,21 @@ export function PremiumDemos() {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [expandedId])
|
}, [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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<Flex mb={2} align="center" gap={4} wrap="wrap">
|
<Flex mb={2} align="center" gap={4} wrap="wrap">
|
||||||
@@ -143,6 +178,7 @@ export function PremiumDemos() {
|
|||||||
<Th>Client</Th>
|
<Th>Client</Th>
|
||||||
<Th>Statut</Th>
|
<Th>Statut</Th>
|
||||||
<Th>URL</Th>
|
<Th>URL</Th>
|
||||||
|
<Th></Th>
|
||||||
</Tr>
|
</Tr>
|
||||||
</Thead>
|
</Thead>
|
||||||
<Tbody>
|
<Tbody>
|
||||||
@@ -198,9 +234,12 @@ export function PremiumDemos() {
|
|||||||
/>
|
/>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Td>
|
</Td>
|
||||||
|
<Td textAlign="right">
|
||||||
|
<HStack justify="flex-end">{renderActions(d)}</HStack>
|
||||||
|
</Td>
|
||||||
</Tr>
|
</Tr>
|
||||||
<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>
|
<Collapse in={isOpen} unmountOnExit animateOpacity>
|
||||||
<Box p={4} bg="chakra-subtle-bg" borderTopWidth="1px">
|
<Box p={4} bg="chakra-subtle-bg" borderTopWidth="1px">
|
||||||
{detailsLoading && !details ? (
|
{detailsLoading && !details ? (
|
||||||
@@ -234,12 +273,29 @@ export function PremiumDemos() {
|
|||||||
detailsLoading={detailsLoading}
|
detailsLoading={detailsLoading}
|
||||||
details={expandedId === d.id ? details : null}
|
details={expandedId === d.id ? details : null}
|
||||||
onEditDomain={() => setEditingDomain(d)}
|
onEditDomain={() => setEditingDomain(d)}
|
||||||
|
actions={renderActions(d)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Stack>
|
</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
|
<EditDomainModal
|
||||||
demo={editingDomain}
|
demo={editingDomain}
|
||||||
onClose={() => setEditingDomain(null)}
|
onClose={() => setEditingDomain(null)}
|
||||||
|
|||||||
Reference in New Issue
Block a user