import SpaceGraph from "~/components/spaces/space-graph"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "~/components/ui/collapsible"; import { Button } from "~/components/ui"; import { Activity, AlertCircle, ChevronDown, Clock, LoaderCircle, } from "lucide-react"; import React from "react"; import { Popover, PopoverContent, PopoverTrigger, } from "~/components/ui/popover"; import { getIcon, IconPicker } from "~/components/icon-picker"; import { SpaceSummary } from "~/components/spaces/space-summary.client"; import { type ActionFunctionArgs, redirect, type LoaderFunctionArgs, } from "@remix-run/server-runtime"; import { requireUserId } from "~/services/session.server"; import { SpaceService } from "~/services/space.server"; import { useTypedLoaderData } from "remix-typedjson"; import { useFetcher } from "@remix-run/react"; import { Badge } from "~/components/ui/badge"; import { ClientOnly } from "remix-utils/client-only"; export async function loader({ request, params }: LoaderFunctionArgs) { const userId = await requireUserId(request); const spaceService = new SpaceService(); const spaceId = params.spaceId; // Get spaceId from URL params const space = await spaceService.getSpace(spaceId as string, userId); return space; } export async function action({ request, params }: ActionFunctionArgs) { const userId = await requireUserId(request); const spaceService = new SpaceService(); const spaceId = params.spaceId; if (!spaceId) { throw new Error("Space ID is required"); } const formData = await request.formData(); const icon = formData.get("icon"); if (typeof icon !== "string") { throw new Error("Invalid icon data"); } await spaceService.updateSpace(spaceId, { icon }, userId); return redirect(`/home/space/${spaceId}/overview`); } // Helper function to get status display info function getStatusDisplay(status?: string | null) { switch (status) { case "processing": return { label: "Processing", variant: "outline" as const, icon: , className: "text-success-foreground bg-success rounded border-none", }; case "pending": return { label: "Pending", variant: "outline" as const, icon: , className: "text-warning-foreground bg-warning rounded border-none", }; case "error": return { label: "Error", variant: "outline" as const, icon: , className: "text-destructive-foreground rounded bg-destructive border-none", }; default: return null; } } export default function Overview() { const [graphOpen, setGraphOpen] = React.useState(true); const [summaryOpen, setSummaryOpen] = React.useState(true); const space = useTypedLoaderData(); const fetcher = useFetcher(); const statusDisplay = getStatusDisplay(space?.status); const handleIconChange = (icon: string) => { const formData = new FormData(); formData.append("icon", icon); fetcher.submit(formData, { method: "post" }); }; return ( {getIcon(space?.icon, 24)} handleIconChange(JSON.stringify({ icon, color })) } onSelectEmoji={(emoji) => handleIconChange(JSON.stringify({ emoji })) } onRemove={() => handleIconChange("")} /> {space.name} {statusDisplay && ( {statusDisplay.icon} {statusDisplay.label} )} Context } > {() => } Graph ); }