feat(WEB): 헤더 바로가기 버튼 추가 및 종합분석 목데이터 적용

- 공용 헤더에 종합분석/품질인정심사 바로가기 버튼 추가 (데스크톱/모바일)
- 종합분석 페이지 목데이터 적용 (API 호출 비활성화)
- 로그인 페이지 기본 계정 설정
- QMS 필터/모달 컴포넌트 개선
- 메뉴 폴링 및 fetch-wrapper 유틸리티 개선

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
byeongcheolryu
2025-12-31 18:40:50 +09:00
parent d4e64c290c
commit 4b1a3abf05
9 changed files with 560 additions and 128 deletions

View File

@@ -22,8 +22,8 @@ export function LoginPage() {
const t = useTranslations('auth');
const tCommon = useTranslations('common');
const tValidation = useTranslations('validation');
const [userId, setUserId] = useState("");
const [password, setPassword] = useState("");
const [userId, setUserId] = useState("TestUser5");
const [password, setPassword] = useState("password123!");
const [showPassword, setShowPassword] = useState(false);
const [rememberMe, setRememberMe] = useState(false);
const [error, setError] = useState("");
@@ -130,6 +130,9 @@ export function LoginPage() {
console.log('💾 localStorage에 저장할 데이터:', userData);
localStorage.setItem('user', JSON.stringify(userData));
// 메뉴 폴링 재시작 플래그 설정 (세션 만료 후 재로그인 시)
sessionStorage.setItem('auth_just_logged_in', 'true');
// 대시보드로 이동
router.push("/dashboard");
} catch (err) {

View File

@@ -34,15 +34,96 @@ const formatAmount = (amount: number): string => {
return new Intl.NumberFormat('ko-KR').format(amount) + '원';
};
// 기본 데이터
// 기본 데이터 (목데이터)
const defaultData: ComprehensiveAnalysisData = {
todayIssue: { filterOptions: ['전체필터'], items: [] },
monthlyExpense: { cards: [], checkPoints: [] },
cardManagement: { cards: [], checkPoints: [] },
entertainment: { cards: [], checkPoints: [] },
welfare: { cards: [], checkPoints: [] },
receivable: { cards: [], checkPoints: [], hasDetailButton: true, detailButtonLabel: '거래처별 미수금 현황', detailButtonPath: '/accounting/receivables-status' },
debtCollection: { cards: [], checkPoints: [] },
todayIssue: {
filterOptions: ['전체필터', '결재', '매출', '매입', '자금'],
items: [
{ id: '1', category: '결재', description: '지출결의서 #2024-001 승인 대기 중', requiresApproval: true, time: '09:30' },
{ id: '2', category: '매출', description: '(주)대한전자 외상매출금 90일 초과', requiresApproval: false, time: '10:15' },
{ id: '3', category: '자금', description: '법인카드 한도 초과 경고', requiresApproval: false, time: '11:00' },
],
},
monthlyExpense: {
cards: [
{ id: 'me1', label: '매입', amount: 3123000, previousAmount: 2826000, previousLabel: '전월 대비 +10.5%' },
{ id: 'me2', label: '카드', amount: 3123000, previousAmount: 2826000, previousLabel: '전월 대비 +10.5%' },
{ id: 'me3', label: '발행어음', amount: 3123000, previousAmount: 2826000, previousLabel: '전월 대비 +10.5%' },
{ id: 'me4', label: '총 예상 지출 합계', amount: 3123000, previousAmount: 2826000, previousLabel: '전월 대비 +10.5%' },
],
checkPoints: [
{ id: 'me-cp1', type: 'warning', message: '이번 달 예상 지출이', highlight: '전월 대비 15% 증가했습니다. 매입 비용 증가가 주요 원인입니다.' },
{ id: 'me-cp2', type: 'error', message: '이번 달 예상 지출이', highlight: '예산을 12% 초과했습니다. 비용 항목별 점검이 필요합니다.' },
{ id: 'me-cp3', type: 'success', message: '이번 달 예상 지출이', highlight: '전월 대비 8% 감소했습니다. (계정과목명) 비용이 줄었습니다.' },
],
},
cardManagement: {
cards: [
{ id: 'cm1', label: '카드', amount: 3123000, subAmount: 50000, subLabel: '약정 5만 (가지급금 예외)' },
{ id: 'cm2', label: '가지급금', amount: 3123000, previousAmount: 2826000, previousLabel: '전월 대비 +10.5%' },
{ id: 'cm3', label: '미정산 가불', amount: 3123000, previousAmount: 2826000, previousLabel: '전월 대비 +10.5%' },
{ id: 'cm4', label: '총 잔액', amount: 3123000, previousAmount: 2826000, previousLabel: '전월 대비 +10.5%' },
],
checkPoints: [
{ id: 'cm-cp1', type: 'warning', message: '법인카드 사용 총 85만원이 가지급금으로 전환되었습니다.', highlight: '연 4.6% 인정이자가 발생합니다.' },
{ id: 'cm-cp2', type: 'warning', message: '전 가지급금 1,520만원은 4.6%,', highlight: '연 약 70만원의 인정이자가 발생합니다.' },
{ id: 'cm-cp3', type: 'warning', message: '상품권/귀금속 등 현대비 불인정 항목 매입 건이 있습니다. 가지급금 처리 예정입니다.' },
{ id: 'cm-cp4', type: 'info', message: '주말 카드 사용 총 100만원 중 결과 지의. 업무관련성 소명이 어려울 수 있으니 기록을 남겨주세요.' },
],
},
entertainment: {
cards: [
{ id: 'et1', label: '접대비 한도', amount: 30000123000, subAmount: 2123, subLabel: '사용' },
{ id: 'et2', label: '접대비 사용액', amount: 40123000 },
{ id: 'et3', label: '한도 잔액', amount: 30123000 },
{ id: 'et4', label: '전월 사용액', amount: 3123000 },
],
checkPoints: [
{ id: 'et-cp1', type: 'success', message: '접대비 사용 총 2,400만원 중 / 한도 4,000만원 (60%).', highlight: '여유 있게 운영 중입니다.' },
{ id: 'et-cp2', type: 'warning', message: '접대비 85% 도달. 연내 한도 600만원 잔액입니다.', highlight: '사용 계획에 집중해 주세요.' },
{ id: 'et-cp3', type: 'error', message: '접대비 한도 초과 320만원 발생.', highlight: '손금불산입되어 법인세 부담 증가합니다.' },
{ id: 'et-cp4', type: 'info', message: '접대비 사용 총 3건(45만원)이 거래처 한도 누락되어있습니다. 기록을 보완해 주세요.' },
],
},
welfare: {
cards: [
{ id: 'wf1', label: '총 복리후생비 한도', amount: 3123000 },
{ id: 'wf2', label: '누적 복리후생비 사용', amount: 1123000 },
{ id: 'wf3', label: '잠정 복리후생비 사용액', amount: 30123000 },
{ id: 'wf4', label: '잠정 복리후생비 누적 한도', amount: 3123000 },
],
checkPoints: [
{ id: 'wf-cp1', type: 'success', message: '1인당 월 복리후생비 18만원. 업계 평균(15~25만원) 내', highlight: '정상 운영 중입니다.' },
{ id: 'wf-cp2', type: 'warning', message: '식대가 월 25만원으로', highlight: '비과세 한도(20만원)를 초과했습니다. 초과분은 근로소득 과세됩니다.' },
],
},
receivable: {
cards: [
{ id: 'rv1', label: '누계 미수금', amount: 30123000, subAmount: 6123000, subLabel: '매출', previousAmount: 30000, previousLabel: '입금' },
{ id: 'rv2', label: '30일 초과', amount: 30123000, subAmount: 60123000, subLabel: '매출', previousAmount: 30000, previousLabel: '입금' },
{ id: 'rv3', label: '60일 초과', amount: 3123000, subAmount: 6123000, subLabel: '매출', previousAmount: 30000, previousLabel: '입금' },
{ id: 'rv4', label: '90일 초과', amount: 3123000, subAmount: 6123000, subLabel: '매출', previousAmount: 30000, previousLabel: '입금' },
],
checkPoints: [
{ id: 'rv-cp1', type: 'error', message: '90일 이상 장기 미수금 3건(2,500만원) 발생.', highlight: '회수 조치가 필요합니다.' },
{ id: 'rv-cp2', type: 'warning', message: '(주)대한전자 미수금 4,500만원으로', highlight: '전체의 35%를 차지합니다. 리스크 분산이 필요합니다.' },
],
hasDetailButton: true,
detailButtonLabel: '거래처별 미수금 현황',
detailButtonPath: '/accounting/receivables-status',
},
debtCollection: {
cards: [
{ id: 'dc1', label: '총 채권', amount: 30123000, subAmount: 25, subLabel: '건' },
{ id: 'dc2', label: '추심 진행', amount: 30123000, subAmount: 12, subLabel: '건' },
{ id: 'dc3', label: '추심 완료', amount: 3123000, subAmount: 3, subLabel: '건' },
{ id: 'dc4', label: '포기/손실', amount: 3123000, subAmount: 10, subLabel: '건' },
],
checkPoints: [
{ id: 'dc-cp1', type: 'info', message: '(주)대한전자 건 지급명령 신청 완료.', highlight: '법원 결정까지 약 2주 소요 예정입니다.' },
{ id: 'dc-cp2', type: 'warning', message: '(주)삼성테크 건 회수 불가 판정.', highlight: '대손 처리 검토가 필요합니다.' },
],
},
};
// Props 인터페이스
@@ -199,25 +280,27 @@ export default function ComprehensiveAnalysis({ initialData }: ComprehensiveAnal
const [rejectTargetId, setRejectTargetId] = useState<string | null>(null);
const [rejectReason, setRejectReason] = useState('');
// 데이터 로드
const loadData = useCallback(async () => {
setIsLoading(true);
try {
const result = await getComprehensiveAnalysis();
if (result.success && result.data) {
setData(result.data);
}
} catch (error) {
console.error('Failed to load comprehensive analysis:', error);
} finally {
setIsLoading(false);
}
}, []);
// 데이터 로드 (API 연동 시 활성화)
// const loadData = useCallback(async () => {
// setIsLoading(true);
// try {
// const result = await getComprehensiveAnalysis();
// if (result.success && result.data) {
// setData(result.data);
// }
// } catch (error) {
// console.error('Failed to load comprehensive analysis:', error);
// } finally {
// setIsLoading(false);
// }
// }, []);
// 초기 로드
// 초기 로드 - 현재 목데이터 사용 중 (API 연동 시 활성화)
useEffect(() => {
loadData();
}, [loadData]);
// API 연동 시 아래 주석 해제
// loadData();
setIsLoading(false);
}, []);
const handleReceivableDetail = () => {
router.push('/ko/accounting/receivables-status');