Files
sam-react-prod/src/components/business/construction/estimates/sections/EstimateDetailTableSection.tsx
유병철 012a661a19 refactor(WEB): 회계/결재/건설 등 공통화 3차 및 검색/상태 유틸 추가
- search.ts: 범용 검색 유틸리티 추출 (텍스트/날짜/상태 필터링)
- status-config.ts: 상태 설정 공통 유틸 추가
- 회계 모듈 types 간소화 및 컬럼 설정 공통 패턴 적용
- 회계 page.tsx 통일 (bad-debt/bills/deposits/sales 등 9개)
- 결재함(승인/기안/참조) 공통 패턴 적용
- 건설 모듈 견적/인수인계/이슈/기성 등 코드 정리
- IntegratedListTemplateV2 개선
- LanguageSelect/ThemeSelect 정리
- 체크리스트 문서 업데이트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:26:27 +09:00

657 lines
32 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import React, { useState } from 'react';
import { X, HelpCircle } from 'lucide-react';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@/components/ui/tooltip';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { NumberInput } from '@/components/ui/number-input';
import { QuantityInput } from '@/components/ui/quantity-input';
import { CurrencyInput } from '@/components/ui/currency-input';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
import type { EstimateDetailItem } from '../types';
import { formatAmount } from '../utils';
import { calculateItemValuesWithApplied, calculateTotalsWithApplied } from '../hooks/useEstimateCalculations';
import type { CommonCodeOption } from '../actions';
// 계산식 정보
const FORMULA_INFO: Record<string, string> = {
weight: '면적 × 25',
area: '(가로 × 0.16) × (세로 × 0.5)',
steelScreen: '면적 × 47,500',
caulking: '(세로 × 4) × 조정단가',
rail: '(세로 × 0.2) × 조정단가',
bottom: '가로 × 조정단가',
boxReinforce: '가로 × 조정단가',
shaft: '가로 × 조정단가',
unitPrice: '철제스크린 + 코킹 + 레일 + 하장 + 박스보강 + 샤프트 + 도장 + 모터 + 제어기 + 가로시공비 + 세로시공비',
expense: '단가 × 공과율',
cost: '단가 + 공과',
costExecution: '원가 × 수량',
marginCost: '원가 × 마진율(1.03)',
marginCostExecution: '마진원가 × 수량',
expenseExecution: '공과 × 수량',
};
// 계산식 툴팁이 있는 헤더 컴포넌트
function FormulaHeader({ label, formulaKey, className }: { label: string; formulaKey: string; className?: string }) {
const formula = FORMULA_INFO[formulaKey];
if (!formula) {
return <span>{label}</span>;
}
return (
<TooltipProvider delayDuration={0}>
<Tooltip>
<TooltipTrigger asChild>
<span className={`inline-flex items-center gap-1 cursor-help ${className || ''}`}>
{label}
<HelpCircle className="h-3.5 w-3.5 text-gray-400 hover:text-gray-600" />
</span>
</TooltipTrigger>
<TooltipContent side="top" className="max-w-xs">
<p className="text-xs font-medium text-gray-700">{label} </p>
<p className="text-xs text-gray-500 mt-1">{formula}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}
// appliedPrices 타입 정의
export interface AppliedPrices {
caulking: number;
rail: number;
bottom: number;
boxReinforce: number;
shaft: number;
painting: number;
motor: number;
controller: number;
}
// 옵션 데이터 타입
export interface EstimateDetailOptions {
materials: CommonCodeOption[];
paintings: CommonCodeOption[];
motors: CommonCodeOption[];
controllers: CommonCodeOption[];
widthConstructions: CommonCodeOption[];
heightConstructions: CommonCodeOption[];
}
interface EstimateDetailTableSectionProps {
detailItems: EstimateDetailItem[];
appliedPrices: AppliedPrices | null;
isViewMode: boolean;
options?: EstimateDetailOptions;
onAddItems: (count: number) => void;
onRemoveItem: (id: string) => void;
onRemoveSelected: () => void;
onItemChange: (id: string, field: keyof EstimateDetailItem, value: string | number) => void;
onSelectItem: (id: string, selected: boolean) => void;
onSelectAll: (selected: boolean) => void;
onApplyAdjustedPrice: () => void;
onReset: () => void;
}
// API 데이터 로드 전 기본 옵션 (폴백용)
const DEFAULT_OPTIONS: EstimateDetailOptions = {
materials: [
{ value: 'screen', label: '스크린', code: 'screen' },
{ value: 'slat', label: '슬랫', code: 'slat' },
{ value: 'bending', label: '벤딩', code: 'bending' },
{ value: 'jointbar', label: '조인트바', code: 'jointbar' },
],
paintings: [
{ value: '0', label: '직접입력', code: '0', price: 0 },
{ value: '50000', label: '도장A', code: 'painting_a', price: 50000 },
{ value: '80000', label: '도장B', code: 'painting_b', price: 80000 },
],
motors: [
{ value: '300000', label: '모터 300,000', code: 'motor_300k', price: 300000 },
{ value: '500000', label: '모터 500,000', code: 'motor_500k', price: 500000 },
],
controllers: [
{ value: '150000', label: '제어기 150,000', code: 'ctrl_150k', price: 150000 },
{ value: '250000', label: '제어기 250,000', code: 'ctrl_250k', price: 250000 },
],
widthConstructions: [
{ value: '300000', label: '3.01~4.0M', code: 'w_3_4m', price: 300000 },
{ value: '400000', label: '4.01~5.0M', code: 'w_4_5m', price: 400000 },
{ value: '500000', label: '5.01~6.0M', code: 'w_5_6m', price: 500000 },
{ value: '600000', label: '6.01~7.0M', code: 'w_6_7m', price: 600000 },
],
heightConstructions: [
{ value: '5000', label: '3.51~4.5M', code: 'h_3_4m', price: 5000 },
{ value: '8000', label: '4.51~5.5M', code: 'h_4_5m', price: 8000 },
{ value: '10000', label: '5.51~6.5M', code: 'h_5_6m', price: 10000 },
],
};
export function EstimateDetailTableSection({
detailItems,
appliedPrices,
isViewMode,
options,
onAddItems,
onRemoveItem,
onRemoveSelected,
onItemChange,
onSelectItem,
onSelectAll,
onApplyAdjustedPrice,
onReset,
}: EstimateDetailTableSectionProps) {
const [detailAddCount, setDetailAddCount] = useState<number | undefined>(1);
// API 옵션이 없으면 기본 옵션 사용
const opts = options || DEFAULT_OPTIONS;
const selectedCount = detailItems.filter((item) => (item as unknown as { selected?: boolean }).selected).length;
const allSelected = detailItems.length > 0 && detailItems.every((item) => (item as unknown as { selected?: boolean }).selected);
const totals = calculateTotalsWithApplied(detailItems, appliedPrices);
return (
<Card>
<CardHeader className="flex flex-row items-center justify-between pb-4">
<div className="flex items-center gap-4">
<CardTitle className="text-lg whitespace-nowrap"> </CardTitle>
<span className="text-sm text-muted-foreground"> {detailItems.length}</span>
{!isViewMode && selectedCount > 0 && (
<div className="flex items-center gap-2">
<span className="text-sm text-muted-foreground">/</span>
<span className="text-sm text-primary font-medium">{selectedCount} </span>
<Button
type="button"
variant="default"
size="sm"
className="bg-gray-900 hover:bg-gray-800"
onClick={onRemoveSelected}
>
</Button>
<Button
type="button"
variant="default"
size="sm"
className="bg-blue-500 hover:bg-blue-600"
onClick={onApplyAdjustedPrice}
>
</Button>
</div>
)}
</div>
{!isViewMode && (
<div className="flex items-center gap-2">
<QuantityInput
min={1}
value={detailAddCount}
onChange={(val) => setDetailAddCount(val)}
className="w-16 text-center"
id="detail-add-count"
/>
<Button
type="button"
variant="default"
size="sm"
className="bg-gray-900 hover:bg-gray-800"
onClick={() => {
const count = Math.max(1, detailAddCount ?? 1);
onAddItems(count);
}}
>
</Button>
{/* TODO: 견적 상세 기획서 수정 후 초기화 버튼 및 테이블 항목/데이터 재작업 필요
<Button type="button" variant="outline" size="sm" onClick={onReset}>
초기화
</Button>
*/}
</div>
)}
</CardHeader>
<CardContent>
<div className="overflow-x-auto max-h-[600px]">
<Table>
<TableHeader className="sticky top-0 bg-white z-10">
<TableRow className="bg-gray-100">
{!isViewMode && (
<TableHead className="w-[40px] text-center sticky left-0 bg-gray-100 z-20">
<input
type="checkbox"
className="h-4 w-4 rounded border-gray-300"
checked={allSelected}
onChange={(e) => onSelectAll(e.target.checked)}
/>
</TableHead>
)}
<TableHead className="w-[100px] text-center"></TableHead>
<TableHead className="w-[80px] text-center"></TableHead>
<TableHead className="w-[70px] text-right"></TableHead>
<TableHead className="w-[70px] text-right"></TableHead>
<TableHead className="w-[70px] text-right">
<FormulaHeader label="무게" formulaKey="weight" />
</TableHead>
<TableHead className="w-[70px] text-right">
<FormulaHeader label="면적" formulaKey="area" />
</TableHead>
<TableHead className="w-[90px] text-right">
<FormulaHeader label="철제,스크린" formulaKey="steelScreen" />
</TableHead>
<TableHead className="w-[80px] text-right">
<FormulaHeader label="코킹" formulaKey="caulking" />
</TableHead>
<TableHead className="w-[80px] text-right">
<FormulaHeader label="레일" formulaKey="rail" />
</TableHead>
<TableHead className="w-[80px] text-right">
<FormulaHeader label="하장" formulaKey="bottom" />
</TableHead>
<TableHead className="w-[90px] text-right">
<FormulaHeader label="박스+보강" formulaKey="boxReinforce" />
</TableHead>
<TableHead className="w-[80px] text-right">
<FormulaHeader label="샤프트" formulaKey="shaft" />
</TableHead>
<TableHead className="w-[80px] text-center"></TableHead>
<TableHead className="w-[80px] text-center"></TableHead>
<TableHead className="w-[80px] text-center"></TableHead>
<TableHead className="w-[100px] text-center"></TableHead>
<TableHead className="w-[100px] text-center"></TableHead>
<TableHead className="w-[90px] text-right">
<FormulaHeader label="단가" formulaKey="unitPrice" />
</TableHead>
<TableHead className="w-[70px] text-right"></TableHead>
<TableHead className="w-[80px] text-right">
<FormulaHeader label="공과" formulaKey="expense" />
</TableHead>
<TableHead className="w-[50px] text-right"></TableHead>
<TableHead className="w-[90px] text-right">
<FormulaHeader label="원가" formulaKey="cost" />
</TableHead>
<TableHead className="w-[90px] text-right">
<FormulaHeader label="원가실행" formulaKey="costExecution" />
</TableHead>
<TableHead className="w-[90px] text-right">
<FormulaHeader label="마진원가" formulaKey="marginCost" />
</TableHead>
<TableHead className="w-[100px] text-right">
<FormulaHeader label="마진원가실행" formulaKey="marginCostExecution" />
</TableHead>
<TableHead className="w-[90px] text-right">
<FormulaHeader label="공과실행" formulaKey="expenseExecution" />
</TableHead>
{!isViewMode && <TableHead className="w-[50px] text-center"></TableHead>}
</TableRow>
</TableHeader>
<TableBody>
{detailItems.length === 0 ? (
<TableRow>
<TableCell
colSpan={isViewMode ? 27 : 29}
className="text-center text-gray-500 py-8"
>
.
</TableCell>
</TableRow>
) : (
<>
{detailItems.map((item) => {
const values = calculateItemValuesWithApplied(item, appliedPrices);
return (
<TableRow key={item.id}>
{!isViewMode && (
<TableCell className="text-center sticky left-0 bg-white">
<input
type="checkbox"
className="h-4 w-4 rounded border-gray-300"
checked={(item as unknown as { selected?: boolean }).selected || false}
onChange={(e) => onSelectItem(item.id, e.target.checked)}
/>
</TableCell>
)}
{/* 01: 명칭 */}
<TableCell>
<Input
value={item.name ?? ''}
onChange={(e) => onItemChange(item.id, 'name', e.target.value)}
disabled={isViewMode}
className={`w-full min-w-[80px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 02: 제품 */}
<TableCell>
<Select
value={item.material ?? ''}
onValueChange={(val) => onItemChange(item.id, 'material', val)}
disabled={isViewMode}
>
<SelectTrigger className={`w-full min-w-[70px] w-auto ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}>
<SelectValue placeholder="선택" />
</SelectTrigger>
<SelectContent>
{opts.materials.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</TableCell>
{/* 03: 가로 */}
<TableCell>
<NumberInput
step={0.01}
allowDecimal
value={item.width ?? 0}
onChange={(value) => onItemChange(item.id, 'width', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[60px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 04: 세로 */}
<TableCell>
<NumberInput
step={0.01}
allowDecimal
value={item.height ?? 0}
onChange={(value) => onItemChange(item.id, 'height', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[60px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 05: 무게 (인풋, 계산값 표시 + 수정 가능) */}
<TableCell>
<NumberInput
step={0.01}
allowDecimal
value={parseFloat(values.weight.toFixed(2))}
onChange={(value) => onItemChange(item.id, 'calcWeight', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[60px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 06: 면적 (인풋, 계산값 표시 + 수정 가능) */}
<TableCell>
<NumberInput
step={0.01}
allowDecimal
value={parseFloat(values.area.toFixed(2))}
onChange={(value) => onItemChange(item.id, 'calcArea', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[60px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 07: 철제,스크린 (인풋, 계산값 표시 + 수정 가능) */}
<TableCell>
<CurrencyInput
value={values.steelScreen}
onChange={(value) => onItemChange(item.id, 'calcSteelScreen', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[80px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 08: 코킹 (인풋, 계산값 표시 + 수정 가능) */}
<TableCell>
<CurrencyInput
value={values.caulking}
onChange={(value) => onItemChange(item.id, 'calcCaulking', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[70px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 09: 레일 (인풋, 계산값 표시 + 수정 가능) */}
<TableCell>
<CurrencyInput
value={values.rail}
onChange={(value) => onItemChange(item.id, 'calcRail', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[70px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 10: 하장 (인풋, 계산값 표시 + 수정 가능) */}
<TableCell>
<CurrencyInput
value={values.bottom}
onChange={(value) => onItemChange(item.id, 'calcBottom', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[70px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 11: 박스+보강 (인풋, 계산값 표시 + 수정 가능) */}
<TableCell>
<CurrencyInput
value={values.boxReinforce}
onChange={(value) => onItemChange(item.id, 'calcBoxReinforce', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[80px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 12: 샤프트 (인풋, 계산값 표시 + 수정 가능) */}
<TableCell>
<CurrencyInput
value={values.shaft}
onChange={(value) => onItemChange(item.id, 'calcShaft', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[70px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 13: 도장 */}
<TableCell>
<Select
value={String(item.coating || '')}
onValueChange={(val) => onItemChange(item.id, 'coating', Number(val))}
disabled={isViewMode}
>
<SelectTrigger className={`w-full min-w-[70px] w-auto ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}>
<SelectValue placeholder="선택" />
</SelectTrigger>
<SelectContent>
{opts.paintings.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</TableCell>
{/* 14: 모터 */}
<TableCell>
<Select
value={String(item.mounting || '300000')}
onValueChange={(val) => onItemChange(item.id, 'mounting', Number(val))}
disabled={isViewMode}
>
<SelectTrigger className={`w-full min-w-[70px] w-auto ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}>
<SelectValue placeholder="선택" />
</SelectTrigger>
<SelectContent>
{opts.motors.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</TableCell>
{/* 15: 제어기 */}
<TableCell>
<Select
value={String(item.controller || '')}
onValueChange={(val) => onItemChange(item.id, 'controller', Number(val))}
disabled={isViewMode}
>
<SelectTrigger className={`w-full min-w-[70px] w-auto ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}>
<SelectValue placeholder="선택" />
</SelectTrigger>
<SelectContent>
{opts.controllers.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</TableCell>
{/* 16: 가로시공비 */}
<TableCell>
<Select
value={String(item.widthConstruction || '')}
onValueChange={(val) => onItemChange(item.id, 'widthConstruction', Number(val))}
disabled={isViewMode}
>
<SelectTrigger className={`w-full min-w-[90px] w-auto ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}>
<SelectValue placeholder="선택" />
</SelectTrigger>
<SelectContent>
{opts.widthConstructions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</TableCell>
{/* 17: 세로시공비 */}
<TableCell>
<Select
value={String(item.heightConstruction || '')}
onValueChange={(val) => onItemChange(item.id, 'heightConstruction', Number(val))}
disabled={isViewMode}
>
<SelectTrigger className={`w-full min-w-[90px] w-auto ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}>
<SelectValue placeholder="선택" />
</SelectTrigger>
<SelectContent>
{opts.heightConstructions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</TableCell>
{/* 18: 단가 (인풋, 계산값 표시 + 수정 가능) */}
<TableCell>
<CurrencyInput
value={values.unitPrice}
onChange={(value) => onItemChange(item.id, 'calcUnitPrice', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[80px] font-medium ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 19: 공과율 */}
<TableCell>
<NumberInput
step={0.01}
allowDecimal
value={item.expense ?? 0}
onChange={(value) => onItemChange(item.id, 'expense', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[60px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 20: 공과 (인풋, 계산값 표시 + 수정 가능) */}
<TableCell>
<CurrencyInput
value={values.expense}
onChange={(value) => onItemChange(item.id, 'calcExpense', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[70px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 21: 수량 */}
<TableCell>
<QuantityInput
min={1}
value={item.quantity ?? 0}
onChange={(value) => onItemChange(item.id, 'quantity', value ?? 0)}
disabled={isViewMode}
className={`text-right min-w-[40px] ${isViewMode ? 'bg-gray-50' : 'bg-white'}`}
/>
</TableCell>
{/* 22: 원가 */}
<TableCell className="text-right bg-gray-50">{formatAmount(values.cost)}</TableCell>
{/* 23: 원가실행 */}
<TableCell className="text-right bg-gray-50">{formatAmount(values.costExecution)}</TableCell>
{/* 24: 마진원가 */}
<TableCell className="text-right bg-gray-50">{formatAmount(values.marginCost)}</TableCell>
{/* 25: 마진원가실행 */}
<TableCell className="text-right bg-gray-50 font-medium">{formatAmount(values.marginCostExecution)}</TableCell>
{/* 26: 공과실행 */}
<TableCell className="text-right bg-gray-50">{formatAmount(values.expenseExecution)}</TableCell>
{!isViewMode && (
<TableCell className="text-center">
<Button
type="button"
variant="ghost"
size="icon"
className="h-8 w-8 text-red-500 hover:text-red-600"
onClick={() => onRemoveItem(item.id)}
>
<X className="h-4 w-4" />
</Button>
</TableCell>
)}
</TableRow>
);
})}
{/* 합계 행 */}
{detailItems.length > 0 && (
<TableRow className="bg-orange-50 font-medium border-t-2 border-orange-300">
{!isViewMode && <TableCell className="sticky left-0 bg-orange-50"></TableCell>}
<TableCell colSpan={4} className="text-center font-bold"></TableCell>
<TableCell className="text-right">{totals.weight.toFixed(2)}</TableCell>
<TableCell className="text-right">{totals.area.toFixed(2)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.steelScreen)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.caulking)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.rail)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.bottom)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.boxReinforce)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.shaft)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.painting)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.motor)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.controller)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.widthConstruction)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.heightConstruction)}</TableCell>
<TableCell className="text-right font-bold">{formatAmount(totals.unitPrice)}</TableCell>
<TableCell className="text-right">-</TableCell>
<TableCell className="text-right">{formatAmount(totals.expense)}</TableCell>
<TableCell className="text-right">{totals.quantity}</TableCell>
<TableCell className="text-right">{formatAmount(totals.cost)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.costExecution)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.marginCost)}</TableCell>
<TableCell className="text-right font-bold">{formatAmount(totals.marginCostExecution)}</TableCell>
<TableCell className="text-right">{formatAmount(totals.expenseExecution)}</TableCell>
{!isViewMode && <TableCell></TableCell>}
</TableRow>
)}
</>
)}
</TableBody>
</Table>
</div>
</CardContent>
</Card>
);
}