diff --git a/frontend/src/components/feedback/StateMessage.vue b/frontend/src/components/feedback/StateMessage.vue index a2da0de..5ab9f57 100644 --- a/frontend/src/components/feedback/StateMessage.vue +++ b/frontend/src/components/feedback/StateMessage.vue @@ -18,7 +18,7 @@ interface Props { tone?: 'neutral' | 'danger' /** 서버 추적 ID — 앞 8자리를 "문의 코드"로 보인다 */ traceId?: string | null - /** 영역을 세로로 가득 채워 가운데 둔다 (본문 영역의 "메일을 선택해 주세요") */ + /** 영역을 세로로 가득 채워 가운데 둔다 (본문 영역의 "고른 메일이 없습니다") */ fill?: boolean } diff --git a/frontend/src/components/mail/ConversationMessagePanel.vue b/frontend/src/components/mail/ConversationMessagePanel.vue index 3fce3e9..0823ed2 100644 --- a/frontend/src/components/mail/ConversationMessagePanel.vue +++ b/frontend/src/components/mail/ConversationMessagePanel.vue @@ -2,6 +2,7 @@ // "같은 대화" 칸에서 펼친 줄의 안 (14단계 — 디자인 원본 Thread14 "하나 펼침") // 받는 사람 · 제목 한 줄씩, 본문(MailBodyFrame — 검색 쿼리 없이 받은 본문이라 강조가 없다), [답장] · [이 메일만 열기](36 — 밀도 예외 --size-notice-action 재사용). // - 본문이 다 보이지 않으면(서버의 isHtmlBodyOmitted · isBodyTruncated) 읽기 화면과 같은 안내 줄(MAIL_BODY_NOTICES)을 본문 위에 — 읽기 화면도 같은 본문이다. +// 앞 문장만 보이고 원문 내려받기(할 일)는 붙이지 않는다 — 이 화면의 ⋯ 는 위에 연 메일의 것이라, 원문은 [이 메일만 열기]로 연 읽기 화면에서 받는다. // 외부 이미지 안내 · 첨부 목록은 두지 않는다 — [이 메일만 열기]로 연 읽기 화면에 있다. 첨부가 있으면 본문 아래 · [답장] 위에 // "첨부 파일 N개는 [이 메일만 열기]를 누르면 볼 수 있습니다." (수는 읽기 화면의 "첨부 파일 N개"와 같다 — 본문 그림 빼고 · 대용량 첨부 더해) // - 본문을 받는 동안은 뼈대(aria-busy), 못 받으면 사전 문구 + [다시 시도]. 그사이 지워진 메일(RES_001)이면 [다시 시도] · [답장] · [이 메일만 열기] 없이 — @@ -49,7 +50,7 @@ const ready = computed(() => (props.detail?.status === 'ready' ? props.detail.de const failure = computed(() => (props.detail?.status === 'error' ? props.detail.error : null)) /** 그사이 지워진 메일 — 다시 해도 같고 그 메일로 갈 곳도 없다 */ const missing = computed(() => failure.value?.code === 'RES_001') -const bodyNotices = computed(() => (ready.value ? mailBodyNotices(ready.value) : [])) +const bodyNotices = computed(() => (ready.value ? mailBodyNotices(ready.value, { withAction: false }) : [])) /** 읽기 화면에서 볼 수 있는 첨부 수 — 본문 그림(isInline)은 빼고 대용량 첨부는 더한다 (MessageReader 의 첨부 칸과 같은 수) */ const attachmentCount = computed(() => ready.value ? listedAttachments(ready.value.attachments).length + (ready.value.largeFiles?.length ?? 0) : 0, diff --git a/frontend/src/components/mail/MailListFrame.spec.ts b/frontend/src/components/mail/MailListFrame.spec.ts index 7f841e9..2f76a64 100644 --- a/frontend/src/components/mail/MailListFrame.spec.ts +++ b/frontend/src/components/mail/MailListFrame.spec.ts @@ -2,6 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { mount } from '@vue/test-utils' import { createPinia, setActivePinia, type Pinia } from 'pinia' +import { MAILBOX_EMPTY_HINTS } from '@/shared/constants/mail' import type { Mailbox, MessageSummary } from '@/shared/types/mail' import { useAuthStore } from '@/stores/auth.store' import { useMailStore } from '@/stores/mail.store' @@ -239,7 +240,9 @@ describe('MailListFrame — 휴지통 · 스팸메일함의 30일 줄 (13단계) expect(wrapper.find('[data-retention-notice]').exists()).toBe(false) expect(wrapper.text()).toContain('휴지통이 비어 있습니다') - expect(wrapper.text()).toContain('삭제한 메일이 여기에 표시됩니다. 들어간 지 30일이 지난 메일은 자동으로 지워집니다.') + expect(wrapper.text()).toContain(MAILBOX_EMPTY_HINTS.trash) + // 줄 대신 이 글이 30일을 알린다 + expect(MAILBOX_EMPTY_HINTS.trash).toContain('30일') }) it('다른 메일함 · 검색 결과에는 없다', async () => { diff --git a/frontend/src/components/mail/MailSearchBox.spec.ts b/frontend/src/components/mail/MailSearchBox.spec.ts index b6791f8..851b59e 100644 --- a/frontend/src/components/mail/MailSearchBox.spec.ts +++ b/frontend/src/components/mail/MailSearchBox.spec.ts @@ -4,6 +4,7 @@ import { createPinia, setActivePinia, type Pinia } from 'pinia' import { CLOCK } from '@/composables/useClock' import { ERROR_CODE_MESSAGES } from '@/shared/constants/error-codes.generated' +import { SEARCH_CONDITIONS_TEXT } from '@/shared/constants/mail-search' import type { Mailbox } from '@/shared/types/mail' import { useAuthStore } from '@/stores/auth.store' import { useMailStore } from '@/stores/mail.store' @@ -245,9 +246,7 @@ describe('MailSearchBox — [조건] · 「조건으로 찾기」 (14단계 디 '최근 1년', '날짜 고르기', ]) - expect(panel.text()).toContain( - '검색 칸의 말과 이 조건에 모두 맞는 메일을 찾습니다. 받는 사람에는 참조로 받은 사람도 들어갑니다.', - ) + expect(panel.text()).toContain(SEARCH_CONDITIONS_TEXT.hint) // 칸 안내 — 내용 칸은 칸 이름과 같은 말로 (2026-11-06 실사용 시험) expect(['from', 'to', 'subject', 'body'].map((name) => field(wrapper, name).attributes('placeholder'))).toEqual([ '이름이나 메일 주소', diff --git a/frontend/src/components/mail/MailSearchEmpty.vue b/frontend/src/components/mail/MailSearchEmpty.vue index e59248b..0620f3b 100644 --- a/frontend/src/components/mail/MailSearchEmpty.vue +++ b/frontend/src/components/mail/MailSearchEmpty.vue @@ -1,6 +1,6 @@