fix: 업무 내용 필수 검증 추가 + 제목 에러 표기 정리
- 업무 내용(*)이 표기상 필수인데 검증이 없던 문제 → 필수로 강제
· 프론트: 인라인 검증(에디터 빨강 테두리 + '업무 내용을 입력해 주세요.'),
입력 시 즉시 해제
· 백엔드: CreateTaskDto.content 를 @ArrayNotEmpty 필수로(데이터 계약 일치)
- 제목 에러 표기 정리: 1.5rem 큰 placeholder 가 빨갛게 변하며 아래 메시지와
이중으로 강조되던 것을 제거 → 작은 인라인 메시지만 표시(차분하게)
검증: 백엔드 build/lint 0·8 tests, 프론트 type-check/lint/build 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -257,12 +257,16 @@ async function uploadPendingFiles(tid: number): Promise<number> {
|
||||
|
||||
// --- 제출 ---
|
||||
const submitting = ref(false)
|
||||
// 필드별 인라인 검증 — 제목·담당자 필수. 입력하면 즉시 해제.
|
||||
// 필드별 인라인 검증 — 제목·내용·담당자 필수. 입력하면 즉시 해제.
|
||||
const titleError = ref(false)
|
||||
const contentError = ref(false)
|
||||
const assigneeError = ref(false)
|
||||
watch(title, (v) => {
|
||||
if (v.trim().length > 0) titleError.value = false
|
||||
})
|
||||
watch(contentText, (v) => {
|
||||
if (v.trim().length > 0) contentError.value = false
|
||||
})
|
||||
watch(
|
||||
assignees,
|
||||
(v) => {
|
||||
@@ -272,8 +276,9 @@ watch(
|
||||
)
|
||||
function validateForm(): boolean {
|
||||
titleError.value = title.value.trim().length === 0
|
||||
contentError.value = contentText.value.trim().length === 0
|
||||
assigneeError.value = assignees.value.length === 0
|
||||
return !titleError.value && !assigneeError.value
|
||||
return !titleError.value && !contentError.value && !assigneeError.value
|
||||
}
|
||||
|
||||
async function submitTask() {
|
||||
@@ -417,7 +422,6 @@ function goBack() {
|
||||
<input
|
||||
v-model="title"
|
||||
class="title-input"
|
||||
:class="{ 'has-error': titleError }"
|
||||
placeholder="업무 제목을 입력하세요"
|
||||
>
|
||||
<div
|
||||
@@ -433,7 +437,10 @@ function goBack() {
|
||||
<div class="field-label">
|
||||
<span class="req">*</span> 업무 내용
|
||||
</div>
|
||||
<div class="editor">
|
||||
<div
|
||||
class="editor"
|
||||
:class="{ 'has-error': contentError }"
|
||||
>
|
||||
<div class="editor-toolbar">
|
||||
<button
|
||||
class="tb"
|
||||
@@ -520,6 +527,12 @@ function goBack() {
|
||||
placeholder="업무 배경과 요구사항을 작성하세요. (줄바꿈은 문단으로 저장됩니다)"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="contentError"
|
||||
class="field-error"
|
||||
>
|
||||
업무 내용을 입력해 주세요.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 체크리스트 -->
|
||||
@@ -981,9 +994,6 @@ function goBack() {
|
||||
.title-input::placeholder {
|
||||
color: #c4c8cf;
|
||||
}
|
||||
.title-input.has-error::placeholder {
|
||||
color: var(--red);
|
||||
}
|
||||
.field-error {
|
||||
font-size: 0.75rem;
|
||||
color: var(--red);
|
||||
@@ -1023,6 +1033,12 @@ function goBack() {
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 3px var(--accent-weak);
|
||||
}
|
||||
.editor.has-error {
|
||||
border-color: var(--red);
|
||||
}
|
||||
.editor.has-error:focus-within {
|
||||
box-shadow: 0 0 0 3px var(--red-weak);
|
||||
}
|
||||
.editor-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user