From 3b78574855600b07c08954c42f3c0c6ae0f21d17 Mon Sep 17 00:00:00 2001 From: ttipo Date: Sun, 21 Jun 2026 19:42:37 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=88=98=EC=A0=95=20=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=20=EB=A9=94=EC=8B=9C=EC=A7=80=EB=A5=BC=20=EC=84=A0=ED=83=9D=20?= =?UTF-8?q?=EC=82=AC=ED=95=AD=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 수정 요청 시 공용 메시지 입력을 필수에서 선택으로 완화한다. - 백엔드: ApprovalChangesDto.note 를 선택값으로 변경, requestChanges 가 빈 메시지면 changesNote 를 null 로 저장 - 프론트: 제출 버튼 비활성(메시지 필수) 해제, 빈 메시지는 미전송, 안내/라벨 문구를 '선택'으로 정리 Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/src/modules/task/dto/approval.dto.ts | 10 +++++----- backend/src/modules/task/task.service.ts | 4 ++-- frontend/src/composables/useTask.ts | 2 +- frontend/src/pages/relay/TaskDetailPage.vue | 13 ++++--------- frontend/src/stores/task.store.ts | 2 +- frontend/src/types/task.ts | 3 ++- 6 files changed, 15 insertions(+), 19 deletions(-) diff --git a/backend/src/modules/task/dto/approval.dto.ts b/backend/src/modules/task/dto/approval.dto.ts index f5e6207..8ebcd5f 100644 --- a/backend/src/modules/task/dto/approval.dto.ts +++ b/backend/src/modules/task/dto/approval.dto.ts @@ -2,7 +2,6 @@ import { ArrayMaxSize, IsArray, IsBoolean, - IsNotEmpty, IsOptional, IsString, IsUUID, @@ -45,16 +44,17 @@ export class ChecklistReviewDto { note?: string; } -// 수정 요청(지시자 → 담당자) — 보완 내용 필수 + 항목별 완료 체크(선택) +// 수정 요청(지시자 → 담당자) — 보완 메시지(선택) + 항목별 완료 체크(선택) export class ApprovalChangesDto { @ApiProperty({ - description: '수정 요청 메시지(보완이 필요한 내용)', + description: '수정 요청 메시지(선택)', + required: false, example: '세로형 카피 가독성이 낮으니 자간과 대비를 조정해 주세요.', }) + @IsOptional() @IsString() - @IsNotEmpty({ message: '수정 요청 내용을 입력해 주세요.' }) @MaxLength(2000) - note!: string; + note?: string; @ApiProperty({ description: '항목별 완료 검토 결과(체크/X). 생략 시 체크리스트 변경 없음', diff --git a/backend/src/modules/task/task.service.ts b/backend/src/modules/task/task.service.ts index a8e5821..05d16e4 100644 --- a/backend/src/modules/task/task.service.ts +++ b/backend/src/modules/task/task.service.ts @@ -892,14 +892,14 @@ export class TaskService { projectId: string, actingUserId: string, seq: number, - note: string, + note: string | undefined, reviews?: { id: string; done: boolean; note?: string }[], ): Promise { const project = await this.getProjectOrThrow(projectId); const membership = await this.assertMember(project.id, actingUserId); const task = await this.getTaskOrThrow(project.id, seq); - task.changesNote = note; + task.changesNote = note?.trim() ? note.trim() : null; task.approvalNote = null; task.approvalRequestedAt = null; diff --git a/frontend/src/composables/useTask.ts b/frontend/src/composables/useTask.ts index 8c10489..0c17c55 100644 --- a/frontend/src/composables/useTask.ts +++ b/frontend/src/composables/useTask.ts @@ -140,7 +140,7 @@ export function useTask() { async function requestChanges( projectId: string, taskId: number, - note: string, + note: string | undefined, checklist?: ChecklistReviewItem[], ): Promise { return (await api.post(`/projects/${projectId}/tasks/${taskId}/approval/changes`, { diff --git a/frontend/src/pages/relay/TaskDetailPage.vue b/frontend/src/pages/relay/TaskDetailPage.vue index 302a6b1..d6ce7b1 100644 --- a/frontend/src/pages/relay/TaskDetailPage.vue +++ b/frontend/src/pages/relay/TaskDetailPage.vue @@ -154,10 +154,6 @@ const reviewPct = computed(() => ) // 보완 항목이 없으면 곧바로 승인 가능 const reviewAllDone = computed(() => reviewTodoCount.value === 0) -// 제출 가능 여부 — 보완 항목이 있으면 메시지 필수 -const reviewSubmittable = computed( - () => reviewAllDone.value || changesNote.value.trim().length > 0, -) // 담당자 표기(푸터) const assigneeNames = computed(() => { const names = task.value?.assignees.map((a) => a.name) ?? [] @@ -205,7 +201,7 @@ function groupClass(cat: ChecklistCategory): string { } // 검토 제출 — 전부 완료면 승인, 보완 항목이 있으면 수정 요청 async function submitChanges() { - if (!task.value || !reviewSubmittable.value) return + if (!task.value) return try { if (reviewAllDone.value) { task.value = await taskStore.approve(projectId.value, task.value.id) @@ -222,7 +218,7 @@ async function submitChanges() { task.value = await taskStore.requestChanges( projectId.value, task.value.id, - changesNote.value.trim(), + changesNote.value.trim() || undefined, checklist.length ? checklist : undefined, ) } @@ -1452,12 +1448,12 @@ function badgeFor(name: string | undefined): { label: string; cls: string } { 모든 항목이 완료되었습니다. 메시지 없이 바로 승인할 수 있어요. - {{ reviewTodoCount }}개 항목에 보완이 필요합니다. 무엇을 수정해야 하는지 적어 주세요. + {{ reviewTodoCount }}개 항목에 보완이 필요합니다. 필요하면 보완 내용을 적어 주세요.
수정 요청 메시지 - {{ reviewAllDone ? '· 선택' : '· 보완 항목이 있어 필수' }} + · 선택