"use client";
import { useMemo } from "react";
import { useStore } from "zustand";
import {
ArrowDown,
ArrowUp,
Check,
ChevronDown,
CircleDot,
Columns3,
Filter,
List,
Plus,
SignalHigh,
SlidersHorizontal,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuSubContent,
} from "@/components/ui/dropdown-menu";
import {
Popover,
PopoverTrigger,
PopoverContent,
} from "@/components/ui/popover";
import { Switch } from "@/components/ui/switch";
import { useModalStore } from "@/features/modals";
import {
ALL_STATUSES,
STATUS_CONFIG,
PRIORITY_ORDER,
PRIORITY_CONFIG,
} from "@/features/issues/config";
import { StatusIcon, PriorityIcon } from "@/features/issues/components";
import {
SORT_OPTIONS,
CARD_PROPERTY_OPTIONS,
} from "@/features/issues/stores/view-store";
import { filterIssues } from "@/features/issues/utils/filter";
import type { Issue } from "@/shared/types";
import { myIssuesViewStore } from "../stores/my-issues-view-store";
// ---------------------------------------------------------------------------
// HoverCheck — shadcn official pattern (PR #6862)
// ---------------------------------------------------------------------------
const FILTER_ITEM_CLASS =
"group/fitem pr-1.5! [&>[data-slot=dropdown-menu-checkbox-item-indicator]]:hidden";
function HoverCheck({ checked }: { checked: boolean }) {
return (
);
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function getActiveFilterCount(state: {
statusFilters: string[];
priorityFilters: string[];
}) {
let count = 0;
if (state.statusFilters.length > 0) count++;
if (state.priorityFilters.length > 0) count++;
return count;
}
function useIssueCounts(allIssues: Issue[]) {
return useMemo(() => {
const status = new Map();
const priority = new Map();
for (const issue of allIssues) {
status.set(issue.status, (status.get(issue.status) ?? 0) + 1);
priority.set(issue.priority, (priority.get(issue.priority) ?? 0) + 1);
}
return { status, priority };
}, [allIssues]);
}
// ---------------------------------------------------------------------------
// MyIssuesHeader
// ---------------------------------------------------------------------------
export function MyIssuesHeader({ allIssues }: { allIssues: Issue[] }) {
const viewMode = useStore(myIssuesViewStore, (s) => s.viewMode);
const statusFilters = useStore(myIssuesViewStore, (s) => s.statusFilters);
const priorityFilters = useStore(myIssuesViewStore, (s) => s.priorityFilters);
const sortBy = useStore(myIssuesViewStore, (s) => s.sortBy);
const sortDirection = useStore(myIssuesViewStore, (s) => s.sortDirection);
const cardProperties = useStore(myIssuesViewStore, (s) => s.cardProperties);
const act = myIssuesViewStore.getState();
const counts = useIssueCounts(allIssues);
const filteredCount = useMemo(
() =>
filterIssues(allIssues, {
statusFilters,
priorityFilters,
assigneeFilters: [],
includeNoAssignee: false,
creatorFilters: [],
}).length,
[allIssues, statusFilters, priorityFilters],
);
const filterCount = getActiveFilterCount({ statusFilters, priorityFilters });
const sortLabel =
SORT_OPTIONS.find((o) => o.value === sortBy)?.label ?? "Manual";
const hasActiveFilters = filterCount > 0;
return (
{/* View toggle */}
{viewMode === "board" ? (
) : (
)}
{viewMode === "board" ? "Board" : "List"}
}
/>
View
act.setViewMode("board")}>
Board
act.setViewMode("list")}>
List
{/* Filter — DropdownMenu with sub-menus */}
Filter
{hasActiveFilters && (
{filterCount}
)}
}
/>
{/* Status */}
Status
{statusFilters.length > 0 && (
{statusFilters.length}
)}
{ALL_STATUSES.map((s) => {
const checked = statusFilters.includes(s);
const count = counts.status.get(s) ?? 0;
return (
act.toggleStatusFilter(s)}
className={FILTER_ITEM_CLASS}
>
{STATUS_CONFIG[s].label}
{count > 0 && (
{count} {count === 1 ? "issue" : "issues"}
)}
);
})}
{/* Priority */}
Priority
{priorityFilters.length > 0 && (
{priorityFilters.length}
)}
{PRIORITY_ORDER.map((p) => {
const checked = priorityFilters.includes(p);
const count = counts.priority.get(p) ?? 0;
return (
act.togglePriorityFilter(p)}
className={FILTER_ITEM_CLASS}
>
{PRIORITY_CONFIG[p].label}
{count > 0 && (
{count} {count === 1 ? "issue" : "issues"}
)}
);
})}
{/* Reset */}
{hasActiveFilters && (
<>
Reset all filters
>
)}
{/* Display settings */}
Display
}
/>
Ordering
{sortLabel}
}
/>
{SORT_OPTIONS.map((opt) => (
act.setSortBy(opt.value)}
>
{opt.label}
))}
Card properties
{CARD_PROPERTY_OPTIONS.map((opt) => (
))}
{filteredCount} {filteredCount === 1 ? "Issue" : "Issues"}
);
}