sn: 도시침수예방사업 사업명 필수
This commit is contained in:
@@ -43,5 +43,5 @@
|
||||
- 선택 지속시간·초과빈도년도의 교차값 한 셀만 색으로 강조하고 헤더는 기존 스타일을 유지한다.
|
||||
- 팝업 표의 선택 지속시간 열은 로딩 완료 후 표 내부 가로 스크롤 영역 중앙에 자동으로 나타난다.
|
||||
- 선택 초과빈도년도의 재현기간 행은 년도와 강수량을 굵게 표시한다.
|
||||
- 분석시각·강우시작시각 열은 고정 폭을 지정하지 않고 말줄임만 해제하여, 전체 시각을 표시하면서 주변 열과 함께 자동으로 너비를 계산한다.
|
||||
- `pnpm --filter sn run typecheck`, `git diff --check`가 통과했다. 3002 포트 개발 서버 실행 중이므로 build는 실행하지 않았다.
|
||||
- 현황 목록은 자동 표 레이아웃을 유지하고 `widthPercent` 합계를 100%로 맞춘다. 분석시각·강우시작시각은 각각 13%를 적용해 분까지 표시하며, 최소 표 너비 112rem과 가로 스크롤을 유지한다.
|
||||
- `pnpm --filter sn run typecheck`, `git diff --check`가 통과했다. 빌드 중 3002 포트 개발 서버가 확인되어 에이전트가 시작한 빌드만 중단했으며, 빌드 완료와 실화면 검증은 미확인이다.
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
- 팝업 하단에 확률관측소코드·관측소명·면적비율 및 API 합계를 표시한다.
|
||||
- 팝업 맨 아래에 `시간은 강우가 지속된 시간입니다` 안내를 표시한다.
|
||||
- 링크 클릭 이벤트는 기존 행 선택의 지도 이동으로 전파하지 않는다.
|
||||
- 침수예측현황 목록의 분석시각·강우시작시각은 말줄임을 적용하지 않고, 고정 열 폭 없이 표의 자동 너비 계산과 가로 스크롤로 분까지 표시한다.
|
||||
- 침수예측현황 목록은 자동 표 레이아웃에서 `widthPercent` 합계 100%를 CSS 너비로 전달한다. 분석시각·강우시작시각은 각각 13%를 적용해 말줄임 없이 분까지 표시하고, 최소 표 너비 112rem과 가로 스크롤을 유지한다.
|
||||
|
||||
## 검증
|
||||
- `pnpm --filter sn run typecheck` 성공
|
||||
- `git diff --check` 성공
|
||||
- 개발 서버(3002)가 실행 중이어서 build는 실행하지 않았다.
|
||||
- 빌드 중 개발 서버(3002)가 확인되어 에이전트가 시작한 빌드만 중단했다. 빌드 완료와 실화면 검증은 미확인이다.
|
||||
|
||||
## 수동 확인 필요
|
||||
- 실제 로그인 화면에서 팝업 크기·가로 스크롤·강조 색상 및 지도 이동 회귀 확인
|
||||
|
||||
@@ -93,7 +93,7 @@ const DETAIL_FIELDS = [
|
||||
] as const;
|
||||
type BasicKey = (typeof BASIC_FIELDS)[number][0];
|
||||
/** 저장 전에 반드시 입력해야 하는 항목이다. 시도는 별도 선택이라 region 키로 관리한다. */
|
||||
const REQUIRED_BASIC_KEYS = new Set<string>(["seqNo", "dsgnYmd"]);
|
||||
const REQUIRED_BASIC_KEYS = new Set<string>(["seqNo", "dsgnYmd", "bizNm"]);
|
||||
type FieldErrorKey = BasicKey | "region" | `soa-${string}`;
|
||||
|
||||
/** 금액·면적 입력의 DB 자릿수 규칙이다. intDigits 는 정수부, scale 은 소수부 한계다. */
|
||||
@@ -390,6 +390,7 @@ export function CtyFldngPrvtnBizFormPage({ id }: { id?: string }) {
|
||||
if (!String(form.ctpvNm ?? "").trim()) nextErrors.region = "시도는 필수입니다.";
|
||||
if (form.seqNo === null || form.seqNo === undefined || String(form.seqNo) === "")
|
||||
nextErrors.seqNo = "사업순번은 필수입니다.";
|
||||
if (!String(form.bizNm ?? "").trim()) nextErrors.bizNm = "사업명은 필수입니다.";
|
||||
if (!String(form.dsgnYmd ?? "").trim())
|
||||
nextErrors.dsgnYmd = "지정일은 필수입니다.";
|
||||
else if (!validDate(form.dsgnYmd))
|
||||
@@ -478,7 +479,7 @@ export function CtyFldngPrvtnBizFormPage({ id }: { id?: string }) {
|
||||
key={key}
|
||||
id={fieldId}
|
||||
label={label}
|
||||
required={key === "bizNm" || REQUIRED_BASIC_KEYS.has(key)}
|
||||
required={REQUIRED_BASIC_KEYS.has(key)}
|
||||
error={fieldErrors[key]}
|
||||
span={span}
|
||||
>
|
||||
|
||||
@@ -76,9 +76,9 @@ const toFloodMapFrequencyCode = (value: number) => {
|
||||
};
|
||||
|
||||
const HEADS: UiHeadProps[] = [
|
||||
{ id: "rowNo", title: "순번", widthPercent: 6 },
|
||||
{ id: "ctpvNm", title: "시도", widthPercent: 8 },
|
||||
{ id: "sggNm", title: "시군구", widthPercent: 9 },
|
||||
{ id: "rowNo", title: "순번", widthPercent: 5 },
|
||||
{ id: "ctpvNm", title: "시도", widthPercent: 7 },
|
||||
{ id: "sggNm", title: "시군구", widthPercent: 8 },
|
||||
{
|
||||
id: "analysisDateTimeDisplay",
|
||||
title: "분석시각",
|
||||
@@ -87,33 +87,33 @@ const HEADS: UiHeadProps[] = [
|
||||
{
|
||||
id: "rainBeginningDateTimeDisplay",
|
||||
title: "강우시작시각",
|
||||
widthPercent: 16,
|
||||
widthPercent: 13,
|
||||
},
|
||||
{
|
||||
id: "observedAccumulatedRainfallDisplay",
|
||||
title: "관측 누적강수량(mm)",
|
||||
widthPercent: 13,
|
||||
widthPercent: 11,
|
||||
align: "right",
|
||||
},
|
||||
{
|
||||
id: "predictionHourDisplay",
|
||||
title: "예측시간",
|
||||
widthPercent: 9,
|
||||
widthPercent: 7,
|
||||
},
|
||||
{
|
||||
id: "predictedAccumulatedRainfallDisplay",
|
||||
title: "예측 누적강수량(mm)",
|
||||
widthPercent: 15,
|
||||
widthPercent: 12,
|
||||
align: "right",
|
||||
},
|
||||
{
|
||||
id: "exceededFrequencyYearDisplay",
|
||||
title: "초과 빈도(년)",
|
||||
widthPercent: 10,
|
||||
widthPercent: 8,
|
||||
align: "right",
|
||||
},
|
||||
{ id: "floodRiskGrade", title: "침수위험도", widthPercent: 10 },
|
||||
{ id: "probabilityRainfallDisplay", title: "확률강우량", widthPercent: 10 },
|
||||
{ id: "floodRiskGrade", title: "침수위험도", widthPercent: 8 },
|
||||
{ id: "probabilityRainfallDisplay", title: "확률강우량", widthPercent: 8 },
|
||||
];
|
||||
|
||||
/** 날짜·시각의 뒷부분이 잘리지 않도록 전체 표시할 목록 열이다. */
|
||||
|
||||
@@ -43,7 +43,8 @@ type MapPopupDataTableProps<T extends Record<string, unknown>> = {
|
||||
headId: string,
|
||||
rowIndex: number,
|
||||
) => ReactNode | undefined;
|
||||
fullTextHeadIds?: string[]; /** 시각처럼 뒤쪽이 잘리면 의미가 달라지는 열은 고정 너비 없이 말줄임만 해제한다. */
|
||||
/** 시각처럼 뒤쪽이 잘리면 의미가 달라지는 열의 말줄임을 해제한다. */
|
||||
fullTextHeadIds?: string[];
|
||||
sort?: UiTableSort;
|
||||
onSortChange?: (sort: UiTableSort | undefined) => void;
|
||||
};
|
||||
@@ -144,15 +145,18 @@ export default function MapPopupDataTable<T extends Record<string, unknown>>({
|
||||
head.align === "left" || head.align === "right"
|
||||
? head.align
|
||||
: "center",
|
||||
width: head.widthPercent,
|
||||
...(fullTextHeadIds?.includes(head.id)
|
||||
? {
|
||||
"data-sn-cell-wrap": "",
|
||||
style: {
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
}
|
||||
? { "data-sn-cell-wrap": "" }
|
||||
: {}),
|
||||
style: {
|
||||
width:
|
||||
head.widthPercent != null
|
||||
? `${head.widthPercent}%`
|
||||
: undefined,
|
||||
...(fullTextHeadIds?.includes(head.id)
|
||||
? { whiteSpace: "nowrap" }
|
||||
: {}),
|
||||
},
|
||||
} as ColumnDef<T>["meta"],
|
||||
})),
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user