feat: quarter board theme, hub column, and team panel UX

Apply preview-style 4-dept layout with center hub, PM/assignee team status linking, task type label updates, and remove task keywords.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
EENE Dashboard
2026-06-08 22:09:46 +09:00
parent 525a4fc1f2
commit cf72281c6d
28 changed files with 4743 additions and 314 deletions

View File

@@ -41,7 +41,6 @@ export interface MappedTask {
issueNote: string | null;
startDate: Date | null;
dueDate: Date | null;
keywords: string | null;
showDate: boolean;
showDescription: boolean;
showStatus: boolean;
@@ -194,7 +193,6 @@ export function mapHrProjectToTask(p: HrProject, quarter = '2026-Q2'): MappedTas
issueNote: pickIssueNote(p),
startDate: parseDate(p.startDate),
dueDate: parseDate(p.endDate),
keywords: p.keywords?.length ? p.keywords.join(', ') : null,
showDate: visible,
showDescription: visible,
showStatus: visible,

View File

@@ -0,0 +1,3 @@
-- 키워드 필드 제거 (데이터 삭제 후 컬럼 drop)
UPDATE "tasks" SET "keywords" = NULL WHERE "keywords" IS NOT NULL;
ALTER TABLE "tasks" DROP COLUMN IF EXISTS "keywords";

View File

@@ -80,7 +80,6 @@ model Task {
showStatus Boolean @default(true)
showIssue Boolean @default(true)
showProgress Boolean @default(true)
keywords String?
creatorId String
assigneeId String?
pmMemberId String?

View File

@@ -39,7 +39,6 @@ type RemoteTask = {
showStatus: boolean;
showIssue: boolean;
showProgress: boolean;
keywords?: string | null;
creatorId: string;
assigneeId?: string | null;
pmMemberId?: string | null;
@@ -314,7 +313,6 @@ async function main() {
showStatus: remote.showStatus,
showIssue: remote.showIssue,
showProgress: remote.showProgress,
keywords: remote.keywords ?? null,
creatorId,
assigneeId,
pmMemberId,

View File

@@ -189,7 +189,6 @@ async function syncTasks(memberIdMap: Map<string, string>) {
showStatus: task.showStatus,
showIssue: task.showIssue,
showProgress: task.showProgress,
keywords: task.keywords,
pmMemberId,
assigneeMemberIds,
});

View File

@@ -56,7 +56,7 @@ router.post('/', async (req, res, next) => {
const body = req.body as Record<string, any>;
const { title, description, status, priority, quarter, category,
section, tag, taskType, progress, issueNote, startDate, dueDate, assigneeId, showDate,
showDescription, showStatus, showIssue, showProgress, keywords, pmMemberId } = body;
showDescription, showStatus, showIssue, showProgress, pmMemberId } = body;
if (!title || !quarter) {
throw new AppError(400, '제목과 분기는 필수입니다.');
@@ -85,7 +85,6 @@ router.post('/', async (req, res, next) => {
showStatus: showStatus !== undefined ? showStatus === 'true' || showStatus === true : true,
showIssue: showIssue !== undefined ? showIssue === 'true' || showIssue === true : true,
showProgress: showProgress !== undefined ? showProgress === 'true' || showProgress === true : true,
keywords: keywords || null,
assigneeId: assigneeId || null,
pmMemberId: pmMemberId || null,
creatorId,
@@ -118,7 +117,7 @@ router.patch('/:id', async (req, res, next) => {
const body = req.body as Record<string, any>;
const { title, description, status, priority, quarter, category,
section, tag, taskType, progress, issueNote, startDate, dueDate, assigneeId, showDate,
showDescription, showStatus, showIssue, showProgress, keywords, pmMemberId } = body;
showDescription, showStatus, showIssue, showProgress, pmMemberId } = body;
const assigneeMemberIds = parseMemberIds(body);
@@ -145,7 +144,6 @@ router.patch('/:id', async (req, res, next) => {
...(showStatus !== undefined && { showStatus: showStatus === true || showStatus === 'true' }),
...(showIssue !== undefined && { showIssue: showIssue === true || showIssue === 'true' }),
...(showProgress !== undefined && { showProgress: showProgress === true || showProgress === 'true' }),
...(keywords !== undefined && { keywords: keywords || null }),
},
});