From 81255c48398bdf8f2ce1cf09a7fe984fea6ece1d Mon Sep 17 00:00:00 2001 From: "jeonghyo.K" Date: Wed, 11 Feb 2026 16:49:26 +0900 Subject: [PATCH] =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81=201.=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EB=84=A4=EC=9D=B4=EC=85=98,=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A1=A4,=20=EB=82=A0=EC=A7=9C=20=EC=84=A0=ED=83=9D?= =?UTF-8?q?=20ui=20=EC=B6=94=EA=B0=80=202.=20=EA=B3=B5=ED=86=B5=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=A1=B0=ED=9A=8C=20api=20=EC=A0=81=EC=9A=A9=20(?= =?UTF-8?q?=EC=9C=84=EC=84=B1=20=EC=A1=B0=ED=9A=8C,=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=20=ED=8C=9D=EC=97=85=20=EB=93=B1)=203.=20=ED=95=84=EC=88=98?= =?UTF-8?q?=EA=B0=92=20=EC=9E=85=EB=A0=A5=20=EB=A9=94=EC=84=B8=EC=A7=80=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/css/common.css | 13 +- .../components/SatelliteImageManage.jsx | 54 ++-- .../SatelliteManageRegisterPopup.jsx | 263 ++++++++++-------- .../SatelliteProviderRegisterPopup.jsx | 248 +++++++++-------- .../components/SatelliteRegisterPopup.jsx | 24 +- src/scss/SideComponent.scss | 24 ++ 6 files changed, 369 insertions(+), 257 deletions(-) diff --git a/public/css/common.css b/public/css/common.css index 6f7b459c..2c5e9079 100644 --- a/public/css/common.css +++ b/public/css/common.css @@ -71,6 +71,8 @@ .schInput{height: 3.5rem; font-family: 'NanumSquare', sans-serif;font-size: var(--fs-m); color: var(--white);background-color: var(--tertiary1);padding: 0 1.2rem; border: 0;} .schInput::placeholder { color:rgba(var(--white-rgb),.3); } .dateInput {background:url(../images/ico_input_cal.svg) no-repeat center right .5rem/2.4rem; padding-right: 3rem; cursor: pointer;} +.dateInput { position: relative; } +.dateInput::-webkit-calendar-picker-indicator { opacity: 0; position: absolute; right: 0; width: 3rem; height: 100%;cursor: pointer; } .dateInput::placeholder { color:var(--white); } /* ========================= @@ -107,6 +109,15 @@ .colList.lineSB li a .title {font-size: var(--fs-m); font-weight: var(--fw-bold);} .colList.lineSB li a .meta {font-size: var(--fs-s); font-weight: var(--fw-regular); color:rgba(var(--white-rgb),.5);} +/* 페이지네이션 */ +.pagination {display: flex; align-items: center; justify-content: center; gap: .5rem; padding: 1.4rem 0;} +.pagination button {min-width: 2.8rem; height: 2.8rem; padding: 0 .6rem; border-radius: .4rem; background-color: var(--secondary1); color: var(--white); font-size: var(--fs-m); font-weight: var(--fw-bold); border: 1px solid var(--secondary3); cursor: pointer; transition: background-color .15s ease, border-color .15s ease;} +.pagination button:hover {background-color: var(--secondary3); border-color: var(--secondary4);} +.pagination button.on {background-color: var(--primary1); border-color: var(--primary1);} +.pagination button.on:hover {background-color: var(--primary2); border-color: var(--primary2);} +.pagination button.disabled {opacity: 0.4; cursor: default; pointer-events: none;} +.pagination .ellipsis {color: rgba(var(--white-rgb), .4); font-size: var(--fs-m); padding: 0 .2rem; user-select: none;} + /* 아코디언리스트 */ .accordionWrap {display: flex;flex-direction: column;transition: max-height 0.3s ease;} .accordionWrap .acdHeader {display: flex; justify-content: space-between; align-items: center; height: 4rem; background-color: var(--secondary1); padding: 1rem; border-bottom: .1rem solid var(--secondary3);} @@ -292,7 +303,7 @@ align-items: center; z-index: 999; } -.popupUtillWrap { position: absolute;top: 50%; left: 50%;transform: translate(-50%, -50%);z-index :85;} +.popupUtillWrap { position: fixed;top: 50%; left: 50%;transform: translate(-50%, -50%);z-index :100;} .popupUtill {display: flex; flex-direction: column; width: 52.5rem; height:auto;max-height: 80vh;overflow: hidden; background-color: var(--secondary2); border: .1rem solid var(--secondary3); padding:2.5rem 3rem;} .popupUtill > .puHeader {display: flex; justify-content: space-between; align-items: center; padding-bottom: 2rem;} .popupUtill > .puHeader > .title {font-weight: var(--fw-bold); font-size: var(--fs-xl);} diff --git a/src/satellite/components/SatelliteImageManage.jsx b/src/satellite/components/SatelliteImageManage.jsx index 4e909e7a..4dc146db 100644 --- a/src/satellite/components/SatelliteImageManage.jsx +++ b/src/satellite/components/SatelliteImageManage.jsx @@ -1,4 +1,5 @@ -import { useState, useCallback } from 'react'; +import { useState, useEffect, useCallback } from 'react'; +import { fetchCommonCodeList } from '@/api/commonApi'; import { fetchSatelliteVideoList, fetchSatelliteCsvFeatures } from '@/api/satelliteApi'; import { useSatelliteStore } from '@/stores/satelliteStore'; import { useMapStore } from '@/stores/mapStore'; @@ -11,6 +12,12 @@ const LIMIT = 10; export default function SatelliteImageManage() { const [isAccordionOpen, setIsAccordionOpen] = useState(false); + // 공통코드 옵션 + const [videoKindOptions, setVideoKindOptions] = useState([]); + const [videoOriginOptions, setVideoOriginOptions] = useState([]); + const [videoOrbitOptions, setVideoOrbitOptions] = useState([]); + const [videoCycleOptions, setVideoCycleOptions] = useState([]); + // 폼 필터 state const [startDate, setStartDate] = useState(''); const [endDate, setEndDate] = useState(''); @@ -42,6 +49,14 @@ export default function SatelliteImageManage() { const setOpacity = useSatelliteStore((s) => s.setOpacity); const setBrightness = useSatelliteStore((s) => s.setBrightness); + // 마운트 시 공통코드 로드 + useEffect(() => { + fetchCommonCodeList('000109').then(setVideoKindOptions).catch(() => setVideoKindOptions([])); + fetchCommonCodeList('000111').then(setVideoOriginOptions).catch(() => setVideoOriginOptions([])); + fetchCommonCodeList('000110').then(setVideoOrbitOptions).catch(() => setVideoOrbitOptions([])); + fetchCommonCodeList('000108').then(setVideoCycleOptions).catch(() => setVideoCycleOptions([])); + }, []); + const toggleAccordion = () => setIsAccordionOpen((prev) => !prev); const search = useCallback(async (targetPage) => { @@ -162,11 +177,11 @@ export default function SatelliteImageManage() { onChange={(e) => setSatelliteVideoKind(e.target.value)} > - - - - - + {videoKindOptions.map((opt) => ( + + ))} @@ -191,10 +207,11 @@ export default function SatelliteImageManage() { onChange={(e) => setSatelliteVideoOrbit(e.target.value)} > - - - - + {videoOrbitOptions.map((opt) => ( + + ))} diff --git a/src/satellite/components/SatelliteManageRegisterPopup.jsx b/src/satellite/components/SatelliteManageRegisterPopup.jsx index 23ef156c..8f787f1c 100644 --- a/src/satellite/components/SatelliteManageRegisterPopup.jsx +++ b/src/satellite/components/SatelliteManageRegisterPopup.jsx @@ -1,6 +1,9 @@ import { useState, useEffect } from 'react'; +import {createPortal} from "react-dom"; +import { showToast } from '@/components/common/Toast'; import { fetchCommonCodeList } from '@/api/commonApi'; import { + fetchSatelliteCompanyList, saveSatelliteManage, fetchSatelliteManageDetail, updateSatelliteManage, @@ -16,6 +19,7 @@ export default function SatelliteManageRegisterPopup({ satelliteManageId, onClos const isEditMode = !!satelliteManageId; const [sensorTypeOptions, setSensorTypeOptions] = useState([]); + const [companyOptions, setCompanyOptions] = useState([]); const [companyNo, setCompanyNo] = useState(''); const [satelliteName, setSatelliteName] = useState(''); @@ -38,9 +42,13 @@ export default function SatelliteManageRegisterPopup({ satelliteManageId, onClos setError(null); try { - const codeList = await fetchCommonCodeList('000092'); + const [codeList, companyList] = await Promise.all([ + fetchCommonCodeList('000092'), + fetchSatelliteCompanyList(), + ]); if (cancelled) return; setSensorTypeOptions(codeList); + setCompanyOptions(companyList); if (satelliteManageId) { const data = await fetchSatelliteManageDetail(satelliteManageId); @@ -65,6 +73,15 @@ export default function SatelliteManageRegisterPopup({ satelliteManageId, onClos }, [satelliteManageId]); const handleSave = async () => { + if (!companyNo) { + showToast('사업자명을 선택해주세요.'); + return; + } + if (!satelliteName.trim()) { + showToast('위성명을 입력해주세요.'); + return; + } + setIsSaving(true); setError(null); @@ -98,134 +115,140 @@ export default function SatelliteManageRegisterPopup({ satelliteManageId, onClos } }; - return ( -
-
-
+ return createPortal( +
+
+
{isEditMode ? '위성 관리 상세' : '위성 관리 등록'} -
+
-
- {isLoading &&
조회 중...
} - {error &&
{error}
} +
+ {isLoading &&
조회 중...
} + {error &&
{error}
} - {!isLoading && ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
위성 관리 등록 - 사업자명, 위성명, 센서 타입, 촬영 해상도, 주파수, 상세내역에 대한 내용을 등록하는 표입니다.
사업자명 * - setCompanyNo(e.target.value)} - /> -
위성명 * - setSatelliteName(e.target.value)} - /> -
센서 타입 - -
촬영 해상도 - setPhotoResolution(e.target.value)} - /> -
주파수 - setFrequency(e.target.value)} - /> -
상세내역 + {!isLoading && ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
위성 관리 등록 - 사업자명, 위성명, 센서 타입, 촬영 해상도, 주파수, 상세내역에 대한 내용을 등록하는 표입니다.
사업자명 * + +
위성명 * + setSatelliteName(e.target.value)} + /> +
센서 타입 + +
촬영 해상도 + setPhotoResolution(e.target.value)} + /> +
주파수 + setFrequency(e.target.value)} + /> +
상세내역