feat: cross-column DnD, fix context menu, rename task types to 실행과제/기반업무

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
EENE Dashboard
2026-06-02 09:11:11 +09:00
parent f07874e8fe
commit 67144d6a30
5 changed files with 249 additions and 174 deletions

View File

@@ -47,9 +47,17 @@ export function TaskManager({ tasks, sectionOptions, quarter, onClose }: TaskMan
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['tasks'] }),
});
// 기반업무 = 상시업무(구), 실행과제 = 프로젝트(구) — 둘 다 매칭
const matchType = (taskType: string | null | undefined, filter: string) => {
if (filter === '전체') return true;
if (filter === '실행과제') return taskType === '실행과제' || taskType === '프로젝트';
if (filter === '기반업무') return taskType === '기반업무' || taskType === '상시업무';
return taskType === filter;
};
const filtered = tasks.filter((t) => {
if (filterSection !== '전체' && t.section !== filterSection) return false;
if (filterType !== '전체' && t.taskType !== filterType) return false;
if (!matchType(t.taskType, filterType)) return false;
return true;
});
@@ -120,7 +128,7 @@ export function TaskManager({ tasks, sectionOptions, quarter, onClose }: TaskMan
<div className="w-px h-5 bg-gray-200" />
{/* 유형 필터 */}
<div className="flex gap-1">
{['전체', '프로젝트', '상시업무'].map((t) => (
{['전체', '실행과제', '기반업무'].map((t) => (
<button key={t} onClick={() => setFilterType(t)}
className={`text-xs font-semibold px-3 py-1.5 rounded-lg transition-colors ${
filterType === t ? 'bg-indigo-600 text-white' : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
@@ -162,9 +170,9 @@ export function TaskManager({ tasks, sectionOptions, quarter, onClose }: TaskMan
<td className="px-4 py-3 text-gray-600 font-medium whitespace-nowrap">{task.section ?? '-'}</td>
<td className="px-4 py-3">
<span className={`text-xs font-bold px-2 py-0.5 rounded-full ${
task.taskType === '상시업무' ? 'bg-amber-100 text-amber-700' : 'bg-blue-100 text-blue-700'
(task.taskType === '상시업무' || task.taskType === '기반업무') ? 'bg-amber-100 text-amber-700' : 'bg-blue-100 text-blue-700'
}`}>
{task.taskType ?? '프로젝트'}
{task.taskType === '상시업무' ? '기반업무' : task.taskType === '프로젝트' ? '실행과제' : (task.taskType ?? '실행과제')}
</span>
</td>
<td className="px-4 py-3 font-semibold text-gray-800 max-w-[200px] truncate">{task.title}</td>
@@ -208,8 +216,8 @@ export function TaskManager({ tasks, sectionOptions, quarter, onClose }: TaskMan
{/* 하단 요약 */}
<div className="px-6 py-3 border-t border-gray-100 shrink-0 flex items-center gap-4 text-xs text-gray-400">
<span> <strong className="text-gray-700">{filtered.length}</strong></span>
<span> <strong className="text-blue-600">{filtered.filter(t => t.taskType !== '상시업무').length}</strong></span>
<span> <strong className="text-amber-600">{filtered.filter(t => t.taskType === '상시업무').length}</strong></span>
<span> <strong className="text-blue-600">{filtered.filter(t => t.taskType !== '상시업무' && t.taskType !== '기반업무').length}</strong></span>
<span> <strong className="text-amber-600">{filtered.filter(t => t.taskType === '상시업무' || t.taskType === '기반업무').length}</strong></span>
</div>
</div>