2025-12-04 20:52:42 +09:00
|
|
|
/**
|
|
|
|
|
* 거래처 상세 보기 컴포넌트
|
|
|
|
|
*
|
|
|
|
|
* 스크린샷 기준 4개 섹션:
|
|
|
|
|
* 1. 기본 정보
|
|
|
|
|
* 2. 연락처 정보
|
|
|
|
|
* 3. 결제 정보
|
|
|
|
|
* 4. 악성채권 정보 (있는 경우 빨간 테두리)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import { Button } from "../ui/button";
|
|
|
|
|
import { Badge } from "../ui/badge";
|
|
|
|
|
import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
|
|
|
|
|
import {
|
|
|
|
|
Building2,
|
|
|
|
|
Phone,
|
|
|
|
|
CreditCard,
|
|
|
|
|
AlertTriangle,
|
|
|
|
|
ArrowLeft,
|
feat: 다중 도메인 UI 개선 및 컴포넌트 리팩토링
- 게시판, HR, 설정, 차량관리, 건설, 견적 등 전반적 UI 개선
- FormField, TabChip, Select 등 공통 컴포넌트 개선
- 가격배분 edit 페이지 제거 및 상세 페이지 통합
- 체크리스트, 근태, 급여, 권한 관리 등 폼 개선
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:30:06 +09:00
|
|
|
Edit,
|
2025-12-04 20:52:42 +09:00
|
|
|
Trash2,
|
|
|
|
|
MapPin,
|
|
|
|
|
Mail,
|
|
|
|
|
} from "lucide-react";
|
|
|
|
|
import { Client } from "../../hooks/useClientList";
|
2025-12-09 18:07:47 +09:00
|
|
|
import { PageLayout } from "../organisms/PageLayout";
|
|
|
|
|
import { PageHeader } from "../organisms/PageHeader";
|
2026-02-11 15:09:51 +09:00
|
|
|
import { useMenuStore } from "@/stores/menuStore";
|
2026-02-20 10:45:47 +09:00
|
|
|
import { formatNumber } from "@/lib/utils/amount";
|
2025-12-04 20:52:42 +09:00
|
|
|
|
|
|
|
|
interface ClientDetailProps {
|
|
|
|
|
client: Client;
|
|
|
|
|
onBack: () => void;
|
|
|
|
|
onEdit: () => void;
|
|
|
|
|
onDelete: () => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 상세 항목 표시 컴포넌트
|
|
|
|
|
function DetailItem({
|
|
|
|
|
label,
|
|
|
|
|
value,
|
|
|
|
|
icon,
|
|
|
|
|
valueClassName,
|
|
|
|
|
}: {
|
|
|
|
|
label: string;
|
|
|
|
|
value: React.ReactNode;
|
|
|
|
|
icon?: React.ReactNode;
|
|
|
|
|
valueClassName?: string;
|
|
|
|
|
}) {
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<p className="text-xs text-muted-foreground mb-1">{label}</p>
|
|
|
|
|
<div className={`flex items-center gap-2 ${valueClassName || ""}`}>
|
|
|
|
|
{icon}
|
|
|
|
|
<span className="font-medium">{value || "-"}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function ClientDetail({
|
|
|
|
|
client,
|
|
|
|
|
onBack,
|
|
|
|
|
onEdit,
|
|
|
|
|
onDelete,
|
|
|
|
|
}: ClientDetailProps) {
|
2026-01-26 15:07:10 +09:00
|
|
|
const sidebarCollapsed = useMenuStore((state) => state.sidebarCollapsed);
|
|
|
|
|
|
2025-12-04 20:52:42 +09:00
|
|
|
// 금액 포맷
|
|
|
|
|
const formatCurrency = (amount: string) => {
|
|
|
|
|
if (!amount) return "-";
|
2026-02-20 10:45:47 +09:00
|
|
|
return `₩${formatNumber(Number(amount))}`;
|
2025-12-04 20:52:42 +09:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
2025-12-09 18:07:47 +09:00
|
|
|
<PageLayout maxWidth="2xl">
|
2026-01-26 15:07:10 +09:00
|
|
|
{/* 헤더 */}
|
2025-12-09 18:07:47 +09:00
|
|
|
<PageHeader
|
|
|
|
|
title={client.name}
|
|
|
|
|
description="거래처 상세 정보"
|
|
|
|
|
icon={Building2}
|
|
|
|
|
/>
|
|
|
|
|
|
2026-01-26 15:07:10 +09:00
|
|
|
<div className="space-y-6 pb-24">
|
2025-12-09 18:07:47 +09:00
|
|
|
{/* 1. 기본 정보 */}
|
2025-12-04 20:52:42 +09:00
|
|
|
<Card>
|
|
|
|
|
<CardHeader>
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<Building2 className="h-5 w-5 text-primary" />
|
|
|
|
|
<CardTitle>기본 정보</CardTitle>
|
|
|
|
|
</div>
|
|
|
|
|
</CardHeader>
|
|
|
|
|
<CardContent className="space-y-4">
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
|
|
|
<DetailItem label="CODE" value={client.code} />
|
|
|
|
|
<DetailItem label="사업자번호" value={client.businessNo} />
|
|
|
|
|
<DetailItem
|
|
|
|
|
label="거래처 유형"
|
|
|
|
|
value={
|
|
|
|
|
<Badge
|
|
|
|
|
variant={
|
|
|
|
|
client.clientType === "매출"
|
|
|
|
|
? "default"
|
|
|
|
|
: client.clientType === "매입"
|
|
|
|
|
? "secondary"
|
|
|
|
|
: "outline"
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{client.clientType}
|
|
|
|
|
</Badge>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
|
|
|
<DetailItem label="거래처명" value={client.name} />
|
|
|
|
|
<DetailItem label="대표자" value={client.representative} />
|
|
|
|
|
<DetailItem
|
|
|
|
|
label="상태"
|
|
|
|
|
value={
|
|
|
|
|
<Badge
|
|
|
|
|
variant={client.status === "활성" ? "default" : "secondary"}
|
|
|
|
|
className={
|
|
|
|
|
client.status === "활성"
|
|
|
|
|
? "bg-green-100 text-green-800"
|
|
|
|
|
: ""
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{client.status}
|
|
|
|
|
</Badge>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
|
|
|
<DetailItem
|
|
|
|
|
label="주소"
|
|
|
|
|
value={client.address}
|
|
|
|
|
icon={<MapPin className="h-4 w-4 text-muted-foreground" />}
|
|
|
|
|
/>
|
|
|
|
|
<DetailItem label="업태" value={client.businessType} />
|
|
|
|
|
<DetailItem label="종목" value={client.businessItem} />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{client.memo && (
|
|
|
|
|
<DetailItem label="비고" value={client.memo} />
|
|
|
|
|
)}
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
|
|
{/* 2. 연락처 정보 */}
|
|
|
|
|
<Card>
|
|
|
|
|
<CardHeader>
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<Phone className="h-5 w-5 text-primary" />
|
|
|
|
|
<CardTitle>연락처 정보</CardTitle>
|
|
|
|
|
</div>
|
|
|
|
|
</CardHeader>
|
|
|
|
|
<CardContent>
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
|
|
|
<DetailItem
|
|
|
|
|
label="전화"
|
|
|
|
|
value={client.phone}
|
|
|
|
|
icon={<Phone className="h-4 w-4 text-muted-foreground" />}
|
|
|
|
|
/>
|
|
|
|
|
<DetailItem
|
|
|
|
|
label="휴대전화"
|
|
|
|
|
value={client.mobile}
|
|
|
|
|
icon={<Phone className="h-4 w-4 text-muted-foreground" />}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
|
|
|
|
|
<DetailItem label="팩스" value={client.fax} />
|
|
|
|
|
<DetailItem
|
|
|
|
|
label="이메일"
|
|
|
|
|
value={client.email}
|
|
|
|
|
icon={<Mail className="h-4 w-4 text-muted-foreground" />}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
|
|
|
|
|
<DetailItem label="담당자명" value={client.managerName} />
|
|
|
|
|
<DetailItem label="담당자 연락처" value={client.managerTel} />
|
|
|
|
|
</div>
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
|
|
{/* 3. 결제 정보 */}
|
|
|
|
|
<Card>
|
|
|
|
|
<CardHeader>
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<CreditCard className="h-5 w-5 text-primary" />
|
|
|
|
|
<CardTitle>결제 정보</CardTitle>
|
|
|
|
|
</div>
|
|
|
|
|
</CardHeader>
|
|
|
|
|
<CardContent>
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
|
|
|
<DetailItem label="매입 결제일" value={client.purchasePaymentDay} />
|
|
|
|
|
<DetailItem label="매출 결제일" value={client.salesPaymentDay} />
|
|
|
|
|
</div>
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
|
|
{/* 4. 악성채권 정보 (있는 경우에만 표시) */}
|
|
|
|
|
{client.badDebt && (
|
|
|
|
|
<Card className="border-red-300 bg-red-50/30">
|
|
|
|
|
<CardHeader>
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<AlertTriangle className="h-5 w-5 text-red-500" />
|
|
|
|
|
<CardTitle className="text-red-700">악성채권 정보</CardTitle>
|
|
|
|
|
</div>
|
|
|
|
|
</CardHeader>
|
|
|
|
|
<CardContent>
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
|
|
|
<DetailItem
|
|
|
|
|
label="악성채권 금액"
|
|
|
|
|
value={formatCurrency(client.badDebtAmount)}
|
|
|
|
|
valueClassName="text-red-600 font-bold"
|
|
|
|
|
/>
|
|
|
|
|
<DetailItem label="수령일" value={client.badDebtReceiveDate} />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
|
|
|
|
|
<DetailItem label="종료일" value={client.badDebtEndDate} />
|
|
|
|
|
<DetailItem label="진행 상태" value={client.badDebtProgress} />
|
|
|
|
|
</div>
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
)}
|
2025-12-09 18:07:47 +09:00
|
|
|
</div>
|
2026-01-26 15:07:10 +09:00
|
|
|
|
|
|
|
|
{/* 하단 액션 버튼 (sticky) */}
|
feat(WEB): 상세 페이지 권한 체계 통합 및 레이아웃/문서 기능 개선
권한 시스템 통합:
- BadDebtDetail, LaborDetail, PricingDetail 권한 로직 정리
- BoardDetail, ClientDetail, ItemDetail 권한 적용 개선
- ProcessDetail, StepDetail, PermissionDetail 권한 리팩토링
- ContractDetail, HandoverReport, ProgressBilling 권한 연동
- ReceivingDetail, ShipmentDetail, WorkOrderDetail 권한 적용
- InspectionDetail, OrderSalesDetail, QuoteFooterBar 권한 개선
기능 개선:
- AuthenticatedLayout 구조 리팩토링
- JointbarInspectionDocument 문서 레이아웃 개선
- PricingTableForm 폼 기능 보강
- DynamicItemForm, SectionsTab 개선
- 주문관리 상세/생산지시 페이지 개선
- VendorLedgerDetail 수정
설정:
- Claude hooks 추가 (빌드 차단, 파일 크기 체크, 미사용 import 체크)
- 품질감사 문서관리 계획 문서 추가
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 20:26:27 +09:00
|
|
|
<div className={`fixed bottom-4 left-4 right-4 px-4 py-3 bg-background/95 backdrop-blur rounded-xl border shadow-lg z-50 transition-all duration-300 md:bottom-6 md:px-6 md:right-[48px] ${sidebarCollapsed ? 'md:left-[156px]' : 'md:left-[316px]'} flex items-center justify-between`}>
|
|
|
|
|
<Button variant="outline" onClick={onBack} size="sm" className="md:size-default">
|
|
|
|
|
<ArrowLeft className="h-4 w-4 md:mr-2" />
|
|
|
|
|
<span className="hidden md:inline">목록으로</span>
|
2026-01-26 15:07:10 +09:00
|
|
|
</Button>
|
feat(WEB): 상세 페이지 권한 체계 통합 및 레이아웃/문서 기능 개선
권한 시스템 통합:
- BadDebtDetail, LaborDetail, PricingDetail 권한 로직 정리
- BoardDetail, ClientDetail, ItemDetail 권한 적용 개선
- ProcessDetail, StepDetail, PermissionDetail 권한 리팩토링
- ContractDetail, HandoverReport, ProgressBilling 권한 연동
- ReceivingDetail, ShipmentDetail, WorkOrderDetail 권한 적용
- InspectionDetail, OrderSalesDetail, QuoteFooterBar 권한 개선
기능 개선:
- AuthenticatedLayout 구조 리팩토링
- JointbarInspectionDocument 문서 레이아웃 개선
- PricingTableForm 폼 기능 보강
- DynamicItemForm, SectionsTab 개선
- 주문관리 상세/생산지시 페이지 개선
- VendorLedgerDetail 수정
설정:
- Claude hooks 추가 (빌드 차단, 파일 크기 체크, 미사용 import 체크)
- 품질감사 문서관리 계획 문서 추가
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 20:26:27 +09:00
|
|
|
<div className="flex items-center gap-1 md:gap-2">
|
|
|
|
|
<Button variant="outline" onClick={onDelete} size="sm" className="text-destructive hover:bg-destructive hover:text-destructive-foreground md:size-default">
|
|
|
|
|
<Trash2 className="h-4 w-4 md:mr-2" />
|
|
|
|
|
<span className="hidden md:inline">삭제</span>
|
2026-01-26 15:07:10 +09:00
|
|
|
</Button>
|
feat(WEB): 상세 페이지 권한 체계 통합 및 레이아웃/문서 기능 개선
권한 시스템 통합:
- BadDebtDetail, LaborDetail, PricingDetail 권한 로직 정리
- BoardDetail, ClientDetail, ItemDetail 권한 적용 개선
- ProcessDetail, StepDetail, PermissionDetail 권한 리팩토링
- ContractDetail, HandoverReport, ProgressBilling 권한 연동
- ReceivingDetail, ShipmentDetail, WorkOrderDetail 권한 적용
- InspectionDetail, OrderSalesDetail, QuoteFooterBar 권한 개선
기능 개선:
- AuthenticatedLayout 구조 리팩토링
- JointbarInspectionDocument 문서 레이아웃 개선
- PricingTableForm 폼 기능 보강
- DynamicItemForm, SectionsTab 개선
- 주문관리 상세/생산지시 페이지 개선
- VendorLedgerDetail 수정
설정:
- Claude hooks 추가 (빌드 차단, 파일 크기 체크, 미사용 import 체크)
- 품질감사 문서관리 계획 문서 추가
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 20:26:27 +09:00
|
|
|
<Button onClick={onEdit} size="sm" className="md:size-default">
|
feat: 다중 도메인 UI 개선 및 컴포넌트 리팩토링
- 게시판, HR, 설정, 차량관리, 건설, 견적 등 전반적 UI 개선
- FormField, TabChip, Select 등 공통 컴포넌트 개선
- 가격배분 edit 페이지 제거 및 상세 페이지 통합
- 체크리스트, 근태, 급여, 권한 관리 등 폼 개선
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:30:06 +09:00
|
|
|
<Edit className="h-4 w-4 md:mr-2" />
|
feat(WEB): 상세 페이지 권한 체계 통합 및 레이아웃/문서 기능 개선
권한 시스템 통합:
- BadDebtDetail, LaborDetail, PricingDetail 권한 로직 정리
- BoardDetail, ClientDetail, ItemDetail 권한 적용 개선
- ProcessDetail, StepDetail, PermissionDetail 권한 리팩토링
- ContractDetail, HandoverReport, ProgressBilling 권한 연동
- ReceivingDetail, ShipmentDetail, WorkOrderDetail 권한 적용
- InspectionDetail, OrderSalesDetail, QuoteFooterBar 권한 개선
기능 개선:
- AuthenticatedLayout 구조 리팩토링
- JointbarInspectionDocument 문서 레이아웃 개선
- PricingTableForm 폼 기능 보강
- DynamicItemForm, SectionsTab 개선
- 주문관리 상세/생산지시 페이지 개선
- VendorLedgerDetail 수정
설정:
- Claude hooks 추가 (빌드 차단, 파일 크기 체크, 미사용 import 체크)
- 품질감사 문서관리 계획 문서 추가
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 20:26:27 +09:00
|
|
|
<span className="hidden md:inline">수정</span>
|
2026-01-26 15:07:10 +09:00
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-12-09 18:07:47 +09:00
|
|
|
</PageLayout>
|
2025-12-04 20:52:42 +09:00
|
|
|
);
|
|
|
|
|
}
|