"use client"; import { useState, useCallback } from "react"; import { Plus, FolderKanban, UserMinus, Check } from "lucide-react"; import { useQuery } from "@tanstack/react-query"; import { projectListOptions } from "@multica/core/projects/queries"; import { useUpdateProject } from "@multica/core/projects/mutations"; import { PROJECT_STATUS_CONFIG, PROJECT_STATUS_ORDER, PROJECT_PRIORITY_CONFIG, PROJECT_PRIORITY_ORDER, } from "@multica/core/projects/config"; import { useWorkspaceId } from "@multica/core/hooks"; import { useWorkspacePaths } from "@multica/core/paths"; import { memberListOptions, agentListOptions } from "@multica/core/workspace/queries"; import { useModalStore } from "@multica/core/modals"; import { AppLink } from "../../navigation"; import { ActorAvatar } from "../../common/actor-avatar"; import { useActorName } from "@multica/core/workspace/hooks"; import { Skeleton } from "@multica/ui/components/ui/skeleton"; import { Button } from "@multica/ui/components/ui/button"; import { cn } from "@multica/ui/lib/utils"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@multica/ui/components/ui/dropdown-menu"; import { Popover, PopoverTrigger, PopoverContent, } from "@multica/ui/components/ui/popover"; import { Tooltip, TooltipTrigger, TooltipContent } from "@multica/ui/components/ui/tooltip"; import type { Project, ProjectStatus, ProjectPriority, UpdateProjectRequest } from "@multica/core/types"; import { PageHeader } from "../../layout/page-header"; import { PriorityIcon } from "../../issues/components/priority-icon"; function formatRelativeDate(date: string): string { const diff = Date.now() - new Date(date).getTime(); const days = Math.floor(diff / (1000 * 60 * 60 * 24)); if (days < 1) return "Today"; if (days === 1) return "1d ago"; if (days < 30) return `${days}d ago`; const months = Math.floor(days / 30); return `${months}mo ago`; } function ProjectRow({ project }: { project: Project }) { const wsId = useWorkspaceId(); const wsPaths = useWorkspacePaths(); const statusCfg = PROJECT_STATUS_CONFIG[project.status]; const priorityCfg = PROJECT_PRIORITY_CONFIG[project.priority]; const updateProject = useUpdateProject(); const { data: members = [] } = useQuery(memberListOptions(wsId)); const { data: agents = [] } = useQuery(agentListOptions(wsId)); const { getActorName } = useActorName(); const [leadOpen, setLeadOpen] = useState(false); const [leadFilter, setLeadFilter] = useState(""); const leadQuery = leadFilter.toLowerCase(); const filteredMembers = members.filter((m) => m.name.toLowerCase().includes(leadQuery)); const filteredAgents = agents.filter((a) => !a.archived_at && a.name.toLowerCase().includes(leadQuery)); const handleUpdate = useCallback( (data: UpdateProjectRequest) => { updateProject.mutate({ id: project.id, ...data }); }, [project.id, updateProject], ); return (
No projects yet