Merge remote-tracking branch 'origin/iipbs/sn/dev' into iipbs/sn/dev_kic
This commit is contained in:
@@ -109,6 +109,7 @@ const BaseLayout = ({
|
||||
onDeleteFile,
|
||||
onAnalysis,
|
||||
onResultView,
|
||||
selectedRowData,
|
||||
isIr = false,
|
||||
isRdii = false,
|
||||
}: BaseLayout) => {
|
||||
@@ -283,11 +284,7 @@ const BaseLayout = ({
|
||||
</Button>
|
||||
)}
|
||||
{resultViewBtn && (
|
||||
<Button
|
||||
type="button"
|
||||
color="white"
|
||||
onClick={onResultView}
|
||||
>
|
||||
<Button type="button" color="white" onClick={onResultView}>
|
||||
{resultViewBtn}
|
||||
</Button>
|
||||
)}
|
||||
@@ -295,6 +292,7 @@ const BaseLayout = ({
|
||||
<Button
|
||||
type="button"
|
||||
color="red"
|
||||
disabled={!selectedRowData}
|
||||
onClick={isDeleteFile}
|
||||
>
|
||||
삭제
|
||||
@@ -321,14 +319,15 @@ const BaseLayout = ({
|
||||
{titleName?.secondCardTitle}
|
||||
</h3>
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
{graphBtn && (
|
||||
<Button type="button">
|
||||
엑셀다운로드
|
||||
</Button>
|
||||
)}
|
||||
{graphBtn && <Button type="button">엑셀다운로드</Button>}
|
||||
{/* 그래프 있을 시 */}
|
||||
{graphBtn && (
|
||||
<Button type="button" color="red">
|
||||
<Button
|
||||
type="button"
|
||||
color="red"
|
||||
disabled={!selectedRowData}
|
||||
onClick={isDeleteFile}
|
||||
>
|
||||
삭제
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -342,7 +342,12 @@ const Page = () => {
|
||||
<Button type="button" onClick={handleRegisterClick}>
|
||||
등록
|
||||
</Button>
|
||||
<Button type="button" color="red" onClick={isDeleteFile}>
|
||||
<Button
|
||||
type="button"
|
||||
color="red"
|
||||
disabled={isLoading || !sbmrgPrevntBizSn}
|
||||
onClick={isDeleteFile}
|
||||
>
|
||||
삭제
|
||||
</Button>
|
||||
</>
|
||||
|
||||
@@ -317,7 +317,12 @@ const Page = () => {
|
||||
<Button type="button" onClick={handleRegister}>
|
||||
등록
|
||||
</Button>
|
||||
<Button type="button" color="red" onClick={handleDelete}>
|
||||
<Button
|
||||
type="button"
|
||||
color="red"
|
||||
disabled={loading || !businessId}
|
||||
onClick={handleDelete}
|
||||
>
|
||||
삭제
|
||||
</Button>
|
||||
</>
|
||||
|
||||
@@ -438,7 +438,7 @@ export function ExmnBusinessRegisterPopupPage({
|
||||
disabled={isLoading || formLocked}
|
||||
onClick={() => void handleSave()}
|
||||
>
|
||||
{isEditMode ? "수정" : "저장"}
|
||||
저장
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
|
||||
@@ -60,9 +60,9 @@ export function ExmnPplUnitDetailTable({
|
||||
const tableWidth = COLUMN_WIDTHS.reduce((sum, width) => sum + width, 0);
|
||||
|
||||
return (
|
||||
<div className="min-h-0 flex-1 overflow-x-auto overflow-y-visible border border-border bg-background">
|
||||
<div className="min-w-0 overflow-x-auto overflow-y-visible bg-background">
|
||||
<table
|
||||
className="border-separate border-spacing-0 text-center text-[1.05rem] text-foreground"
|
||||
className="table-ui default border-separate border-spacing-0 text-center text-foreground"
|
||||
style={{ width: "100%", minWidth: `${tableWidth}px` }}
|
||||
>
|
||||
<colgroup>
|
||||
@@ -70,17 +70,17 @@ export function ExmnPplUnitDetailTable({
|
||||
<col key={`unit-column-${index}`} style={{ width: `${width}px` }} />
|
||||
))}
|
||||
</colgroup>
|
||||
<thead className="sticky top-0 z-30 bg-primary text-center text-[1.2rem] font-medium leading-[1.2] text-primary-foreground">
|
||||
<thead className="sticky top-0 z-30 text-center font-medium leading-[1.2]">
|
||||
<tr>
|
||||
<th
|
||||
rowSpan={2}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
className="border-b border-r border-border px-2 py-[1.2rem] text-center"
|
||||
>
|
||||
관로번호
|
||||
</th>
|
||||
<th
|
||||
rowSpan={2}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
className="border-b border-r border-border px-2 py-[1.2rem] text-center"
|
||||
>
|
||||
단위
|
||||
<br />
|
||||
@@ -88,7 +88,7 @@ export function ExmnPplUnitDetailTable({
|
||||
</th>
|
||||
<th
|
||||
rowSpan={2}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
className="border-b border-r border-border px-2 py-[1.2rem] text-center"
|
||||
>
|
||||
단위
|
||||
<br />
|
||||
@@ -98,7 +98,7 @@ export function ExmnPplUnitDetailTable({
|
||||
</th>
|
||||
<th
|
||||
rowSpan={2}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
className="border-b border-r border-border px-2 py-[1.2rem] text-center"
|
||||
>
|
||||
결함
|
||||
<br />
|
||||
@@ -108,58 +108,58 @@ export function ExmnPplUnitDetailTable({
|
||||
</th>
|
||||
<th
|
||||
colSpan={6}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
className="border-b border-r border-border px-2 py-[1.2rem] text-center"
|
||||
>
|
||||
결함
|
||||
</th>
|
||||
<th
|
||||
colSpan={2}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
className="border-b border-r border-border px-2 py-[1.2rem] text-center"
|
||||
>
|
||||
등급점수(점)
|
||||
</th>
|
||||
<th
|
||||
rowSpan={2}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
className="border-b border-r border-border px-2 py-[1.2rem] text-center"
|
||||
>
|
||||
조사중단사유
|
||||
</th>
|
||||
<th
|
||||
rowSpan={2}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
className="border-b border-r border-border px-2 py-[1.2rem] text-center"
|
||||
>
|
||||
비고
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground">
|
||||
<th className="border-b border-r border-border px-2 py-[1.2rem] text-center">
|
||||
종류
|
||||
</th>
|
||||
<th className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground">
|
||||
<th className="border-b border-r border-border px-2 py-[1.2rem] text-center">
|
||||
코드
|
||||
</th>
|
||||
<th className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground">
|
||||
<th className="border-b border-r border-border px-2 py-[1.2rem] text-center">
|
||||
등급
|
||||
</th>
|
||||
<th className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground">
|
||||
<th className="border-b border-r border-border px-2 py-[1.2rem] text-center">
|
||||
발생
|
||||
<br />
|
||||
위치
|
||||
</th>
|
||||
<th className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground">
|
||||
<th className="border-b border-r border-border px-2 py-[1.2rem] text-center">
|
||||
침입수
|
||||
<br />
|
||||
가점
|
||||
</th>
|
||||
<th className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground">
|
||||
<th className="border-b border-r border-border px-2 py-[1.2rem] text-center">
|
||||
연속
|
||||
<br />
|
||||
결함
|
||||
</th>
|
||||
<th className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground">
|
||||
<th className="border-b border-r border-border px-2 py-[1.2rem] text-center">
|
||||
구조적
|
||||
</th>
|
||||
<th className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground">
|
||||
<th className="border-b border-r border-border px-2 py-[1.2rem] text-center">
|
||||
운영적
|
||||
</th>
|
||||
</tr>
|
||||
@@ -181,7 +181,7 @@ export function ExmnPplUnitDetailTable({
|
||||
{showPipeCell && (
|
||||
<td
|
||||
rowSpan={pipeSpan?.count}
|
||||
className="border-b border-r border-border bg-background px-2 py-2.5 align-middle font-medium text-primary"
|
||||
className="border-b border-r border-border bg-background px-2 py-[1.2rem] align-middle font-medium text-primary"
|
||||
>
|
||||
{row.pipeNo}
|
||||
</td>
|
||||
@@ -190,49 +190,49 @@ export function ExmnPplUnitDetailTable({
|
||||
<>
|
||||
<td
|
||||
rowSpan={unitSpan?.count}
|
||||
className="border-b border-r border-border bg-background px-2 py-2.5 align-middle font-medium"
|
||||
className="border-b border-r border-border bg-background px-2 py-[1.2rem] align-middle font-medium"
|
||||
>
|
||||
{row.unitSeq}
|
||||
</td>
|
||||
<td
|
||||
rowSpan={unitSpan?.count}
|
||||
className="border-b border-r border-border bg-background px-2 py-2.5 align-middle"
|
||||
className="border-b border-r border-border bg-background px-2 py-[1.2rem] align-middle"
|
||||
>
|
||||
{row.unitLengthM}
|
||||
</td>
|
||||
</>
|
||||
)}
|
||||
<td className="border-b border-r border-border px-2 py-2.5">
|
||||
<td className="border-b border-r border-border px-2 py-[1.2rem]">
|
||||
{formatOptionalValue(row.defectPositionM)}
|
||||
</td>
|
||||
<td className="border-b border-r border-border px-2 py-2.5 text-left">
|
||||
<td className="border-b border-r border-border px-2 py-[1.2rem] text-left">
|
||||
{row.defectName}
|
||||
</td>
|
||||
<td className="border-b border-r border-border px-2 py-2.5">
|
||||
<td className="border-b border-r border-border px-2 py-[1.2rem]">
|
||||
{row.code}
|
||||
</td>
|
||||
<td className="border-b border-r border-border px-2 py-2.5">
|
||||
<td className="border-b border-r border-border px-2 py-[1.2rem]">
|
||||
{row.severity ? SEVERITY_LABELS[row.severity] : "-"}
|
||||
</td>
|
||||
<td className="border-b border-r border-border px-2 py-2.5">
|
||||
<td className="border-b border-r border-border px-2 py-[1.2rem]">
|
||||
{formatOptionalValue(row.occurrencePosition)}
|
||||
</td>
|
||||
<td className="border-b border-r border-border px-2 py-2.5">
|
||||
<td className="border-b border-r border-border px-2 py-[1.2rem]">
|
||||
{formatOptionalValue(row.infiltrationBonus)}
|
||||
</td>
|
||||
<td className="border-b border-r border-border px-2 py-2.5">
|
||||
<td className="border-b border-r border-border px-2 py-[1.2rem]">
|
||||
{row.continuous == null ? "-" : row.continuous ? "Y" : "N"}
|
||||
</td>
|
||||
<td className="border-b border-r border-border px-2 py-2.5">
|
||||
<td className="border-b border-r border-border px-2 py-[1.2rem]">
|
||||
{formatOptionalValue(row.structuralScore)}
|
||||
</td>
|
||||
<td className="border-b border-r border-border px-2 py-2.5">
|
||||
<td className="border-b border-r border-border px-2 py-[1.2rem]">
|
||||
{formatOptionalValue(row.operationalScore)}
|
||||
</td>
|
||||
<td className="border-b border-r border-border px-2 py-2.5">
|
||||
<td className="border-b border-r border-border px-2 py-[1.2rem]">
|
||||
{formatOptionalValue(row.surveyStopReason)}
|
||||
</td>
|
||||
<td className="border-b border-r border-border px-2 py-2.5">
|
||||
<td className="border-b border-r border-border px-2 py-[1.2rem]">
|
||||
{formatOptionalValue(row.remark)}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -633,7 +633,7 @@ export function ExmnRegistrationPage() {
|
||||
<Button
|
||||
type="button"
|
||||
color="primary"
|
||||
disabled={isLoading}
|
||||
disabled={isLoading || !selectedBusiness}
|
||||
onClick={openBusinessUpdate}
|
||||
>
|
||||
수정
|
||||
|
||||
@@ -76,7 +76,7 @@ const FIXED_COLUMNS = [
|
||||
const REPORT_COLUMN_LEFT = 0;
|
||||
const PIPE_COLUMN_LEFT = FIXED_COLUMNS[0].width;
|
||||
const STICKY_COLUMN_COUNT = 2;
|
||||
const STICKY_DIVIDER_SHADOW = "2px 0 0 #b8c5d1";
|
||||
const STICKY_DIVIDER_SHADOW = "2px 0 0 hsl(var(--border))";
|
||||
const SEVERITY_COLUMN_WIDTH = 52;
|
||||
type ExmnDetailFixedColumnId = (typeof FIXED_COLUMNS)[number]["id"];
|
||||
|
||||
@@ -247,21 +247,6 @@ export function ExmnSurveyDetailPopupPage({
|
||||
}, [actualUnitRows, appliedDetailNumberKeyword, isUnitMode]);
|
||||
const rows = filteredRows;
|
||||
|
||||
/** 팝업 문서 자체 스크롤을 잠그고 넓은 표의 스크롤은 표 영역에서만 처리한다. */
|
||||
useEffect(() => {
|
||||
const previousHtmlOverflow = document.documentElement.style.overflow;
|
||||
const previousBodyOverflow = document.body.style.overflow;
|
||||
const previousBodyWidth = document.body.style.width;
|
||||
document.documentElement.style.overflow = "hidden";
|
||||
document.body.style.overflow = "hidden";
|
||||
document.body.style.width = "100%";
|
||||
return () => {
|
||||
document.documentElement.style.overflow = previousHtmlOverflow;
|
||||
document.body.style.overflow = previousBodyOverflow;
|
||||
document.body.style.width = previousBodyWidth;
|
||||
};
|
||||
}, []);
|
||||
|
||||
/** 관로·맨홀 조사유형 또는 결함 범위가 바뀌면 이전 검색 조건과 안내를 초기화한다. */
|
||||
useEffect(() => {
|
||||
setDetailMode("PIPE");
|
||||
@@ -730,11 +715,6 @@ export function ExmnSurveyDetailPopupPage({
|
||||
: defectType === "ALL"
|
||||
? `${selectedTrtdstNm} ${definition.defectGroupTitle}조사 집계표`
|
||||
: `${selectedTrtdstNm} ${definition.defectGroupTitle}조사 ${defectTypeLabel} 집계표`;
|
||||
const visibleDefectGroupTitle =
|
||||
defectType === "ALL"
|
||||
? definition.defectGroupTitle
|
||||
: `${definition.defectGroupTitle} ${defectTypeLabel}`;
|
||||
|
||||
return (
|
||||
<StandardPopupLayout
|
||||
title={popupTitle}
|
||||
@@ -753,115 +733,122 @@ export function ExmnSurveyDetailPopupPage({
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
bodyClassName="flex flex-col overflow-hidden"
|
||||
bodyClassName="overflow-x-hidden"
|
||||
>
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
{notice && (
|
||||
<div
|
||||
role="status"
|
||||
className="border-primary/20 mb-3 shrink-0 rounded-sm border bg-secondary px-4 py-2 text-[1.05rem] text-primary"
|
||||
className="border-primary/20 rounded-sm border bg-secondary px-4 py-2 text-[1.3rem] text-primary"
|
||||
>
|
||||
{notice.text}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<section className="flex min-h-0 flex-1 flex-col overflow-hidden">
|
||||
<section className="flex min-w-0 flex-col gap-[1.2rem]">
|
||||
{!isDefectTypeView && (
|
||||
<div className="card card-border !m-0 mb-3 flex shrink-0 flex-wrap items-end justify-between gap-4 !p-3">
|
||||
<div className="flex flex-wrap items-end gap-3">
|
||||
<div className="grid w-[18rem] gap-1.5">
|
||||
<Label htmlFor="exmn-detail-district">처리분구</Label>
|
||||
<Select
|
||||
value={selectedTrtdstId}
|
||||
onValueChange={(value) => {
|
||||
setSelectedTrtdstId(value);
|
||||
setActualRows([]);
|
||||
setActualUnitRows([]);
|
||||
setDetailNumberKeyword("");
|
||||
setAppliedDetailNumberKeyword("");
|
||||
setNotice(null);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger id="exmn-detail-district" className="w-full">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{districtOptions.length > 0 ? (
|
||||
districtOptions.map((district) => (
|
||||
<SelectItem
|
||||
key={district.trtdstId}
|
||||
value={district.trtdstId}
|
||||
>
|
||||
{district.trtdstNm}
|
||||
</SelectItem>
|
||||
))
|
||||
) : (
|
||||
<SelectItem value={trtdstId}>{trtdstNm}</SelectItem>
|
||||
)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="grid w-[30rem] gap-1.5">
|
||||
<Label htmlFor="exmn-detail-pipe-number">관로번호</Label>
|
||||
<Input
|
||||
id="exmn-detail-pipe-number"
|
||||
value={detailNumberKeyword}
|
||||
placeholder="관로번호 입력"
|
||||
onChange={(event) =>
|
||||
setDetailNumberKeyword(event.target.value)
|
||||
}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === "Enter") handleSearch();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="card card-border !m-0 flex flex-wrap items-center gap-3 !p-[1.2rem]">
|
||||
<div className="flex items-center gap-2">
|
||||
<Label
|
||||
htmlFor="exmn-detail-district"
|
||||
className="mr-2 whitespace-nowrap text-label"
|
||||
>
|
||||
처리분구
|
||||
</Label>
|
||||
<Select
|
||||
value={selectedTrtdstId}
|
||||
onValueChange={(value) => {
|
||||
setSelectedTrtdstId(value);
|
||||
setActualRows([]);
|
||||
setActualUnitRows([]);
|
||||
setDetailNumberKeyword("");
|
||||
setAppliedDetailNumberKeyword("");
|
||||
setNotice(null);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger id="exmn-detail-district" className="w-[18rem]">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{districtOptions.length > 0 ? (
|
||||
districtOptions.map((district) => (
|
||||
<SelectItem
|
||||
key={district.trtdstId}
|
||||
value={district.trtdstId}
|
||||
>
|
||||
{district.trtdstNm}
|
||||
</SelectItem>
|
||||
))
|
||||
) : (
|
||||
<SelectItem value={trtdstId}>{trtdstNm}</SelectItem>
|
||||
)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap items-end gap-3">
|
||||
{jobType === "PPL" && (
|
||||
<fieldset className="grid gap-1.5">
|
||||
<legend className="mb-1 text-sm font-medium text-label">
|
||||
상세구분
|
||||
</legend>
|
||||
<div
|
||||
className="flex items-center gap-1"
|
||||
role="group"
|
||||
aria-label="관로 상세보기 모드"
|
||||
>
|
||||
{(
|
||||
Object.keys(PPL_DETAIL_MODE_LABELS) as ExmnPplDetailMode[]
|
||||
).map((mode) => (
|
||||
<Button
|
||||
key={mode}
|
||||
type="button"
|
||||
color={detailMode === mode ? "primary" : "white"}
|
||||
aria-pressed={detailMode === mode}
|
||||
onClick={() => handleDetailModeChange(mode)}
|
||||
>
|
||||
{PPL_DETAIL_MODE_LABELS[mode]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</fieldset>
|
||||
)}
|
||||
<div className="flex items-center gap-2">
|
||||
<Label
|
||||
htmlFor="exmn-detail-pipe-number"
|
||||
className="mr-2 whitespace-nowrap text-label"
|
||||
>
|
||||
관로번호
|
||||
</Label>
|
||||
<Input
|
||||
id="exmn-detail-pipe-number"
|
||||
className="w-[30rem]"
|
||||
value={detailNumberKeyword}
|
||||
placeholder="관로번호 입력"
|
||||
onChange={(event) => setDetailNumberKeyword(event.target.value)}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === "Enter") handleSearch();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{jobType === "PPL" && (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button type="button" color="primary" onClick={handleSearch}>
|
||||
조회
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
color="white"
|
||||
onClick={() => {
|
||||
setDetailNumberKeyword("");
|
||||
setAppliedDetailNumberKeyword("");
|
||||
setNotice(null);
|
||||
}}
|
||||
<Label className="mr-2 whitespace-nowrap text-label">
|
||||
상세구분
|
||||
</Label>
|
||||
<div
|
||||
className="flex items-center gap-1"
|
||||
role="group"
|
||||
aria-label="관로 상세보기 모드"
|
||||
>
|
||||
초기화
|
||||
</Button>
|
||||
{(
|
||||
Object.keys(PPL_DETAIL_MODE_LABELS) as ExmnPplDetailMode[]
|
||||
).map((mode) => (
|
||||
<Button
|
||||
key={mode}
|
||||
type="button"
|
||||
color={detailMode === mode ? "primary" : "white"}
|
||||
aria-pressed={detailMode === mode}
|
||||
onClick={() => handleDetailModeChange(mode)}
|
||||
>
|
||||
{PPL_DETAIL_MODE_LABELS[mode]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
<Button type="button" color="primary" onClick={handleSearch}>
|
||||
조회
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
color="white"
|
||||
onClick={() => {
|
||||
setSelectedTrtdstId(trtdstId);
|
||||
setDetailMode("PIPE");
|
||||
setDetailNumberKeyword("");
|
||||
setAppliedDetailNumberKeyword("");
|
||||
setNotice(null);
|
||||
}}
|
||||
>
|
||||
초기화
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -869,374 +856,375 @@ export function ExmnSurveyDetailPopupPage({
|
||||
{loadError && (
|
||||
<div
|
||||
role="alert"
|
||||
className="shrink-0 border border-red-200 bg-red-50 px-4 py-2 text-[1.05rem] text-red-700"
|
||||
className="border-destructive/30 bg-destructive/10 rounded-sm border px-4 py-2 text-[1.3rem] text-destructive"
|
||||
>
|
||||
{loadError}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex shrink-0 items-center justify-between gap-4 py-3">
|
||||
<div className="flex min-w-0 items-baseline gap-3">
|
||||
<h2 className="shrink-0 text-[1.25rem] font-semibold text-title">
|
||||
{tableTitle}
|
||||
</h2>
|
||||
<div className="card card-border !m-0 min-w-0 overflow-hidden !p-0">
|
||||
<div className="card-header flex flex-wrap items-center justify-between gap-4">
|
||||
<h2 className="text-2xl font-medium text-label">{tableTitle}</h2>
|
||||
<div className="flex flex-wrap items-center gap-x-7 gap-y-2 whitespace-nowrap text-xl text-muted-foreground">
|
||||
{isUnitMode ? (
|
||||
<>
|
||||
<span>
|
||||
<strong className="mr-2 font-medium text-foreground">
|
||||
관로번호
|
||||
</strong>
|
||||
{appliedDetailNumberKeyword || "전체"}
|
||||
</span>
|
||||
<span>
|
||||
<strong className="mr-2 font-medium text-foreground">
|
||||
단위구간
|
||||
</strong>
|
||||
{unitSectionCount.toLocaleString("ko-KR")}개
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span>
|
||||
<strong className="mr-2 font-medium text-foreground">
|
||||
연장거리 합계
|
||||
</strong>
|
||||
{formatNumber(totals.extensionM)}m
|
||||
</span>
|
||||
<span>
|
||||
<strong className="mr-2 font-medium text-foreground">
|
||||
주행거리 합계
|
||||
</strong>
|
||||
{formatNumber(totals.drivingDistanceM)}m
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-7 whitespace-nowrap text-[1.05rem] text-label">
|
||||
{isUnitMode ? (
|
||||
<>
|
||||
<span>
|
||||
<strong className="mr-2 text-foreground">관로번호</strong>
|
||||
{appliedDetailNumberKeyword || "전체"}
|
||||
</span>
|
||||
<span>
|
||||
<strong className="mr-2 text-foreground">단위구간</strong>
|
||||
{unitSectionCount.toLocaleString("ko-KR")}개
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span>
|
||||
<strong className="mr-2 text-foreground">
|
||||
연장거리 합계
|
||||
</strong>
|
||||
{formatNumber(totals.extensionM)}m
|
||||
</span>
|
||||
<span>
|
||||
<strong className="mr-2 text-foreground">
|
||||
주행거리 합계
|
||||
</strong>
|
||||
{formatNumber(totals.drivingDistanceM)}m
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isUnitMode ? (
|
||||
<ExmnPplUnitDetailTable
|
||||
rows={unitRows}
|
||||
emptyMessage={
|
||||
appliedDetailNumberKeyword
|
||||
? "입력한 관로번호에 해당하는 본단위구간이 없습니다."
|
||||
: "조회된 본단위구간이 없습니다."
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className="min-h-0 flex-1 overflow-x-auto overflow-y-visible border border-border bg-background"
|
||||
onScroll={handleTableScroll}
|
||||
>
|
||||
<table
|
||||
className="border-separate border-spacing-0 text-center text-[1.05rem] text-foreground"
|
||||
style={{ width: `${tableWidth}px`, minWidth: `${tableWidth}px` }}
|
||||
>
|
||||
<colgroup>
|
||||
{fixedColumns.map((column) => (
|
||||
<col key={column.id} style={{ width: `${column.width}px` }} />
|
||||
))}
|
||||
{Array.from({
|
||||
length:
|
||||
(visibleDefectColumns.length + 1) *
|
||||
EXMN_DETAIL_SEVERITIES.length,
|
||||
}).map((_, index) => (
|
||||
<col
|
||||
key={`severity-col-${index}`}
|
||||
style={{ width: `${SEVERITY_COLUMN_WIDTH}px` }}
|
||||
/>
|
||||
))}
|
||||
</colgroup>
|
||||
<thead className="sticky top-0 z-30 bg-primary text-center text-[1.3rem] font-medium leading-[1.2] text-primary-foreground">
|
||||
<tr>
|
||||
{fixedColumns.map((column, columnIndex) => {
|
||||
const sticky = columnIndex < STICKY_COLUMN_COUNT;
|
||||
const columnLabel = column.label;
|
||||
return (
|
||||
<th
|
||||
<div className="card !m-[1.2rem] min-w-0 overflow-hidden !p-0">
|
||||
{isUnitMode ? (
|
||||
<ExmnPplUnitDetailTable
|
||||
rows={unitRows}
|
||||
emptyMessage={
|
||||
appliedDetailNumberKeyword
|
||||
? "입력한 관로번호에 해당하는 본단위구간이 없습니다."
|
||||
: "조회된 본단위구간이 없습니다."
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className="min-w-0 overflow-x-auto overflow-y-visible bg-background"
|
||||
onScroll={handleTableScroll}
|
||||
>
|
||||
<table
|
||||
className="table-ui default border-separate border-spacing-0 text-center text-foreground"
|
||||
style={{
|
||||
width: `${tableWidth}px`,
|
||||
minWidth: `${tableWidth}px`,
|
||||
}}
|
||||
>
|
||||
<colgroup>
|
||||
{fixedColumns.map((column) => (
|
||||
<col
|
||||
key={column.id}
|
||||
rowSpan={4}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
style={
|
||||
sticky
|
||||
? {
|
||||
position: "sticky",
|
||||
left:
|
||||
columnIndex === 0
|
||||
? REPORT_COLUMN_LEFT
|
||||
: PIPE_COLUMN_LEFT,
|
||||
zIndex: 60,
|
||||
boxShadow:
|
||||
columnIndex === STICKY_COLUMN_COUNT - 1 &&
|
||||
showStickyDivider
|
||||
? STICKY_DIVIDER_SHADOW
|
||||
: undefined,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<span className="whitespace-pre-line">
|
||||
{columnLabel}
|
||||
</span>
|
||||
</th>
|
||||
);
|
||||
})}
|
||||
<th
|
||||
colSpan={
|
||||
(visibleDefectColumns.length + 1) *
|
||||
EXMN_DETAIL_SEVERITIES.length
|
||||
}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
>
|
||||
이상항목
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
colSpan={EXMN_DETAIL_SEVERITIES.length}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
>
|
||||
합계
|
||||
</th>
|
||||
<th
|
||||
colSpan={
|
||||
visibleDefectColumns.length *
|
||||
EXMN_DETAIL_SEVERITIES.length
|
||||
}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
>
|
||||
{visibleDefectGroupTitle}
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
{EXMN_DETAIL_SEVERITIES.map((severity) => (
|
||||
<th
|
||||
key={`total-${severity}`}
|
||||
rowSpan={2}
|
||||
className="border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
>
|
||||
{SEVERITY_LABELS[severity]}
|
||||
</th>
|
||||
))}
|
||||
{visibleDefectColumns.map((column) => (
|
||||
<th
|
||||
key={column.code}
|
||||
colSpan={EXMN_DETAIL_SEVERITIES.length}
|
||||
title={`${column.label} (${column.code})`}
|
||||
className="whitespace-nowrap border-b border-r border-border bg-primary px-2 py-2 text-center text-primary-foreground"
|
||||
>
|
||||
{column.label} ({column.code})
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
<tr>
|
||||
{visibleDefectColumns.flatMap((column) =>
|
||||
EXMN_DETAIL_SEVERITIES.map((severity) => (
|
||||
style={{ width: `${column.width}px` }}
|
||||
/>
|
||||
))}
|
||||
{Array.from({
|
||||
length:
|
||||
(visibleDefectColumns.length + 1) *
|
||||
EXMN_DETAIL_SEVERITIES.length,
|
||||
}).map((_, index) => (
|
||||
<col
|
||||
key={`severity-col-${index}`}
|
||||
style={{ width: `${SEVERITY_COLUMN_WIDTH}px` }}
|
||||
/>
|
||||
))}
|
||||
</colgroup>
|
||||
<thead className="sticky top-0 z-30 text-center font-medium leading-[1.2]">
|
||||
<tr>
|
||||
{fixedColumns.map((column, columnIndex) => {
|
||||
const sticky = columnIndex < STICKY_COLUMN_COUNT;
|
||||
const columnLabel = column.label;
|
||||
return (
|
||||
<th
|
||||
key={column.id}
|
||||
rowSpan={3}
|
||||
className="border-b border-r border-border !py-[0.8rem] px-2 text-center"
|
||||
style={
|
||||
sticky
|
||||
? {
|
||||
position: "sticky",
|
||||
left:
|
||||
columnIndex === 0
|
||||
? REPORT_COLUMN_LEFT
|
||||
: PIPE_COLUMN_LEFT,
|
||||
zIndex: 60,
|
||||
boxShadow:
|
||||
columnIndex === STICKY_COLUMN_COUNT - 1 &&
|
||||
showStickyDivider
|
||||
? STICKY_DIVIDER_SHADOW
|
||||
: undefined,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<span className="whitespace-pre-line">
|
||||
{columnLabel}
|
||||
</span>
|
||||
</th>
|
||||
);
|
||||
})}
|
||||
<th
|
||||
key={`${column.code}-${severity}`}
|
||||
className="border-b border-r border-border bg-primary px-2 py-1.5 text-center font-medium text-primary-foreground"
|
||||
colSpan={
|
||||
(visibleDefectColumns.length + 1) *
|
||||
EXMN_DETAIL_SEVERITIES.length
|
||||
}
|
||||
className="border-b border-r border-border !py-[0.8rem] px-2 text-center"
|
||||
>
|
||||
{SEVERITY_LABELS[severity]}
|
||||
이상항목
|
||||
</th>
|
||||
)),
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows.length > 0 ? (
|
||||
<>
|
||||
{rows.map((row) => {
|
||||
const visibleAnomalyTotals = getVisibleAnomalyTotals(
|
||||
row,
|
||||
visibleDefectColumns,
|
||||
);
|
||||
return (
|
||||
<tr
|
||||
key={row.reportNo}
|
||||
className="transition-colors hover:bg-container"
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
colSpan={EXMN_DETAIL_SEVERITIES.length}
|
||||
className="border-b border-r border-border !py-[0.6rem] px-2 text-center"
|
||||
>
|
||||
합계
|
||||
</th>
|
||||
{visibleDefectColumns.map((column) => (
|
||||
<th
|
||||
key={column.code}
|
||||
colSpan={EXMN_DETAIL_SEVERITIES.length}
|
||||
title={`${column.label} (${column.code})`}
|
||||
className="whitespace-nowrap border-b border-r border-border !py-[0.6rem] px-2 text-center"
|
||||
>
|
||||
{fixedColumns.map((column, columnIndex) => {
|
||||
const sticky = columnIndex < STICKY_COLUMN_COUNT;
|
||||
return (
|
||||
<td
|
||||
key={`${row.reportNo}-${column.id}`}
|
||||
className="whitespace-nowrap border-b border-r border-border bg-background px-2 py-2.5"
|
||||
style={
|
||||
sticky
|
||||
? {
|
||||
position: "sticky",
|
||||
left:
|
||||
columnIndex === 0
|
||||
? REPORT_COLUMN_LEFT
|
||||
: PIPE_COLUMN_LEFT,
|
||||
zIndex: 10,
|
||||
boxShadow:
|
||||
columnIndex ===
|
||||
STICKY_COLUMN_COUNT - 1 &&
|
||||
showStickyDivider
|
||||
? STICKY_DIVIDER_SHADOW
|
||||
: undefined,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{getFixedCellValue(row, column.id)}
|
||||
</td>
|
||||
);
|
||||
})}
|
||||
{column.label} ({column.code})
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
<tr>
|
||||
{EXMN_DETAIL_SEVERITIES.map((severity) => (
|
||||
<th
|
||||
key={`total-${severity}`}
|
||||
className="border-b border-r border-border !py-[0.6rem] px-2 text-center"
|
||||
>
|
||||
{SEVERITY_LABELS[severity]}
|
||||
</th>
|
||||
))}
|
||||
{visibleDefectColumns.flatMap((column) =>
|
||||
EXMN_DETAIL_SEVERITIES.map((severity) => (
|
||||
<th
|
||||
key={`${column.code}-${severity}`}
|
||||
className="border-b border-r border-border !py-[0.6rem] px-2 text-center font-medium"
|
||||
>
|
||||
{SEVERITY_LABELS[severity]}
|
||||
</th>
|
||||
)),
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows.length > 0 ? (
|
||||
<>
|
||||
{rows.map((row) => {
|
||||
const visibleAnomalyTotals = getVisibleAnomalyTotals(
|
||||
row,
|
||||
visibleDefectColumns,
|
||||
);
|
||||
return (
|
||||
<tr
|
||||
key={row.reportNo}
|
||||
className="transition-colors hover:bg-container"
|
||||
>
|
||||
{fixedColumns.map((column, columnIndex) => {
|
||||
const sticky =
|
||||
columnIndex < STICKY_COLUMN_COUNT;
|
||||
return (
|
||||
<td
|
||||
key={`${row.reportNo}-${column.id}`}
|
||||
className="whitespace-nowrap border-b border-r border-border bg-background px-2 py-[1.2rem]"
|
||||
style={
|
||||
sticky
|
||||
? {
|
||||
position: "sticky",
|
||||
left:
|
||||
columnIndex === 0
|
||||
? REPORT_COLUMN_LEFT
|
||||
: PIPE_COLUMN_LEFT,
|
||||
zIndex: 10,
|
||||
boxShadow:
|
||||
columnIndex ===
|
||||
STICKY_COLUMN_COUNT - 1 &&
|
||||
showStickyDivider
|
||||
? STICKY_DIVIDER_SHADOW
|
||||
: undefined,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{getFixedCellValue(row, column.id)}
|
||||
</td>
|
||||
);
|
||||
})}
|
||||
{EXMN_DETAIL_SEVERITIES.map((severity) => (
|
||||
<td
|
||||
key={`${row.reportNo}-total-${severity}`}
|
||||
className="border-b border-r border-border bg-background px-2 py-[1.2rem]"
|
||||
>
|
||||
{formatCount(visibleAnomalyTotals[severity])}
|
||||
</td>
|
||||
))}
|
||||
{visibleDefectColumns.flatMap((column) =>
|
||||
EXMN_DETAIL_SEVERITIES.map((severity) => (
|
||||
<td
|
||||
key={`${row.reportNo}-${column.code}-${severity}`}
|
||||
className="border-b border-r border-border px-2 py-[1.2rem]"
|
||||
>
|
||||
{formatCount(
|
||||
row.defectCounts[column.code]?.[severity],
|
||||
)}
|
||||
</td>
|
||||
)),
|
||||
)}
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
<tr className="bg-background font-medium">
|
||||
<td
|
||||
colSpan={STICKY_COLUMN_COUNT}
|
||||
className="sticky left-0 z-20 border-b border-border bg-background px-2 py-[1.2rem] text-center align-middle"
|
||||
style={{
|
||||
boxShadow: showStickyDivider
|
||||
? STICKY_DIVIDER_SHADOW
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className="inline-block whitespace-nowrap"
|
||||
style={{
|
||||
transform: `translateX(${summaryLabelOffset}px)`,
|
||||
}}
|
||||
>
|
||||
소계
|
||||
</span>
|
||||
</td>
|
||||
{summaryLabelColumnCount > STICKY_COLUMN_COUNT && (
|
||||
<td
|
||||
aria-hidden="true"
|
||||
colSpan={
|
||||
summaryLabelColumnCount - STICKY_COLUMN_COUNT
|
||||
}
|
||||
className="border-b border-r border-border bg-background px-2 py-[1.2rem]"
|
||||
/>
|
||||
)}
|
||||
{fixedSummaryValues.map((summary) => (
|
||||
<td
|
||||
key={`subtotal-fixed-${summary.key}`}
|
||||
className="border-b border-r border-border bg-background px-2 py-[1.2rem] text-center"
|
||||
>
|
||||
{summary.value}
|
||||
</td>
|
||||
))}
|
||||
{EXMN_DETAIL_SEVERITIES.map((severity) => (
|
||||
<td
|
||||
key={`${row.reportNo}-total-${severity}`}
|
||||
className="border-b border-r border-border bg-background px-2 py-2.5"
|
||||
key={`subtotal-anomaly-${severity}`}
|
||||
className="border-b border-r border-border px-2 py-[1.2rem]"
|
||||
>
|
||||
{formatCount(visibleAnomalyTotals[severity])}
|
||||
{formatCount(
|
||||
defectSummary.anomalySubtotals[severity],
|
||||
)}
|
||||
</td>
|
||||
))}
|
||||
{visibleDefectColumns.flatMap((column) =>
|
||||
EXMN_DETAIL_SEVERITIES.map((severity) => (
|
||||
<td
|
||||
key={`${row.reportNo}-${column.code}-${severity}`}
|
||||
className="border-b border-r border-border px-2 py-2.5"
|
||||
key={`subtotal-${column.code}-${severity}`}
|
||||
className="border-b border-r border-border px-2 py-[1.2rem]"
|
||||
>
|
||||
{formatCount(
|
||||
row.defectCounts[column.code]?.[severity],
|
||||
defectSummary.defectSubtotals[column.code]?.[
|
||||
severity
|
||||
],
|
||||
)}
|
||||
</td>
|
||||
)),
|
||||
)}
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
<tr className="bg-background font-medium">
|
||||
<td
|
||||
colSpan={STICKY_COLUMN_COUNT}
|
||||
className="sticky left-0 z-20 border-b border-border bg-background px-2 py-2.5 text-center align-middle"
|
||||
style={{
|
||||
boxShadow: showStickyDivider
|
||||
? STICKY_DIVIDER_SHADOW
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className="inline-block whitespace-nowrap"
|
||||
style={{
|
||||
transform: `translateX(${summaryLabelOffset}px)`,
|
||||
}}
|
||||
>
|
||||
소계
|
||||
</span>
|
||||
</td>
|
||||
{summaryLabelColumnCount > STICKY_COLUMN_COUNT && (
|
||||
<td
|
||||
aria-hidden="true"
|
||||
colSpan={
|
||||
summaryLabelColumnCount - STICKY_COLUMN_COUNT
|
||||
}
|
||||
className="border-b border-r border-border bg-background px-2 py-2.5"
|
||||
/>
|
||||
)}
|
||||
{fixedSummaryValues.map((summary) => (
|
||||
<td
|
||||
key={`subtotal-fixed-${summary.key}`}
|
||||
className="border-b border-r border-border bg-background px-2 py-2.5 text-center"
|
||||
>
|
||||
{summary.value}
|
||||
</td>
|
||||
))}
|
||||
{EXMN_DETAIL_SEVERITIES.map((severity) => (
|
||||
<td
|
||||
key={`subtotal-anomaly-${severity}`}
|
||||
className="border-b border-r border-border px-2 py-2.5"
|
||||
>
|
||||
{formatCount(
|
||||
defectSummary.anomalySubtotals[severity],
|
||||
)}
|
||||
</td>
|
||||
))}
|
||||
{visibleDefectColumns.flatMap((column) =>
|
||||
EXMN_DETAIL_SEVERITIES.map((severity) => (
|
||||
<tr className="bg-secondary font-medium">
|
||||
<td
|
||||
key={`subtotal-${column.code}-${severity}`}
|
||||
className="border-b border-r border-border px-2 py-2.5"
|
||||
colSpan={STICKY_COLUMN_COUNT}
|
||||
className="sticky left-0 z-20 border-b border-border bg-secondary px-2 py-[1.2rem] text-center align-middle"
|
||||
style={{
|
||||
boxShadow: showStickyDivider
|
||||
? STICKY_DIVIDER_SHADOW
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
{formatCount(
|
||||
defectSummary.defectSubtotals[column.code]?.[
|
||||
severity
|
||||
],
|
||||
)}
|
||||
<span
|
||||
className="inline-block whitespace-nowrap"
|
||||
style={{
|
||||
transform: `translateX(${summaryLabelOffset}px)`,
|
||||
}}
|
||||
>
|
||||
합계
|
||||
</span>
|
||||
</td>
|
||||
)),
|
||||
)}
|
||||
</tr>
|
||||
<tr className="bg-secondary font-medium">
|
||||
<td
|
||||
colSpan={STICKY_COLUMN_COUNT}
|
||||
className="sticky left-0 z-20 border-b border-border bg-secondary px-2 py-2.5 text-center align-middle"
|
||||
style={{
|
||||
boxShadow: showStickyDivider
|
||||
? STICKY_DIVIDER_SHADOW
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className="inline-block whitespace-nowrap"
|
||||
style={{
|
||||
transform: `translateX(${summaryLabelOffset}px)`,
|
||||
}}
|
||||
>
|
||||
합계
|
||||
</span>
|
||||
</td>
|
||||
{summaryLabelColumnCount > STICKY_COLUMN_COUNT && (
|
||||
{summaryLabelColumnCount > STICKY_COLUMN_COUNT && (
|
||||
<td
|
||||
aria-hidden="true"
|
||||
colSpan={
|
||||
summaryLabelColumnCount - STICKY_COLUMN_COUNT
|
||||
}
|
||||
className="border-b border-r border-border bg-secondary px-2 py-[1.2rem]"
|
||||
/>
|
||||
)}
|
||||
{fixedSummaryValues.map((summary) => (
|
||||
<td
|
||||
key={`total-fixed-${summary.key}`}
|
||||
className="border-b border-r border-border bg-secondary px-2 py-[1.2rem] text-center"
|
||||
>
|
||||
{summary.value}
|
||||
</td>
|
||||
))}
|
||||
<td
|
||||
colSpan={EXMN_DETAIL_SEVERITIES.length}
|
||||
className="border-b border-r border-border px-2 py-[1.2rem] text-center"
|
||||
>
|
||||
{formatCount(defectSummary.anomalyTotal)}
|
||||
</td>
|
||||
{visibleDefectColumns.map((column) => (
|
||||
<td
|
||||
key={`total-${column.code}`}
|
||||
colSpan={EXMN_DETAIL_SEVERITIES.length}
|
||||
className="border-b border-r border-border px-2 py-[1.2rem] text-center"
|
||||
>
|
||||
{formatCount(
|
||||
defectSummary.defectTotals[column.code],
|
||||
)}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
</>
|
||||
) : (
|
||||
<tr>
|
||||
<td
|
||||
aria-hidden="true"
|
||||
colSpan={
|
||||
summaryLabelColumnCount - STICKY_COLUMN_COUNT
|
||||
fixedColumns.length +
|
||||
(visibleDefectColumns.length + 1) *
|
||||
EXMN_DETAIL_SEVERITIES.length
|
||||
}
|
||||
className="border-b border-r border-border bg-secondary px-2 py-2.5"
|
||||
/>
|
||||
)}
|
||||
{fixedSummaryValues.map((summary) => (
|
||||
<td
|
||||
key={`total-fixed-${summary.key}`}
|
||||
className="border-b border-r border-border bg-secondary px-2 py-2.5 text-center"
|
||||
className="h-28 border-b border-r border-border text-center text-muted-foreground"
|
||||
>
|
||||
{summary.value}
|
||||
조회된 상세 결과가 없습니다.
|
||||
</td>
|
||||
))}
|
||||
<td
|
||||
colSpan={EXMN_DETAIL_SEVERITIES.length}
|
||||
className="border-b border-r border-border px-2 py-2.5 text-center"
|
||||
>
|
||||
{formatCount(defectSummary.anomalyTotal)}
|
||||
</td>
|
||||
{visibleDefectColumns.map((column) => (
|
||||
<td
|
||||
key={`total-${column.code}`}
|
||||
colSpan={EXMN_DETAIL_SEVERITIES.length}
|
||||
className="border-b border-r border-border px-2 py-2.5 text-center"
|
||||
>
|
||||
{formatCount(defectSummary.defectTotals[column.code])}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
</>
|
||||
) : (
|
||||
<tr>
|
||||
<td
|
||||
colSpan={
|
||||
fixedColumns.length +
|
||||
(visibleDefectColumns.length + 1) *
|
||||
EXMN_DETAIL_SEVERITIES.length
|
||||
}
|
||||
className="h-28 border-b border-r border-border text-center text-muted-foreground"
|
||||
>
|
||||
조회된 상세 결과가 없습니다.
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
</StandardPopupLayout>
|
||||
);
|
||||
|
||||
@@ -626,7 +626,7 @@ export function TrtdstManagementPage() {
|
||||
<Button
|
||||
type="button"
|
||||
color="primary"
|
||||
disabled={isLoading}
|
||||
disabled={isLoading || !selectedRow}
|
||||
onClick={handleEdit}
|
||||
>
|
||||
수정
|
||||
@@ -644,7 +644,7 @@ export function TrtdstManagementPage() {
|
||||
color={
|
||||
selectedRow?.rowStatus === "deletePending" ? "white" : "red"
|
||||
}
|
||||
disabled={isLoading}
|
||||
disabled={isLoading || !selectedRow}
|
||||
onClick={() => void handleDelete()}
|
||||
>
|
||||
{selectedRow?.rowStatus === "deletePending"
|
||||
|
||||
@@ -25,7 +25,7 @@ export const windowPopupDefinitions = {
|
||||
key: "exmnSurveyDetail",
|
||||
title: "조사 상세현황",
|
||||
width: 1500,
|
||||
height: 720,
|
||||
height: 650,
|
||||
requiredParams: ["exmnBizId", "trtdstId", "trtdstNm", "jobType"],
|
||||
},
|
||||
dredgingRegister: {
|
||||
|
||||
Reference in New Issue
Block a user