내 이슈를 전체적으로 재정비할 필요성이 생겼다.
const filteredIssues = useMemo(() => {
return issues.filter((issue) => {
const matchesSearch =
issue.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
(issue.description || "").toLowerCase().includes(searchTerm.toLowerCase());
const matchesType = typeFilter === "전체" || issue.issue_type === typeFilter;
const matchesStatus = statusFilter === "전체" || issue.status === statusFilter;
return matchesSearch && matchesType && matchesStatus;
});
}, [issues, typeFilter, statusFilter]);
유형별, 타입별로 정렬하기 위해 filter을 사용해서 정렬을 시켜준다.
useMemo : 컴퓨터 프로그램이 동일한 계산을 반복해야해서 이전에 계산한 값을 메모리에 넣을 필요가 있을 때 사용한다.
필터링 값이 매 렌더마다 불필요하게 반복되는것을 막기 위해 사용한다.
계산된 필터링 값은
<Select value={typeFilter} onValueChange={setTypeFilter}>
<SelectTrigger className="w-32">
<SelectValue placeholder="유형" />
</SelectTrigger>
<SelectContent>
{typeOptions.map(opt => (
<SelectItem key={opt.value} value={opt.value}>
<span className="flex items-center">{opt.icon}{opt.label}</span>
</SelectItem>
))}
</SelectContent>
</Select>
<Select value={statusFilter} onValueChange={setStatusFilter}>
<SelectTrigger className="w-32">
<SelectValue placeholder="상태" />
</SelectTrigger>
<SelectContent>
{statusOptions.map(opt => (
<SelectItem key={opt.value} value={opt.value}>{opt.label}</SelectItem>
))}
</SelectContent>
</Select>
위와 같이 Selector 태그에서 사용해준다.
const typeOptions: { value: string; label: string; icon: ReactNode }[] = [
{ value: "전체", label: "유형 전체", icon: <></> },
{ value: "bug", label: "버그", icon: <Bug className="w-5 h-5 mr-1" color="#ff0000" /> },
{ value: "story", label: "스토리", icon: <Book className="w-5 h-5 mr-1" color="#ff9500" /> },
{ value: "task", label: "작업", icon: <SquareCheckBig className="w-5 h-5 mr-1" color="#3729ff" /> },
];
const statusOptions: { value: string; label: string }[] = [
{ value: "전체", label: "상태 전체" },
{ value: "BACKLOG", label: "백로그" },
{ value: "TODO", label: "해야 할 일" },
{ value: "IN_PROGRESS", label: "진행 중" },
{ value: "IN_REVIEW", label: "리뷰 중" },
{ value: "DONE", label: "완료" },
];
필터링된 값은 위와 같이 하드코딩 되어있다.