Files
sam-react-prod/src/components/accounting/IncomeStatement/PeriodView.tsx

223 lines
7.0 KiB
TypeScript

'use client';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
import { formatNumber } from '@/lib/utils/amount';
import type { IncomeStatementData } from './types';
import { HIGHLIGHT_CODES } from './types';
interface PeriodViewProps {
data: IncomeStatementData;
showPrevious: boolean;
unitLabel: string;
}
export function PeriodView({ data, showPrevious, unitLabel }: PeriodViewProps) {
const { period, sections } = data;
const colSpan = showPrevious ? 5 : 3; // 과목 + (금액+소계) * 기수
return (
<div className="space-y-1">
<div className="rounded-md border overflow-x-auto">
<div className="min-w-[400px]">
<Table>
<TableHeader>
{/* 1행: 과목 + 기수 헤더 (녹색 배경) */}
<TableRow className="bg-green-700 hover:bg-green-700">
<TableHead
rowSpan={2}
className="font-semibold text-xs md:text-sm text-white w-[40%] border-r border-green-600"
>
</TableHead>
<TableHead
colSpan={2}
className="font-semibold text-center text-xs md:text-sm text-white border-b border-green-600"
>
{period.current.label}
</TableHead>
{showPrevious && (
<TableHead
colSpan={2}
className="font-semibold text-center text-xs md:text-sm text-white border-b border-green-600 border-l border-green-600"
>
{period.previous.label}
</TableHead>
)}
</TableRow>
{/* 2행: 금 액 서브헤더 */}
<TableRow className="bg-green-700 hover:bg-green-700">
<TableHead
colSpan={2}
className="font-semibold text-center text-xs md:text-sm text-white"
>
</TableHead>
{showPrevious && (
<TableHead
colSpan={2}
className="font-semibold text-center text-xs md:text-sm text-white border-l border-green-600"
>
</TableHead>
)}
</TableRow>
</TableHeader>
<TableBody>
{sections.map((section) => {
const isHighlight = HIGHLIGHT_CODES.includes(section.code);
const hasItems = section.items.length > 0;
return (
<SectionRows
key={section.code}
code={section.code}
name={section.name}
currentAmount={section.currentAmount}
previousAmount={section.previousAmount}
items={section.items}
isHighlight={isHighlight}
hasItems={hasItems}
showPrevious={showPrevious}
/>
);
})}
</TableBody>
</Table>
</div>
</div>
{/* 하단 단위 표기 */}
<div className="text-xs text-muted-foreground text-right px-1">
(: {unitLabel})
</div>
</div>
);
}
interface SectionRowsProps {
code: string;
name: string;
currentAmount: number;
previousAmount: number;
items: { code: string; name: string; current: number; previous: number }[];
isHighlight: boolean;
hasItems: boolean;
showPrevious: boolean;
}
function SectionRows({
code,
name,
currentAmount,
previousAmount,
items,
isHighlight,
hasItems,
showPrevious,
}: SectionRowsProps) {
const highlightClass = isHighlight ? 'bg-green-50' : '';
// 계산 항목 (III, V, VIII, X 등) — 소계열에만 금액 표시
if (!hasItems && isHighlight) {
return (
<TableRow className={highlightClass}>
<TableCell className="text-xs md:text-sm font-semibold">
{code}. {name}
</TableCell>
<TableCell />
<TableCell className="text-right text-xs md:text-sm font-bold whitespace-nowrap">
{formatNumber(currentAmount)}
</TableCell>
{showPrevious && (
<>
<TableCell />
<TableCell className="text-right text-xs md:text-sm font-bold whitespace-nowrap">
{formatNumber(previousAmount)}
</TableCell>
</>
)}
</TableRow>
);
}
// 세부과목 없는 합계 항목 (VIII 등) — 소계열에만 금액
if (!hasItems) {
return (
<TableRow className={highlightClass}>
<TableCell className="text-xs md:text-sm font-semibold">
{code}. {name}
</TableCell>
<TableCell />
<TableCell className="text-right text-xs md:text-sm font-semibold whitespace-nowrap">
{currentAmount !== 0 ? formatNumber(currentAmount) : ''}
</TableCell>
{showPrevious && (
<>
<TableCell />
<TableCell className="text-right text-xs md:text-sm font-semibold whitespace-nowrap">
{previousAmount !== 0 ? formatNumber(previousAmount) : ''}
</TableCell>
</>
)}
</TableRow>
);
}
// 세부 과목이 있는 항목 (I, II, IV, VI, VII, IX)
const lastIdx = items.length - 1;
return (
<>
{/* 섹션 헤더 — 금액 표시 안 함 */}
<TableRow>
<TableCell className="text-xs md:text-sm font-semibold">
{code}. {name}
</TableCell>
<TableCell />
<TableCell />
{showPrevious && (
<>
<TableCell />
<TableCell />
</>
)}
</TableRow>
{/* 세부 과목 행 — 들여쓰기 */}
{items.map((item, idx) => {
const isLast = idx === lastIdx;
return (
<TableRow key={item.code}>
<TableCell className="text-xs md:text-sm pl-8 text-muted-foreground">
{item.name}
</TableCell>
{/* 금액 열 */}
<TableCell className="text-right text-xs md:text-sm whitespace-nowrap">
{item.current !== 0 ? formatNumber(item.current) : ''}
</TableCell>
{/* 소계 열 — 마지막 세부항목에만 섹션 합계 표시 */}
<TableCell className="text-right text-xs md:text-sm whitespace-nowrap font-semibold">
{isLast ? formatNumber(currentAmount) : ''}
</TableCell>
{showPrevious && (
<>
<TableCell className="text-right text-xs md:text-sm whitespace-nowrap">
{item.previous !== 0 ? formatNumber(item.previous) : ''}
</TableCell>
<TableCell className="text-right text-xs md:text-sm whitespace-nowrap font-semibold">
{isLast ? formatNumber(previousAmount) : ''}
</TableCell>
</>
)}
</TableRow>
);
})}
</>
);
}