"use client"; import { useAtomValue } from "jotai"; import { AlertCircle, Info } from "lucide-react"; import { useCallback, useMemo, useState } from "react"; import { toast } from "sonner"; import { membersAtom, myAccessAtom } from "@/atoms/members/members-query.atoms"; import { deletePublicChatSnapshotMutationAtom } from "@/atoms/public-chat-snapshots/public-chat-snapshots-mutation.atoms"; import { publicChatSnapshotsAtom } from "@/atoms/public-chat-snapshots/public-chat-snapshots-query.atoms"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Card, CardContent } from "@/components/ui/card"; import { Skeleton } from "@/components/ui/skeleton"; import type { PublicChatSnapshotDetail } from "@/contracts/types/chat-threads.types"; import { PublicChatSnapshotsList } from "./public-chat-snapshots-list"; interface PublicChatSnapshotsManagerProps { searchSpaceId: number; } export function PublicChatSnapshotsManager({ searchSpaceId: _searchSpaceId, }: PublicChatSnapshotsManagerProps) { const [deletingId, setDeletingId] = useState(); // Data fetching const { data: snapshotsData, isLoading, isError } = useAtomValue(publicChatSnapshotsAtom); // Members for user resolution const { data: members } = useAtomValue(membersAtom); const memberMap = useMemo(() => { const map = new Map(); if (members) { for (const m of members) { map.set(m.user_id, { name: m.user_display_name || m.user_email || "Unknown", email: m.user_email || undefined, avatarUrl: m.user_avatar_url || undefined, }); } } return map; }, [members]); // Permissions const { data: access } = useAtomValue(myAccessAtom); const canView = useMemo(() => { if (!access) return false; if (access.is_owner) return true; return access.permissions?.includes("public_sharing:view") ?? false; }, [access]); const canDelete = useMemo(() => { if (!access) return false; if (access.is_owner) return true; return access.permissions?.includes("public_sharing:delete") ?? false; }, [access]); // Mutations const { mutateAsync: deleteSnapshot } = useAtomValue(deletePublicChatSnapshotMutationAtom); // Handlers const handleCopy = useCallback((snapshot: PublicChatSnapshotDetail) => { const publicUrl = `${window.location.origin}/public/${snapshot.share_token}`; navigator.clipboard.writeText(publicUrl); }, []); const handleDelete = useCallback( async (snapshot: PublicChatSnapshotDetail) => { try { setDeletingId(snapshot.id); await deleteSnapshot({ thread_id: snapshot.thread_id, snapshot_id: snapshot.id, }); } catch (error) { console.error("Failed to delete snapshot:", error); } finally { setDeletingId(undefined); } }, [deleteSnapshot] ); // Loading state if (isLoading) { return (
{/* Info alert skeleton */} {/* Cards grid skeleton */}
{["skeleton-a", "skeleton-b", "skeleton-c"].map((key) => ( {/* Header: Title */}
{/* Message count badge */}
{/* URL skeleton */} {/* Footer: Date + Creator */}
))}
); } // Error state if (isError) { return ( Failed to load public chat links. Please try again later. ); } // Permission denied if (!canView) { return ( You don't have permission to view public chat links in this search space. ); } const snapshots = snapshotsData?.snapshots ?? []; return (
Public chat links allow anyone with the URL to view a snapshot of a chat. These links do not update when the original chat changes.
); }