"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 { 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", } export function PublicSharesSection() { const [q, setQ] = useState("") const [page, setPage] = useState(1) const queryParams = useMemo( () => ({ page, page_size: 25, q: q.trim() || undefined, }), [page, q] ) const { data, isFetching, isError, refetch } = useAdminPublicShares(queryParams) const revoke = useRevokeAdminPublicShare() const shares = data?.shares ?? [] const total = data?.pagination.total ?? 0 const pageSize = data?.pagination.page_size ?? 25 const totalPages = Math.max(1, Math.ceil(total / pageSize)) return ( <> refetch()} />
{ setQ(e.target.value) setPage(1) }} placeholder="Propriétaire, chemin, token, destinataire…" />
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, }) } /> )) )}
{totalPages > 1 ? (
{total.toLocaleString("fr-FR")} partage(s)
) : null} ) } 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 }