통수위험 팝업 디자인 보완

This commit is contained in:
kiminchan
2026-06-15 17:34:24 +09:00
parent e47c00f0b6
commit 2ea207a63a
2 changed files with 98 additions and 51 deletions
@@ -57,21 +57,18 @@ const DEFAULT_SETTING_FILTERS: SettingFilters = {
};
const TOOLBAR_INPUT_CLASS_NAME =
"h-[30px] rounded-none border border-[#8f98a3] bg-white px-2 text-[12px] text-[#1f2937] outline-none";
const TOOLBAR_BUTTON_CLASS_NAME =
"h-[30px] min-w-[44px] rounded-none border border-[#7c5a20] bg-[#ef8d2f] px-3 text-[12px] font-semibold text-white hover:bg-[#df7f24]";
"h-10 rounded-md border border-slate-300 bg-white px-3 text-[1.05rem] text-slate-700 outline-none";
const SECONDARY_BUTTON_CLASS_NAME =
"h-[28px] rounded-none border border-[#8f98a3] bg-white px-3 text-[12px] text-[#334155] hover:bg-[#f8fafc]";
"h-10 rounded-md border border-slate-300 bg-white px-5 text-[1.05rem] text-slate-700 hover:bg-slate-100";
const ACTION_BUTTON_CLASS_NAME =
"h-[28px] rounded-[6px] border border-[#2e77bc] bg-[#3f8fd7] px-3 text-[12px] font-semibold text-white hover:bg-[#337ec1]";
"h-10 px-5 !text-[1.05rem]";
const WATER_RISK_PAGE_SIZE = 10;
const RESULT_TABLE_CONTAINER_CLASS_NAME =
"min-h-0 overflow-hidden rounded-[10px] border border-[#d6e1ee] bg-[linear-gradient(180deg,#ffffff_0%,#f9fbfe_100%)] shadow-[0_6px_16px_rgba(31,59,87,0.06)]";
"min-h-0 overflow-hidden border border-[#dbe2e6] bg-white";
const SETTING_TABLE_CONTAINER_CLASS_NAME =
"min-h-0 overflow-hidden rounded-[10px] border border-[#d6e1ee] bg-[linear-gradient(180deg,#ffffff_0%,#f9fbfe_100%)] shadow-[0_6px_16px_rgba(31,59,87,0.06)]";
"min-h-0 overflow-hidden border border-[#dbe2e6] bg-white";
const postMessageToOpener = (type: string, payload?: Record<string, unknown>) => {
if (typeof window === "undefined" || !window.opener) return;
@@ -396,28 +393,28 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
};
return (
<main className="flex h-screen flex-col overflow-hidden bg-[linear-gradient(180deg,#f7f9fc_0%,#eef4fa_100%)] text-[#202a36]">
<header className="flex h-[46px] items-center border-b border-[#e2ebf5] bg-[linear-gradient(180deg,#ffffff_0%,#f3f8fd_100%)] px-[18px]">
<main className="flex h-screen flex-col overflow-hidden bg-white text-slate-800">
<header className="flex min-h-[44px] items-center border-b border-[#dbe2e6] bg-primary px-5 py-3">
{activeView === "setting" ? (
<button
type="button"
className="mr-3 text-[12px] font-semibold text-[#51657a] hover:text-[#1f2937]"
className="mr-3 text-[1.05rem] font-medium text-white/90 hover:text-white"
onClick={handleReturnToResultView}
>
← 결과조회
</button>
) : null}
<h1 className="text-[1.1rem] font-semibold tracking-[-0.01em] text-[#1f3b57]">
<h1 className="text-[1.45rem] font-semibold text-white">
{activeView === "result" ? "통수위험분석" : "통수위험분석 설정"}
</h1>
</header>
<section className="flex-1 overflow-hidden px-[12px] pb-[12px] pt-[10px]">
<section className="flex-1 overflow-y-auto p-4">
{activeView === "result" ? (
<section className="flex h-full min-h-0 flex-col gap-[8px]">
<div className="overflow-x-auto">
<div className="flex min-w-max items-center gap-[12px] rounded-[10px] border border-[#d6e1ee] bg-[linear-gradient(180deg,#ffffff_0%,#f9fbfe_100%)] px-[10px] py-[8px] shadow-[0_6px_16px_rgba(31,59,87,0.06)]">
<div className="flex flex-1 items-center gap-[4px]">
<section className="flex h-full min-h-0 flex-col gap-3">
<div className="grid grid-cols-1 gap-3 border-b border-slate-200 bg-slate-50 pb-4 md:grid-cols-[160px_140px_140px_140px_180px_120px_auto] md:items-end">
<label className="block">
<div className="mb-1 text-[1.05rem] font-medium text-slate-700">기준일자</div>
<input
type="date"
value={draftResultFilters.analysisDate}
@@ -428,8 +425,11 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
}))
}
aria-label="년월일"
className={`${TOOLBAR_INPUT_CLASS_NAME} w-[120px]`}
className={`${TOOLBAR_INPUT_CLASS_NAME} w-full`}
/>
</label>
<label className="block">
<div className="mb-1 text-[1.05rem] font-medium text-slate-700">기준시간</div>
<input
type="time"
value={draftResultFilters.analysisTime}
@@ -440,8 +440,11 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
}))
}
aria-label="시간"
className={`${TOOLBAR_INPUT_CLASS_NAME} w-[100px]`}
className={`${TOOLBAR_INPUT_CLASS_NAME} w-full`}
/>
</label>
<label className="block">
<div className="mb-1 text-[1.05rem] font-medium text-slate-700">시도</div>
<select
value={draftResultFilters.sidoName}
onChange={(event) =>
@@ -452,7 +455,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
}))
}
aria-label="시도"
className={`${TOOLBAR_INPUT_CLASS_NAME} w-[94px]`}
className={`${TOOLBAR_INPUT_CLASS_NAME} w-full`}
>
{WATER_RISK_SIDO_OPTIONS.map((option) => (
<option key={option} value={option}>
@@ -460,6 +463,9 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
</option>
))}
</select>
</label>
<label className="block">
<div className="mb-1 text-[1.05rem] font-medium text-slate-700">시군구</div>
<select
value={draftResultFilters.sggName}
onChange={(event) =>
@@ -469,7 +475,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
}))
}
aria-label="시군구"
className={`${TOOLBAR_INPUT_CLASS_NAME} w-[94px]`}
className={`${TOOLBAR_INPUT_CLASS_NAME} w-full`}
>
{resultSggOptions.map((option) => (
<option key={option} value={option}>
@@ -477,6 +483,9 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
</option>
))}
</select>
</label>
<label className="block">
<div className="mb-1 text-[1.05rem] font-medium text-slate-700">중점관리지역</div>
<select
value={draftResultFilters.areaId}
onChange={(event) =>
@@ -486,7 +495,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
}))
}
aria-label="중점관리지역"
className={`${TOOLBAR_INPUT_CLASS_NAME} w-[120px]`}
className={`${TOOLBAR_INPUT_CLASS_NAME} w-full`}
>
<option value="ALL">중점관리지역</option>
{resultAreaOptions.map((option) => (
@@ -495,6 +504,9 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
</option>
))}
</select>
</label>
<label className="block">
<div className="mb-1 text-[1.05rem] font-medium text-slate-700">위험상태</div>
<select
value={draftResultFilters.riskStatus}
onChange={(event) =>
@@ -504,18 +516,19 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
}))
}
aria-label="위험상태"
className={`${TOOLBAR_INPUT_CLASS_NAME} w-[74px]`}
className={`${TOOLBAR_INPUT_CLASS_NAME} w-full`}
>
<option value="ALL">위험</option>
<option value="ALL">전체</option>
<option value="DANGER">위험</option>
<option value="NORMAL">정상</option>
</select>
</div>
<div className="ml-auto flex items-center gap-[4px]">
</label>
<div className="flex flex-wrap items-end justify-end gap-2">
<Button
type="button"
size="sm"
className="h-[30px] min-w-[48px] rounded-[4px] bg-[#2f7ec4] px-[10px] text-[12px] font-semibold text-white hover:bg-[#266fad]"
color="primary"
className="h-10 px-5 !text-[1.05rem]"
onClick={handleApplyResultFilters}
>
조회
@@ -523,19 +536,25 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
<Button
type="button"
size="sm"
className="h-[30px] min-w-[48px] rounded-[4px] bg-[#ef8d2f] px-[10px] text-[12px] font-semibold text-white hover:bg-[#df7f24]"
color="white"
className={SECONDARY_BUTTON_CLASS_NAME}
onClick={handleOpenSettingView}
>
설정
</Button>
</div>
</div>
<div className="card-header">
<h3 className="text-2xl font-medium text-label">
통수위험 분석 결과 {visibleResultRows.length.toLocaleString("ko-KR")}건
</h3>
</div>
<div className={RESULT_TABLE_CONTAINER_CLASS_NAME}>
<div className="overflow-x-auto overflow-y-hidden">
<table
className="border-collapse text-[12px]"
className="border-collapse text-[1.05rem]"
style={{ minWidth: `${resultTableMinWidth}px`, width: "100%" }}
>
<thead>
@@ -620,10 +639,10 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
) : null}
</section>
) : (
<section className="flex h-full min-h-0 flex-col gap-2">
<div className="overflow-x-auto">
<div className="flex min-w-max items-center gap-[12px] rounded-[10px] border border-[#d6e1ee] bg-[linear-gradient(180deg,#ffffff_0%,#f9fbfe_100%)] px-[8px] py-[8px] shadow-[0_6px_16px_rgba(31,59,87,0.06)]">
<div className="flex flex-1 items-center gap-[4px]">
<section className="flex h-full min-h-0 flex-col gap-3">
<div className="grid grid-cols-1 gap-3 border-b border-slate-200 bg-slate-50 pb-4 md:grid-cols-[160px_160px_220px_auto] md:items-end">
<label className="block">
<div className="mb-1 text-[1.05rem] font-medium text-slate-700">시도</div>
<select
value={draftSettingFilters.sidoName}
onChange={(event) =>
@@ -634,7 +653,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
}))
}
aria-label="시도"
className={`${TOOLBAR_INPUT_CLASS_NAME} w-[94px]`}
className={`${TOOLBAR_INPUT_CLASS_NAME} w-full`}
>
{WATER_RISK_SIDO_OPTIONS.map((option) => (
<option key={option} value={option}>
@@ -642,6 +661,9 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
</option>
))}
</select>
</label>
<label className="block">
<div className="mb-1 text-[1.05rem] font-medium text-slate-700">시군구</div>
<select
value={draftSettingFilters.sggName}
onChange={(event) =>
@@ -651,7 +673,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
}))
}
aria-label="시군구"
className={`${TOOLBAR_INPUT_CLASS_NAME} w-[94px]`}
className={`${TOOLBAR_INPUT_CLASS_NAME} w-full`}
>
{settingSggOptions.map((option) => (
<option key={option} value={option}>
@@ -659,6 +681,9 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
</option>
))}
</select>
</label>
<label className="block">
<div className="mb-1 text-[1.05rem] font-medium text-slate-700">중점관리지역</div>
<select
value={draftSettingFilters.areaId}
onChange={(event) =>
@@ -668,7 +693,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
}))
}
aria-label="중점관리지역"
className={`${TOOLBAR_INPUT_CLASS_NAME} w-[120px]`}
className={`${TOOLBAR_INPUT_CLASS_NAME} w-full`}
>
<option value="ALL">중점관리지역</option>
{settingAreaOptions.map((option) => (
@@ -677,18 +702,24 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
</option>
))}
</select>
</div>
<div className="ml-auto flex items-center gap-[4px]">
</label>
<div className="flex flex-wrap items-end justify-end gap-2">
<Button
type="button"
size="sm"
className="h-[30px] min-w-[48px] rounded-[4px] bg-[#2f7ec4] px-[10px] text-[12px] font-semibold text-white hover:bg-[#266fad]"
color="primary"
className="h-10 px-5 !text-[1.05rem]"
onClick={handleApplySettingFilters}
>
조회
</Button>
</div>
</div>
<div className="card-header">
<h3 className="text-2xl font-medium text-label">
통수위험 설정 현황 {visibleSettingRows.length.toLocaleString("ko-KR")}건
</h3>
</div>
<div
@@ -696,7 +727,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
>
<div className="overflow-x-auto overflow-y-hidden">
<table
className="border-collapse text-[12px]"
className="border-collapse text-[1.05rem]"
style={{ minWidth: `${settingTableMinWidth}px`, width: "100%" }}
>
<thead className="bg-[#eaf3fb] text-[#647784]">
@@ -754,10 +785,10 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
) : null}
{showSettingEditor ? (
<div className="min-h-0 flex-1 overflow-hidden rounded-[10px] border border-[#d6e1ee] bg-[linear-gradient(180deg,#ffffff_0%,#f9fbfe_100%)] shadow-[0_6px_16px_rgba(31,59,87,0.06)]">
<div className="min-h-0 flex-1 overflow-hidden border border-[#dbe2e6] bg-white">
<div className="flex h-full min-h-0 flex-col">
<div className="flex items-center justify-between border-b border-[#e2ebf5] px-3 py-2">
<div className="text-[12px] font-semibold text-[#1f3b57]">
<div className="flex items-center justify-between border-b border-slate-200 bg-slate-50 px-4 py-3">
<div className="text-[1.05rem] font-medium text-slate-700">
설정 편집 대상: {currentSettingAreaName || "선택 전"}
</div>
<div className="flex items-center gap-2">
@@ -765,7 +796,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
type="button"
size="sm"
color="white"
className="h-[28px] rounded-[4px] border border-[#cad7e6] bg-white px-[10px] text-[12px] text-[#43566b] hover:bg-[#f8fbff]"
className="h-9 rounded-md border border-slate-300 bg-white px-4 text-[1.05rem] text-slate-700 hover:bg-slate-100"
onClick={handleStopSettingEdit}
>
편집 종료
@@ -774,7 +805,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
type="button"
size="sm"
color="white"
className="h-[28px] rounded-[4px] border border-[#cad7e6] bg-white px-[10px] text-[12px] text-[#43566b] hover:bg-[#f8fbff]"
className="h-9 rounded-md border border-slate-300 bg-white px-4 text-[1.05rem] text-slate-700 hover:bg-slate-100"
onClick={handleClearStagedPipes}
disabled={snapshot.stagedPipes.length === 0}
>
@@ -783,6 +814,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
<Button
type="button"
size="sm"
color="primary"
className={ACTION_BUTTON_CLASS_NAME}
onClick={handlePreviewSave}
>
@@ -792,7 +824,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
</div>
<div className="min-h-0 flex-1 overflow-auto">
<table className="w-full border-collapse text-[12px]">
<table className="w-full border-collapse text-[1.05rem]">
<thead className="bg-[#e1ebf5] text-[#24364d]">
<tr>
<th className="border border-[#dbe4ec] px-2 py-2">순번</th>
@@ -832,7 +864,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
type="button"
size="sm"
color="white"
className="h-[28px] rounded-[4px] border border-[#cad7e6] bg-white px-[10px] text-[12px] text-[#43566b] hover:bg-[#f8fbff]"
className="h-9 rounded-md border border-slate-300 bg-white px-4 text-[1.05rem] text-slate-700 hover:bg-slate-100"
onClick={() => handleMoveStagedPipe(pipe.pipeId, "UP")}
disabled={index === 0}
>
@@ -842,7 +874,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
type="button"
size="sm"
color="white"
className="h-[28px] rounded-[4px] border border-[#cad7e6] bg-white px-[10px] text-[12px] text-[#43566b] hover:bg-[#f8fbff]"
className="h-9 rounded-md border border-slate-300 bg-white px-4 text-[1.05rem] text-slate-700 hover:bg-slate-100"
onClick={() => handleMoveStagedPipe(pipe.pipeId, "DOWN")}
disabled={index === snapshot.stagedPipes.length - 1}
>
@@ -852,7 +884,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) {
type="button"
size="sm"
color="white"
className="h-[28px] rounded-none border border-[#e7b7b7] bg-white px-3 text-[12px] text-[#c62828] hover:bg-[#fff8f8]"
className="h-9 rounded-md border border-[#e7b7b7] bg-white px-4 text-[1.05rem] text-[#c62828] hover:bg-[#fff8f8]"
onClick={() => handleRemoveStagedPipe(pipe.pipeId)}
>
삭제
@@ -95,6 +95,21 @@
- 남은 메모
- 실제 운영에서 요구되는 카드 고정 규칙과 사용성은 브라우저 수동 검증에서 한 번 더 확정할 필요가 있다.
### 4.6 2026-06-15 통수위험 팝업 디자인 톤 재정렬
- 반영 파일
- `FE_APP_ROOT/app/(map-layout)/map/components/waterRisk/WaterRiskPopupPage.tsx`
- 배경
- 사용자 피드백 기준으로 현재 `통수위험분석` 팝업은 `관로분석`, `노후관로` 계열과 비교해 별도 그라데이션/카드/버튼 톤이 강해 혼자 튀는 상태로 보였다.
- 이번 라운드에서는 기능 흐름은 유지하고, 시각 언어만 기존 지도형 팝업 계열과 같은 방향으로 다시 맞추는 것을 목표로 했다.
- 구현 내용
- 상단 헤더를 `bg-primary` + 흰색 제목 구조로 바꿔 `관로분석`, `노후관로` 팝업과 같은 첫인상을 맞췄다.
- 본문 배경을 흰색으로 단순화하고, 조회조건 영역을 `slate-50` 기반 필터 바 형태로 바꿨다.
- 결과/설정 화면 모두에 `card-header` 스타일의 제목 줄을 추가해 기존 팝업의 표 제목 리듬과 맞췄다.
- 버튼 높이, 입력 높이, 테이블 외곽선, 편집 영역 상단 바를 기존 팝업 계열과 가까운 톤으로 조정했다.
- 남은 메모
- 현재는 `노후관로`/`관로분석` 계열에 시각 톤을 맞춘 1차 정리이며, 실제 사용자 체감 기준에서 간격이나 글자 크기 보정이 더 필요하면 후속 유지보수로 미세조정할 수 있다.
## 5. 기능별 현재 상태
### 5.1 결과 조회