diff --git a/src/components/ui/AgentSummary/AgentSummary.module.css b/src/components/ui/AgentSummary/AgentSummary.module.css index a6a548a..497bed8 100644 --- a/src/components/ui/AgentSummary/AgentSummary.module.css +++ b/src/components/ui/AgentSummary/AgentSummary.module.css @@ -32,11 +32,5 @@ .action { align-self: flex-start; - font-size: 14px; - font-weight: 500; - color: var(--brand-primary); - background: none; - border: none; - padding: 0; - cursor: pointer; + margin-top: var(--fowoco-spacing-4); } diff --git a/src/components/ui/AgentSummary/AgentSummary.tsx b/src/components/ui/AgentSummary/AgentSummary.tsx index 9590651..e68680f 100644 --- a/src/components/ui/AgentSummary/AgentSummary.tsx +++ b/src/components/ui/AgentSummary/AgentSummary.tsx @@ -1,4 +1,5 @@ import styles from './AgentSummary.module.css' +import { Button } from '../Button/Button' export interface AgentSummaryProps { headline: string @@ -13,9 +14,9 @@ export function AgentSummary({ headline, body, actionLabel, onAction }: AgentSum
AGENT가 준비한 다음 행동
{headline}
{body}
- ) } diff --git a/src/pages/CaseDetailPage/CaseDetailPage.module.css b/src/pages/CaseDetailPage/CaseDetailPage.module.css index 8d25c11..37a59ff 100644 --- a/src/pages/CaseDetailPage/CaseDetailPage.module.css +++ b/src/pages/CaseDetailPage/CaseDetailPage.module.css @@ -259,6 +259,10 @@ text-align: center; } +.workflowAction { + margin-top: var(--fowoco-spacing-16); +} + .stepTitle { margin: 0; font-size: 14px; diff --git a/src/pages/CaseDetailPage/CaseDetailPage.test.tsx b/src/pages/CaseDetailPage/CaseDetailPage.test.tsx index 582324b..d1004d6 100644 --- a/src/pages/CaseDetailPage/CaseDetailPage.test.tsx +++ b/src/pages/CaseDetailPage/CaseDetailPage.test.tsx @@ -938,6 +938,17 @@ describe('CaseDetailPage', () => { expect(await screen.findByText(/완료 처리 불가 · 승인 · 필수 체크리스트/)).toBeInTheDocument() }) + it('offers a visible action that opens the checklist required for progress', async () => { + const user = userEvent.setup() + mockTaskAndActivities() + renderPage() + + await user.click(await screen.findByRole('button', { name: '필수 항목 확인하기' })) + + expect(screen.getByRole('tab', { name: '체크리스트' })).toHaveAttribute('aria-selected', 'true') + expect(screen.getByRole('button', { name: /여권 사본 확인/ })).toBeInTheDocument() + }) + it('blocks completion and offers retry when document readiness cannot be verified', async () => { const user = userEvent.setup() mockTaskAndActivities({}, [], errorResponse(503, 'SERVICE_UNAVAILABLE', '서류 상태 확인 지연')) diff --git a/src/pages/CaseDetailPage/CaseDetailPage.tsx b/src/pages/CaseDetailPage/CaseDetailPage.tsx index ac271d3..5945702 100644 --- a/src/pages/CaseDetailPage/CaseDetailPage.tsx +++ b/src/pages/CaseDetailPage/CaseDetailPage.tsx @@ -1155,6 +1155,15 @@ export function CaseDetailPage() { })} )} + {!checklistReady && ( +업무 생성 {prefill}
+ const state = location.state as { draft?: { request?: string } } | null + return{`업무 검토 ${state?.draft?.request ?? ''}${location.search}`}
} function WorkListProbe() { @@ -120,7 +121,7 @@ function renderPage() {입력한 원문 그대로 분석합니다 · Enter로 분석 · Shift+Enter로 줄바꿈
+ {analysisError && ( ++ {analysisError} +
+ )} diff --git a/src/pages/ReviewWorkPage/AiRunReview.module.css b/src/pages/ReviewWorkPage/AiRunReview.module.css index 03b2c54..59bd7eb 100644 --- a/src/pages/ReviewWorkPage/AiRunReview.module.css +++ b/src/pages/ReviewWorkPage/AiRunReview.module.css @@ -187,9 +187,17 @@ margin-top: 16px; } +.fieldGridSingle { + display: grid; + grid-template-columns: minmax(0, 1fr); + gap: 16px; + margin-top: 16px; +} + @media (max-width: 560px) { .fieldGrid, - .fieldGridTwo { + .fieldGridTwo, + .fieldGridSingle { grid-template-columns: 1fr; } } @@ -273,6 +281,21 @@ margin-top: 16px; } +.questionLabel { + display: block; + margin: 12px 0 4px; + font-size: 14px; + font-weight: 700; + color: var(--text-primary); +} + +.questionHelp { + margin: 0 0 8px; + font-size: 12px; + line-height: 18px; + color: var(--text-secondary); +} + .questionInput { width: 100%; min-height: 42px; @@ -284,6 +307,29 @@ box-sizing: border-box; } +.dateTimeSelect { + display: grid; + grid-template-columns: repeat(3, minmax(88px, 1fr)) repeat(2, minmax(76px, 0.8fr)); + gap: 8px; +} + +.dateTimeSelect select { + width: 100%; + min-height: 42px; + padding: 8px 10px; + color: var(--text-primary); + background: var(--surface-default); + border: 1px solid var(--border-default); + border-radius: var(--fowoco-radius-6); + font: inherit; +} + +@media (max-width: 760px) { + .dateTimeSelect { + grid-template-columns: repeat(3, minmax(72px, 1fr)); + } +} + .errorCard { padding: var(--fowoco-spacing-20) var(--fowoco-spacing-24); background: var(--fowoco-red-50, #fff1f1); diff --git a/src/pages/ReviewWorkPage/AiRunReview.test.tsx b/src/pages/ReviewWorkPage/AiRunReview.test.tsx index daee650..0f7b49d 100644 --- a/src/pages/ReviewWorkPage/AiRunReview.test.tsx +++ b/src/pages/ReviewWorkPage/AiRunReview.test.tsx @@ -122,7 +122,7 @@ function needsInfoRun(): AiRunResponse { { slot_key: 'due_at', label: '신청 목표일을 입력해 주세요.', - input_type: 'DATE', + input_type: 'TEXT', required: true, answer: null, }, @@ -270,7 +270,7 @@ describe('AiRunReview 분석 근거', () => { expect(await screen.findByText('체류만료일이 30일 이내로 확인됨')).toBeInTheDocument() }) - it('falls back to a placeholder when the API has no evidence yet', async () => { + it('does not render an evidence field when the API has no evidence span', async () => { mockCatalogAndWorkers() render(사용자가 입력한 원문
{run.instruction}
-요청 유형
{intentLabel(run.detected_intent)}
분석 근거
-- {run.evidence ?? '현재 분석 API에서 제공하지 않음'} -
-분석 근거
+{run.evidence}
++ {questionView.label} + {question.required ? ' *' : ''} +
+ {questionView.help && ( ++ {questionView.help} +
+ )} + {question.slot_key === 'due_at' ? ( +답변은 현재 분석 실행에 저장되며 새 분석 시도로 이어집니다.
@@ -439,12 +667,11 @@ export function AiRunReview({ initialRun, initialDraft }: AiRunReviewProps) { {run.status === 'FAILED' && (- 오류 코드: {run.error_code ?? 'UNKNOWN_ERROR'} -
+{failure.description}
- 업무는 생성되지 않았습니다. 원문은 그대로 유지됩니다. + 업무는 생성되지 않았습니다. 원문은 그대로 유지됩니다. 참고 코드:{' '} + {run.error_code ?? 'UNKNOWN_ERROR'}
- 분석 근거는 API가 실제 근거 데이터를 제공할 때만 표시합니다. 근거 없는 확률 점수는 사용하지 - 않습니다. + Agent가 원문에서 실제 근거 구절을 제공한 경우에만 해당 구절을 표시합니다.