Files
multica/packages/views/projects/components/project-badge.tsx
Anderson Shindy Oki 65feb890b8 feat: Add project list responsive compact and comfortable views (MUL-2464) (#2840)
* feat: Add project screen compact and comfortable views

* wip

* i18n

* refactor and add search

* refactor
2026-05-21 13:56:11 +08:00

80 lines
3.2 KiB
TypeScript

"use client";
import { Check } from "lucide-react";
import {
PROJECT_STATUS_CONFIG,
PROJECT_STATUS_ORDER,
PROJECT_PRIORITY_CONFIG,
PROJECT_PRIORITY_ORDER
} from "@multica/core/projects/config";
import { cn } from "@multica/ui/lib/utils";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@multica/ui/components/ui/dropdown-menu";
import type { Project, ProjectStatus, ProjectPriority, UpdateProjectRequest } from "@multica/core/types";
import { PriorityIcon } from "../../issues/components/priority-icon";
import { useProjectStatusLabels, useProjectPriorityLabels } from "./labels";
export function ProjectStatusBadge({ project, handleUpdate, triggerClassName, align = "end" }: { project: Project; handleUpdate: (data: UpdateProjectRequest) => void; triggerClassName?: string; align?: "start" | "end" | "center" }) {
const statusLabels = useProjectStatusLabels();
const statusCfg = PROJECT_STATUS_CONFIG[project.status];
return (
<DropdownMenu>
<DropdownMenuTrigger
render={
<button type="button" className={cn(
"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs font-medium cursor-pointer hover:opacity-80 transition-opacity",
statusCfg.badgeBg, statusCfg.badgeText,
triggerClassName
)}>
{statusLabels[project.status]}
</button>
}
/>
<DropdownMenuContent align={align} className="w-44">
{PROJECT_STATUS_ORDER.map((s) => (
<DropdownMenuItem key={s} onClick={() => handleUpdate({ status: s as ProjectStatus })}>
<span className={cn("size-2 rounded-full", PROJECT_STATUS_CONFIG[s].dotColor)} />
<span>{statusLabels[s]}</span>
{s === project.status && <Check className="ml-auto h-3.5 w-3.5" />}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
);
}
export function ProjectPriorityBadge({ project, handleUpdate, triggerClassName, align = "end" }: { project: Project; handleUpdate: (data: UpdateProjectRequest) => void; triggerClassName?: string; align?: "start" | "end" | "center" }) {
const priorityLabels = useProjectPriorityLabels();
const priorityCfg = PROJECT_PRIORITY_CONFIG[project.priority];
return (
<DropdownMenu>
<DropdownMenuTrigger
render={
<button type="button" className={cn(
"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs font-medium hover:bg-accent/60 transition-colors cursor-pointer",
triggerClassName
)}>
<PriorityIcon priority={project.priority} />
<span className={cn("text-xs", priorityCfg.color)}>{priorityLabels[project.priority]}</span>
</button>
}
/>
<DropdownMenuContent align={align} className="w-44">
{PROJECT_PRIORITY_ORDER.map((p) => (
<DropdownMenuItem key={p} onClick={() => handleUpdate({ priority: p as ProjectPriority })}>
<PriorityIcon priority={p} />
<span>{priorityLabels[p]}</span>
{p === project.priority && <Check className="ml-auto h-3.5 w-3.5" />}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
);
}