From e48c1593fa4137764c0dda3b450fa8de9b8c0d7a Mon Sep 17 00:00:00 2001 From: LMS10 Date: Tue, 26 May 2026 02:19:35 +0900 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor:=20ReceiptPayInfo?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EC=97=90=20AI=20?= =?UTF-8?q?=ED=8C=90=EB=8B=A8=20=EA=B7=BC=EA=B1=B0=20=EC=84=B9=EC=85=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ReceiptPayInfo.tsx | 272 ++++++++++++++++++------------ 1 file changed, 166 insertions(+), 106 deletions(-) diff --git a/src/components/ReceiptPayInfo.tsx b/src/components/ReceiptPayInfo.tsx index 939c12a..c4140ca 100644 --- a/src/components/ReceiptPayInfo.tsx +++ b/src/components/ReceiptPayInfo.tsx @@ -23,6 +23,65 @@ import StatusChip from './StatusChip'; import 'react-datepicker/dist/react-datepicker.css'; registerLocale('ko', ko); +type InappropriateReason = + | 'NIGHT_PAYMENT' + | 'HOLIDAY_PAYMENT' + | 'SUSPICIOUS_ENTERTAINMENT' + | 'SPLIT_PAYMENT_SUSPICIOUS'; + +const REASON_DESCRIPTIONS: Record = { + NIGHT_PAYMENT: { + title: '심야 결제', + description: + '결제 시간이 심야 시간대(23시~06시)에 해당합니다. 공식적인 활동 목적의 지출이 맞는지 확인해 주세요.', + }, + HOLIDAY_PAYMENT: { + title: '공휴일 결제', + description: + '공휴일에 발생한 결제입니다. 공식 일정 외의 지출일 수 있으니 사용 목적을 검토해 주세요.', + }, + SUSPICIOUS_ENTERTAINMENT: { + title: '유흥업소 의심', + description: + '가맹점 정보와 영수증 상세 품목을 분석한 결과 유흥 목적의 지출로 의심됩니다. 공동 경비 사용 목적에 맞는지 검토가 필요합니다.', + }, + SPLIT_PAYMENT_SUSPICIOUS: { + title: '분할결제 의심', + description: + '동일 가맹점에서 단기간 내 복수의 결제가 감지되었습니다. 결제 한도 우회를 위한 분할결제일 가능성이 있습니다.', + }, +}; + +function AIJudgmentBasis({ reasons }: { reasons: string[] }) { + const validReasons = reasons.filter((r): r is InappropriateReason => r in REASON_DESCRIPTIONS); + if (validReasons.length === 0) return null; + + return ( +
+

+ + AI 판단 근거 +

+
    + {validReasons.map((reason) => { + const { title, description } = REASON_DESCRIPTIONS[reason]; + return ( +
  • + {title} + {description} +
  • + ); + })} +
+
+ ); +} + interface ReceiptPayInfoProps { editable?: boolean; uploadData?: ReceiptUploadResponse['data']; @@ -143,9 +202,7 @@ const ReceiptPayInfo = forwardRef( group='sub' variant='blue' disabled={!rejectReason.trim()} - onClick={() => { - setConfirmStatus('REJECTED'); - }} + onClick={() => setConfirmStatus('REJECTED')} className={cn('h-5 w-8.5 rounded-sm text-[10px] leading-4.5 font-medium')} > 저장 @@ -187,7 +244,6 @@ const ReceiptPayInfo = forwardRef( ) : (
- {' '} {data.status === 'REJECTED' && data.rejectionReason && (