"use client" import { useMemo, useState } from "react" import { ExternalLink, Link2, Trash2 } from "lucide-react" import { SettingsSectionHeader } from "@/components/gmail/settings/settings-section-header" import { SettingsSyncBanner } from "@/components/gmail/settings/settings-sync-banner" import { AdminListControls } from "@/components/admin/settings/admin-list-controls" import { useAdminPublicShares } from "@/lib/api/hooks/use-admin-queries" import { useRevokeAdminPublicShare } from "@/lib/api/hooks/use-admin-mutations" import type { AdminPublicShare } from "@/lib/api/admin-types" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Badge } from "@/components/ui/badge" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" const ACCESS_MODE_LABELS: Record = { public: "Lien public", email: "Invitation e-mail", internal: "Interne", } const PUBLIC_SHARE_SORT_OPTIONS = [ { value: "-created_at", label: "Créé (récent)" }, { value: "created_at", label: "Créé (ancien)" }, { value: "-last_access_at", label: "Dernier accès (récent)" }, { value: "last_access_at", label: "Dernier accès (ancien)" }, { value: "-access_count", label: "Accès (plus)" }, { value: "access_count", label: "Accès (moins)" }, { value: "path", label: "Chemin (A→Z)" }, { value: "-path", label: "Chemin (Z→A)" }, { value: "owner_email", label: "Propriétaire (A→Z)" }, { value: "-owner_email", label: "Propriétaire (Z→A)" }, ] as const export function PublicSharesSection() { const [q, setQ] = useState("") const [page, setPage] = useState(1) const [pageSize, setPageSize] = useState(25) const [sort, setSort] = useState("-created_at") const queryParams = useMemo( () => ({ page, page_size: pageSize, sort, q: q.trim() || undefined, }), [page, pageSize, sort, q] ) const { data, isFetching, isError, refetch } = useAdminPublicShares(queryParams) const revoke = useRevokeAdminPublicShare() const shares = data?.shares ?? [] const total = data?.pagination.total ?? 0 const resolvedPageSize = data?.pagination.page_size ?? pageSize const totalPages = Math.max(1, Math.ceil(total / resolvedPageSize)) return ( <> refetch()} />
{ setQ(e.target.value) setPage(1) }} placeholder="Propriétaire, chemin, token, destinataire…" />
{ setPageSize(next) setPage(1) }} onSortChange={(next) => { setSort(next) setPage(1) }} itemLabel="partage(s)" />
Ressource Propriétaire Type Créé le Dernier accès Accès {shares.length === 0 ? ( {isFetching ? "Chargement…" : "Aucun partage externe actif."} ) : ( shares.map((share) => ( void revoke.mutateAsync({ shareId: share.id, ownerNcUserId: share.owner_nc_user_id, }) } /> )) )}
) } function ShareRow({ share, revoking, onRevoke, }: { share: AdminPublicShare revoking: boolean onRevoke: () => void }) { const modeLabel = ACCESS_MODE_LABELS[share.access_mode] ?? (share.share_type === 4 ? "Invitation e-mail" : "Lien public") function handleRevoke() { const label = share.path || share.token if ( confirm( `Révoquer le partage « ${label} » créé par ${share.owner_email} ?\nLe lien ne sera plus accessible.` ) ) { onRevoke() } } return (
{basename(share.path) || "—"}
{share.path}
{share.share_with ? (
→ {share.share_with_display_name || share.share_with}
) : null}
{share.owner_display_name || "—"}
{share.owner_email}
{modeLabel} {share.has_password ? Mot de passe : null}
{formatDateTime(share.created_at)} {share.last_access_at ? formatDateTime(share.last_access_at) : "Jamais"} {share.access_count > 0 ? share.access_count.toLocaleString("fr-FR") : "—"}
{share.url ? ( ) : null}
) } function formatDateTime(value?: string | null): string { if (!value) return "—" const d = new Date(value) if (Number.isNaN(d.getTime())) return "—" return d.toLocaleString("fr-FR", { dateStyle: "short", timeStyle: "short", }) } function basename(path: string): string { const trimmed = path.replace(/\/+$/, "") const idx = trimmed.lastIndexOf("/") if (idx < 0) return trimmed return trimmed.slice(idx + 1) || trimmed }