Files
frontend/apps/as/src/pages/checklist-management/ui/cklst-rvw-row.tsx
T
jcchoi 48999f5699
Deploy Frontend / deploy (push) Successful in 9m6s
웹 접근성 조치
2026-10-11 15:32:56 +09:00

154 lines
4.8 KiB
TypeScript

"use client";
import type { CklstArtcl } from "@/entities/cklst";
import {
Button,
Input,
Label,
RadioGroup,
RadioGroupItem,
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
TableCell,
TableRow,
} from "@common/components";
import {
canAddChildRow,
formatRvwCnLvNo,
formatTreeBranchPrefix,
} from "../model/build-rvw-display-rows";
import type { CklstRvwRow } from "../model/cklst-rvw-row-types";
interface CklstRvwRowProps {
row: CklstRvwRow;
depth: number;
artclOptions: CklstArtcl[];
onChange: (patch: Partial<CklstRvwRow>) => void;
onAddChild: () => void;
onDelete: () => void;
}
function CklstRvwRowComponent({
row,
depth,
artclOptions,
onChange,
onAddChild,
onDelete,
}: CklstRvwRowProps) {
const levelLabel = formatRvwCnLvNo(row.rvwCnLvNo);
const branchPrefix = formatTreeBranchPrefix(depth);
return (
<TableRow>
<TableCell>
<div className="flex min-w-[12rem] items-center gap-1">
{branchPrefix ? (
<span className="shrink-0 font-mono text-muted">{branchPrefix}</span>
) : null}
<Select
value={row.cklstArtclSn ? String(row.cklstArtclSn) : ""}
onValueChange={(v) => onChange({ cklstArtclSn: Number(v), isDirty: true })}
disabled={!row.isNew}
>
{/* 비활성(기존 항목) 상태에서도 텍스트 명도 대비 4.5:1 이상 유지 */}
<SelectTrigger
title="점검항목 선택"
className="w-full flex-1 disabled:opacity-100"
>
<SelectValue placeholder="점검항목 선택" />
</SelectTrigger>
<SelectContent>
{artclOptions.map((artcl) => (
<SelectItem key={artcl.cklstArtclSn} value={String(artcl.cklstArtclSn)}>
{artcl.cklstArtclNm ?? artcl.cklstArtclSn}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</TableCell>
<TableCell>
<Input
value={row.rvwCn ?? ""}
onChange={(e) => onChange({ rvwCn: e.target.value, isDirty: true })}
placeholder="주요 검토내용"
title="주요 검토내용"
/>
</TableCell>
<TableCell align="center">
<RadioGroup
value={row.useYn ?? "Y"}
onValueChange={(v) => onChange({ useYn: v as "Y" | "N", isDirty: true })}
aria-label="사용 여부"
className="flex justify-center gap-4"
>
<div className="flex items-center gap-2">
<RadioGroupItem value="Y" id={`${row.rowKey}-use-y`} />
<Label htmlFor={`${row.rowKey}-use-y`}>예</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="N" id={`${row.rowKey}-use-n`} />
<Label htmlFor={`${row.rowKey}-use-n`}>아니오</Label>
</div>
</RadioGroup>
</TableCell>
<TableCell align="center">
<RadioGroup
value={row.bchckUseYn ?? "Y"}
onValueChange={(v) => onChange({ bchckUseYn: v as "Y" | "N", isDirty: true })}
aria-label="체크 사용"
className="flex justify-center gap-4"
>
<div className="flex items-center gap-2">
<RadioGroupItem value="Y" id={`${row.rowKey}-bchck-y`} />
<Label htmlFor={`${row.rowKey}-bchck-y`}>예</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="N" id={`${row.rowKey}-bchck-n`} />
<Label htmlFor={`${row.rowKey}-bchck-n`}>아니오</Label>
</div>
</RadioGroup>
</TableCell>
<TableCell align="center">
<Input
type="number"
min={0}
title="정렬 순서"
value={row.sortSeq ?? ""}
onChange={(e) =>
onChange({
sortSeq: e.target.value ? Number(e.target.value) : undefined,
isDirty: true,
})
}
className="w-20"
/>
</TableCell>
<TableCell align="center">{levelLabel}</TableCell>
<TableCell align="center">
<div className="flex justify-center gap-2">
<Button
type="button"
size="sm"
color="white"
disabled={row.isNew || !canAddChildRow(row.rvwCnLvNo)}
onClick={onAddChild}
>
하위추가
</Button>
<Button type="button" size="sm" color="gray" onClick={onDelete}>
삭제
</Button>
</div>
</TableCell>
</TableRow>
);
}
export { CklstRvwRowComponent };