Compare commits
179
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba2ccf6f97 | ||
|
|
0149f489a7 | ||
|
|
b644281348 | ||
|
|
1572711749 | ||
|
|
93d4cb57e6 | ||
|
|
a256379633 | ||
|
|
2873d1b0b9 | ||
|
|
12bed29eb9 | ||
|
|
6817d34bc3 | ||
|
|
efbef8283b | ||
|
|
af7c2a4f6f | ||
|
|
60c515a654 | ||
|
|
78e3e8e20e | ||
|
|
3b23113955 | ||
|
|
fbe355f6cf | ||
|
|
c439d3e58a | ||
|
|
057175b65c | ||
|
|
794fdc482f | ||
|
|
28d7a1bd29 | ||
|
|
e79590b70d | ||
|
|
6904144ef8 | ||
|
|
be2dcdc6f0 | ||
|
|
636af7b14d | ||
|
|
e376fc7373 | ||
|
|
0f7e8c1de3 | ||
|
|
0b14d1c0b5 | ||
|
|
226c61eee9 | ||
|
|
8d1af396ec | ||
|
|
89df17aaeb | ||
|
|
e762720a01 | ||
|
|
3b8fd2129b | ||
|
|
8565331e68 | ||
|
|
d0faa58f3c | ||
|
|
064898333c | ||
|
|
94f8e53184 | ||
|
|
d08df3ff35 | ||
|
|
4b0b08761c | ||
|
|
610d3d1c38 | ||
|
|
56d47ca1d0 | ||
|
|
0e90277e90 | ||
|
|
18413509fc | ||
|
|
cfddd6c0ae | ||
|
|
d861cfa811 | ||
|
|
f88d42493c | ||
|
|
0459bcd4fd | ||
|
|
eca74c1f2e | ||
|
|
42d6010efa | ||
|
|
ded46a7b6d | ||
|
|
7227b98961 | ||
|
|
6f07aca860 | ||
|
|
912e335b27 | ||
|
|
b9cb8959ee | ||
|
|
4ee12d127d | ||
|
|
830cbf97d1 | ||
|
|
d32d73a681 | ||
|
|
9eb40c46e5 | ||
|
|
8a160dc97c | ||
|
|
1884f3733d | ||
|
|
15dd319b21 | ||
|
|
2947fb1524 | ||
|
|
2582bdd08c | ||
|
|
2e24da3c83 | ||
|
|
88eb32f4fc | ||
|
|
68c5548252 | ||
|
|
ee9e309413 | ||
|
|
9fc6be1256 | ||
|
|
2469a84068 | ||
|
|
80598a5b6a | ||
|
|
b4a905d2ed | ||
|
|
599e8a95c7 | ||
|
|
9881653bae | ||
|
|
2fe73c7480 | ||
|
|
af636453e0 | ||
|
|
51d8eb50aa | ||
|
|
e94782f56a | ||
|
|
8552957fb5 | ||
|
|
35a44ff7aa | ||
|
|
93d090b23f | ||
|
|
66930f2e93 | ||
|
|
0240e1fc7a | ||
|
|
011104b548 | ||
|
|
c077c0507c | ||
|
|
042f839e41 | ||
|
|
292c17d682 | ||
|
|
e875700105 | ||
|
|
c036ce41c9 | ||
|
|
b4f3c0108e | ||
|
|
2a6fa899e3 | ||
|
|
8252561050 | ||
|
|
20cbd7ebcd | ||
|
|
71e412d030 | ||
|
|
bb1cbb9ac0 | ||
|
|
7af1ef94cb | ||
|
|
a3797c7ae1 | ||
|
|
2cfcddc365 | ||
|
|
7fa390ccb1 | ||
|
|
5e7eae3e9e | ||
|
|
b83a55d1af | ||
|
|
2eddbacc7f | ||
|
|
1b64bccc55 | ||
|
|
57151eae76 | ||
|
|
9729b42837 | ||
|
|
fd106f3729 | ||
|
|
4da4f5cd62 | ||
|
|
c73a01d27d | ||
|
|
eae2c15aaf | ||
|
|
ece49f0ae2 | ||
|
|
810bedb414 | ||
|
|
5492ea70ed | ||
|
|
f61e952d28 | ||
|
|
b5709ab2e2 | ||
|
|
d9d5b49057 | ||
|
|
1c7be567f4 | ||
|
|
c4ca48be62 | ||
|
|
a4147a4c67 | ||
|
|
0b8ace2f0d | ||
|
|
185bda696a | ||
|
|
2e03b79031 | ||
|
|
cbded3e605 | ||
|
|
81306a7b82 | ||
|
|
c6d66c54b5 | ||
|
|
69a0dd47ff | ||
|
|
1ad61e0fa5 | ||
|
|
4b895ac5d4 | ||
|
|
f86301a771 | ||
|
|
f7c691ef9f | ||
|
|
2bf04dd288 | ||
|
|
96aecb9847 | ||
|
|
e0b631ec25 | ||
|
|
55bf8df00d | ||
|
|
591f47a3ff | ||
|
|
c281f688b5 | ||
|
|
97e448c5c8 | ||
|
|
8de5317d28 | ||
|
|
54e60d83a0 | ||
|
|
25e41a356b | ||
|
|
7abae34531 | ||
|
|
877a548c6f | ||
|
|
28f841adc8 | ||
|
|
69820d8e4c | ||
|
|
36146c3fc4 | ||
|
|
8318888f6d | ||
|
|
7e9f294ae8 | ||
|
|
7d51674516 | ||
|
|
3830273119 | ||
|
|
d065fe669b | ||
|
|
9fcd719382 | ||
|
|
55b3752f49 | ||
|
|
32ad548de2 | ||
|
|
074d82a3bd | ||
|
|
90c977300c | ||
|
|
01ef993601 | ||
|
|
a542cdd87d | ||
|
|
f57fd44db9 | ||
|
|
ce44289ff1 | ||
|
|
52e94bc943 | ||
|
|
7876fea738 | ||
|
|
ef2e0ccfea | ||
|
|
086478b41e | ||
|
|
66560d661e | ||
|
|
c6f13b35a1 | ||
|
|
2009c54a00 | ||
|
|
822081b318 | ||
|
|
2080927302 | ||
|
|
f0272e1f82 | ||
|
|
b59ab18fa6 | ||
|
|
8006a9ef09 | ||
|
|
97435b7113 | ||
|
|
6cee09b72e | ||
|
|
35ae83034c | ||
|
|
deaf1b53ee | ||
|
|
cda8044183 | ||
|
|
47f41faee3 | ||
|
|
3d7fc84a2e | ||
|
|
68f8a7be38 | ||
|
|
4d537a7bbc | ||
|
|
6c6aaebdc8 | ||
|
|
ba4062f826 | ||
|
|
019415f124 |
@@ -25,3 +25,4 @@ apps/fo/.next/**/*
|
||||
pnpm-lock.yaml
|
||||
settings.json
|
||||
.npmrc
|
||||
.cursor
|
||||
@@ -15,4 +15,3 @@ export async function POST() {
|
||||
cookieStore.delete(CLAIM_NAME);
|
||||
return NextResponse.json({ message: "Logged out" }, { status: 200 });
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AUTH_USER_ID, CLAIM_NAME } from "@/shared/config";
|
||||
import { ACCESS_TOKEN, AUTH_USER_ID, CLAIM_NAME, REFRESH_TOKEN } from "@/shared/config";
|
||||
import { getCookie, setCookie, removeCookie } from "@/shared/lib";
|
||||
|
||||
export class TokenManager {
|
||||
@@ -76,6 +76,8 @@ export class TokenManager {
|
||||
|
||||
this.removeToken(CLAIM_NAME);
|
||||
this.removeToken(AUTH_USER_ID);
|
||||
this.removeToken(REFRESH_TOKEN);
|
||||
this.removeToken(ACCESS_TOKEN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getCoreRowModel } from "@tanstack/react-table";
|
||||
import { PostApi, type MyPost } from "@/entities/post";
|
||||
import { PostApi, type MyPost, type NoticePost } from "@/entities/post";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { useDataTable } from "@/shared/lib";
|
||||
import {
|
||||
@@ -23,15 +23,21 @@ const MyPostList: React.FC = () => {
|
||||
}),
|
||||
});
|
||||
|
||||
const handleMyPostRowClick = (row: MyPost) => {
|
||||
router.push(`/cms/${row.bbsTypeCd.toLowerCase()}/${row.bbsId}/${row.pstNo}`);
|
||||
};
|
||||
|
||||
const { tableComponent: myPostTableComponent } = useDataTable({
|
||||
query: myPostQuery,
|
||||
tableOptions: {
|
||||
columns: myPostTableColumns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
columns: myPostTableColumns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
},
|
||||
dataTableOptions: {
|
||||
variant: "line",
|
||||
variant: "line",
|
||||
onRowClick: handleMyPostRowClick
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -26,7 +26,7 @@ const NoticeList: React.FC = () => {
|
||||
});
|
||||
|
||||
const handleNoticePostRowClick = (row: NoticePost) => {
|
||||
router.push(`/bbs/bbsnotice/${row.bbsId}/${row.pstNo}`);
|
||||
router.push(`/cms/${row.bbsTypeCd.toLowerCase()}/${row.bbsId}/${row.pstNo}`);
|
||||
};
|
||||
|
||||
const handleMoreClick = () => {
|
||||
@@ -40,12 +40,12 @@ const NoticeList: React.FC = () => {
|
||||
const { tableComponent: noticePostTableComponent } = useDataTable({
|
||||
query: noticePostQuery,
|
||||
tableOptions: {
|
||||
columns: noticePostTableColumns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
columns: noticePostTableColumns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
},
|
||||
dataTableOptions: {
|
||||
variant: "line",
|
||||
onRowClick: handleNoticePostRowClick,
|
||||
variant: "line",
|
||||
onRowClick: handleNoticePostRowClick,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,831 @@
|
||||
# 표준단어정의서
|
||||
|
||||
AI 이해용으로 정리된 표준단어명, 영문약어명, 영문명 목록입니다.
|
||||
|
||||
| 표준단어명 | 표준단어 영문약어명 | 표준단어 영문명 |
|
||||
|-----------|-------------------|----------------|
|
||||
| BOD | BOD | Biochemical Oxygen Demand |
|
||||
| C/N비 | CNR | Carbon-Nitrogen Ratio |
|
||||
| COD | COD | Chemical Oxygen Demand |
|
||||
| F/M비 | FMR | Food-Microorganism Ratio |
|
||||
| GISD | GISDATA | Geographic Information System Data |
|
||||
| HTML | HTML | Hypertext Markup Language |
|
||||
| ID | ID | Id |
|
||||
| IP | IP | Internet Protocol |
|
||||
| KEY | KEY | Key |
|
||||
| ND | ND | Not Detected |
|
||||
| NON | NON | Non |
|
||||
| NTU | NTU | Nephelometry Turbidity Unit |
|
||||
| OPT | OPT | Opt |
|
||||
| PAC | PAC | Polyaluminium Chloride |
|
||||
| PH | PH | Hydrogen Exponent |
|
||||
| PKI | PKI | Public Key Infrastructure |
|
||||
| POOL | POOL | Pool |
|
||||
| SS | SS | Suspended Solids (Ss) |
|
||||
| TCE | TCE | Trichloroethane |
|
||||
| TM | TM | Transverse Mercator |
|
||||
| T-N | TN | Total Nitrogen |
|
||||
| TOC | TOC | Total Organic Carbon |
|
||||
| T-P | TP | Total Phosphorus |
|
||||
| URL | URL | Uniform Resource Locator |
|
||||
| 가구 | HSHD | Household |
|
||||
| 가능 | PSBL | Possible |
|
||||
| 가동 | OPR | Operation |
|
||||
| 가산 | ADTN | Addition |
|
||||
| 가성소다 | NAOH | Caustic Soda(Nach) |
|
||||
| 가축분뇨 | ANMA | Animal Manure |
|
||||
| 값 | VAL | Value |
|
||||
| 강도 | IN | Intensity |
|
||||
| 강우 | RAIN | Rain |
|
||||
| 개방 | OPN | Opening |
|
||||
| 개별 | INDIV | Individual |
|
||||
| 개보수비 | RPAFEE | Repair Fee |
|
||||
| 개설 | ESTBL | Establishment |
|
||||
| 개시 | STRT | Start |
|
||||
| 개정 | RVSN | Revision |
|
||||
| 개조 | REMDEL | Remodeling |
|
||||
| 개체 | INDVD | Individual |
|
||||
| 개체군 | POPU | Population |
|
||||
| 개폐 | RORGN | Reorganization |
|
||||
| 갱신 | UPDT | Update |
|
||||
| 건물 | BLDG | Building |
|
||||
| 건설 | CONC | Construction |
|
||||
| 건수 | NOCS | The Number Of Cases |
|
||||
| 건조 | DRY | Dry |
|
||||
| 검사 | INSP | Inspection |
|
||||
| 검사서 | EXRPT | Examination Report |
|
||||
| 검정 | RCGN | Recognition |
|
||||
| 검증 | VRFC | Verification |
|
||||
| 검출 | DETECT | Detection |
|
||||
| 검토 | RVW | Review |
|
||||
| 격자 | LATTC | Lattice |
|
||||
| 결과 | RSLT | Result |
|
||||
| 결의 | DCIS | Decision |
|
||||
| 결정 | DCSN | Decision |
|
||||
| 경계 | BNDRY | Boundary |
|
||||
| 경과 | PROC | Process |
|
||||
| 경도 | LOT | Longitude |
|
||||
| 경보 | ALARM | Alarm |
|
||||
| 경사판 | ICNTPT | Inclination plate |
|
||||
| 계 | SUM | Summation |
|
||||
| 계량기 | MRNR | Measuring Instrument |
|
||||
| 계량기분리 | METRSPRT | Meter Separation |
|
||||
| 계면 | SGLV | Sludge Level |
|
||||
| 계산식 | FMUL | Formula |
|
||||
| 계약 | CTRT | Contract |
|
||||
| 계약기간 | CNTRPD | Contract Period |
|
||||
| 계절 | SEASON | Season |
|
||||
| 계획 | PLAN | Plan |
|
||||
| 고도처리 | AWTR | Advanced Water Treatment |
|
||||
| 고시 | ANCMNT | Announcement |
|
||||
| 고액분리 | SLSPRT | Solid-Liquid Separation |
|
||||
| 고형물체류시간 | SRT | Solid Retention Time |
|
||||
| 공간데이터 | SPCEDATA | Space Data |
|
||||
| 공공 | PUBLIC | Public |
|
||||
| 공급 | SPLY | Supply |
|
||||
| 공기 | AIR | Air |
|
||||
| 공기여과 | ARFT | Air Filter |
|
||||
| 공문 | ODOC | Official Documnet |
|
||||
| 공법 | MSRC | Method Of Construction |
|
||||
| 공사 | CSTRN | Construction |
|
||||
| 공사비 | CONSTEXPN | Construction Expenses |
|
||||
| 공업지역 | MNFTR_ARA | Manufacturing Area |
|
||||
| 공용면적 | CMAR | Common Area |
|
||||
| 공통 | CMMN | Commonness |
|
||||
| 관 | PP | Pipe |
|
||||
| 관계 | REL | Relation |
|
||||
| 관련 | RLTN | Relation |
|
||||
| 관로 | PPLINE | Pipe Line |
|
||||
| 관리 | MNG | Management |
|
||||
| 관리기관 | MGC | Management Agency |
|
||||
| 관리자 | MNGR | Manager |
|
||||
| 관찰 | WTCH | Watch |
|
||||
| 관측 | OBSR | Observation |
|
||||
| 관측소 | OBSRVT | Observatory |
|
||||
| 교반기 | AGITOR | Agirator |
|
||||
| 교정 | CRRC | Correction |
|
||||
| 구간 | SCTN | Section |
|
||||
| 구동 | DRIVE | Drive |
|
||||
| 구분 | SE | Section |
|
||||
| 구성 | CMPSG | Composing |
|
||||
| 구역 | ZONE | Zone |
|
||||
| 구조 | STRCT | Structure |
|
||||
| 권역 | DSTR | District |
|
||||
| 권한 | AUTH | Authority |
|
||||
| 규격 | STNDRD | Standard |
|
||||
| 규모 | SCAL | Scale |
|
||||
| 규제 | REGL | Regulation |
|
||||
| 균등 | EQLTY | Equality |
|
||||
| 금액 | AMT | Amount |
|
||||
| 급수 | WSP | Water Supply |
|
||||
| 기간 | WHL | While |
|
||||
| 기관 | INST | Institution |
|
||||
| 기록 | RECD | Recording |
|
||||
| 기록부 | REGI | Register |
|
||||
| 기밀 | SCRET | Secret |
|
||||
| 기법 | TECQU | Techniques |
|
||||
| 기본 | BSIC | Basics |
|
||||
| 기본정보 | BASINF | Bassinfo |
|
||||
| 기본키 | PK | Primary Key |
|
||||
| 기상 | WETHER | Weather |
|
||||
| 기안 | DRFTG | Drafting |
|
||||
| 기재 | WRIT | Write |
|
||||
| 기점 | CDPNT | Cardinal Point |
|
||||
| 기존 | LGCY | Legacy |
|
||||
| 기준 | CRTR | Criteria |
|
||||
| 기타 | ETC | Etc |
|
||||
| 기한 | TERM | Term |
|
||||
| 기후 | CLMT | Climate |
|
||||
| 긴급 | EMRG | Emergency |
|
||||
| 날개벽 | WW | Wing Wall |
|
||||
| 날씨 | WETHR | Weather |
|
||||
| 날짜 | DATE | DATE |
|
||||
| 남조류 | BLAL | Blue-Green Algae |
|
||||
| 납 | PB | Plumbum |
|
||||
| 내려받기 | DWLD | Download |
|
||||
| 내부반송 | ITNRCC | Internal Recycl |
|
||||
| 내용 | CN | Content |
|
||||
| 내용연수 | SVLF | Service Life |
|
||||
| 냄새 | SMELL | Smell |
|
||||
| 년 | YY | Year |
|
||||
| 년간 | FAYR | For A Year |
|
||||
| 노즐 | NZL | Nozzle |
|
||||
| 노출 | EXPSR | Exposure |
|
||||
| 농도 | DNSTY | Density |
|
||||
| 농축 | TKN | Thickened |
|
||||
| 누적 | ACML | Accumulate |
|
||||
| 누출 | LKG | Leakage |
|
||||
| 눈 | SNW | Snow |
|
||||
| 단가 | UNPRC | Unit Price |
|
||||
| 단기 | SRTPD | Short Period |
|
||||
| 단순 | SIMPL | Simplicity |
|
||||
| 단위 | UNIT | Unit |
|
||||
| 대구역 | LZONE | Large Zone |
|
||||
| 대분류 | LCLAS | Large Classification |
|
||||
| 대장 | REGSTR | Register |
|
||||
| 대장균 | COLI | Coliform, Fecal Coliform |
|
||||
| 대장균군 | COLIB | Coliform Bacteria |
|
||||
| 대지면적 | SIAR | Site Area |
|
||||
| 대체 | RPLC | Replace |
|
||||
| 덮개 | COVR | Cover |
|
||||
| 데이타 | DAT | Data |
|
||||
| 도구 | UNT | Unit |
|
||||
| 도래 | ADVNT | Advent |
|
||||
| 도로 | ROAD | Road |
|
||||
| 도로명 | RN | Road Name |
|
||||
| 도시 | CTY | City |
|
||||
| 도엽 | MAPDMC | Map Demarcation |
|
||||
| 도표 | CHART | Chart |
|
||||
| 독성 | TOXCTY | Toxicity |
|
||||
| 동의 | AGRE | Agreement |
|
||||
| 동절기 | WSESN | The Winter Season |
|
||||
| 등급 | GRD | Grade |
|
||||
| 등기 | RG | Registered |
|
||||
| 등록 | REG | Registration |
|
||||
| 디바이스 | DVICE | Device |
|
||||
| 디코딩 | DCD | Decoding |
|
||||
| 레이어 | LYR | Layer |
|
||||
| 로그인 | LGN | Login |
|
||||
| 로우 | ROW | Row |
|
||||
| 마감 | DDLN | Deadline |
|
||||
| 마이크로필터 | MCRFT | Micro Filter |
|
||||
| 막 | MBRN | Membrane |
|
||||
| 만족도 | STFDG | Satisfaction Degree |
|
||||
| 맑음 | CLAR | Clear |
|
||||
| 매각 | SAL | Sale |
|
||||
| 맨홀 | MH | Manhole |
|
||||
| 맵 | MAP | Map |
|
||||
| 메인 | MAIN | Main |
|
||||
| 메일 | EMAIL | Email |
|
||||
| 메탄올 | MTN | Methanol(CH3OH) |
|
||||
| 명 | NM | Name |
|
||||
| 모니터링 | MTRG | Monitoring |
|
||||
| 모델 | MODL | Model |
|
||||
| 모델링 | MODLNG | Modeling |
|
||||
| 모래 | SAND | Sand |
|
||||
| 목 | MOK | Mok |
|
||||
| 무산소 | ANX | Anoxic |
|
||||
| 무산소조 | ANX_TANK | Anoxic Tank |
|
||||
| 무인센서 | MNLSENSR | Manless Sensor |
|
||||
| 문서 | DCMT | Document |
|
||||
| 물 | WTR | Water |
|
||||
| 미급수 | NONWTRSPL | Non Water Supply |
|
||||
| 미생물 | BLGC | Biological |
|
||||
| 미세먼지 | PM | Particulate Matter |
|
||||
| 미세목 | MCRB | Micro Bar |
|
||||
| 민간위탁 | ETSVN | Entrustment To Civilian |
|
||||
| 민감 | SST | Sensitive |
|
||||
| 민원 | CVLCPT | Civil Complaint |
|
||||
| 바이러스 | VIRS | Virus |
|
||||
| 반기 | HT | Half Term |
|
||||
| 반류수 | SIDSWT | Side Stream Water |
|
||||
| 반송 | SNDBK | Send Back |
|
||||
| 반송수 | RCCWT | Recycled Water |
|
||||
| 반송슬러지 | RTNSLG | Return Sludge |
|
||||
| 반영 | RFLT | Reflection |
|
||||
| 반응조 | RETNK | Reactant Tank |
|
||||
| 반출 | EXPRT | Export |
|
||||
| 반토 | ALUM | Alumina |
|
||||
| 반환 | GVBK | Giving Back |
|
||||
| 받이 | INL | Inlet |
|
||||
| 발생 | OCRN | Occurrence |
|
||||
| 발전 | PWGNRT | Power Generation |
|
||||
| 발주기관 | ORNT | Order Institution |
|
||||
| 방류 | DCWTR | Discharge Water Stock Etc |
|
||||
| 방류구 | DSCHG | Discharge |
|
||||
| 방류수 | EFLEC | Effluence |
|
||||
| 방문 | VST | Visit |
|
||||
| 방문자 | VSTR | Visitor |
|
||||
| 방법 | MTHD | Method |
|
||||
| 방사 | RLSE | Release |
|
||||
| 배관 | PLINE | Pipeline |
|
||||
| 배분 | DSTRB | Distirbution |
|
||||
| 배설물 | EXCRTN | Excretion |
|
||||
| 배수 | DRNG | Drainage |
|
||||
| 배수구역 | DRANGZN | Drainage Zone |
|
||||
| 배출 | EXHST | Exhaust |
|
||||
| 배출가스 | EMGA | Emission Gases |
|
||||
| 배출구 | VENT | Vent |
|
||||
| 배출시설 | DHGP | Discharge Equipment |
|
||||
| 배출시험 | EXHTST | Exhaust Test |
|
||||
| 배출자 | DCHGR | Discharge Person |
|
||||
| 밸브 | VALVE | Valve |
|
||||
| 번호 | NO | Number |
|
||||
| 법 | LAW | Law |
|
||||
| 법적 | LGL | Legal |
|
||||
| 법정 | STTY | Statutory |
|
||||
| 법정동 | STDG | Statutory Dong(Administrative District) |
|
||||
| 법정리 | STLI | Statutory Li(Administrative District) |
|
||||
| 변경 | CHG | Change |
|
||||
| 변동 | FLCTN | Fluctuation |
|
||||
| 변속기 | TRMIS | Transmission |
|
||||
| 보고 | RPT | Report |
|
||||
| 보고서 | RPOT | Report |
|
||||
| 보관 | STORG | Storage |
|
||||
| 보수 | MEND | Mend |
|
||||
| 보유 | HOLD | Hold |
|
||||
| 보정 | RVSION | Revision |
|
||||
| 보조 | ASSISC | Assistance |
|
||||
| 보조금 | SBSIDY | Subsidy |
|
||||
| 복개 | COVE | Cover |
|
||||
| 복토 | CWTH | Covering With Soil |
|
||||
| 본류 | MI_RV | Main River |
|
||||
| 본번 | MNO | Main Number |
|
||||
| 부검 | ATPSY | Autopsy |
|
||||
| 부과 | LEVY | Levy |
|
||||
| 부과금 | LVYAMT | Levy Amount |
|
||||
| 부기 | BUKIP | Bookkeeping |
|
||||
| 부담금 | ALOTM | Allotment |
|
||||
| 부번 | SNO | Sub Number |
|
||||
| 부산물 | BYPRD | By-Product |
|
||||
| 부서 | DEPT | Department |
|
||||
| 부숙화 | DECPZ | Decomposed ~Ize |
|
||||
| 부적합 | IMPPRTY | Impropriety |
|
||||
| 부착 | ASN | Adhesion |
|
||||
| 부품 | CMPNT | Components |
|
||||
| 부하량 | LOADQTY | Load Quantity |
|
||||
| 분과 | DIVSN | Division |
|
||||
| 분뇨 | ENSO | Excreta, Night Soil |
|
||||
| 분류 | CL | Classification |
|
||||
| 분류군 | TAXON | Taxon |
|
||||
| 분리막 | SPRTMBR | Separation Membrane |
|
||||
| 분배 | DTRBT | Distribution |
|
||||
| 분배조 | DTRBT_TANK | Distribution Tank |
|
||||
| 분야 | RLM | Realm |
|
||||
| 분원성 | FECL | Fecal |
|
||||
| 분원성대장균군 | FCOLI | Fecal Coliform |
|
||||
| 분원성연쇄상구균 | FCSTRCCI | Fecal Streptococci |
|
||||
| 분할 | PRTIN | Partition |
|
||||
| 비밀번호 | PSWD | Password |
|
||||
| 비상 | EMGNY | Emergency |
|
||||
| 비정상 | ABNRM | Abnormality |
|
||||
| 사양 | SPECS | Specification |
|
||||
| 사업비 | WCT | Working Cost |
|
||||
| 사업장 | BPLC | Business Place |
|
||||
| 사여과지 | SAND_ FILTR | Sand Filter |
|
||||
| 사용 | USE | Use |
|
||||
| 사용가능 | USABLE | Usable |
|
||||
| 사용권 | RIOUS | Right Of Using |
|
||||
| 사용량 | USG | USAGE |
|
||||
| 사용자 | USER | User |
|
||||
| 사위 | FDG | Four Directions Girth |
|
||||
| 사유 | RESN | Reason |
|
||||
| 사이클 | CYCLE | Cycle |
|
||||
| 사이트 | SITE | Site |
|
||||
| 사진 | PHOT | Photograph |
|
||||
| 사항 | MATTR | Matter |
|
||||
| 사후 | AFTFAT | After Fact |
|
||||
| 삭제 | DEL | Deletion |
|
||||
| 산기관 | DFS | Diffuser |
|
||||
| 산업 | INDUST | Industrial |
|
||||
| 산화환원전위 | ORP | Oxidation Reduction Potential |
|
||||
| 살모넬라 | SLMN | Salmonella |
|
||||
| 삼원촉매장치 | TWCTLC | Three Way Catalytic Converter |
|
||||
| 상세 | DTL | Details |
|
||||
| 상세주소 | DADDR | Detailed Address |
|
||||
| 상수 | WT | Water |
|
||||
| 상업지역 | CMCL_ARA | Commercial Area |
|
||||
| 상태 | STUS | Status |
|
||||
| 상품 | GDS | Goods |
|
||||
| 상향류 | UFW | Upflow |
|
||||
| 상호 | CONM | Company Name |
|
||||
| 색도 | CRMTY | Chromaticity |
|
||||
| 생략 | OMS | Omission |
|
||||
| 생물 | LVB | Living Being |
|
||||
| 생물반응조 | BIRAT | Bioreactor |
|
||||
| 생물서식처 | ORGNHBT | Organism Habitat |
|
||||
| 생물종 | BISP | Biological Species |
|
||||
| 생성 | CRT | Creation |
|
||||
| 생슬러지 | RSLG | Raw Sludge |
|
||||
| 생태 | ECLGY | Ecology |
|
||||
| 생태독성 | ECTOX | ecotoxicity |
|
||||
| 서류 | PAPE | Papers |
|
||||
| 서명 | SIGN | Signing |
|
||||
| 서버 | SRVR | Server |
|
||||
| 서비스 | SRVC | Service |
|
||||
| 설계 | DESGN | Design |
|
||||
| 설계용량 | DESGN_CPCT | Design Capacity |
|
||||
| 설립 | FNDN | Foundation |
|
||||
| 설정 | STNG | Setting |
|
||||
| 설치 | INSTL | Installation |
|
||||
| 성격 | CHTR | Character |
|
||||
| 성공 | SCS | Success |
|
||||
| 성능 | PRFMNC | Performance |
|
||||
| 성능검사 | EFTST | Efficiency Test |
|
||||
| 성적서 | SCRRP | Score Report |
|
||||
| 세균 | BCLS | Bacillus |
|
||||
| 세목 | FB | Fine bar |
|
||||
| 세부 | DETAIL | Detail |
|
||||
| 세정 | WS | Washing |
|
||||
| 세정제 | CNML | Cleaning Material |
|
||||
| 소 | SML | Small |
|
||||
| 소독 | DSNF | Disinfection |
|
||||
| 소독제 | DSINF | Disinfectant |
|
||||
| 소분류 | SCLAS | Small Classification |
|
||||
| 소수점 | DCPT | Decimal Point |
|
||||
| 소요 | REQ | Required |
|
||||
| 소유 | OWN | Own |
|
||||
| 소유역 | SBASIN | Sub Basin |
|
||||
| 소재지 | PLAC | Place Of Location |
|
||||
| 소포 | ATFM | Antifoaming |
|
||||
| 소포수 | FBW | Foam Breaking Water |
|
||||
| 소포제 | ANAG | Antifoaming Agent |
|
||||
| 송부 | SENDNG | Sending |
|
||||
| 송신 | SNDM | Send Message |
|
||||
| 송풍기 | BLW | Blower |
|
||||
| 수 | CNT | Count |
|
||||
| 수거 | TKAWY | Take Away |
|
||||
| 수계 | WWBH | Watershed, Water Basin, Hydrosphere |
|
||||
| 수동 | HOPR | Hand Operation |
|
||||
| 수리학적 체류시간 | HRT | Hydraulic Retention Time |
|
||||
| 수문 | Gate | Gate |
|
||||
| 수산화나트륨 | SOHY | Sodium Hydroxide |
|
||||
| 수소이온 | HION | Hydrogen Ion |
|
||||
| 수신 | RCPTN | Reception |
|
||||
| 수용가 | RCPTR | Receptor |
|
||||
| 수위 | WAL | Water Level |
|
||||
| 수정 | MDFCN | Modification |
|
||||
| 수정자 | MDFR | Modifier |
|
||||
| 수제 | SPRDIKE | Superdike |
|
||||
| 수조 | Tank | Tank |
|
||||
| 수질 | QTWT | Quality Of Water |
|
||||
| 수질개선 | WTRQLIMP | Water Quality Improvement |
|
||||
| 수질기준 | WQST | Water Quality Standards |
|
||||
| 수질배출정보 | WTDI | Water Discharge Information |
|
||||
| 수집 | CLCT | Collection |
|
||||
| 순환 | CCL | Cycling |
|
||||
| 쉬겔라 | SHIGLA | Shigella |
|
||||
| 스컴 | SCM | Scum |
|
||||
| 스크린 | SCR | Screen |
|
||||
| 슬러지 | SLG | Sludge |
|
||||
| 슬러지 밀도지수 | SDI | sludge density index |
|
||||
| 슬러지 용량 지표 | SVI | Sludge Volume Index |
|
||||
| 습지 | WTLN | Wetland |
|
||||
| 승인 | APRV | Approval |
|
||||
| 승인권 | APPRVRGT | Right Of Approval |
|
||||
| 시각 | TIME | Time |
|
||||
| 시간 | HR | Hour |
|
||||
| 시군구 | SGG | Si/Gun/Gu |
|
||||
| 시나리오 | SCEN | Scenario |
|
||||
| 시도 | CTPV | Cities And Provinces |
|
||||
| 시료 | SMPL | Sample |
|
||||
| 시설 | FCLT | Facility |
|
||||
| 시설면적 | FCAR | Facility Area |
|
||||
| 시설물 | FCLTS | Facilities |
|
||||
| 시스템 | SYS | System |
|
||||
| 시안 | CYN | Cyaan |
|
||||
| 시운전 | TSTRN | Test Run |
|
||||
| 시작 | BGNG | Beginning |
|
||||
| 시점 | PTM | Point Time |
|
||||
| 시행 | ENFC | Enforcement |
|
||||
| 시험 | TEST | Test |
|
||||
| 신고 | DCLR | Declaration |
|
||||
| 신고자 | DCL | Declarer |
|
||||
| 신규 | NEW | New |
|
||||
| 신기술 | NTCH | New Technology |
|
||||
| 신뢰 | CNFDNC | Confidence |
|
||||
| 신뢰성 | CRDIBLTY | Credibility |
|
||||
| 실시 | OPRT | Operation |
|
||||
| 실적 | ACRS | Actual Result |
|
||||
| 실행 | EXCN | Execution |
|
||||
| 심사 | SRNG | Screening |
|
||||
| 심의 | DLBR | Deliberation |
|
||||
| 아황산환원혐기성포자형성균 | SFSRA | Spore Forming Sulfite Reducing Anaerobes |
|
||||
| 안정화 | STBLZT | Stabilization |
|
||||
| 암롤박스(컨테이너) | ARTCT | Arm roll type container |
|
||||
| 암모니아성질소 | NHN | Ammonia Nitrogen |
|
||||
| 압력 | PRESSR | Pressure |
|
||||
| 압송 | PUMPNG | Pumping |
|
||||
| 압축 | CMPRS | Compress |
|
||||
| 액비 | LQFERTLZ | Liquid Fertilizer |
|
||||
| 액상 | LIQD | Liquid |
|
||||
| 약 | GENTLE | Gentle |
|
||||
| 약품 | CMC | Chemical |
|
||||
| 약품비 | MEDFEE | Medicine Fee |
|
||||
| 약품사용 | USMD | Use Medicines |
|
||||
| 업로드 | UPLD | Upload |
|
||||
| 업무 | DTY | Duty |
|
||||
| 없음 | NOT | Nothing |
|
||||
| 에너지 | ENR | Energy |
|
||||
| 에틸벤젠 | ETBNZN | Ethylbenzene |
|
||||
| 여과 | FILTR | Filteration |
|
||||
| 여과수 | FTWT | Filtered Water |
|
||||
| 여과재 | FTMTRL | Filter Material |
|
||||
| 여과형 | FILTRFOM | Filter Form |
|
||||
| 여부 | YN | Yes or No |
|
||||
| 여시니아균 | YERSNA | Yersinia |
|
||||
| 역률 | PWRER_FCT | Power Factor |
|
||||
| 역세척 | BWS | Back Wash |
|
||||
| 연결 | CONN | Connection |
|
||||
| 연계 | LINK | Link |
|
||||
| 연도 | YR | Year |
|
||||
| 연락 | CNTC | Contact |
|
||||
| 연령 | AGE | Age |
|
||||
| 연료화 | FUELZ | Fuelize |
|
||||
| 연월 | YM | Year and Month |
|
||||
| 염소 | CLRN | Chlorine |
|
||||
| 염소소독 | CHDI | Chlorine Disinfection |
|
||||
| 염소이온 | CLION | Chlorine Ion |
|
||||
| 염화제이철 | IRCLD | Iron(III) Chloride |
|
||||
| 예보 | FRCST | Forecast |
|
||||
| 예비 | PRPT | Preparation |
|
||||
| 예산 | BGT | Budget |
|
||||
| 예상 | EXPCT | Expectation |
|
||||
| 예약 | RSVT | Reservation |
|
||||
| 예외 | EXCPT | Exception |
|
||||
| 예정 | PRNG | Prearrangement |
|
||||
| 예찰 | PRDICT | Prediction |
|
||||
| 오류 | ERR | Error |
|
||||
| 오수받이 | HUS_INL | House Inlet |
|
||||
| 오염물질 | CNTMN | Contaminant |
|
||||
| 오염원 | POLUSRC | Pollution Source |
|
||||
| 오존 | OZN | Ozone |
|
||||
| 오프로드 | OFFRD | Off Road |
|
||||
| 옥살산 | OXACID | Oxalic Acid |
|
||||
| 와류 | VORTEX | Vortex |
|
||||
| 와류형 | VORTXFOM | Vortex From |
|
||||
| 완결 | COMPLT | Completion |
|
||||
| 완료 | CMPTN | Completion |
|
||||
| 완전 | PRFECT | Perfection |
|
||||
| 요건 | REQSIT | Requisite |
|
||||
| 요막액 | ALLNTFLD | Allantoic Fluid |
|
||||
| 요청 | DMND | Demand |
|
||||
| 용량 | CPCT | Capacity |
|
||||
| 용역 | SERVC | Service |
|
||||
| 용존산소 | DO | Dissolved Oxygen |
|
||||
| 용해 | DSLV | Dissolving |
|
||||
| 우량 | EXLT | Excellent |
|
||||
| 우수 | ST | Storm |
|
||||
| 우수받이 | STRT_INL | Street Inlet |
|
||||
| 우수토구 | STM_OVFL_MUT | Storm Overflow Mouth |
|
||||
| 우회 | BP | BY PASS |
|
||||
| 운반 | CNVY | Conveyance |
|
||||
| 운영 | OPER | Operation |
|
||||
| 운영비 | OPEXP | Operation Expense |
|
||||
| 운행 | OPRAT | Operation |
|
||||
| 원격 | RMRT | Rmrt |
|
||||
| 원격감시체계 | TMS | Tele Monitoring System |
|
||||
| 원료 | MTRAL | Material |
|
||||
| 원수 | ORGWT | Origin'S Water |
|
||||
| 원인자 | ORGPR | The Origin Person |
|
||||
| 월 | MM | Month |
|
||||
| 위도 | LAT | Latitude |
|
||||
| 위반 | CNTR | Contravene |
|
||||
| 위촉 | ENTRST | Entrusting |
|
||||
| 위치 | LOC | Location |
|
||||
| 위탁 | CNSG | Consign |
|
||||
| 위탁자 | CONSGNR | Consignor |
|
||||
| 유기인 | ORGP | Organic Phosphorus |
|
||||
| 유량 | FLUX | Flux |
|
||||
| 유량조정조 | EQLZT__TANK | Equalization Tank |
|
||||
| 유입 | INFlOW | Inflow |
|
||||
| 유입수 | INFWTR | Influent Water |
|
||||
| 유주 | SWARMG | Swarming |
|
||||
| 유지 | MNTNC | Maintenance |
|
||||
| 유지용수공급 | MWRS | Maintenance Water Requirement Supply |
|
||||
| 유체 | FLUID | Fluid |
|
||||
| 유출 | EFFLUX | Efflux |
|
||||
| 유충 | LAVL | Larval |
|
||||
| 유형 | TY | Type |
|
||||
| 유효 | VLD | Validity |
|
||||
| 음용 | DKPS | For Drinking Purpose |
|
||||
| 읍면동 | EMD | Eup/Myun/Dong |
|
||||
| 응답 | RSPNS | Response |
|
||||
| 응집제 | COAG | Cohesive Agents |
|
||||
| 이관 | TRNSF | Transfer |
|
||||
| 이동 | MVMN | Movement |
|
||||
| 이력 | HST | History |
|
||||
| 이메일 | EML | Email |
|
||||
| 이상 | ABOVE | Above |
|
||||
| 이송 | TRSF | Transfer |
|
||||
| 이의 | OBJC | Objection |
|
||||
| 이차 | SCDR | Secondary |
|
||||
| 이차침전지 | SCDR_SDMT_TANK | Secondary Sedimaentation |
|
||||
| 이행 | MIG | Migratation |
|
||||
| 인건비 | PEXP | Personnel Expenses{Expenditure] |
|
||||
| 인계 | HNDVR | Handover |
|
||||
| 인계서 | HDOVDC | Handover Document |
|
||||
| 인구 | POPL | Population |
|
||||
| 인산 | PHACID | Phosphoric Acid |
|
||||
| 인산염인 | POP | phosphate |
|
||||
| 인양기 | LFT | Lifter |
|
||||
| 인원수 | NOPE | The Number of Persons |
|
||||
| 인증 | CERT | Certification |
|
||||
| 인처리 | PPRCS | Phosphorus Process |
|
||||
| 인허가 | APVL | Approval |
|
||||
| 일 | DY | Day |
|
||||
| 일련번호 | SN | Serial Number |
|
||||
| 일반 | GNRL | General |
|
||||
| 일별 | DALY | Daily |
|
||||
| 일시 | DT | Date and Time |
|
||||
| 일자 | YMD | YEAR Month Day |
|
||||
| 일지 | DIARY | Diary |
|
||||
| 일차 | PRM | Primary |
|
||||
| 일차침전지 | PST_SDMT_TANK | Primary Sedimentation Tank |
|
||||
| 일평균 | DYRG | Day Average |
|
||||
| 임시 | TMPR | Temporary |
|
||||
| 임의 | RNDM | Random |
|
||||
| 입고 | WRHS | Warehousing |
|
||||
| 입력 | INPT | Input |
|
||||
| 잉여 | SPS | Surplus |
|
||||
| 잉여슬러지 | EC_SLG | Excess Sludge |
|
||||
| 자 | MAN | Man |
|
||||
| 자갈 | GRAVEL | Gravel |
|
||||
| 자료 | DATA | Data |
|
||||
| 자리 | DIGIT | Digit |
|
||||
| 자립화 | SLFRLI | Self Reliance |
|
||||
| 자연형 | NATRLFOM | Natural Form |
|
||||
| 자외선 | URLI | Ultraviolet Rays, Light |
|
||||
| 자재 | MTRIL | Material |
|
||||
| 자체 | ITSL | Itself |
|
||||
| 작성 | WRT | Writing |
|
||||
| 작업 | JOB | Job |
|
||||
| 잠금 | LOCK | Lock |
|
||||
| 장기 | LNGTR | Long Term |
|
||||
| 장소 | PLCE | Place |
|
||||
| 장착 | MNTNG | Mounting |
|
||||
| 재 | RE | Re |
|
||||
| 재이용 | REUSE | Reuse |
|
||||
| 재이용수 | | Reuse Water |
|
||||
| 재활용 | RUSE | Reuse |
|
||||
| 저감 | REDUC | Reduction |
|
||||
| 저류조 | DTT_TANK | Detention Tank |
|
||||
| 저온 | LOWTMP | Low Temperature |
|
||||
| 저장 | STRG | Storage |
|
||||
| 저장소 | STORGE | Storage |
|
||||
| 적발 | DSCL | Disclose |
|
||||
| 적산 | ADD | Addition |
|
||||
| 적용 | APLCN | Application |
|
||||
| 적합 | STBLT | Suitability |
|
||||
| 전기 | ELCTY | Electricity |
|
||||
| 전기료 | ELFEE | Electricity Fee |
|
||||
| 전력 | PWRER | Power |
|
||||
| 전문 | SPCY | Specially |
|
||||
| 전산 | CMPUTT | Computation |
|
||||
| 전송 | TRSM | Transmission |
|
||||
| 전압 | VLTGE | Voltage |
|
||||
| 전용 | EXUSE | Exclusive Use |
|
||||
| 전원 | SELCT | Source Of Electricity |
|
||||
| 전처리 | PRETR | Pretreatment |
|
||||
| 점검 | CHCK | Check |
|
||||
| 접속 | CNTN | Connection |
|
||||
| 정밀 | PRCIS | Precision |
|
||||
| 정보 | INFO | Information |
|
||||
| 정산 | CLCLN | Calculation |
|
||||
| 정상 | NRMLT | Normality |
|
||||
| 정수장 | WPPW | Water Purification Plant, Waterworks |
|
||||
| 정제 | REFINE | Refining |
|
||||
| 정지 | STP | Stop |
|
||||
| 제거 | RMV | Removal |
|
||||
| 제수변 | SL_VALVE | Sluice Valve |
|
||||
| 제작 | MNFCT | Manufacture |
|
||||
| 제조사 | MKR | Maker |
|
||||
| 제출 | SBMSN | Submission |
|
||||
| 제한 | LIMT | Limitation |
|
||||
| 조류 | ALG | Algae |
|
||||
| 조목 | CSB | Coarse Bar |
|
||||
| 조사 | EXMN | Examination |
|
||||
| 조성 | MAKE | Make |
|
||||
| 조정 | EQLT | Equalization |
|
||||
| 조치 | ACTN | Action |
|
||||
| 조회 | INQ | Inquiry |
|
||||
| 존재 | EXST | Existence |
|
||||
| 종결 | TRMN | Termination |
|
||||
| 종균제 | MICBA | Microbial Agent |
|
||||
| 종료 | END | End |
|
||||
| 종류 | KND | Kind |
|
||||
| 종목 | IEM | Item |
|
||||
| 종별 | ASORT | Assortment |
|
||||
| 종사자 | ENFSN | Enfilade Person |
|
||||
| 종점 | TMNL | Terminal |
|
||||
| 좌표 | COOR | Coordinate |
|
||||
| 주간 | WIK | Week |
|
||||
| 주변 | CFR | Circumference |
|
||||
| 주소 | ADDR | Address |
|
||||
| 주입 | IJTN | Injection |
|
||||
| 주파수 | FQNC | Frequency |
|
||||
| 준공 | CMCN | Completion Of Construction |
|
||||
| 중권역 | MDSTRC | Medium District |
|
||||
| 중복 | DPCN | Duplication |
|
||||
| 중분류 | MLSFC | Middle Classification |
|
||||
| 중온 | MESPH | Mesophilic |
|
||||
| 중첩 | RETRTN | Reiteration |
|
||||
| 중화설비 | NUTEQP | Neutralization Equipment |
|
||||
| 중화제 | CNTAG | Counteragent |
|
||||
| 증가 | INCRS | Increase |
|
||||
| 지도점검표사본 | CITBMR | Copy of Instruction Checklist |
|
||||
| 지방자치단체 | LGOV | Local Governments |
|
||||
| 지번 | LOTNO | Lot Number |
|
||||
| 지상 | GRND | Ground |
|
||||
| 지역 | ARA | Area |
|
||||
| 지질 | NTRFS | Nature Of Soil |
|
||||
| 지질도 | GEOMAP | Geological Map |
|
||||
| 지하 | UDGD | Underground |
|
||||
| 지하수 | GROU | Groundwater |
|
||||
| 지형 | TPGRPH | Topography |
|
||||
| 진공 | VCM | Vacuum |
|
||||
| 진단 | DGNSS | Diagnosis |
|
||||
| 진동 | VIBRAT | Vibration |
|
||||
| 진행 | PRGRE | Progress |
|
||||
| 질산 | NIACID | Nitric Acid. |
|
||||
| 질산성질소 | NO3N | Nitrate Nitrogen |
|
||||
| 집계 | TOT | Total |
|
||||
| 집계구 | SUMDST | Summation District |
|
||||
| 집행 | IMPL | Implementation |
|
||||
| 찌꺼기 | LEES | Lees |
|
||||
| 차아염소산 | NAOCL | Hypochlorous Acid |
|
||||
| 차집 | ITCT | Intercepting |
|
||||
| 착공 | BGNCST | Begin Construction |
|
||||
| 채수 | SAMWT | Sampling Of Water |
|
||||
| 채수기 | WTRSMPLR | Water Sampler |
|
||||
| 채수병 | WTRBOTL | Water Bottle |
|
||||
| 처리 | PRCS | Process |
|
||||
| 처리비 | PSSFEE | Process Fee |
|
||||
| 처리수 | TRT_WT | Treated Water |
|
||||
| 처리수조 | TRT_WT_TANK | Treated Water Tank |
|
||||
| 처리시설 | TRTMTFCLT | Treatment Facility |
|
||||
| 처리자 | PRCR | Processor |
|
||||
| 처분 | DSPS | Disposition |
|
||||
| 철염 | FESLT | Ferric Salt |
|
||||
| 첨부 | ATCH | Attachment |
|
||||
| 첨부파일 | ATFI | Attachment File |
|
||||
| 초과 | EXCS | Excess |
|
||||
| 초기화 | INITL | Initialization |
|
||||
| 촉매 | CTLY | Catalyst |
|
||||
| 총계 | TSM | Summation |
|
||||
| 총대장균군 | TCOLFGRP | Total Coliform Group |
|
||||
| 총량 | TQT | Total Quantity |
|
||||
| 총면적 | GFA | Gross Floor Area |
|
||||
| 총사업비 | TPCO | Total Project Cost |
|
||||
| 총인구 | TPOPLTN | Total Population |
|
||||
| 총인처리시설 | TPFCT | Total Phosphorus facility |
|
||||
| 최근 | RCNT | Recent |
|
||||
| 최대값 | MAXV | Maximum Value |
|
||||
| 최소값 | MINV | Minimum Value |
|
||||
| 최적 | BMTB | Being The Most Suitable |
|
||||
| 최종 | LAST | Last |
|
||||
| 최초 | FRST | First |
|
||||
| 추출 | EXTR | Extraction |
|
||||
| 추출정보 | EXTRINFO | Extraction Information |
|
||||
| 축 | AXS | Axis |
|
||||
| 출력 | OTPT | Output |
|
||||
| 출발 | LVE | Leave |
|
||||
| 충전기 | CHRGR | Charger |
|
||||
| 취득 | ACQS | Acquisition |
|
||||
| 취소 | RTRCN | Retraction |
|
||||
| 측정 | MSUR | Measurement |
|
||||
| 측정기 | MSRR | Measurement Instrument |
|
||||
| 측정소 | MSRSTN | Measurement Station |
|
||||
| 침사지 | GTCB | Grit Chamber |
|
||||
| 침전 | SDMT | Sediment |
|
||||
| 침전지 | SDMT_TANK | sedimentation tank |
|
||||
| 컨베이어 | CVY | Conveyor |
|
||||
| 컬럼 | COL | Column |
|
||||
| 코드 | CD | Code |
|
||||
| 크기 | SZ | Size |
|
||||
| 크실렌 | XYLEN | Xylene |
|
||||
| 탄화 | CARB | Carbonization |
|
||||
| 탈거 | CRYOFF | Carry Off |
|
||||
| 탈리액 | SPNT | Supernatant |
|
||||
| 탈수 | DWTR | Dewatering |
|
||||
| 탈수기 | DEHYM | Dehydration Machine |
|
||||
| 탈질 | DNTFCT | Denitrificatio |
|
||||
| 탈취 | DODRZ | Deodorization |
|
||||
| 탈취기 | DEODRZ | Deodorizer |
|
||||
| 탈취제 | DEODR | Deodorant |
|
||||
| 탈황제 | DSLFA | Desulfurizing Agent |
|
||||
| 터널형 | YUNLTP | Tunnel Type |
|
||||
| 테이블 | TBL | Table |
|
||||
| 토구 | OTFL | Outfall |
|
||||
| 토지 | LAD | Land |
|
||||
| 토지면적 | LDAR | Land Area |
|
||||
| 통계 | STATS | Statistics |
|
||||
| 통보 | NTFCTN | Notification |
|
||||
| 통신 | COMM | Communication |
|
||||
| 통지 | AVTSMT | Avertissement |
|
||||
| 통합 | UNTY | Unity |
|
||||
| 특성 | CHRT | Character |
|
||||
| 특수 | SPECL | Special |
|
||||
| 특정유해물질 | SHCH | Specified Hazardous Chemicals |
|
||||
| 파일 | FILE | File |
|
||||
| 판정 | JGMT | Judgement |
|
||||
| 펌프 | PUMP | Pump |
|
||||
| 펌프장 | PUMP_STT | Pump Station |
|
||||
| 페놀 | PHNL | Phenol |
|
||||
| 평가 | EVL | Evaluation |
|
||||
| 폐기 | DSCD | Discard |
|
||||
| 폐기물 | WSTE | Waste |
|
||||
| 폐쇄 | CLSG | Closing |
|
||||
| 폐수 | WAWA | Waste Water |
|
||||
| 폐수처리 | WSWT | Wastewater Treatment |
|
||||
| 폐열 | WASTHET | Waste Heat |
|
||||
| 포기 | ARTN | Aeration |
|
||||
| 포트 | PORT | Port |
|
||||
| 폭기조 | ARTN_TANK | Aeration Tank |
|
||||
| 폴리머 | PLYMR | Polymer |
|
||||
| 폴리철 | FRRCSU | Ferric Sulfate |
|
||||
| 표고 | AL | Altitude |
|
||||
| 표기 | MARK | Mark |
|
||||
| 표시 | INDCT | Indication |
|
||||
| 표준 | STD | Standard |
|
||||
| 표출 | EPRSS | Expression |
|
||||
| 플래그 | FLAG | Flag |
|
||||
| 필드 | FILD | Field |
|
||||
| 필수 | ESNTL | Essential |
|
||||
| 필증 | CERFIN | Certificate Of Finishing |
|
||||
| 필터 | FLTER | Filter |
|
||||
| 하수 | SWGE | Sewage |
|
||||
| 하수도 | DRNGSYS | Drainage System |
|
||||
| 하수미처리 | SEWGUNTTM | Un Sewage Treatment |
|
||||
| 하수처리 | SEWGTRTM | Sewage Treatment |
|
||||
| 하수처리수 | STWTR | Sewage Treatment Water |
|
||||
| 하위 | LOWR | Lower |
|
||||
| 하향류 | DWFW | Downflow |
|
||||
| 할인 | DSCNT | Discount |
|
||||
| 함수율 | MISTR_CTNT | Moisture content |
|
||||
| 합계 | SMM | Summation |
|
||||
| 해당 | RLVT | Relevant |
|
||||
| 해석 | INTRPRTT | Interpretation |
|
||||
| 해양투기 | OCDU | Ocean Dumping |
|
||||
| 행망 | ADMNW | Administration Network |
|
||||
| 행정 | ADMN | Administration |
|
||||
| 행정구역 | ADMI | Administrative District |
|
||||
| 행정동 | DONG | Dong (Administrative District) |
|
||||
| 허가 | PRMSN | Permission |
|
||||
| 허용 | PERM | Permission |
|
||||
| 현상 | PHNMN | Phenomenon |
|
||||
| 혐기 | AARB | Anaerobic |
|
||||
| 혐기조 | AARB_TANK | Anaerobic tank |
|
||||
| 협잡물 | CCMT | Concomitant |
|
||||
| 형태 | SHAP | Shape |
|
||||
| 호기 | ARB | Aerobic |
|
||||
| 호기조 | ARB_TANK | Aerobic Tank |
|
||||
| 호소수 | LMSHWT | Lake And Marsh Water |
|
||||
| 호수 | LKE | Lake |
|
||||
| 호안 | RVTMNT | Revetment |
|
||||
| 호이스트 | HIST | Hoist |
|
||||
| 혼합 | CMPN | Compound |
|
||||
| 혼합액현탁고형물 | MLSS | Mixed liquor suspended solids |
|
||||
| 혼화지 | MXG_TNAK | Mixing tank |
|
||||
| 홈페이지 | HMPG | Homepage |
|
||||
| 홍수 | FLOOD | Flood |
|
||||
| 확인 | IDNTY | Identify |
|
||||
| 확인서 | CNFRMN | Confirmation |
|
||||
| 확인자 | IDFR | Identifier |
|
||||
| 확장자 | EXTN | Extension |
|
||||
| 확정 | CFMTN | Confirmation |
|
||||
| 환경 | ENVR | Environment |
|
||||
| 환경기초시설 | ENINF | Environmental Infrastructure |
|
||||
| 환원 | RSTORE | Restoration |
|
||||
| 활성탄 | AC | Activated Carbon |
|
||||
| 활성화 | PRMT | Promote/Facilitate |
|
||||
| 활용 | PRUS | Practical Use |
|
||||
| 황산 | ECCBT | Encyclopaedia Britannica (H2So4) |
|
||||
| 회사 | CO | Company |
|
||||
| 회수 | RTRVL | Retrieval |
|
||||
| 회신 | RPLY | Reply |
|
||||
| 효율 | EFC | Efficiency |
|
||||
| 효율성 | EFFCTV | Effectiveness |
|
||||
| 휴대 | MBL | Mobile |
|
||||
| 흡수정 | EXTTW | Extraction Well |
|
||||
| 흡착 | ADST | Adsorption |
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
keepPreviousData,
|
||||
useQuery,
|
||||
@@ -75,7 +75,7 @@ function AddAdminDialog() {
|
||||
});
|
||||
|
||||
const query = useQuery({
|
||||
queryKey: [ENDPOINT.USER_SERVICE.USERS, pagination, "normal-user"],
|
||||
queryKey: [ENDPOINT.USER_SERVICE.USERS, "findPageUser", pagination],
|
||||
queryFn: () =>
|
||||
UserApi.findPageUser({
|
||||
...userSearchQuery,
|
||||
@@ -181,6 +181,21 @@ function AddAdminDialog() {
|
||||
query.refetch();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
setRowSelection({});
|
||||
setSelectedGroupId("");
|
||||
setUserSearchQuery({
|
||||
keywordType: "userName",
|
||||
keyword: "",
|
||||
});
|
||||
setPagination({ pageIndex: 0, pageSize: 10 });
|
||||
queryClient.removeQueries({
|
||||
queryKey: [ENDPOINT.USER_SERVICE.USERS, "findPageUser"],
|
||||
});
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
|
||||
@@ -1,53 +1,22 @@
|
||||
// import { client } from "@/shared/api";
|
||||
// import { ENDPOINT } from "@/shared/config";
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import {
|
||||
type BoardStatisticsParams,
|
||||
type BoardStatistics,
|
||||
type BoardStatisticsService,
|
||||
} from "../model/board-statistics-interface";
|
||||
|
||||
// 임시 모의 데이터
|
||||
const mockBoardStatisticsData: BoardStatistics = {
|
||||
totalPosts: 2456,
|
||||
totalComments: 156,
|
||||
averageRating: 4.2,
|
||||
totalViews: 45678,
|
||||
dayList: [
|
||||
{ date: "1월", posts: 10, comments: 5, views: 800 },
|
||||
{ date: "2월", posts: 15, comments: 8, views: 1200 },
|
||||
{ date: "3월", posts: 12, comments: 10, views: 1000 },
|
||||
{ date: "4월", posts: 18, comments: 15, views: 1500 },
|
||||
{ date: "5월", posts: 22, comments: 20, views: 1800 },
|
||||
{ date: "6월", posts: 20, comments: 18, views: 1600 },
|
||||
{ date: "7월", posts: 25, comments: 22, views: 2000 },
|
||||
],
|
||||
boardList: [
|
||||
{ boardType: "notice", boardName: "공지사항", count: 45 },
|
||||
{ boardType: "faq", boardName: "FAQ", count: 120 },
|
||||
{ boardType: "qna", boardName: "Q&A", count: 180 },
|
||||
{ boardType: "free", boardName: "자유게시판", count: 95 },
|
||||
],
|
||||
statusList: [
|
||||
{ status: "completed", statusName: "답변완료", count: 75 },
|
||||
{ status: "waiting", statusName: "답변대기", count: 25 },
|
||||
],
|
||||
};
|
||||
|
||||
class BoardStatisticsApiService implements BoardStatisticsService {
|
||||
async getBoardStatistics(
|
||||
params: BoardStatisticsParams,
|
||||
): Promise<BoardStatistics> {
|
||||
console.log("params: ", params);
|
||||
try {
|
||||
// 실제 API 연동 시 아래 코드 사용
|
||||
// const response = await client.get<BoardStatistics>(
|
||||
// `${ENDPOINT.CMS_SERVICE.BOARD_STATISTICS}`,
|
||||
// { params },
|
||||
// );
|
||||
// return response.data;
|
||||
|
||||
// 임시 모의 데이터 반환
|
||||
return Promise.resolve(mockBoardStatisticsData);
|
||||
const response = await client.get<BoardStatistics>(
|
||||
`${ENDPOINT.BOARD_SERVICE.STATISTICS}`,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error("게시판 통계 데이터 조회 실패:", error);
|
||||
throw error;
|
||||
|
||||
@@ -12,32 +12,36 @@ export interface BoardStatisticsParams extends PageableParams {
|
||||
}
|
||||
|
||||
export interface BoardStatistics {
|
||||
totalPosts: number;
|
||||
totalComments: number;
|
||||
averageRating: number;
|
||||
totalViews: number;
|
||||
dayList: DayStatistics[];
|
||||
boardList: BoardTypeStatistics[];
|
||||
statusList: StatusStatistics[];
|
||||
bbsTotalDto: BbsTotalDto; // 게시판 전체 통계
|
||||
pstAnsList: PstAnswerStatistics[]; // 게시물 답변 상태별 통계 목록
|
||||
bbsDailyList: BbsDailyStatistics[]; // 게시판 일별 통계 목록
|
||||
bbsPstCntList: BbsPostCountStatistics[]; // 게시판별 게시물 건수 통계 목록
|
||||
}
|
||||
|
||||
interface DayStatistics {
|
||||
date: string;
|
||||
posts: number;
|
||||
comments: number;
|
||||
views: number;
|
||||
interface BbsTotalDto {
|
||||
pstInqCnt: number; // 게시물 조회 건수
|
||||
pstEvlAvg: number; // 게시물 평가 평균
|
||||
pstTotCnt: number; // 게시물 총 건수
|
||||
pstAnsWaitCnt: number; // 게시물 답변 대기 건수
|
||||
}
|
||||
|
||||
interface BoardTypeStatistics {
|
||||
boardType: string;
|
||||
boardName: string;
|
||||
count: number;
|
||||
interface PstAnswerStatistics {
|
||||
answerNm: string; // 답변 명
|
||||
answerYn: string; // 답변 여부 (Y/N)
|
||||
ansCnt: number; // 답변 건수
|
||||
}
|
||||
|
||||
interface StatusStatistics {
|
||||
status: string;
|
||||
statusName: string;
|
||||
count: number;
|
||||
interface BbsDailyStatistics {
|
||||
dayYmd: string; // 일자 (YYYY-MM-DD)
|
||||
pstInqCnt: number; // 게시물 조회 건수
|
||||
pstCmntCnt: number; // 게시물 댓글 건수
|
||||
pstNewCnt: number; // 게시물 신규 건수
|
||||
}
|
||||
|
||||
interface BbsPostCountStatistics {
|
||||
bbsId: number; // 게시판 ID
|
||||
bbsNm: string; // 게시판 명
|
||||
pstCnt: number; // 게시물 건수
|
||||
}
|
||||
|
||||
export interface BoardStatisticsService {
|
||||
|
||||
@@ -11,20 +11,20 @@ export const chartData = {
|
||||
} => {
|
||||
return {
|
||||
data: {
|
||||
labels: data.dayList.map((item) => item.date),
|
||||
labels: data.bbsDailyList.map((item) => item.dayYmd),
|
||||
datasets: [
|
||||
{
|
||||
type: "line",
|
||||
label: "신규게시물",
|
||||
data: data.dayList.map((item) => item.posts),
|
||||
data: data.bbsDailyList.map((item) => item.pstNewCnt),
|
||||
borderColor: getCssVariableValue("--chart-1"),
|
||||
backgroundColor: "rgba(59, 130, 246, 0.1)",
|
||||
tension: 0.4,
|
||||
},
|
||||
{
|
||||
type: "line",
|
||||
label: "답변대기",
|
||||
data: data.dayList.map((item) => item.comments),
|
||||
label: "댓글수",
|
||||
data: data.bbsDailyList.map((item) => item.pstCmntCnt),
|
||||
borderColor: getCssVariableValue("--chart-2"),
|
||||
backgroundColor: "rgba(236, 72, 153, 0.1)",
|
||||
tension: 0.4,
|
||||
@@ -32,11 +32,10 @@ export const chartData = {
|
||||
{
|
||||
type: "line",
|
||||
label: "조회수",
|
||||
data: data.dayList.map((item) => item.views),
|
||||
data: data.bbsDailyList.map((item) => item.pstInqCnt),
|
||||
borderColor: getCssVariableValue("--chart-3"),
|
||||
backgroundColor: "rgba(168, 85, 247, 0.1)",
|
||||
tension: 0.4,
|
||||
hidden: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -67,13 +66,13 @@ export const chartData = {
|
||||
} => {
|
||||
return {
|
||||
data: {
|
||||
labels: data.boardList.map((item) => item.boardName),
|
||||
labels: data.bbsPstCntList.map((item) => item.bbsNm),
|
||||
datasets: [
|
||||
{
|
||||
type: "bar",
|
||||
label: "게시판별 분포",
|
||||
data: data.boardList.map((item) => item.count),
|
||||
backgroundColor: data.boardList.map((_, index) =>
|
||||
data: data.bbsPstCntList.map((item) => item.pstCnt),
|
||||
backgroundColor: data.bbsPstCntList.map((_, index) =>
|
||||
getCssVariableValue(`--chart-${(index % 5) + 1}`),
|
||||
),
|
||||
},
|
||||
@@ -106,12 +105,12 @@ export const chartData = {
|
||||
} => {
|
||||
return {
|
||||
data: {
|
||||
labels: data.statusList.map((item) => item.statusName),
|
||||
labels: data.pstAnsList.map((item) => item.answerNm),
|
||||
datasets: [
|
||||
{
|
||||
type: "doughnut",
|
||||
data: data.statusList.map((item) => item.count),
|
||||
backgroundColor: data.statusList.map((_, index) =>
|
||||
data: data.pstAnsList.map((item) => item.ansCnt),
|
||||
backgroundColor: data.pstAnsList.map((_, index) =>
|
||||
getCssVariableValue(`--chart-${(index % 5) + 1}`),
|
||||
),
|
||||
},
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
SelectValue,
|
||||
} from "@common/components";
|
||||
import { SiteSelect } from "@/entities/site";
|
||||
// import { ENDPOINT } from "@/shared/config";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { NoData } from "@/shared/ui/no-data";
|
||||
import { InputDateRangePicker } from "@/shared/ui/input-date-range-picker";
|
||||
import { BoardStatisticsApi } from "../api/board-statistics-service";
|
||||
@@ -66,7 +66,7 @@ function BoardStatisticsPage() {
|
||||
});
|
||||
|
||||
const { data: boardStatisticsData } = useQuery({
|
||||
queryKey: ["board-statistics", searchParams],
|
||||
queryKey: [ENDPOINT.BOARD_SERVICE.STATISTICS, searchParams],
|
||||
queryFn: () =>
|
||||
BoardStatisticsApi.getBoardStatistics({
|
||||
...searchParams,
|
||||
@@ -176,7 +176,8 @@ function BoardStatisticsPage() {
|
||||
<h3 className="text-lg font-medium text-gray-500">총 게시물</h3>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="mt-2 text-4xl font-bold">
|
||||
{boardStatisticsData?.totalPosts.toLocaleString() || 0}
|
||||
{boardStatisticsData?.bbsTotalDto?.pstTotCnt?.toLocaleString() ||
|
||||
0}
|
||||
</div>
|
||||
<div className="h-16 w-24">
|
||||
<Line
|
||||
@@ -210,7 +211,8 @@ function BoardStatisticsPage() {
|
||||
<h3 className="text-lg font-medium text-gray-500">답변대기</h3>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="mt-2 text-4xl font-bold">
|
||||
{boardStatisticsData?.totalComments.toLocaleString() || 0}
|
||||
{boardStatisticsData?.bbsTotalDto?.pstAnsWaitCnt?.toLocaleString() ||
|
||||
0}
|
||||
</div>
|
||||
<div className="h-16 w-24">
|
||||
<Line
|
||||
@@ -244,7 +246,7 @@ function BoardStatisticsPage() {
|
||||
<h3 className="text-lg font-medium text-gray-500">평균평점</h3>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="mt-2 text-4xl font-bold">
|
||||
{boardStatisticsData?.averageRating.toFixed(1) || 0}
|
||||
{boardStatisticsData?.bbsTotalDto?.pstEvlAvg?.toFixed(1) || 0}
|
||||
</div>
|
||||
<div className="h-16 w-24">
|
||||
<Line
|
||||
@@ -278,7 +280,8 @@ function BoardStatisticsPage() {
|
||||
<h3 className="text-lg font-medium text-gray-500">총 조회수</h3>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="mt-2 text-4xl font-bold">
|
||||
{boardStatisticsData?.totalViews.toLocaleString() || 0}
|
||||
{boardStatisticsData?.bbsTotalDto?.pstInqCnt?.toLocaleString() ||
|
||||
0}
|
||||
</div>
|
||||
<div className="h-16 w-24">
|
||||
<Line
|
||||
@@ -315,7 +318,7 @@ function BoardStatisticsPage() {
|
||||
<h3 className="text-2xl font-medium">일별 게시물 현황</h3>
|
||||
</div>
|
||||
<div className="h-96 p-4">
|
||||
{boardStatisticsData?.dayList?.length ? (
|
||||
{boardStatisticsData?.bbsDailyList?.length ? (
|
||||
<Line {...chartData.day(boardStatisticsData)} />
|
||||
) : (
|
||||
<NoData />
|
||||
@@ -329,7 +332,7 @@ function BoardStatisticsPage() {
|
||||
<h3 className="text-2xl font-medium">답변상태</h3>
|
||||
</div>
|
||||
<div className="h-96 p-4">
|
||||
{boardStatisticsData?.statusList?.length ? (
|
||||
{boardStatisticsData?.pstAnsList?.length ? (
|
||||
<Doughnut {...chartData.status(boardStatisticsData)} />
|
||||
) : (
|
||||
<NoData />
|
||||
@@ -342,7 +345,7 @@ function BoardStatisticsPage() {
|
||||
<h3 className="text-2xl font-medium">게시판별 분포</h3>
|
||||
</div>
|
||||
<div className="h-96 p-4">
|
||||
{boardStatisticsData?.boardList?.length ? (
|
||||
{boardStatisticsData?.bbsPstCntList?.length ? (
|
||||
<Bar {...chartData.board(boardStatisticsData)} />
|
||||
) : (
|
||||
<NoData />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { memo } from "react";
|
||||
import { memo, useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
@@ -140,6 +140,10 @@ const LwpoCodeManagementDialog = memo(
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) form.reset();
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange} {...props}>
|
||||
<DialogTrigger asChild>{children}</DialogTrigger>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { memo } from "react";
|
||||
import { memo, useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
@@ -96,6 +96,10 @@ const UpCodeManagementDialog = memo(
|
||||
if (await confirm(confirmMessage)) callback(data);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) form.reset();
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange} {...props}>
|
||||
<DialogTrigger asChild>{children}</DialogTrigger>
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import type { Dashboard, DashboardService } from "../model/dashboard-interface";
|
||||
import type {
|
||||
Dashboard,
|
||||
DashboardService,
|
||||
NoticeUser,
|
||||
Schedule,
|
||||
ScheduleQueryParams,
|
||||
} from "../model/dashboard-interface";
|
||||
import type { PageableList } from "@/shared/model";
|
||||
|
||||
export class DashboardApiService implements DashboardService {
|
||||
public async getDashboard(): Promise<Dashboard> {
|
||||
@@ -9,6 +16,25 @@ export class DashboardApiService implements DashboardService {
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getNoticeUserList(
|
||||
recvUnqId: string,
|
||||
): Promise<PageableList<NoticeUser>> {
|
||||
const response = await client.get<PageableList<NoticeUser>>(
|
||||
`${ENDPOINT.CMS_SERVICE.NOTICE_USER}/${recvUnqId}/list`,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getScheduleList(
|
||||
params?: ScheduleQueryParams,
|
||||
): Promise<Schedule[]> {
|
||||
const response = await client.get<Schedule[]>(
|
||||
ENDPOINT.CMS_SERVICE.SCHEDULES,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
export const DashboardApi = new DashboardApiService();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { PageableList } from "@/shared/model";
|
||||
|
||||
export interface SiteStatisticsContent {
|
||||
siteId: string;
|
||||
siteNm: string;
|
||||
@@ -27,6 +29,42 @@ export interface Dashboard {
|
||||
menuAccessList: MenuStatisticsContent[];
|
||||
}
|
||||
|
||||
export interface NoticeUser {
|
||||
notiId: number;
|
||||
recvUnqId: string;
|
||||
senderUnqId: string;
|
||||
notiType: string;
|
||||
notiTtl: string;
|
||||
notReadYn: string;
|
||||
regDt: string;
|
||||
}
|
||||
|
||||
export interface Schedule {
|
||||
schdlBgngDt: string;
|
||||
schdlEndDt: string;
|
||||
actualDate: string;
|
||||
schdlSn: number;
|
||||
siteId: string;
|
||||
schdlTtl: string;
|
||||
schdlSeCd: string;
|
||||
schdlCn: string;
|
||||
reptYn: string;
|
||||
commSchdlYn: string;
|
||||
atflCd: string | null;
|
||||
}
|
||||
|
||||
export interface ScheduleQueryParams {
|
||||
siteId?: string;
|
||||
schdlTtl?: string;
|
||||
schdlSeCd?: string;
|
||||
schdlBgngYmd?: string;
|
||||
schdlEndYmd?: string;
|
||||
reptYn?: string;
|
||||
commSchdlYn?: string;
|
||||
}
|
||||
|
||||
export interface DashboardService {
|
||||
getDashboard(): Promise<Dashboard>;
|
||||
getNoticeUserList(recvUnqId: string): Promise<PageableList<NoticeUser>>;
|
||||
getScheduleList(params?: ScheduleQueryParams): Promise<Schedule[]>;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import dayjs from "dayjs";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getCoreRowModel } from "@tanstack/react-table";
|
||||
@@ -17,8 +18,8 @@ import {
|
||||
} from "chart.js";
|
||||
import { Bar, Line } from "react-chartjs-2";
|
||||
import { PostApi, type RecentPost } from "@/entities/post";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { useDataTable } from "@/shared/lib";
|
||||
import { AUTH_USER_ID, ENDPOINT, SITE_ID } from "@/shared/config";
|
||||
import { getCookie, useDataTable } from "@/shared/lib";
|
||||
import { DashboardApi } from "../api/dashboard-service";
|
||||
import { chartData } from "../model/chart-data";
|
||||
import {
|
||||
@@ -39,12 +40,44 @@ ChartJS.register(
|
||||
);
|
||||
|
||||
function DashboardPage() {
|
||||
const userId = getCookie(AUTH_USER_ID) ?? "";
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const { data } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.DASHBOARD],
|
||||
queryFn: () => DashboardApi.getDashboard(),
|
||||
});
|
||||
|
||||
const { data: noticeUserList } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.NOTICE_USER],
|
||||
queryFn: () => DashboardApi.getNoticeUserList(userId),
|
||||
enabled: !!userId,
|
||||
select: (data) => {
|
||||
// 오늘 ~ 한 달 전 사이의 일정
|
||||
const today = dayjs().endOf("day");
|
||||
const monthAgo = dayjs().subtract(1, "month").startOf("day");
|
||||
return data.content?.filter((item) => {
|
||||
const regDt = dayjs(item.regDt);
|
||||
return (
|
||||
(regDt.isSame(monthAgo) || regDt.isAfter(monthAgo)) &&
|
||||
(regDt.isSame(today) || regDt.isBefore(today))
|
||||
);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const { data: scheduleList } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.SCHEDULES],
|
||||
queryFn: () =>
|
||||
DashboardApi.getScheduleList({
|
||||
siteId: SITE_ID,
|
||||
schdlBgngYmd: dayjs().format("YYYY-MM-DD"),
|
||||
schdlEndYmd: dayjs().add(1, "month").format("YYYY-MM-DD"),
|
||||
commSchdlYn: "Y",
|
||||
}),
|
||||
});
|
||||
|
||||
const noticePostQuery = useQuery({
|
||||
queryKey: [ENDPOINT.BOARD_SERVICE.POSTS],
|
||||
queryFn: () =>
|
||||
@@ -323,22 +356,15 @@ function DashboardPage() {
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="space-y-4 text-foreground">
|
||||
<div className="flex items-center justify-between border-b border-border pb-4">
|
||||
<span className="font-medium">신규 사용자 가입</span>
|
||||
<span>{(1).toLocaleString()}분 전</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between border-b border-border pb-4">
|
||||
<span className="font-medium">메뉴 수정 요청</span>
|
||||
<span>{(5).toLocaleString()}분 전</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between border-b border-border pb-4">
|
||||
<span className="font-medium">게시물 신고</span>
|
||||
<span>{(10).toLocaleString()}분 전</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-medium">컨텐츠 승인 요청</span>
|
||||
<span>{(15).toLocaleString()}분 전</span>
|
||||
</div>
|
||||
{noticeUserList?.map((item) => (
|
||||
<div
|
||||
key={item.notiId}
|
||||
className="flex items-center justify-between border-b border-border pb-4"
|
||||
>
|
||||
<span className="font-medium">{item.notiTtl}</span>
|
||||
<span>{dayjs(item.regDt).fromNow()}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -349,24 +375,44 @@ function DashboardPage() {
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="space-y-4 text-foreground">
|
||||
<div className="flex items-center justify-between border-b border-border pb-4">
|
||||
<span className="font-medium">
|
||||
{(3).toLocaleString()}월 정기 시스템 점검
|
||||
</span>
|
||||
<span>내일</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between border-b border-border pb-4">
|
||||
<span className="font-medium">서버 업데이트 예정</span>
|
||||
<span>{(3).toLocaleString()}일 후</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between border-b border-border pb-4">
|
||||
<span className="font-medium">백업 스케줄</span>
|
||||
<span>{(5).toLocaleString()}일 후</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-medium">정기 보안 점검</span>
|
||||
<span>{(7).toLocaleString()}일 후</span>
|
||||
</div>
|
||||
{scheduleList && scheduleList.length > 0 ? (
|
||||
scheduleList.map((schedule, index) => {
|
||||
const today = dayjs();
|
||||
const scheduleDate = dayjs(schedule.actualDate);
|
||||
const daysUntil = scheduleDate.diff(today, "day");
|
||||
|
||||
let timeText = "";
|
||||
if (daysUntil === 0) {
|
||||
timeText = "오늘";
|
||||
} else if (daysUntil === 1) {
|
||||
timeText = "내일";
|
||||
} else if (daysUntil > 1) {
|
||||
timeText = `${daysUntil}일 후`;
|
||||
} else {
|
||||
timeText = scheduleDate.format("YYYY-MM-DD");
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={schedule.schdlSn}
|
||||
className={`flex items-center justify-between ${
|
||||
index < scheduleList.length - 1
|
||||
? "border-b border-border pb-4"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
<span className="font-medium">
|
||||
{schedule.schdlTtl}
|
||||
</span>
|
||||
<span>{timeText}</span>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<div className="text-center text-muted-foreground">
|
||||
예정된 일정이 없습니다.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
@@ -48,25 +48,14 @@ function MenuAuthorityDialog({ groupId }: MenuAuthorityDialogProps) {
|
||||
keywordType: "",
|
||||
siteId: "",
|
||||
});
|
||||
|
||||
const handleReset = () => {
|
||||
if (inputRef.current) inputRef.current.value = "";
|
||||
setKeywordType("");
|
||||
setSiteId("");
|
||||
setSearchParams({
|
||||
keyword: "",
|
||||
keywordType: "",
|
||||
siteId: "",
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const query = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.MENU_AUTHRTS, groupId, searchParams],
|
||||
queryFn: () => MenuAuthorityApi.getGroupMenuAuthorityList({
|
||||
groupId,
|
||||
...searchParams
|
||||
}),
|
||||
queryFn: () =>
|
||||
MenuAuthorityApi.getGroupMenuAuthorityList({
|
||||
groupId,
|
||||
...searchParams,
|
||||
}),
|
||||
enabled: open && !!groupId,
|
||||
});
|
||||
|
||||
@@ -117,6 +106,21 @@ function MenuAuthorityDialog({ groupId }: MenuAuthorityDialogProps) {
|
||||
});
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
if (inputRef.current) inputRef.current.value = "";
|
||||
setSiteId("");
|
||||
setKeywordType("");
|
||||
setSearchParams({
|
||||
keyword: "",
|
||||
keywordType: "",
|
||||
siteId: "",
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) handleReset();
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, memo } from "react";
|
||||
import { useState, memo, useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
@@ -90,6 +90,10 @@ const ManagementAuthorityDialog = memo(
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) form.reset();
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { getCoreRowModel, type ColumnDef } from "@tanstack/react-table";
|
||||
import {
|
||||
@@ -113,6 +113,10 @@ function MappingRoleDialog({
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) handleReset();
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange} {...props}>
|
||||
<DialogTrigger asChild>
|
||||
|
||||
@@ -56,6 +56,7 @@ export const ENDPOINT = {
|
||||
APILOG: "/cms-service/api/v1/api-logs",
|
||||
SITE_AUTHORITY: "/cms-service/api/v1/site-authrt",
|
||||
CONNECTION_LOG: "/cms-service/api/v1/cntnlog",
|
||||
NOTICE_USER: "/cms-service/api/v1/noti/user",
|
||||
},
|
||||
BOARD_SERVICE: {
|
||||
BBS: "/board-service/api/v1/bbs",
|
||||
@@ -63,6 +64,7 @@ export const ENDPOINT = {
|
||||
POSTS: "/board-service/api/v1/posts",
|
||||
POSTS_COMMENTS: "/board-service/api/v1/posts-cmnts",
|
||||
POST_EVALUATION: "/board-service/api/v1/pstEvl",
|
||||
STATISTICS: "/board-service/api/v1/stat/bbs",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+2
-1
@@ -38,4 +38,5 @@ yarn-error.log*
|
||||
next-env.d.ts
|
||||
|
||||
.env*
|
||||
!.env.example
|
||||
!.env.example
|
||||
*.md
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
{
|
||||
"plugins": ["prettier-plugin-tailwindcss"]
|
||||
"plugins": ["prettier-plugin-tailwindcss"],
|
||||
"tabWidth": 4
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useCallback } from "react";
|
||||
import { useEffect, useCallback, useMemo } from "react";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useQueryClient, useQuery } from "@tanstack/react-query";
|
||||
|
||||
import type { MenuItem } from "@/entities/menu";
|
||||
import { useMenuStore, useAlertStore } from "@/shared/lib";
|
||||
import { useTabStore, getTabStoreState } from "@/store/tab-store";
|
||||
import { useTabStore as gridTabStore } from "@rsone/components";
|
||||
import { getConfig } from "@common/config";
|
||||
import { getCookie } from "@/shared/lib";
|
||||
import { getMenuList } from "../../../../packages/common/components/src/api";
|
||||
@@ -29,10 +30,17 @@ export default function WithBaseLayout({
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo);
|
||||
const currentMenuInfo = useMenuStore((state) => state.currentMenuInfo);
|
||||
|
||||
const addTab = useTabStore((state) => state.addTab);
|
||||
const setActiveTab = useTabStore((state) => state.setActiveTab);
|
||||
const setMenuList = useTabStore((state) => state.setMenuList);
|
||||
const activeTabId = useTabStore((state) => state.activeTabId);
|
||||
const menuList = useTabStore((state) => state.menuList);
|
||||
const tabs = useTabStore((state) => state.tabs);
|
||||
const addTabForGrid = gridTabStore((state) => state.addTab);
|
||||
const setActiveTabForGrid = gridTabStore((state) => state.setActiveTab);
|
||||
const setMenuListForGrid = gridTabStore((state) => state.setMenuList);
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
|
||||
const { data: menuListData } = useQuery({
|
||||
@@ -44,8 +52,9 @@ export default function WithBaseLayout({
|
||||
useEffect(() => {
|
||||
if (menuListData) {
|
||||
setMenuList(menuListData);
|
||||
setMenuListForGrid(menuListData);
|
||||
}
|
||||
}, [menuListData, setMenuList]);
|
||||
}, [menuListData, setMenuList, setMenuListForGrid]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!pathname) return;
|
||||
@@ -55,23 +64,73 @@ export default function WithBaseLayout({
|
||||
const tab = currentTabs.find((t) => t.path === pathname);
|
||||
if (tab) {
|
||||
setActiveTab(tab.id);
|
||||
setActiveTabForGrid(tab.id);
|
||||
}
|
||||
}, [pathname, setActiveTab]);
|
||||
}, [pathname, setActiveTab, setActiveTabForGrid]);
|
||||
|
||||
// 활성 탭의 메뉴를 찾아서 urlPath를 가져옴. 탭이 전부 닫히면 ''를 넘겨 LNB에서 메뉴 강조 제거
|
||||
const currentPath = useMemo(() => {
|
||||
if (tabs.length === 0) return "";
|
||||
|
||||
if (activeTabId && menuList) {
|
||||
// menuList에서 활성 탭의 메뉴 찾기
|
||||
const findMenuByEngNm = (items: MenuItem[]): MenuItem | null => {
|
||||
for (const item of items) {
|
||||
if (item.menuEngNm === activeTabId) {
|
||||
return item;
|
||||
}
|
||||
if (item.children) {
|
||||
const found = findMenuByEngNm(item.children);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const activeMenu = findMenuByEngNm(menuList);
|
||||
|
||||
if (activeMenu?.urlPath) {
|
||||
return activeMenu.urlPath;
|
||||
}
|
||||
}
|
||||
|
||||
// 탭에서 직접 찾기
|
||||
if (activeTabId) {
|
||||
const currentTabs = getTabStoreState().tabs;
|
||||
const activeTab = currentTabs.find((t) => t.id === activeTabId);
|
||||
if (activeTab?.menuItem?.urlPath) {
|
||||
return activeTab.menuItem.urlPath;
|
||||
}
|
||||
}
|
||||
|
||||
// currentMenuInfo에서 가져오기
|
||||
if (currentMenuInfo?.urlPath) {
|
||||
return currentMenuInfo.urlPath;
|
||||
}
|
||||
|
||||
// 기본값으로 pathname 사용
|
||||
return pathname ?? "";
|
||||
}, [tabs.length, activeTabId, menuList, currentMenuInfo, pathname]);
|
||||
|
||||
const handleMenuClick = useCallback((item: MenuItem) => {
|
||||
setCurrentMenuInfo(item);
|
||||
const addTabResult: boolean = addTab(item);
|
||||
|
||||
// packages/rsone의 스토어에도 동기화
|
||||
if (addTabResult) {
|
||||
addTabForGrid(item);
|
||||
}
|
||||
|
||||
if (!addTabResult) {
|
||||
alert(`최대 추가 할 수 있는 화면 수를 초과 하였습니다.
|
||||
기존 화면을 닫은 후 이용해주세요.`);
|
||||
}
|
||||
}, [setCurrentMenuInfo, addTab]);
|
||||
}, [setCurrentMenuInfo, addTab, addTabForGrid, alert]);
|
||||
|
||||
return (
|
||||
<BaseLayout
|
||||
queryClient={queryClient}
|
||||
currentPath={pathname ?? ""}
|
||||
currentPath={currentPath}
|
||||
handleMenuClick={handleMenuClick}
|
||||
>
|
||||
<StatisticsPageLayout>{children}</StatisticsPageLayout>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { statisticsPage } from "@/pages/statistics";
|
||||
import { StatisticsPage } from "@/pages/statistics";
|
||||
|
||||
export default statisticsPage;
|
||||
export default StatisticsPage;
|
||||
|
||||
@@ -32,7 +32,7 @@ export function middleware(req: NextRequest) {
|
||||
`[Request]\n Original Pathname: ${pathname}`,
|
||||
];
|
||||
|
||||
if (pathname.startsWith("/st-service")) {
|
||||
if (pathname.startsWith("/st-management-service") || pathname.startsWith("/st-input-service")) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const token = req.cookies.get(CLAIM_NAME)?.value;
|
||||
const userId = req.cookies.get(AUTH_USER_ID)?.value;
|
||||
@@ -138,5 +138,5 @@ export function middleware(req: NextRequest) {
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ["/server/:path*", "/attach-service/:path*", "/api/link/:path*", "/st-service/:path*", "/"],
|
||||
matcher: ["/server/:path*", "/attach-service/:path*", "/api/link/:path*", "/st-management-service/:path*", "/st-input-service/:path*", "/"],
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"@common/assets": "workspace:*",
|
||||
"@common/components": "workspace:*",
|
||||
"@common/config": "workspace:*",
|
||||
"@faker-js/faker": "^9.9.0",
|
||||
"@fontsource-variable/noto-sans-kr": "^5.2.5",
|
||||
"@frontend-opensource/use-react-hooks": "^1.1.4",
|
||||
"@fullcalendar/core": "^6.1.17",
|
||||
@@ -25,6 +26,7 @@
|
||||
"@radix-ui/react-label": "^2.1.2",
|
||||
"@radix-ui/react-slot": "^1.1.2",
|
||||
"@radix-ui/react-tooltip": "^1.1.8",
|
||||
"@rsone/components": "workspace:*",
|
||||
"@tanstack/react-query": "^5.67.1",
|
||||
"@tanstack/react-query-devtools": "^5.75.5",
|
||||
"@tanstack/react-table": "^8.21.2",
|
||||
|
||||
@@ -13,6 +13,7 @@ import { PromptDialog } from "@/shared/ui/prompt-dialog";
|
||||
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
|
||||
import { SelectPromptDialog } from "@/shared/ui/select-prompt-dialog";
|
||||
import { PromptProvider, StoreProvider } from "@/shared/providers";
|
||||
import { AlertDialog as RsoneAlertDialog } from "@rsone/components";
|
||||
|
||||
const AppProvider = ({ children }: Readonly<{ children: React.ReactNode }>) => {
|
||||
const queryClient = new QueryClient();
|
||||
@@ -31,6 +32,7 @@ const AppProvider = ({ children }: Readonly<{ children: React.ReactNode }>) => {
|
||||
</DndProvider>
|
||||
</MenuWrapper>
|
||||
<AlertDialog />
|
||||
<RsoneAlertDialog />
|
||||
<PromptDialog />
|
||||
<ConfirmDialog />
|
||||
<SelectPromptDialog />
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Button } from "@common/components";
|
||||
|
||||
interface AddArticleButtonProps {
|
||||
addArticleFunc: () => void;
|
||||
}
|
||||
|
||||
const AddArticleButton = ({ addArticleFunc }: AddArticleButtonProps) => {
|
||||
return (
|
||||
<Button className="h-[3.2rem] w-[96px]" onClick={addArticleFunc}>
|
||||
<i className="ri-add-fill" />
|
||||
<span>항목 추가</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddArticleButton;
|
||||
@@ -6,9 +6,9 @@ interface ApproveButtonProps {
|
||||
|
||||
const ApproveButton = ({ approveFunc }: ApproveButtonProps) => {
|
||||
return (
|
||||
<Button color="emerald" className="px-6" onClick={approveFunc}>
|
||||
<i className="diveicon di-check-circle translate-y-[1px]" />
|
||||
<span className="translate-y-[-1px]">승인</span>
|
||||
<Button className="h-[3.2rem] w-[96px]" onClick={approveFunc}>
|
||||
<i className="diveicon di-check-circle" />
|
||||
<span>승인</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Button } from "@common/components";
|
||||
|
||||
interface DeleteArticleButtonProps {
|
||||
deleteArticleFunc: () => void;
|
||||
}
|
||||
|
||||
const DeleteArticleButton = ({ deleteArticleFunc }: DeleteArticleButtonProps) => {
|
||||
return (
|
||||
<Button className="h-[3.2rem] w-[96px]" color="red" onClick={deleteArticleFunc}>
|
||||
<i className="ri-subtract-fill"></i>
|
||||
<span>항목 제거</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteArticleButton;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Button } from "@common/components";
|
||||
|
||||
interface InstallationStatusButtonProps {
|
||||
installationStatusFunc: () => void;
|
||||
}
|
||||
|
||||
const InstallationStatusButton = ({ installationStatusFunc }: InstallationStatusButtonProps) => {
|
||||
return (
|
||||
<Button className="h-[3.2rem] w-[176px]" color="lightGray" onClick={installationStatusFunc}>
|
||||
<i className="diveicon di-server-line"></i>
|
||||
<span>시설별 설치 현황관리</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default InstallationStatusButton;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Button } from "@common/components";
|
||||
|
||||
interface LastYearDataButtonProps {
|
||||
getLastYearDataFunc: () => void;
|
||||
}
|
||||
|
||||
const LastYearDataButton = ({ getLastYearDataFunc }: LastYearDataButtonProps) => {
|
||||
return (
|
||||
<Button color="emerald" className="h-[3.2rem] w-[176px]" onClick={getLastYearDataFunc}>
|
||||
<i className="diveicon di-search" />
|
||||
<span>지난연도 데이터 가져오기</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default LastYearDataButton;
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Checkbox, buttonVariants, cn } from "@common/components";
|
||||
import type React from "react";
|
||||
|
||||
interface NotApplicableCheckButtonProp {
|
||||
isCheck: boolean;
|
||||
setIsCheck: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
const NotApplicableCheckButton = ({ isCheck, setIsCheck }: NotApplicableCheckButtonProp) => {
|
||||
|
||||
const handleCheckChange = (value: boolean) => {
|
||||
setIsCheck(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={cn(buttonVariants({ variant: "default", size: "default" }), "w-[124px] bg-[#ebebeb] border border-[#999] text-[rgb(146 146 146)] text-opacity-100")}>
|
||||
<label htmlFor="notApplicable">해당사항 없음</label>
|
||||
<Checkbox
|
||||
id="notApplicable"
|
||||
className="!border-[#999] data-[state=checked]:!bg-[#999]"
|
||||
checked={isCheck}
|
||||
onCheckedChange={handleCheckChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotApplicableCheckButton;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Button } from "@common/components";
|
||||
|
||||
interface OperateDataButtonProps {
|
||||
getOperateDataFunc: () => void;
|
||||
}
|
||||
|
||||
const OperateDataButton = ({ getOperateDataFunc }: OperateDataButtonProps) => {
|
||||
return (
|
||||
<Button color="emerald" className="h-[3.2rem] w-[176px]" onClick={getOperateDataFunc}>
|
||||
<i className="diveicon di-arrow-left-right" />
|
||||
<span>운영 데이터 가져오기</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default OperateDataButton;
|
||||
@@ -6,9 +6,9 @@ interface RejectButtonProps {
|
||||
|
||||
const RejectButton = ({ rejectFunc }: RejectButtonProps) => {
|
||||
return (
|
||||
<Button color="red" className="px-6" onClick={rejectFunc}>
|
||||
<i className="diveicon di-exclamation-circle translate-y-[1px]" />
|
||||
<span className="translate-y-[-1px]">보완 요청</span>
|
||||
<Button color="red" className="h-[3.2rem] w-[96px]" onClick={rejectFunc}>
|
||||
<i className="diveicon di-exclamation-circle" />
|
||||
<span>보완 요청</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Button } from "@common/components";
|
||||
|
||||
interface ReturnButtonProps {
|
||||
returnFunc: () => void;
|
||||
}
|
||||
|
||||
const ReturnButton = ({ returnFunc }: ReturnButtonProps) => {
|
||||
return (
|
||||
<Button color="red" className="h-[3.2rem] w-[96px]" onClick={returnFunc}>
|
||||
<i className="diveicon di-arrow-reset" />
|
||||
<span>반려</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReturnButton;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Button } from "@common/components";
|
||||
|
||||
interface ReviewOpinionButtonProps {
|
||||
reviewOpinionFunc: () => void;
|
||||
}
|
||||
|
||||
const ReviewOpinionButton = ({ reviewOpinionFunc }: ReviewOpinionButtonProps) => {
|
||||
return (
|
||||
<Button color="emerald" className="h-[3.2rem] w-[124px]" onClick={reviewOpinionFunc}>
|
||||
<i className="diveicon di-pencil" />
|
||||
<span>검토의견 작성</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReviewOpinionButton;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Button } from "@common/components";
|
||||
|
||||
interface SaveButtonProps {
|
||||
saveFunc: () => void;
|
||||
}
|
||||
|
||||
const SaveButton = ({ saveFunc }: SaveButtonProps) => {
|
||||
return (
|
||||
<Button color="green" className="h-[3.2rem] w-[96px]" onClick={saveFunc}>
|
||||
<i className="diveicon di-download" />
|
||||
<span>저장</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default SaveButton;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Button } from "@common/components";
|
||||
|
||||
interface SubmitExceptionButtonProps {
|
||||
SubmitExceptionFunc: () => void;
|
||||
}
|
||||
|
||||
const SubmitExceptionButton = ({ SubmitExceptionFunc }: SubmitExceptionButtonProps) => {
|
||||
return (
|
||||
<Button color="red" className="h-[3.2rem] w-[96px]" onClick={SubmitExceptionFunc}>
|
||||
<i className="diveicon di-box-arrow-upload" />
|
||||
<span>예외제출</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default SubmitExceptionButton;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Button } from "@common/components";
|
||||
|
||||
interface SubmitButtonProps {
|
||||
submitFunc: () => void;
|
||||
}
|
||||
|
||||
const SubmitButton = ({ submitFunc }: SubmitButtonProps) => {
|
||||
return (
|
||||
<Button className="h-[3.2rem] w-[96px]" onClick={submitFunc}>
|
||||
<i className="diveicon di-upload" />
|
||||
<span>제출</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default SubmitButton;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Button } from "@common/components";
|
||||
|
||||
interface UpdateOperateDataButtonProps {
|
||||
updateOperateDataButtonFunc: () => void;
|
||||
}
|
||||
|
||||
const UpdateOperateDataButton = ({ updateOperateDataButtonFunc }: UpdateOperateDataButtonProps) => {
|
||||
return (
|
||||
<Button color="emerald" className="h-[3.2rem] w-[176px]" onClick={updateOperateDataButtonFunc}>
|
||||
<i className="diveicon di-arrow-up-down" />
|
||||
<span>운영 데이터 업데이트</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default UpdateOperateDataButton;
|
||||
@@ -1,105 +1,43 @@
|
||||
/* RealGrid2 폰트 설정 - 루트 폰트와 일치 */
|
||||
.rg-root,
|
||||
.rg-grid,
|
||||
.rg-body,
|
||||
.rg-cell,
|
||||
.rg-header,
|
||||
.rg-head,
|
||||
.rg-rowbarcontainer {
|
||||
font-family: "Noto Sans KR", sans-serif !important;
|
||||
font-size: 12px !important;
|
||||
font-weight: 500;
|
||||
color: #333 !important;
|
||||
@tailwind components;
|
||||
|
||||
@layer components {
|
||||
.rg-grid .rg-header .rg-table .rg-header-group-cell {
|
||||
@apply !bg-[#466995] !text-[#fff];
|
||||
}
|
||||
.rg-grid .rg-header .rg-table .rg-header-cell {
|
||||
@apply !bg-[#5987bf] !text-[#fff];
|
||||
}
|
||||
.rg-grid .rg-body .rg-table .rg-data-row .rg-data-cell {
|
||||
@apply !bg-white;
|
||||
}
|
||||
|
||||
[data-theme="black"] {
|
||||
.rg-grid .rg-header .rg-table .rg-header-group-cell {
|
||||
@apply !bg-[#3C4043] !text-[#fff];
|
||||
}
|
||||
.rg-grid .rg-header .rg-table .rg-header-cell {
|
||||
@apply !bg-[#62686d] !text-[#fff];
|
||||
}
|
||||
.rg-grid .rg-body .rg-table .rg-data-row .rg-data-cell {
|
||||
@apply !bg-[#545556] !text-[#fff];
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme="red"] {
|
||||
.rg-grid .rg-header .rg-table .rg-header-group-cell {
|
||||
@apply !bg-[#646469] !text-[#fff];
|
||||
}
|
||||
.rg-grid .rg-header .rg-table .rg-header-cell {
|
||||
@apply !bg-[#8d8d94] !text-[#fff];
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme="green"] {
|
||||
.rg-grid .rg-header .rg-table .rg-header-group-cell {
|
||||
@apply !bg-[#518585] !text-[#fff];
|
||||
}
|
||||
.rg-grid .rg-header .rg-table .rg-header-cell {
|
||||
@apply !bg-[#6bafae] !text-[#fff];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* RealGrid2 컨테이너 스타일 */
|
||||
.rg-root {
|
||||
border-radius: 0.5rem !important;
|
||||
overflow: hidden !important;
|
||||
border: 1px solid #dbe2e6 !important;
|
||||
}
|
||||
|
||||
.rg-grid {
|
||||
border-radius: 0.5rem !important;
|
||||
/* box-shadow: 0 0 10px -1px rgba(0, 0, 0, 0.06); */
|
||||
}
|
||||
|
||||
/* 헤더 스타일 */
|
||||
.rg-header,
|
||||
.rg-head,
|
||||
.rg-foot,
|
||||
.rg-footer,
|
||||
.rg-fixed-footer {
|
||||
background-color: #f5f7fa !important;
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
/* 헤더 셀 스타일 */
|
||||
.rg-header .rg-cell,
|
||||
.rg-head .rg-cell {
|
||||
background-color: #f5f7fa !important;
|
||||
}
|
||||
|
||||
/* 헤더 필터링 영역 위치 조정 - 오른쪽 여백 추가 */
|
||||
.rg-header-filtering {
|
||||
left: auto !important;
|
||||
right: 8px !important;
|
||||
}
|
||||
|
||||
/* 그룹 헤더 스타일 */
|
||||
.rg-header-group,
|
||||
.rg-header-group-cell {
|
||||
background-color: #f5f7fa !important;
|
||||
}
|
||||
|
||||
/* 첫 번째 헤더 셀 - 왼쪽 상단 모서리 */
|
||||
.rg-header .rg-cell:first-child,
|
||||
.rg-head .rg-cell:first-child {
|
||||
border-top-left-radius: 8px !important;
|
||||
}
|
||||
|
||||
/* 마지막 헤더 셀 - 오른쪽 상단 모서리 */
|
||||
.rg-header .rg-cell:last-child,
|
||||
.rg-head .rg-cell:last-child {
|
||||
border-top-right-radius: 8px !important;
|
||||
}
|
||||
|
||||
/* border color 통일 */
|
||||
.rg-header .rg-table tr td,
|
||||
.rg-head .rg-table tr td:not(:first-child),
|
||||
.rg-body .rg-table tr td,
|
||||
.rg-rowbarcontainer .rg-table tr td:not(:first-child) {
|
||||
border-left: 1px solid #dbe2e6 !important;
|
||||
border-bottom: 1px solid #dbe2e6 !important;
|
||||
border-right: none !important;
|
||||
}
|
||||
.rg-rowindicator-head,
|
||||
.rg-rowbarcontainer .rg-table tr td:first-child {
|
||||
border-right: none !important;
|
||||
border-bottom: 1px solid #dbe2e6 !important;
|
||||
border-left: none !important;
|
||||
}
|
||||
.rg-footer .rg-table tr td,
|
||||
.rg-fixed-footer .rg-table tr td,
|
||||
.rg-foot .rg-table tr td {
|
||||
border-right: 1px solid #dbe2e6 !important;
|
||||
border-top: 1px solid #dbe2e6 !important;
|
||||
}
|
||||
|
||||
.rg-rowbarcontainer .rg-table tr td {
|
||||
background-color: #f5f7fa !important;
|
||||
}
|
||||
|
||||
/* 푸터 마지막 요소 - 오른쪽 border 제거 */
|
||||
.rg-footer .rg-table tr td:last-child {
|
||||
border-right: none !important;
|
||||
}
|
||||
|
||||
/* 고정 컬럼 바 */
|
||||
.rg-fixed-column-bar {
|
||||
background-color: #ccc !important;
|
||||
border-right: 1px solid #ccc !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
import { useRef, useEffect } from "react"
|
||||
import { ValueType } from "realgrid"
|
||||
|
||||
import RealGrid, { GridFitStyle } from "realgrid"
|
||||
import { RealGridReact, RGDataColumn } from "realgrid-react"
|
||||
import type { DataGridProps, RealGridColumnInfo, GridViewWithSetColumns, FooterItemWithCallback } from "../type/DataGrid.type"
|
||||
import { getComputedValueCallback } from "@/components/util/grid/computedFieldCallbacks"
|
||||
|
||||
// RealGrid 타입 확장
|
||||
declare module "realgrid" {
|
||||
interface GridView {
|
||||
setOptions(options: {
|
||||
footer?: { visible?: boolean };
|
||||
summaryMode?: 'aggregate' | 'statistical' | 'none';
|
||||
checkBar?: { visible?: boolean };
|
||||
}): void;
|
||||
}
|
||||
}
|
||||
|
||||
RealGrid.setLicenseKey(process.env.NEXT_PUBLIC_ST_REALGRID_KEY || '');
|
||||
|
||||
/** setDataComparer(field, comparer) - setFields 없이 숫자 정렬용. comparer(field, row1, row2) => -1|0|1 */
|
||||
interface RealGridDataProviderComparer {
|
||||
setDataComparer?(field: string | number, comparer: (field: string | number, row1: number, row2: number) => number): void;
|
||||
getValue?(row: number, field: string | number): unknown;
|
||||
}
|
||||
|
||||
/** columnInfo → RealGrid DataField 배열 (computed → valueCallback 포함, setFields용) */
|
||||
function buildFieldsFromColumns(columns: { fieldName: string; valueType?: ValueType; computed?: import("../type/DataGrid.type").ComputedFieldConfig }[]) {
|
||||
return columns.map((col) => {
|
||||
const field: { fieldName: string; dataType: string; valueCallback?: (prod: unknown, dataRow: number, fieldName: string, fieldNames: string[], values: unknown[]) => number } = {
|
||||
fieldName: col.fieldName,
|
||||
dataType: col.valueType === ValueType.NUMBER ? "number" : "text",
|
||||
};
|
||||
if (col.computed) {
|
||||
const hasFields = "fields" in col.computed && col.computed.fields.length > 0;
|
||||
const hasNumeratorDenominator = "numeratorFields" in col.computed && col.computed.numeratorFields.length > 0 && col.computed.denominatorFields.length > 0;
|
||||
if (hasFields || hasNumeratorDenominator) {
|
||||
field.valueCallback = getComputedValueCallback(col.computed) as (prod: unknown, dataRow: number, fieldName: string, fieldNames: string[], values: unknown[]) => number;
|
||||
}
|
||||
}
|
||||
return field;
|
||||
});
|
||||
}
|
||||
|
||||
/** setDataComparer용 숫자 비교기. setFields 없이 숫자 정렬. */
|
||||
function createNumberComparer(dp: RealGridDataProviderComparer): (field: string | number, row1: number, row2: number) => number {
|
||||
return (field, row1, row2) => {
|
||||
const get = dp.getValue?.bind(dp);
|
||||
if (!get) return 0;
|
||||
const val1 = get(row1, field);
|
||||
const val2 = get(row2, field);
|
||||
if (val1 == null && val2 == null) return 0;
|
||||
if (val1 == null) return 1;
|
||||
if (val2 == null) return -1;
|
||||
const num1 = typeof val1 === "number" ? val1 : parseFloat(String(val1));
|
||||
const num2 = typeof val2 === "number" ? val2 : parseFloat(String(val2));
|
||||
if (isNaN(num1) && isNaN(num2)) return 0;
|
||||
if (isNaN(num1)) return 1;
|
||||
if (isNaN(num2)) return -1;
|
||||
return num1 > num2 ? 1 : num1 < num2 ? -1 : 0;
|
||||
};
|
||||
}
|
||||
|
||||
const CompactDataGrid = ({ columnInfo, fixedColumns, showHeaderCheckbox = false, rowData, setRowData }: DataGridProps) => {
|
||||
const { columns, columnLayout } = columnInfo;
|
||||
const gridRef = useRef<RealGridReact>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!gridRef.current?.gridView || !gridRef.current?.dataProvider) return;
|
||||
|
||||
const gridView = gridRef.current.gridView;
|
||||
const dataProvider = gridRef.current.dataProvider;
|
||||
|
||||
// setDataComparer로 숫자 정렬 (setFields 미사용 → 데이터 유실·필드 중복 오류 없음)
|
||||
const dp = dataProvider as RealGridDataProviderComparer;
|
||||
if (typeof dp.setDataComparer === "function" && typeof dp.getValue === "function") {
|
||||
const numberComparer = createNumberComparer(dp);
|
||||
const seen = new Set<string>();
|
||||
columns.forEach((col) => {
|
||||
if (col.valueType === ValueType.NUMBER && col.fieldName && !seen.has(col.fieldName)) {
|
||||
seen.add(col.fieldName);
|
||||
try {
|
||||
dp.setDataComparer!(col.fieldName, numberComparer);
|
||||
} catch (e) {
|
||||
console.warn("setDataComparer:", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
gridView.setDisplayOptions({
|
||||
fitStyle: GridFitStyle.EVEN
|
||||
});
|
||||
|
||||
gridView.header.height = 60;
|
||||
|
||||
// 헤더 체크박스 표시 여부 설정
|
||||
gridView.setOptions({
|
||||
checkBar: { visible: showHeaderCheckbox },
|
||||
rowIndicator: { visible: false },
|
||||
});
|
||||
|
||||
// footer가 있는 컬럼이 있으면 footer 높이 설정
|
||||
const hasFooter = columns.some(col => col.footer);
|
||||
if (hasFooter) {
|
||||
// footer가 배열이거나 multiRow가 true인 footer가 있으면 멀티푸터 설정 (여러 행)
|
||||
const hasArrayFooter = columns.some(col => col.footer && Array.isArray(col.footer));
|
||||
const hasMultiRowFooter = columns.some(col => {
|
||||
const footer = col.footer;
|
||||
return footer && !Array.isArray(footer) && 'multiRow' in footer && footer.multiRow === true;
|
||||
});
|
||||
if (hasArrayFooter || hasMultiRowFooter) {
|
||||
// footer 배열의 길이를 확인하여 행 수 결정
|
||||
const arrayFooterLengths = columns
|
||||
.filter(col => col.footer && Array.isArray(col.footer))
|
||||
.map(col => (col.footer as unknown[]).length);
|
||||
const maxFooterLength = arrayFooterLengths.length > 0
|
||||
? Math.max(...arrayFooterLengths)
|
||||
: 2; // 기본값 2
|
||||
const footerHeights = Array.from({ length: maxFooterLength }, () => ({ height: 40 }));
|
||||
gridView.setFooters?.(footerHeights);
|
||||
} else {
|
||||
gridView.footer.height = 40;
|
||||
}
|
||||
}
|
||||
|
||||
// 고정 컬럼 설정
|
||||
if (fixedColumns !== undefined && fixedColumns > 0) {
|
||||
gridView.setFixedOptions({
|
||||
colCount: fixedColumns,
|
||||
});
|
||||
}
|
||||
|
||||
gridView.setOptions({
|
||||
summaryMode: "aggregate"
|
||||
});
|
||||
|
||||
// footerUserSpans가 있는 경우 setColumnLayout으로 설정
|
||||
const checkFooterUserSpans = (layout: unknown[]): boolean => {
|
||||
return layout.some(item => {
|
||||
if (typeof item === 'string') return false;
|
||||
if (item && typeof item === 'object' && 'footerUserSpans' in item) return true;
|
||||
if (item && typeof item === 'object' && 'items' in item && Array.isArray(item.items)) {
|
||||
return checkFooterUserSpans(item.items);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
if (checkFooterUserSpans(columnLayout)) {
|
||||
// setColumnLayout은 그리드가 완전히 렌더링된 후 호출해야 함
|
||||
setTimeout(() => {
|
||||
if (gridRef.current?.gridView && columnLayout) {
|
||||
gridRef.current.gridView.setColumnLayout?.(columnLayout);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// footer 설정 (배열 또는 단일 객체 모두 처리)
|
||||
// setFooters 호출 후 footer 배열 설정
|
||||
setTimeout(() => {
|
||||
const currentGridView = gridRef.current?.gridView;
|
||||
if (!currentGridView || !currentGridView.columnByName) {
|
||||
console.warn('GridView not available for footer setup');
|
||||
return;
|
||||
}
|
||||
|
||||
// footer가 배열인 컬럼이 있으면 setColumns를 다시 호출하여 footer 설정
|
||||
const hasArrayFooter = columns.some(col => col.footer && Array.isArray(col.footer));
|
||||
if (hasArrayFooter) {
|
||||
// 모든 컬럼 정보를 다시 가져와서 footer 배열을 포함하여 setColumns 호출
|
||||
const columnsWithFooter: RealGridColumnInfo[] = columns.map(col => {
|
||||
const colInfo: RealGridColumnInfo = {
|
||||
name: col.name,
|
||||
fieldName: col.fieldName,
|
||||
header: col.header,
|
||||
editable: col.editable,
|
||||
valueType: col.valueType,
|
||||
dataFormat: col.dataFormat,
|
||||
...(col.styleName != null && { styleName: col.styleName }),
|
||||
...(col.mergeCells && { mergeRule: { criteria: 'value' as const } }),
|
||||
};
|
||||
|
||||
if (col.footer) {
|
||||
if (Array.isArray(col.footer)) {
|
||||
colInfo.footer = col.footer;
|
||||
} else {
|
||||
colInfo.footer = {
|
||||
text: col.footer.text,
|
||||
expression: col.footer.expression,
|
||||
numberFormat: col.footer.numberFormat,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return colInfo;
|
||||
});
|
||||
|
||||
try {
|
||||
(currentGridView as GridViewWithSetColumns).setColumns?.(columnsWithFooter);
|
||||
|
||||
// setColumns 호출 후 footer 배열의 valueCallback을 다시 설정
|
||||
setTimeout(() => {
|
||||
columns.forEach(col => {
|
||||
if (!col.footer || !Array.isArray(col.footer)) return;
|
||||
|
||||
try {
|
||||
const column = currentGridView.columnByName(col.name);
|
||||
if (!column) return;
|
||||
|
||||
// footer 배열의 각 요소에 valueCallback 설정
|
||||
col.footer.forEach((footerItem, index) => {
|
||||
if (footerItem.valueCallback && column.footer) {
|
||||
// footer가 배열인 경우
|
||||
if (Array.isArray(column.footer) && column.footer[index]) {
|
||||
(column.footer[index] as FooterItemWithCallback).valueCallback = footerItem.valueCallback;
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn(`Error setting footer array valueCallback for column ${col.name}:`, e);
|
||||
}
|
||||
});
|
||||
}, 50);
|
||||
} catch (e) {
|
||||
console.warn('Failed to set columns with footer array:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// footer가 단일 객체이고 valueCallback이 있는 경우
|
||||
columns.forEach(col => {
|
||||
if (!col.footer || Array.isArray(col.footer)) return;
|
||||
|
||||
try {
|
||||
const column = currentGridView.columnByName(col.name);
|
||||
if (!column || !column.footer) return;
|
||||
|
||||
if (col.footer.valueCallback) {
|
||||
(column.footer as { valueCallback?: typeof col.footer.valueCallback }).valueCallback = col.footer.valueCallback;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(`Error setting footer valueCallback for column ${col.name}:`, e);
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
|
||||
}, [columns, columnLayout, fixedColumns, rowData, showHeaderCheckbox]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-[0.6rem] mx-[0.6rem] w-1/2">
|
||||
<div className="h-[65vh]">
|
||||
<RealGridReact
|
||||
ref={gridRef}
|
||||
autoGenerateField={true}
|
||||
layout={columnLayout}
|
||||
rows={rowData}
|
||||
onInitialized={(grid) => {
|
||||
const dp = gridRef.current?.dataProvider as { setFields?: (fields: unknown[]) => void } | undefined;
|
||||
if (dp?.setFields) {
|
||||
dp.setFields(buildFieldsFromColumns(columns));
|
||||
}
|
||||
}}
|
||||
>
|
||||
{columns.map((column) => (
|
||||
<RGDataColumn
|
||||
key={column.name}
|
||||
name={column.name}
|
||||
fieldName={column.fieldName}
|
||||
valueType={column.valueType ? column.valueType : ValueType.TEXT}
|
||||
{...(column.valueType === ValueType.NUMBER && { numberFormat: column.dataFormat ? column.dataFormat : '#,##0.000' })}
|
||||
header={column.header}
|
||||
editable={column.editable}
|
||||
{...(column.styleName != null
|
||||
? { styleName: column.styleName }
|
||||
: column.editable === false
|
||||
? { styleName: 'rg-cell-readonly' as const }
|
||||
: {})}
|
||||
{...(column.visible === false && { visible: false })}
|
||||
footer={column.footer && !Array.isArray(column.footer) ? {
|
||||
text: column.footer.text,
|
||||
expression: column.footer.expression,
|
||||
numberFormat: column.footer.numberFormat,
|
||||
} : undefined}
|
||||
mergeRule={column.mergeCells ? { criteria: 'value' } : undefined}
|
||||
sortable={!column.sortdisable}
|
||||
/>
|
||||
))}
|
||||
</RealGridReact>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CompactDataGrid;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import useSWR from 'swr';
|
||||
|
||||
import {
|
||||
@@ -18,9 +18,9 @@ from "@common/components";
|
||||
import { useAlertStore } from "@/shared/lib";
|
||||
import { type SearchFormProps, type SearchFormValues, defaultSearchFormProps } from "../type/SearchForm.type";
|
||||
import { statisticsAPi } from "@/entities/statistics/api/statistics-service";
|
||||
import type { ApiResponse, Sido, Sgg } from "@/entities/statistics/model/statistics-interface";
|
||||
import type { ApiResponse, SearchCondition, Sgg } from "@/entities/statistics/model/statistics-interface";
|
||||
|
||||
const getSidoListFetcher = async (): Promise<ApiResponse<Sido[]>> => {
|
||||
const getSidoListFetcher = async (): Promise<ApiResponse<SearchCondition>> => {
|
||||
return statisticsAPi.getSidoList();
|
||||
};
|
||||
|
||||
@@ -31,15 +31,11 @@ const getSggListFetcher = async (key: [string, string]): Promise<ApiResponse<Sgg
|
||||
const SearchForm = (props: SearchFormProps = {}) => {
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
const mergedProps = { ...defaultSearchFormProps, ...props };
|
||||
const [values, setValues] = useState<SearchFormValues>({
|
||||
sido: props.defaultValues?.sido || "",
|
||||
sgg: props.defaultValues?.sgg || "",
|
||||
year: props.defaultValues?.year || "",
|
||||
order: props.defaultValues?.order || "",
|
||||
fctName: props.defaultValues?.fctName || "",
|
||||
});
|
||||
|
||||
const { data: sidoList } = useSWR<ApiResponse<Sido[]>>(
|
||||
const currentYear = new Date().getFullYear();
|
||||
const defaultYear = currentYear - 1;
|
||||
|
||||
const { data: sidoList } = useSWR<ApiResponse<SearchCondition>>(
|
||||
"sido-list",
|
||||
getSidoListFetcher,
|
||||
{
|
||||
@@ -61,6 +57,15 @@ const SearchForm = (props: SearchFormProps = {}) => {
|
||||
}
|
||||
);
|
||||
|
||||
const [values, setValues] = useState<SearchFormValues>({
|
||||
sido: props.defaultValues?.sido || '',
|
||||
gugun: props.defaultValues?.gugun || '',
|
||||
year: props.defaultValues?.year || defaultYear.toString(),
|
||||
order: props.defaultValues?.order || '',
|
||||
fctName: props.defaultValues?.fctName || '',
|
||||
bsnmCd: props.defaultValues?.bsnmCd || '',
|
||||
});
|
||||
|
||||
const { data: sggList } = useSWR<ApiResponse<Sgg[]>>(
|
||||
values.sido && values.sido !== "ALL" ? ["sgg-list", values.sido] : null,
|
||||
getSggListFetcher,
|
||||
@@ -83,6 +88,7 @@ const SearchForm = (props: SearchFormProps = {}) => {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
props.onSubmit?.(values);
|
||||
@@ -90,17 +96,44 @@ const SearchForm = (props: SearchFormProps = {}) => {
|
||||
|
||||
const handleReset = () => {
|
||||
const resetValues: SearchFormValues = {
|
||||
sido: "",
|
||||
sgg: "",
|
||||
year: "",
|
||||
order: "",
|
||||
fctName: "",
|
||||
sido: '',
|
||||
gugun: '',
|
||||
year: String(defaultYear),
|
||||
order: '',
|
||||
fctName: '',
|
||||
bsnmCd: '',
|
||||
};
|
||||
setValues(resetValues);
|
||||
props.onReset?.();
|
||||
props.onSubmit?.(resetValues);
|
||||
};
|
||||
|
||||
const handleSidoChange = (value: string) => {
|
||||
const selectedBsnm = sidoList?.data.sidoList.find((v) => v.sido === value)?.bsnmCd || '';
|
||||
|
||||
setValues((prev) => ({
|
||||
...prev,
|
||||
sido: value,
|
||||
gugun: '',
|
||||
bsnmCd: selectedBsnm,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleSggChange = (value: string) => {
|
||||
const selectedBsnm = value === 'ALL'
|
||||
? (sidoList?.data.sidoList.find((v) => v.sido === values.sido)?.bsnmCd || '')
|
||||
: (sggList?.data?.find((v) => v.gugun === value)?.bsnmCd || '');
|
||||
|
||||
setValues((prev) => ({
|
||||
...prev,
|
||||
gugun: value,
|
||||
bsnmCd: selectedBsnm,
|
||||
}));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
props.onValuesChange?.(values);
|
||||
}, [values]);
|
||||
|
||||
return (
|
||||
<div className="card card-border">
|
||||
<form onSubmit={handleSubmit}>
|
||||
@@ -110,13 +143,13 @@ const SearchForm = (props: SearchFormProps = {}) => {
|
||||
<Label className="text-label">
|
||||
시도
|
||||
</Label>
|
||||
<Select value={values.sido} onValueChange={(value) => setValues((prev) => ({ ...prev, sido: value, sgg: 'ALL' }))}>
|
||||
<Select value={values.sido} onValueChange={handleSidoChange}>
|
||||
<SelectTrigger className="w-[12rem]">
|
||||
<SelectValue placeholder="전체"></SelectValue>
|
||||
<SelectValue placeholder="선택"></SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="ALL">전체</SelectItem>
|
||||
{sidoList?.data?.map((sido) => (
|
||||
<SelectItem value="ALL">선택</SelectItem>
|
||||
{sidoList?.data?.sidoList?.map((sido) => (
|
||||
<SelectItem key={sido.adstDstrCd} value={sido.sido}>
|
||||
{sido.sido}
|
||||
</SelectItem>
|
||||
@@ -125,12 +158,12 @@ const SearchForm = (props: SearchFormProps = {}) => {
|
||||
</Select>
|
||||
</div>
|
||||
}
|
||||
{mergedProps.sgg &&
|
||||
{mergedProps.gugun &&
|
||||
<div className="flex items-center gap-2">
|
||||
<Label className="text-label">
|
||||
시군구
|
||||
</Label>
|
||||
<Select value={values.sgg} onValueChange={(value) => setValues({ ...values, sgg: value })}>
|
||||
<Select value={values.gugun} onValueChange={handleSggChange}>
|
||||
<SelectTrigger className="w-[12rem]">
|
||||
<SelectValue placeholder="전체"></SelectValue>
|
||||
</SelectTrigger>
|
||||
@@ -152,10 +185,14 @@ const SearchForm = (props: SearchFormProps = {}) => {
|
||||
</Label>
|
||||
<Select value={values.year} onValueChange={(value) => setValues({ ...values, year: value })}>
|
||||
<SelectTrigger className="w-[10rem]">
|
||||
<SelectValue placeholder="전체"></SelectValue>
|
||||
<SelectValue placeholder="선택"></SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="ALL">전체</SelectItem>
|
||||
{sidoList?.data?.yearList.map((year) => (
|
||||
<SelectItem key={year} value={String(year)}>
|
||||
{year}년
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@@ -176,10 +213,10 @@ const SearchForm = (props: SearchFormProps = {}) => {
|
||||
</div>
|
||||
}
|
||||
<div className="flex items-center gap-2 ml-auto">
|
||||
<Button color="green" className="h-[3.2rem]" type="button" onClick={handleReset}>
|
||||
<Button color="green" className="h-[3.2rem] w-[96px]" type="button" onClick={handleReset}>
|
||||
초기화
|
||||
</Button>
|
||||
<Button className="h-[3.2rem]" type="submit">
|
||||
<Button className="h-[3.2rem] w-[96px]" type="submit">
|
||||
조회
|
||||
</Button>
|
||||
</div>
|
||||
@@ -202,7 +239,7 @@ const SearchForm = (props: SearchFormProps = {}) => {
|
||||
}
|
||||
{mergedProps.userMenual &&
|
||||
<div className="flex items-center gap-2 ml-auto">
|
||||
<Button className="h-[3.2rem]" type="button">
|
||||
<Button className="h-[3.2rem] w-[124px]" type="button">
|
||||
<i className="diveicon di-person-fill" />
|
||||
사용자 메뉴얼
|
||||
</Button>
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import CompactDataGrid from "./CompactDataGrid";
|
||||
import type { SplitDataGridProps } from "../type/DataGrid.type";
|
||||
|
||||
const SplitDataGrid = ({
|
||||
leftColumnInfo,
|
||||
rightColumnInfo,
|
||||
leftFixedColumns,
|
||||
rightFixedColumns,
|
||||
showHeaderCheckbox = false,
|
||||
leftRowData,
|
||||
rightRowData,
|
||||
setLeftRowData,
|
||||
setRightRowData,
|
||||
}: SplitDataGridProps) => {
|
||||
return (
|
||||
<div className="flex gap-[0.6rem] mx-[0.6rem]">
|
||||
<CompactDataGrid
|
||||
columnInfo={leftColumnInfo}
|
||||
fixedColumns={leftFixedColumns}
|
||||
showHeaderCheckbox={showHeaderCheckbox}
|
||||
rowData={leftRowData}
|
||||
setRowData={setLeftRowData}
|
||||
/>
|
||||
<CompactDataGrid
|
||||
columnInfo={rightColumnInfo}
|
||||
fixedColumns={rightFixedColumns}
|
||||
showHeaderCheckbox={showHeaderCheckbox}
|
||||
rowData={rightRowData}
|
||||
setRowData={setRightRowData}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SplitDataGrid;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,80 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { DataGrid } from "@rsone/components";
|
||||
import SubmitButton from "@/components/button/SumitButton";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import LastYearDataButton from "@/components/button/LastYearDataButton";
|
||||
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
|
||||
import AddArticleButton from "@/components/button/AddArticleButton";
|
||||
import DeleteArticleButton from "@/components/button/DeleteArticleButton";
|
||||
import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton";
|
||||
|
||||
import { ExcretaTreatFactInpColumn } from "@/components/util/column/input/ExcretaTreatFactInpColumn"
|
||||
|
||||
// 하수도 통계 관리 > 07. 분뇨처리시설
|
||||
const ExcretaTreatmentFacilityInp = () => {
|
||||
|
||||
const submitExceptionFunc = () => {
|
||||
console.log('submit exception');
|
||||
// 예외제출 로직
|
||||
};
|
||||
|
||||
const getLastYearDataFunc = () => {
|
||||
console.log('get last year data');
|
||||
// 지난연도 데이터 가져오기 로직
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
console.log('submit');
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('save');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const addArticleFunc = () => {
|
||||
console.log('save');
|
||||
// 항목 추가 로직
|
||||
};
|
||||
|
||||
const deleteArticleFunc = () => {
|
||||
console.log('save');
|
||||
// 항목 제외 로직
|
||||
};
|
||||
|
||||
const [rowData, setRowData] = useState<Record<string, string | number>[]>([]);
|
||||
const [isNotApplicable, setIsNotApplicable] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<SubmitExceptionButton SubmitExceptionFunc={submitExceptionFunc} />
|
||||
<LastYearDataButton getLastYearDataFunc={getLastYearDataFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
<SubmitButton submitFunc={submitFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<NotApplicableCheckButton isCheck={isNotApplicable} setIsCheck={setIsNotApplicable} />
|
||||
<AddArticleButton addArticleFunc={addArticleFunc} />
|
||||
<DeleteArticleButton deleteArticleFunc={deleteArticleFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<DataGrid
|
||||
columnInfo={ExcretaTreatFactInpColumn}
|
||||
rowStartNum={2}
|
||||
fixedColumns={2}
|
||||
rowData={rowData}
|
||||
setRowData={setRowData}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExcretaTreatmentFacilityInp;
|
||||
@@ -0,0 +1,62 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { TabDataGrid } from "@rsone/components";
|
||||
import SubmitButton from "@/components/button/SumitButton";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
|
||||
import LastYearDataButton from "@/components/button/LastYearDataButton";
|
||||
|
||||
import { SewageTreatFactStatusInpColumn } from "@/components/util/column/input/privateSewageFacility/SewageTreatFactStatusInpColumn"
|
||||
import { SepticTankStatusInpColumn } from "@/components/util/column/input/privateSewageFacility/SepticTankStatusInpColumn"
|
||||
import { PrivateSewageDesigStatusInpColumn } from "@/components/util/column/input/privateSewageFacility/PrivateSewageDesigStatusInpColumn"
|
||||
|
||||
// 하수도 통계 관리 > 08. 개인하수처리시설
|
||||
const PrivateSewageFacilityInp = () => {
|
||||
|
||||
// tab list
|
||||
const PrivateSewageFacilityInpTabList = [
|
||||
SewageTreatFactStatusInpColumn,
|
||||
SepticTankStatusInpColumn,
|
||||
PrivateSewageDesigStatusInpColumn
|
||||
];
|
||||
|
||||
const submitExceptionFunc = () => {
|
||||
// 예외 제출 로직
|
||||
};
|
||||
|
||||
const lastYearDataFunc = () => {
|
||||
// 지난연도 데이터 가져오기 로직
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<SubmitExceptionButton SubmitExceptionFunc={submitExceptionFunc} />
|
||||
<LastYearDataButton getLastYearDataFunc={lastYearDataFunc} />
|
||||
<SubmitButton submitFunc={submitFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid
|
||||
columnInfo={PrivateSewageFacilityInpTabList}
|
||||
rowDataMap={rowDataMap}
|
||||
setRowDataMap={setRowDataMap}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PrivateSewageFacilityInp;
|
||||
@@ -0,0 +1,73 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import SearchForm from '@/components/module/SearchForm';
|
||||
import { DataGrid } from '@rsone/components';
|
||||
import SubmitButton from '@/components/button/SumitButton';
|
||||
import SaveButton from '@/components/button/SaveButton';
|
||||
import SubmitExceptionButton from '@/components/button/SubmitExceptionButton';
|
||||
import OperateDataButton from '@/components/button/OperateDataButton';
|
||||
import UpdateOperateDataButton from "@/components/button/UpdateOperateDataButton"
|
||||
import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton";
|
||||
|
||||
import { PublicSewageFactInpColumn } from '@/components/util/column/input/PublicSewageFactInpColumn';
|
||||
|
||||
// 하수도 통계 관리 > 06. 공공하수처리시설
|
||||
const PublicSewageFacilityInp = () => {
|
||||
|
||||
const SubmitExceptionFunc = () => {
|
||||
console.log('submitException');
|
||||
// 예외제출 로직
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
console.log('submit');
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('save');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const getOperateDataFunc = () => {
|
||||
console.log('get operate data');
|
||||
// 운영 데이터 가져오기
|
||||
};
|
||||
|
||||
const updateOperateDataButtonFunc = () => {
|
||||
console.log('updatedOperateData');
|
||||
// 운영 데이터 업데이트 로직
|
||||
};
|
||||
|
||||
const [rowData, setRowData] = useState<Record<string, string | number>[]>([]);
|
||||
const [isNotApplicable, setIsNotApplicable] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<SubmitExceptionButton SubmitExceptionFunc={SubmitExceptionFunc} />
|
||||
<SubmitButton submitFunc={submitFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<NotApplicableCheckButton isCheck={isNotApplicable} setIsCheck={setIsNotApplicable} />
|
||||
<UpdateOperateDataButton updateOperateDataButtonFunc={updateOperateDataButtonFunc} />
|
||||
<OperateDataButton getOperateDataFunc={getOperateDataFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<DataGrid
|
||||
columnInfo={ PublicSewageFactInpColumn }
|
||||
rowStartNum={3}
|
||||
fixedColumns={2}
|
||||
rowData={rowData}
|
||||
setRowData={setRowData}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PublicSewageFacilityInp;
|
||||
@@ -0,0 +1,80 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { DataGrid } from '@rsone/components';
|
||||
import SubmitButton from "@/components/button/SumitButton";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import LastYearDataButton from "@/components/button/LastYearDataButton";
|
||||
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
|
||||
import AddArticleButton from "@/components/button/AddArticleButton";
|
||||
import DeleteArticleButton from "@/components/button/DeleteArticleButton";
|
||||
import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton";
|
||||
|
||||
import { PumpingStationInpColumn } from "@/components/util/column/input/PumpingStationInpColumn"
|
||||
|
||||
// 하수도 통계 관리 > 05. 펌프장
|
||||
const PumpingStationInp = () => {
|
||||
|
||||
const SubmitExceptionFunc = () => {
|
||||
console.log('submit exception');
|
||||
// 예외 제출 로직
|
||||
};
|
||||
|
||||
const getLastYearDataFunc = () => {
|
||||
console.log('get last year data');
|
||||
// 지난연도 데이터 가져오기 로직
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
console.log('submit');
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('save');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const addArticleFunc = () => {
|
||||
console.log('save');
|
||||
// 항목 추가 로직
|
||||
};
|
||||
|
||||
const deleteArticleFunc = () => {
|
||||
console.log('save');
|
||||
// 항목 제외 로직
|
||||
};
|
||||
|
||||
const [rowData, setRowData] = useState<Record<string, string | number>[]>([]);
|
||||
const [isNotApplicable, setIsNotApplicable] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<SubmitExceptionButton SubmitExceptionFunc={SubmitExceptionFunc} />
|
||||
<LastYearDataButton getLastYearDataFunc={getLastYearDataFunc} />
|
||||
<SubmitButton submitFunc={submitFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<NotApplicableCheckButton isCheck={isNotApplicable} setIsCheck={setIsNotApplicable} />
|
||||
<AddArticleButton addArticleFunc={addArticleFunc} />
|
||||
<DeleteArticleButton deleteArticleFunc={deleteArticleFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<DataGrid
|
||||
columnInfo={ PumpingStationInpColumn }
|
||||
rowStartNum={3}
|
||||
fixedColumns={3}
|
||||
rowData={rowData}
|
||||
setRowData={setRowData}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PumpingStationInp;
|
||||
@@ -0,0 +1,81 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { TabDataGrid } from "@rsone/components";
|
||||
import SubmitButton from "@/components/button/SumitButton";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
|
||||
import LastYearDataButton from "@/components/button/LastYearDataButton";
|
||||
import AddArticleButton from "@/components/button/AddArticleButton";
|
||||
import DeleteArticleButton from "@/components/button/DeleteArticleButton";
|
||||
|
||||
import { PublicInstitutionSewerIndustryInpColumn } from "@/components/util/column/input/sewageExcretaRelated/PublicInstitutionSewerIndustryInpColumn"
|
||||
import { PublicInstitutionExcretaIndustryInpColumn } from "@/components/util/column/input/sewageExcretaRelated/PublicInstitutionExcretaIndustryInpColumn"
|
||||
import { ExcretaRelatedIndustryInpColumn } from "@/components/util/column/input/sewageExcretaRelated/ExcretaRelatedIndustryInpColumn";
|
||||
import { PrivateSewageTreatRelatedIndustryInpColumn } from "@/components/util/column/input/sewageExcretaRelated/PrivateSewageTreatRelatedIndustryInpColumn";
|
||||
|
||||
// 하수도 통계 관리 > 12. 하수 및 분뇨관련산업
|
||||
const SewageExcretaRelatedInp = () => {
|
||||
|
||||
// tab list
|
||||
const SewageExcretaRelatedInpTabList = [
|
||||
PublicInstitutionSewerIndustryInpColumn,
|
||||
PublicInstitutionExcretaIndustryInpColumn,
|
||||
ExcretaRelatedIndustryInpColumn,
|
||||
PrivateSewageTreatRelatedIndustryInpColumn
|
||||
];
|
||||
|
||||
const submitExceptionFunc = () => {
|
||||
// 예외 제출 로직
|
||||
};
|
||||
|
||||
const lastYearDataFunc = () => {
|
||||
// 지난연도 데이터 가져오기 로직
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const addArticleFunc = () => {
|
||||
// 항목 추가 로직
|
||||
};
|
||||
|
||||
const deleteArticleFunc = () => {
|
||||
console.log('save');
|
||||
// 항목 제외 로직
|
||||
};
|
||||
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<SubmitExceptionButton SubmitExceptionFunc={submitExceptionFunc} />
|
||||
<LastYearDataButton getLastYearDataFunc={lastYearDataFunc} />
|
||||
<SubmitButton submitFunc={submitFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<AddArticleButton addArticleFunc={addArticleFunc} />
|
||||
<DeleteArticleButton deleteArticleFunc={deleteArticleFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid
|
||||
columnInfo={SewageExcretaRelatedInpTabList}
|
||||
rowDataMap={rowDataMap}
|
||||
setRowDataMap={setRowDataMap}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewageExcretaRelatedInp;
|
||||
@@ -0,0 +1,84 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { TabDataGrid } from "@rsone/components";
|
||||
import SubmitButton from "@/components/button/SumitButton";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
|
||||
import LastYearDataButton from "@/components/button/LastYearDataButton";
|
||||
import AddArticleButton from "@/components/button/AddArticleButton";
|
||||
import DeleteArticleButton from "@/components/button/DeleteArticleButton";
|
||||
import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton";
|
||||
|
||||
import { SlurgeProcessingFacStatusInpColumn } from "@/components/util/column/input/sewageExcretaSlurge/SlurgeProcessingFacStatusInpColumn";
|
||||
import { DigestorOperatingStatusInpColumn } from "@/components/util/column/input/sewageExcretaSlurge/DigestorOperatingStatusInpColumn";
|
||||
import { SewageSlurgeProcessingFacStatusInpColumn } from "@/components/util/column/input/sewageExcretaSlurge/SewageSlurgeProcessingFacStatusInpColumn";
|
||||
import { ExcretaSlurgeProcessingStatusInpColumn } from "@/components/util/column/input/sewageExcretaSlurge/ExcretaSlurgeProcessingStatusInpColumn";
|
||||
|
||||
|
||||
// 하수도 통계 관리 > 11. 하수 및 분뇨찌꺼기(슬러지)처리
|
||||
const SewageExcretaSlurgeInp = () => {
|
||||
|
||||
// tab list
|
||||
const SewageExcretaSlurgeInpTabList = [
|
||||
SlurgeProcessingFacStatusInpColumn,
|
||||
DigestorOperatingStatusInpColumn,
|
||||
SewageSlurgeProcessingFacStatusInpColumn,
|
||||
ExcretaSlurgeProcessingStatusInpColumn
|
||||
];
|
||||
|
||||
const submitExceptionFunc = () => {
|
||||
// 예외 제출 로직
|
||||
};
|
||||
|
||||
const lastYearDataFunc = () => {
|
||||
// 지난연도 데이터 가져오기 로직
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const addArticleFunc = () => {
|
||||
// 항목 추가 로직
|
||||
};
|
||||
|
||||
const deleteArticleFunc = () => {
|
||||
// 항목 제외 로직
|
||||
};
|
||||
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
const [isNotApplicable, setIsNotApplicable] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<SubmitExceptionButton SubmitExceptionFunc={submitExceptionFunc} />
|
||||
<LastYearDataButton getLastYearDataFunc={lastYearDataFunc} />
|
||||
<SubmitButton submitFunc={submitFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<NotApplicableCheckButton isCheck={isNotApplicable} setIsCheck={setIsNotApplicable} />
|
||||
<AddArticleButton addArticleFunc={addArticleFunc} />
|
||||
<DeleteArticleButton deleteArticleFunc={deleteArticleFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid
|
||||
columnInfo={SewageExcretaSlurgeInpTabList}
|
||||
rowDataMap={rowDataMap}
|
||||
setRowDataMap={setRowDataMap}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewageExcretaSlurgeInp;
|
||||
@@ -0,0 +1,78 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { TabDataGrid } from '@rsone/components';
|
||||
import SubmitButton from "@/components/button/SumitButton";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import LastYearDataButton from "@/components/button/LastYearDataButton";
|
||||
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
|
||||
import InstallationStatusButton from "@/components/button/InstallationStatusButton";
|
||||
|
||||
import { RegionalFactStatusInpColumn } from "@/components/util/column/input/sewagePipe/RegionalFactStatusInpColumn";
|
||||
import { FactInstallStatusInpColumn } from "@/components/util/column/input/sewagePipe/FactInstallStatusInpColumn";
|
||||
import { PipeTypeStatusInpColumn } from "@/components/util/column/input/sewagePipe/PipeTypeStatusInpColumn";
|
||||
import { PipeDiameterStatusInpColumn } from "@/components/util/column/input/sewagePipe/PipeDiameterStatusInpColumn";
|
||||
import { ManholeStatusInpColumn } from "@/components/util/column/input/sewagePipe/ManholeStatusInpColumn";
|
||||
import { ConnectionStatusInpColumn } from "@/components/util/column/input/sewagePipe/ConnectionStatusInpColumn";
|
||||
|
||||
// 하수도 통계 관리 > 02. 하수관로
|
||||
const SewagePipeInp = () => {
|
||||
|
||||
// tab List
|
||||
const SewagePipeInpTapList = [
|
||||
RegionalFactStatusInpColumn,
|
||||
FactInstallStatusInpColumn,
|
||||
PipeTypeStatusInpColumn,
|
||||
PipeDiameterStatusInpColumn,
|
||||
ManholeStatusInpColumn,
|
||||
ConnectionStatusInpColumn,
|
||||
];
|
||||
|
||||
const SubmitExceptionFunc = () => {
|
||||
// 예외 제출 로직
|
||||
};
|
||||
|
||||
const getLastYearDataFunc = () => {
|
||||
// 지난연도 데이터 가져오기 로직
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const installationStatusFunc = () => {
|
||||
// 시설별 설치현황관리 로직
|
||||
};
|
||||
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] mx-[0.6rem]">
|
||||
<SubmitExceptionButton SubmitExceptionFunc={SubmitExceptionFunc} />
|
||||
<LastYearDataButton getLastYearDataFunc={getLastYearDataFunc} />
|
||||
<SubmitButton submitFunc={submitFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] mx-[0.6rem]">
|
||||
<InstallationStatusButton installationStatusFunc={installationStatusFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid
|
||||
columnInfo={SewagePipeInpTapList}
|
||||
rowDataMap={rowDataMap}
|
||||
setRowDataMap={setRowDataMap}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewagePipeInp;
|
||||
@@ -0,0 +1,64 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { TabDataGrid } from '@rsone/components';
|
||||
import SubmitButton from "@/components/button/SumitButton";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import LastYearDataButton from "@/components/button/LastYearDataButton";
|
||||
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
|
||||
|
||||
import { RepairStatusInpColumn } from "@/components/util/column/input/sewagePipeMaintain/RepairStatusInpColumn";
|
||||
import { PipeDredgingStatusInpColumn } from "@/components/util/column/input/sewagePipeMaintain/PipeDredgingStatusInpColumn";
|
||||
|
||||
// 하수도 통계 관리 > 03. 하수관로 유지관리
|
||||
const SewagePipeMaintainInp = () => {
|
||||
|
||||
// tab List
|
||||
const SewagePipeMaintainInpTabList = [
|
||||
RepairStatusInpColumn,
|
||||
PipeDredgingStatusInpColumn
|
||||
];
|
||||
|
||||
const SubmitExceptionFunc = () => {
|
||||
console.log('submit exception');
|
||||
// 예외 제출 로직
|
||||
};
|
||||
|
||||
const getLastYearDataFunc = () => {
|
||||
console.log('get last year data');
|
||||
// 지난연도 데이터 가져오기 로직
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
console.log('submit');
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('save');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<SubmitExceptionButton SubmitExceptionFunc={SubmitExceptionFunc} />
|
||||
<LastYearDataButton getLastYearDataFunc={getLastYearDataFunc} />
|
||||
<SubmitButton submitFunc={submitFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid
|
||||
columnInfo={SewagePipeMaintainInpTabList}
|
||||
rowDataMap={rowDataMap}
|
||||
setRowDataMap={setRowDataMap}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewagePipeMaintainInp;
|
||||
@@ -0,0 +1,85 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { TabDataGrid } from '@rsone/components';
|
||||
import SubmitButton from "@/components/button/SumitButton";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import LastYearDataButton from "@/components/button/LastYearDataButton";
|
||||
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
|
||||
import AddArticleButton from "@/components/button/AddArticleButton";
|
||||
import DeleteArticleButton from "@/components/button/DeleteArticleButton";
|
||||
import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton";
|
||||
|
||||
import { SewageReservoirInpColumn } from "@/components/util/column/input/sewageReservoirPump/SewageReservoirInpColumn";
|
||||
import { RainfallPumpStationInpColumn } from "@/components/util/column/input/sewageReservoirPump/RainfallPumpStationInpColumn";
|
||||
|
||||
// 하수도 통계 관리 > 04. 하수저류 시설 및 빗물 펌프장
|
||||
const SewageReservoirPumpInp = () => {
|
||||
|
||||
// tab List
|
||||
const SewageReservoirPumpInpTabList = [
|
||||
SewageReservoirInpColumn,
|
||||
RainfallPumpStationInpColumn
|
||||
];
|
||||
|
||||
const submitExceptionFunc = () => {
|
||||
console.log('submit exception');
|
||||
// 예외 제출 로직
|
||||
};
|
||||
|
||||
const getLastYearDataFunc = () => {
|
||||
console.log('get last year data');
|
||||
// 지난연도 데이터 가져오기 로직
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
console.log('submit');
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('save');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const addArticleFunc = () => {
|
||||
console.log('save');
|
||||
// 항목 추가 로직
|
||||
};
|
||||
|
||||
const deleteArticleFunc = () => {
|
||||
console.log('save');
|
||||
// 항목 제외 로직
|
||||
};
|
||||
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
const [isNotApplicable, setIsNotApplicable] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<SubmitExceptionButton SubmitExceptionFunc={submitExceptionFunc} />
|
||||
<LastYearDataButton getLastYearDataFunc={getLastYearDataFunc} />
|
||||
<SubmitButton submitFunc={submitFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<NotApplicableCheckButton isCheck={isNotApplicable} setIsCheck={setIsNotApplicable} />
|
||||
<AddArticleButton addArticleFunc={addArticleFunc} />
|
||||
<DeleteArticleButton deleteArticleFunc={deleteArticleFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid
|
||||
columnInfo={SewageReservoirPumpInpTabList}
|
||||
rowDataMap={rowDataMap}
|
||||
setRowDataMap={setRowDataMap}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewageReservoirPumpInp;
|
||||
@@ -0,0 +1,64 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { TabDataGrid } from '@rsone/components';
|
||||
import SubmitButton from "@/components/button/SumitButton";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
|
||||
import LastYearDataButton from "@/components/button/LastYearDataButton";
|
||||
|
||||
import { SewerageFinanceSettleInpColumn } from "@/components/util/column/input/sewerageFinance/SewerageFinanceSettleInpColumn"
|
||||
import { SewerageChargeInpColumn } from "@/components/util/column/input/sewerageFinance/SewerageChargeInpColumn"
|
||||
import { SewerageUsageFeeInpColumn } from "@/components/util/column/input/sewerageFinance/SewerageUsageFeeInpColumn"
|
||||
import { CauserBurdenInpColumn } from "@/components/util/column/input/sewerageFinance/CauserBurdenInpColumn"
|
||||
|
||||
// 하수도 통계 관리 > 09. 하수도재정
|
||||
const SewerageFinanceInp = () => {
|
||||
|
||||
// tab list
|
||||
const SewerageFinanceInpTabList = [
|
||||
SewerageFinanceSettleInpColumn,
|
||||
SewerageChargeInpColumn,
|
||||
SewerageUsageFeeInpColumn,
|
||||
CauserBurdenInpColumn
|
||||
];
|
||||
|
||||
const submitExceptionFunc = () => {
|
||||
// 예외 제출 로직
|
||||
};
|
||||
|
||||
const lastYearDataFunc = () => {
|
||||
// 지난연도 데이터 가져오기 로직
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<SubmitExceptionButton SubmitExceptionFunc={submitExceptionFunc} />
|
||||
<LastYearDataButton getLastYearDataFunc={lastYearDataFunc} />
|
||||
<SubmitButton submitFunc={submitFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid
|
||||
columnInfo={SewerageFinanceInpTabList}
|
||||
rowDataMap={rowDataMap}
|
||||
setRowDataMap={setRowDataMap}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewerageFinanceInp;
|
||||
@@ -0,0 +1,283 @@
|
||||
import { useState, useMemo, useRef } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
// import { DataGrid } from "@rsone/components";
|
||||
import DataGrid from "@/components/module/DataGrid";
|
||||
import SubmitButton from "@/components/button/SumitButton";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import LastYearDataButton from "@/components/button/LastYearDataButton";
|
||||
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
|
||||
import { LoadingWithAnimation } from "@common/components";
|
||||
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
|
||||
|
||||
import { useAlertStore } from "@/shared/lib";
|
||||
import { statisticsInputAPi } from "@/entities/statistics/api/statistics-input-service";
|
||||
import type { SearchFormValues } from "@/components/type/SearchForm.type";
|
||||
import type {
|
||||
SewerageSupplyRateItem,
|
||||
SewerageSupplyRateRequestParams,
|
||||
SewerageSupplyRateSaveItem,
|
||||
} from "@/entities/statistics/model/statistics-input-interface";
|
||||
import { SeweragePenetrationRateInpColumn } from "@/components/util/column/input/SeweragePenetrationRateInpColumn";
|
||||
import { toGridRows } from "@/components/util/grid/gridFunction";
|
||||
import { getFooterSummary } from "@/components/util/grid/footerSummary";
|
||||
import { getUserInfo } from "../../../../../../packages/common/components/src/api";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
|
||||
function getSewerageSupplyRateParams(
|
||||
values: SearchFormValues,
|
||||
overrides?: { yr?: string; demoYr?: string; mode?: string }
|
||||
): SewerageSupplyRateRequestParams {
|
||||
return {
|
||||
sido: values.sido,
|
||||
gugun: values.gugun === 'ALL' ? '' : values.gugun,
|
||||
bsnmCd: values.bsnmCd,
|
||||
yr: overrides?.yr ?? values.year,
|
||||
...(overrides?.mode && { mode: overrides.mode }),
|
||||
};
|
||||
}
|
||||
|
||||
// 하수도 통계 관리 > 01. 하수도 보급률
|
||||
const SeweragePenetrationRateInp = () => {
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
const [rowData, setRowData] = useState<Record<string, string | number>[]>([]);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [searchValues, setSearchValues] = useState<SearchFormValues | null>(null);
|
||||
const [isEnterable, setIsEnterable] = useState<boolean>(true);
|
||||
const [lastSearchedYear, setLastSearchedYear] = useState<string | null>(null);
|
||||
const { confirm } = useConfirm();
|
||||
|
||||
const [footerFromApi, setFooterFromApi] = useState<{ totalPopl?: number; poplSm?: number; frgnrPoplSm?: number } | null>(null);
|
||||
const getGridDataRef = useRef<(() => Record<string, string | number>[]) | null>(null);
|
||||
|
||||
const footerFieldNames = ['totalPopl', 'poplSm', 'frgnrPoplSm'] as const;
|
||||
const footerWithApiDefault = (fieldName: (typeof footerFieldNames)[number], numberFormat: string) => ({
|
||||
expression: 'sum' as const,
|
||||
numberFormat,
|
||||
valueCallback: (grid: Parameters<typeof getFooterSummary>[0], column: Parameters<typeof getFooterSummary>[1]) =>
|
||||
(footerFromApi && footerFromApi[fieldName] != null ? footerFromApi[fieldName] : null) ?? getFooterSummary(grid, column),
|
||||
});
|
||||
|
||||
// 최상위 관리자일땐 모든 상황에서 edit 가능하게 수정 필요.
|
||||
const columnInfo = useMemo(() => {
|
||||
const { columns, columnLayout } = SeweragePenetrationRateInpColumn;
|
||||
const base = isEnterable ? columns : columns.map((col) => ({ ...col, editable: false as const }));
|
||||
return {
|
||||
columnLayout,
|
||||
columns: base.map((col) => {
|
||||
if (col.fieldName === 'totalPopl') return { ...col, footer: footerWithApiDefault('totalPopl', '#,##0') };
|
||||
if (col.fieldName === 'poplSm') return { ...col, footer: footerWithApiDefault('poplSm', '#,##0') };
|
||||
if (col.fieldName === 'frgnrPoplSm') return { ...col, footer: footerWithApiDefault('frgnrPoplSm', '#,##0') };
|
||||
return col;
|
||||
}),
|
||||
};
|
||||
}, [isEnterable, footerFromApi]);
|
||||
|
||||
const handleReset = () => {
|
||||
setRowData([]);
|
||||
setLastSearchedYear(null);
|
||||
setFooterFromApi(null);
|
||||
};
|
||||
|
||||
const fetchSewerageSupplyRate = async (params: SewerageSupplyRateRequestParams) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const response = await statisticsInputAPi.getSewerageSupplyRateList(params);
|
||||
if (response.status === 'success' && response.data) {
|
||||
const commonInfo = response.data.commonInfo;
|
||||
const convertedData: SewerageSupplyRateItem[] = response.data.sewerageSupplyRateList.map((d) => ({
|
||||
...d,
|
||||
sido: commonInfo.sido,
|
||||
speclCntrplnAr: d.speclCntrplnAr === '' || d.speclCntrplnAr === null ? '해당없음' : d.speclCntrplnAr,
|
||||
piplSupprt: commonInfo.piplSupprt,
|
||||
}));
|
||||
setRowData(toGridRows(convertedData));
|
||||
|
||||
setFooterFromApi(
|
||||
commonInfo
|
||||
? {
|
||||
totalPopl: commonInfo.bsnmTotalPopl,
|
||||
poplSm: commonInfo.bsnmPoplSm,
|
||||
frgnrPoplSm: commonInfo.bsnmFrgnrPoplSm,
|
||||
}
|
||||
: null
|
||||
);
|
||||
} else {
|
||||
alert(response.message);
|
||||
}
|
||||
} catch {
|
||||
alert('데이터 조회 중 오류가 발생했습니다.');
|
||||
setRowData([]);
|
||||
setFooterFromApi(null);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSearch = async (values: SearchFormValues) => {
|
||||
if (values.sido === '' || values.sido === 'ALL') {
|
||||
alert('시도를 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await statisticsInputAPi.checkInputPeriod(values.year || '');
|
||||
|
||||
if (response.status === 'success') {
|
||||
setIsEnterable(response.data);
|
||||
setLastSearchedYear(values.year || null);
|
||||
|
||||
await fetchSewerageSupplyRate(getSewerageSupplyRateParams(values));
|
||||
} else {
|
||||
alert(response.message);
|
||||
}
|
||||
} catch {
|
||||
alert('데이터 조회 중 오류가 발생했습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
const SubmitExceptionFunc = () => {
|
||||
// 예외 제출 로직
|
||||
};
|
||||
|
||||
const getLastYearDataFunc = async (values: SearchFormValues) => {
|
||||
if (values.sido === '' || values.sido === 'ALL') {
|
||||
alert('시도를 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 실제 조회된 연도가 없으면 실행 불가
|
||||
if (!lastSearchedYear) {
|
||||
alert('먼저 데이터를 조회해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
await fetchSewerageSupplyRate(getSewerageSupplyRateParams(values, { mode: 'PRE' }));
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = async () => {
|
||||
try {
|
||||
if (await confirm('저장 하시겠습니까?')) {
|
||||
setIsLoading(true);
|
||||
|
||||
const userInfo = await getUserInfo();
|
||||
const currentData = getGridDataRef.current?.();
|
||||
|
||||
if (!currentData || currentData.length === 0) {
|
||||
alert('저장할 데이터가 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 컬럼 정의에서 dataFormat 추출 (소수점 자리수 맞추기 위해)
|
||||
const columnFormatMap = new Map<string, string>();
|
||||
SeweragePenetrationRateInpColumn.columns.forEach((col) => {
|
||||
if (col.fieldName && col.dataFormat) {
|
||||
columnFormatMap.set(col.fieldName, col.dataFormat);
|
||||
}
|
||||
});
|
||||
|
||||
// 숫자 포맷팅 함수 (dataFormat에 따라 소수점 자리수 맞춤)
|
||||
const formatNumber = (value: string | number | null | undefined, fieldName: string): number => {
|
||||
if (value === null || value === undefined || value === '') return 0;
|
||||
const num = typeof value === 'string' ? parseFloat(value.replace(/,/g, '')) : value;
|
||||
if (isNaN(num)) return 0;
|
||||
|
||||
const format = columnFormatMap.get(fieldName);
|
||||
if (!format) return num;
|
||||
|
||||
// #,##0.000 → 소수점 3자리, #,##0.0 → 소수점 1자리, #,##0 → 정수
|
||||
const decimalPlaces = format.match(/\.(\d+)/)?.[1]?.length ?? 0;
|
||||
return decimalPlaces > 0 ? parseFloat(num.toFixed(decimalPlaces)) : Math.round(num);
|
||||
};
|
||||
|
||||
// SaveItem 타입에 정의된 필드만 추출
|
||||
const convertedData: SewerageSupplyRateSaveItem[] = currentData.map((d) => ({
|
||||
bsnmCd: searchValues?.bsnmCd ?? '',
|
||||
sido: d.sido as string,
|
||||
gugun: (d.gugun as string) || null,
|
||||
yr: searchValues?.year ?? '',
|
||||
adstCd: d.adstCd as string,
|
||||
adstDong: d.adstDong as string,
|
||||
bstrm: d.bstrm as string,
|
||||
speclCntrplnAr: d.speclCntrplnAr === '해당없음' ? null : (d.speclCntrplnAr as string | null),
|
||||
pblswrgPrmTrt: formatNumber(d.pblswrgPrmTrt, 'pblswrgPrmTrt'),
|
||||
pblswrgScdTrt: formatNumber(d.pblswrgScdTrt, 'pblswrgScdTrt'),
|
||||
pblswrgTertTrt: formatNumber(d.pblswrgTertTrt, 'pblswrgTertTrt'),
|
||||
wstrPrmTrt: formatNumber(d.wstrPrmTrt, 'wstrPrmTrt'),
|
||||
wstrScdTrt: formatNumber(d.wstrScdTrt, 'wstrScdTrt'),
|
||||
wstrTertTrt: formatNumber(d.wstrTertTrt, 'wstrTertTrt'),
|
||||
notConectPopltn: formatNumber(d.notConectPopltn, 'notConectPopltn'),
|
||||
swgeProcZoneInnerAr: formatNumber(d.swgeProcZoneInnerAr, 'swgeProcZoneInnerAr'),
|
||||
townUnprocPopltn: formatNumber(d.townUnprocPopltn, 'townUnprocPopltn'),
|
||||
townSwttPopltn: formatNumber(d.townSwttPopltn, 'townSwttPopltn'),
|
||||
townWrrtnPopltn: formatNumber(d.townWrrtnPopltn, 'townWrrtnPopltn'),
|
||||
swgeProcZoneOuterAr: formatNumber(d.swgeProcZoneOuterAr, 'swgeProcZoneOuterAr'),
|
||||
rmk: (d.rmk as string) ?? '',
|
||||
popltnSm: formatNumber(d.popltnSm, 'popltnSm'),
|
||||
arSm: formatNumber(d.arSm, 'arSm'),
|
||||
swgeProcZoneInnerSm: formatNumber(d.swgeProcZoneInnerSm, 'swgeProcZoneInnerSm'),
|
||||
pblswrgPopltnSm: formatNumber(d.pblswrgPopltnSm, 'pblswrgPopltnSm'),
|
||||
wstrPopltnSm: formatNumber(d.wstrPopltnSm, 'wstrPopltnSm'),
|
||||
swgeProcZoneOuterSm: formatNumber(d.swgeProcZoneOuterSm, 'swgeProcZoneOuterSm'),
|
||||
pblswrgPopltnSuprt: formatNumber(d.pblswrgPopltnSuprt, 'pblswrgPopltnSuprt'),
|
||||
adtrtPopltnSuprt: formatNumber(d.adtrtPopltnSuprt, 'adtrtPopltnSuprt'),
|
||||
swrgInstlrt: formatNumber(d.swrgInstlrt, 'swrgInstlrt'),
|
||||
userId: userInfo.userName,
|
||||
}));
|
||||
|
||||
const response = await statisticsInputAPi.saveSewerageSupplyRate(convertedData);
|
||||
console.log(convertedData)
|
||||
console.log(response);
|
||||
} else {
|
||||
// 저장 취소
|
||||
}
|
||||
} catch {
|
||||
alert('데이터 저장 중 오류가 발생했습니다.');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="relative">
|
||||
<SearchForm onSubmit={handleSearch} onReset={handleReset} onValuesChange={setSearchValues} />
|
||||
{rowData.length > 0 &&
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] mx-[0.6rem]">
|
||||
{isEnterable && <SubmitExceptionButton SubmitExceptionFunc={SubmitExceptionFunc} />}
|
||||
{isEnterable && <LastYearDataButton getLastYearDataFunc={() => getLastYearDataFunc(searchValues ?? {})} />}
|
||||
{isEnterable && <SubmitButton submitFunc={submitFunc} />}
|
||||
{
|
||||
// 최고 관리자일땐 저장 가능하게
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
{isLoading && <div className="absolute inset-0 z-50 [data-theme='black']:bg-transparent rounded-lg p-10 flex justify-center items-center">
|
||||
<div className="relative size-[5rem]">
|
||||
<LoadingWithAnimation color="primary" />
|
||||
</div>
|
||||
</div>}
|
||||
<DataGrid
|
||||
key={isEnterable ? 'enterable' : 'readonly'}
|
||||
columnInfo={columnInfo}
|
||||
isExcelImport={(rowData.length > 0) && isEnterable}
|
||||
rowStartNum={3}
|
||||
fixedColumns={1}
|
||||
rowData={rowData}
|
||||
setRowData={setRowData}
|
||||
getGridDataRef={getGridDataRef}
|
||||
/>
|
||||
</div>
|
||||
<ConfirmDialog isOpen={false} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SeweragePenetrationRateInp;
|
||||
@@ -0,0 +1,67 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { TabDataGrid } from '@rsone/components';
|
||||
import SubmitButton from "@/components/button/SumitButton";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import LastYearDataButton from "@/components/button/LastYearDataButton";
|
||||
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
|
||||
import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton";
|
||||
|
||||
import { ComplaintInpColumn } from "@/components/util/column/input/sewerageServiceLevel/ComplaintInpColumn";
|
||||
import { ResidentFriendlyFactInpColumn } from "@/components/util/column/input/sewerageServiceLevel/ResidentFriendlyFactInpColumn";
|
||||
|
||||
// 하수도 통계 관리 > 13. 하수도 서비스 수준
|
||||
const SewerageServiceLevelInp = () => {
|
||||
|
||||
// tab List
|
||||
const SewerageServiceLevelInpTabList = [
|
||||
ComplaintInpColumn,
|
||||
ResidentFriendlyFactInpColumn
|
||||
];
|
||||
|
||||
const submitExceptionFunc = () => {
|
||||
// 예외 제출 로직
|
||||
};
|
||||
|
||||
const getLastYearDataFunc = () => {
|
||||
// 지난연도 데이터 가져오기 로직
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
const [isNotApplicable, setIsNotApplicable] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<SubmitExceptionButton SubmitExceptionFunc={submitExceptionFunc} />
|
||||
<LastYearDataButton getLastYearDataFunc={getLastYearDataFunc} />
|
||||
<SubmitButton submitFunc={submitFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<NotApplicableCheckButton isCheck={isNotApplicable} setIsCheck={setIsNotApplicable} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid
|
||||
columnInfo={SewerageServiceLevelInpTabList}
|
||||
rowDataMap={rowDataMap}
|
||||
setRowDataMap={setRowDataMap}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewerageServiceLevelInp;
|
||||
@@ -0,0 +1,44 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { DataGrid } from "@rsone/components";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import RejectButton from "@/components/button/RejectButton";
|
||||
|
||||
import { StatsInputStatusInpColumn } from "@/components/util/column/input/StatsInputStatusInpColumn";
|
||||
|
||||
// 하수도 통계 관리 > 00. 통계 입력 현황
|
||||
const StatsInputStatusInp = () => {
|
||||
|
||||
const rejectFunc = () => {
|
||||
// 보완 요청 로직
|
||||
};
|
||||
|
||||
const approveFunc = () => {
|
||||
// 승인 요청 로직
|
||||
};
|
||||
|
||||
const [rowData, setRowData] = useState<Record<string, string | number>[]>([]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<RejectButton rejectFunc={rejectFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<DataGrid
|
||||
columnInfo={ StatsInputStatusInpColumn }
|
||||
rowStartNum={2}
|
||||
fixedColumns={3}
|
||||
rowData={rowData}
|
||||
setRowData={setRowData}
|
||||
isExcelImport={false}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatsInputStatusInp;
|
||||
@@ -0,0 +1,92 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { TabDataGrid } from '@rsone/components';
|
||||
import SubmitButton from "@/components/button/SumitButton";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import LastYearDataButton from "@/components/button/LastYearDataButton";
|
||||
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
|
||||
import UpdateOperateDataButton from "@/components/button/UpdateOperateDataButton"
|
||||
import AddArticleButton from "@/components/button/AddArticleButton";
|
||||
import DeleteArticleButton from "@/components/button/DeleteArticleButton";
|
||||
import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton";
|
||||
|
||||
import { PublicSewageTreatWaterReuseInpColumn } from "@/components/util/column/input/waterReuse/PublicSewageTreatWaterReuseInpColumn";
|
||||
import { RecycledWaterStatusInpColumn } from "@/components/util/column/input/waterReuse/RecycledWaterStatusInpColumn";
|
||||
import { RainFallUtilFactStatusInpColumn } from "@/components/util/column/input/waterReuse/RainFallUtilFactStatusInpColumn";
|
||||
import { TreatWaterReuseDesignConstStatusInpColumn } from "@/components/util/column/input/waterReuse/TreatWaterReuseDesignConstStatusInpColumn";
|
||||
import { TreatWaterReuseBusinessApprStatusInpColumn } from "@/components/util/column/input/waterReuse/TreatWaterReuseBusinessApprStatusInpColumn";
|
||||
|
||||
// 하수도 통계 관리 > 10. 물 재이용
|
||||
const WaterReuseInp = () => {
|
||||
|
||||
// tab list
|
||||
const WaterReuseInpTabList = [
|
||||
PublicSewageTreatWaterReuseInpColumn,
|
||||
RecycledWaterStatusInpColumn,
|
||||
RainFallUtilFactStatusInpColumn,
|
||||
TreatWaterReuseDesignConstStatusInpColumn,
|
||||
TreatWaterReuseBusinessApprStatusInpColumn
|
||||
];
|
||||
const SubmitExceptionFunc = () => {
|
||||
// 예외 제출 로직
|
||||
};
|
||||
|
||||
const getLastYearDataFunc = () => {
|
||||
// 전연도 데이터 가져오기 로직
|
||||
};
|
||||
|
||||
const submitFunc = () => {
|
||||
// 제출 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const updateOperateDataButtonFunc = () => {
|
||||
// 운영 데이터 업데이트 로직 - tab1. 공공하수처리수 재이용
|
||||
};
|
||||
|
||||
const addArticleFunc = () => {
|
||||
console.log('save');
|
||||
// 항목 추가 로직
|
||||
};
|
||||
|
||||
const deleteArticleFunc = () => {
|
||||
console.log('save');
|
||||
// 항목 제외 로직
|
||||
};
|
||||
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
const [isNotApplicable, setIsNotApplicable] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<SubmitExceptionButton SubmitExceptionFunc={SubmitExceptionFunc} />
|
||||
<LastYearDataButton getLastYearDataFunc={getLastYearDataFunc} />
|
||||
<SubmitButton submitFunc={submitFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<NotApplicableCheckButton isCheck={isNotApplicable} setIsCheck={setIsNotApplicable} />
|
||||
<UpdateOperateDataButton updateOperateDataButtonFunc={updateOperateDataButtonFunc} />
|
||||
<AddArticleButton addArticleFunc={addArticleFunc} />
|
||||
<DeleteArticleButton deleteArticleFunc={deleteArticleFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid
|
||||
columnInfo={WaterReuseInpTabList}
|
||||
rowDataMap={rowDataMap}
|
||||
setRowDataMap={setRowDataMap}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default WaterReuseInp;
|
||||
@@ -1,11 +0,0 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const ExcretaTreatmentFacilityMng = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExcretaTreatmentFacilityMng;
|
||||
@@ -0,0 +1,41 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { DataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import type { ColumnConfig } from "@/components/type/DataGrid.type";
|
||||
|
||||
const NotEnteredStatus = () => {
|
||||
const [rowData, setRowData] = useState<Record<string, string | number>[]>([]);
|
||||
|
||||
const columns: ColumnConfig[] = [
|
||||
{ name: 'sido', fieldName: '시도', header: { text: '시도' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
{ name: 'sgg', fieldName: '시군구', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
{ name: '1', fieldName: '1', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
{ name: '2-1', fieldName: '2-1', header: { text: '2-1' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
{ name: '2-2', fieldName: '2-2', header: { text: '2-2' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
{ name: '2-3', fieldName: '2-3', header: { text: '2-3' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
{ name: '2-4', fieldName: '2-4', header: { text: '2-4' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
{ name: '3-1', fieldName: '3-1', header: { text: '3-1' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
{ name: '3-2', fieldName: '3-2', header: { text: '3-2' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
];
|
||||
|
||||
const columnLayout = [
|
||||
'sido',
|
||||
'sgg',
|
||||
{
|
||||
name: 'groupA',
|
||||
hideChildHeaders: false,
|
||||
header: { text: '미입력 하수도 통계 세부항목(번호)' },
|
||||
items: ['1', '2-1', '2-2', '2-3', '2-4', '3-1', '3-2'],
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
<DataGrid columnInfo={{ columns, columnLayout }} rowData={rowData} setRowData={setRowData} isExcelImport={false} fixedColumns={2} rowStartNum={2} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotEnteredStatus;
|
||||
@@ -1,11 +0,0 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const PrivateSewageFacilityMng = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PrivateSewageFacilityMng;
|
||||
@@ -1,11 +0,0 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const PublicSewageFacilityMng = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PublicSewageFacilityMng;
|
||||
@@ -1,11 +0,0 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const PumpingStationMng = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PumpingStationMng;
|
||||
@@ -1,11 +0,0 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const SewageExcretaRelatedMng = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewageExcretaRelatedMng;
|
||||
@@ -1,11 +0,0 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const SewageExcretaSlurgeMng = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewageExcretaSlurgeMng;
|
||||
@@ -1,11 +0,0 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const SewagePipeMaintainMng = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewagePipeMaintainMng;
|
||||
@@ -1,11 +0,0 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const SewageReservoirPumpMng = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewageReservoirPumpMng;
|
||||
@@ -1,11 +0,0 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const SewerageFinanceMng = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewerageFinanceMng;
|
||||
@@ -1,11 +0,0 @@
|
||||
import SearchForm from "../../module/SearchForm";
|
||||
|
||||
const SewerageServiceLevelMng = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewerageServiceLevelMng;
|
||||
@@ -0,0 +1,39 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { DataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import type { ColumnConfig } from "@/components/type/DataGrid.type";
|
||||
|
||||
const StatisticsInputManagement = () => {
|
||||
const [rowData, setRowData] = useState<Record<string, string | number>[]>([]);
|
||||
|
||||
const columns: ColumnConfig[] = [
|
||||
{ name: 'sido', fieldName: '시도', header: { text: '시도' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
{ name: 'sgg', fieldName: '시군구', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
{ name: '구분', fieldName: '구분', header: { text: '구분' }, editable: false, sortdisable: true },
|
||||
{ name: '광역자치단체', fieldName: '광역자치단체', header: { text: '광역자치단체' }, editable: false, sortdisable: true },
|
||||
{ name: '공단', fieldName: '공단', header: { text: '공단' }, editable: false, sortdisable: true },
|
||||
{ name: '처리내역', fieldName: '처리내역', header: { text: '처리내역' }, editable: false, sortdisable: true },
|
||||
];
|
||||
|
||||
const columnLayout = [
|
||||
'sido',
|
||||
'sgg',
|
||||
'구분',
|
||||
{
|
||||
name: 'groupA',
|
||||
hideChildHeaders: false,
|
||||
header: { text: '검토내역' },
|
||||
items: ['광역자치단체', '공단', '처리내역'],
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm sgg={false} sido={false} />
|
||||
<DataGrid columnInfo={{ columns, columnLayout }} rowData={rowData} setRowData={setRowData} isExcelImport={false} isExcelExport={false} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatisticsInputManagement;
|
||||
@@ -0,0 +1,11 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const StatisticsPopulationManagement = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm sgg={false} sido={false} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatisticsPopulationManagement;
|
||||
@@ -0,0 +1,39 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { DataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import type { ColumnConfig } from "@/components/type/DataGrid.type";
|
||||
|
||||
const StatisticsReviewHistory = () => {
|
||||
const [rowData, setRowData] = useState<Record<string, string | number>[]>([]);
|
||||
|
||||
const columns: ColumnConfig[] = [
|
||||
{ name: 'sido', fieldName: '시도', header: { text: '시도' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
{ name: 'sgg', fieldName: '시군구', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true },
|
||||
{ name: '구분', fieldName: '구분', header: { text: '구분' }, editable: false, sortdisable: true },
|
||||
{ name: '광역자치단체', fieldName: '광역자치단체', header: { text: '광역자치단체' }, editable: false, sortdisable: true },
|
||||
{ name: '공단', fieldName: '공단', header: { text: '공단' }, editable: false, sortdisable: true },
|
||||
{ name: '처리내역', fieldName: '처리내역', header: { text: '처리내역' }, editable: false, sortdisable: true },
|
||||
];
|
||||
|
||||
const columnLayout = [
|
||||
'sido',
|
||||
'sgg',
|
||||
'구분',
|
||||
{
|
||||
name: 'groupA',
|
||||
hideChildHeaders: false,
|
||||
header: { text: '검토내역' },
|
||||
items: ['광역자치단체', '공단', '처리내역'],
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
<DataGrid columnInfo={{ columns, columnLayout }} rowStartNum={2} fixedColumns={3} rowData={rowData} setRowData={setRowData} isExcelImport={false} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatisticsReviewHistory;
|
||||
@@ -1,55 +0,0 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import DataGrid from "@/components/module/DataGrid";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import RejectButton from "@/components/button/RejectButton";
|
||||
|
||||
const StatsInputSatusMng = () => {
|
||||
const columns = [
|
||||
{ name: 'sido', fieldName: '시도', header: { text: '시도' } },
|
||||
{ name: 'sgg', fieldName: '구군', header: { text: '구군' } },
|
||||
{ name: 'menu_nm', fieldName: '구분', header: { text: '구분' } },
|
||||
{ name: 'locg_status_nm', fieldName: '진행상황', header: { text: '진행상황' } },
|
||||
{ name: 'locg_status', fieldName: '작성률', header: { text: '작성률' } },
|
||||
{ name: 'locg_charger', fieldName: '작성자', header: { text: '작성자' } },
|
||||
{ name: 'locg_cttpc', fieldName: '작성자 연락처', header: { text: '작성자 연락처' } },
|
||||
{ name: 'locg_dept', fieldName: '작성자 부서', header: { text: '작성자 부서' } },
|
||||
{ name: 'locg_job', fieldName: '작성자 직제', header: { text: '작성자 직제' } },
|
||||
{ name: 'locg_cnfirm_nm', fieldName: '승인자', header: { text: '승인자' } },
|
||||
{ name: 'locg_cnfirm_dept', fieldName: '승인자 부서', header: { text: '승인자 부서' } },
|
||||
{ name: 'locg_cnfirm_job', fieldName: '승인자 직제', header: { text: '승인자 직제' } },
|
||||
{ name: 'return_opinion_sm', fieldName: '반려 사유', header: { text: '반려 사유' } },
|
||||
];
|
||||
|
||||
const columnLayout = [
|
||||
'sido',
|
||||
'sgg',
|
||||
'menu_nm',
|
||||
{
|
||||
name: 'groupA',
|
||||
hideChildHeaders: false,
|
||||
header: { text: '하수도사업자' },
|
||||
items: columns.filter((c) => ['sido', 'sgg', 'menu_nm'].includes(c.name) === false).map((m) => m.name),
|
||||
},
|
||||
];
|
||||
|
||||
const approveFunc = () => {
|
||||
console.log('appoved');
|
||||
};
|
||||
|
||||
const rejectFunc = () => {
|
||||
console.log('reject');
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<RejectButton rejectFunc={rejectFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
</div>
|
||||
<DataGrid columnInfo={{columns, columnLayout}} rowStartNum={2} isExcelImport={true} fixedColumns={3} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatsInputSatusMng;
|
||||
@@ -1,11 +0,0 @@
|
||||
import SearchForm from "../../module/SearchForm";
|
||||
|
||||
const WaterReuseMng = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default WaterReuseMng;
|
||||
@@ -0,0 +1,38 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { TabDataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
|
||||
import { ExcretaTreatmentFacilityInfoList } from "@/components/util/column/review/ExcretaTreatmentFacilityRvwColumn";
|
||||
|
||||
// 하수도 통계 관리 07.분뇨처리 시설
|
||||
const ExcretaTreatmentFacilityRvw = () => {
|
||||
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
const approveFunc = () => console.log('approveFunc');
|
||||
const saveFunc = () => console.log('submit');
|
||||
const reviewOpinionFunc = () => console.log('reviewOpinionFunc');
|
||||
const returnFunc = () => console.log('returnFunc');
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid columnInfo={ExcretaTreatmentFacilityInfoList} isExcelImport={false} rowDataMap={rowDataMap} setRowDataMap={setRowDataMap} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExcretaTreatmentFacilityRvw;
|
||||
@@ -0,0 +1,52 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { TabDataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
|
||||
import { PrivateSewageFacilityInfoListRvw } from "@/components/util/column/review/PrivateSewageFacilityColumn";
|
||||
|
||||
// 하수도 통계 관리 08.개인하수처리시설
|
||||
const PrivateSewageFacilityRvw = () => {
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
const approveFunc = () => {
|
||||
console.log('approveFunc');
|
||||
// 승인 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('submit');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const reviewOpinionFunc = () => {
|
||||
console.log('reviewOpinionFunc');
|
||||
// 검토의견 작성
|
||||
};
|
||||
|
||||
const returnFunc = () => {
|
||||
console.log('returnFunc');
|
||||
// 반려
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid columnInfo={PrivateSewageFacilityInfoListRvw} isExcelImport={false} rowDataMap={rowDataMap} setRowDataMap={setRowDataMap} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PrivateSewageFacilityRvw;
|
||||
@@ -0,0 +1,48 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { DataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
|
||||
import { PublicSewageFacilityInfoList } from "@/components/util/column/review/PublicSewageFacilityRvwColumn";
|
||||
|
||||
// 하수도 통계 관리 06.공공하수처리시설
|
||||
const PublicSewageFacilityRvw = () => {
|
||||
const [rowData, setRowData] = useState<Record<string, string | number>[]>([]);
|
||||
|
||||
const approveFunc = () => {
|
||||
console.log('approveFunc');
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('submit');
|
||||
};
|
||||
|
||||
const reviewOpinionFunc = () => {
|
||||
console.log('reviewOpinionFunc');
|
||||
};
|
||||
|
||||
const returnFunc = () => {
|
||||
console.log('returnFunc');
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<DataGrid columnInfo={PublicSewageFacilityInfoList} isExcelImport={false} rowStartNum={3} fixedColumns={3} rowData={rowData} setRowData={setRowData} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PublicSewageFacilityRvw;
|
||||
@@ -1,12 +1,37 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { useState } from "react";
|
||||
|
||||
import { DataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
|
||||
import { PumpingStationInfoList } from "@/components/util/column/review/PumpingStationRvwColumn";
|
||||
|
||||
// 하수도 통계 관리 05.펌프장
|
||||
const PumpingStationRvw = () => {
|
||||
|
||||
const [rowData, setRowData] = useState<Record<string, string | number>[]>([]);
|
||||
|
||||
const approveFunc = () => { console.log('approveFunc'); };
|
||||
const saveFunc = () => { console.log('submit'); };
|
||||
const reviewOpinionFunc = () => { console.log('reviewOpinionFunc'); };
|
||||
const returnFunc = () => { console.log('returnFunc'); };
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} fctName={true} />
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<DataGrid columnInfo={PumpingStationInfoList} isExcelImport={false} rowStartNum={3} fixedColumns={3} rowData={rowData} setRowData={setRowData} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default PumpingStationRvw;
|
||||
@@ -0,0 +1,53 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { TabDataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
|
||||
import { SewageExcretaRelatedInfoListRvw } from "@/components/util/column/review/SewageExcretaRelatedRvwColumn";
|
||||
|
||||
// 하수도 통계 관리 12. 하수 및 분뇨 관련 산업
|
||||
const SewageExcretaRelatedRvw = () => {
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
const approveFunc = () => {
|
||||
console.log('approveFunc');
|
||||
// 승인 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('submit');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const reviewOpinionFunc = () => {
|
||||
console.log('reviewOpinionFunc');
|
||||
// 검토의견 작성
|
||||
};
|
||||
|
||||
const returnFunc = () => {
|
||||
console.log('returnFunc');
|
||||
// 반려
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid columnInfo={SewageExcretaRelatedInfoListRvw} isExcelImport={false} rowDataMap={rowDataMap} setRowDataMap={setRowDataMap} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default SewageExcretaRelatedRvw;
|
||||
@@ -0,0 +1,52 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { TabDataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
|
||||
import { SewageExcretaSludgeInfoListRvw } from "@/components/util/column/review/SewageExcretaSlurgeRvwColumn";
|
||||
|
||||
// 하수도 통계 관리 11. 하수 및 분뇨 찌꺼기(슬러지) 처리
|
||||
const SewageExcretaSlurgeRvw = () => {
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
const approveFunc = () => {
|
||||
console.log('approveFunc');
|
||||
// 승인 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('submit');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const reviewOpinionFunc = () => {
|
||||
console.log('reviewOpinionFunc');
|
||||
// 검토의견 작성
|
||||
};
|
||||
|
||||
const returnFunc = () => {
|
||||
console.log('returnFunc');
|
||||
// 반려
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid columnInfo={SewageExcretaSludgeInfoListRvw} isExcelImport={false} rowDataMap={rowDataMap} setRowDataMap={setRowDataMap} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewageExcretaSlurgeRvw;
|
||||
@@ -1,11 +1,52 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { useState } from "react";
|
||||
|
||||
import { TabDataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
|
||||
import { SewagePipeMaintainColumnInfoList } from "@/components/util/column/review/SewagePipeMaintainRvwColumn";
|
||||
|
||||
// 하수도 통계 관리 03. 하수관로 유지 관리
|
||||
const SewagePipeMaintainRvw = () => {
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
const approveFunc = () => {
|
||||
console.log('approveFunc');
|
||||
// 승인 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('submit');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const reviewOpinionFunc = () => {
|
||||
console.log('reviewOpinionFunc');
|
||||
// 검토의견 작성
|
||||
};
|
||||
|
||||
const returnFunc = () => {
|
||||
console.log('returnFunc');
|
||||
// 반려
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid columnInfo={SewagePipeMaintainColumnInfoList} isExcelImport={false} rowDataMap={rowDataMap} setRowDataMap={setRowDataMap} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default SewagePipeMaintainRvw;
|
||||
@@ -1,11 +1,148 @@
|
||||
import { useState, useMemo, useRef } from "react";
|
||||
import TabDataGrid from "@/components/module/TabDataGrid";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
import { LoadingWithAnimation } from "@common/components";
|
||||
|
||||
import { useAlertStore } from "@/shared/lib";
|
||||
import { statisticsManagementApi } from "@/entities/statistics/api/statistics-management-service";
|
||||
import { SewagePipeColumnInfoListRvw } from "@/components/util/column/review/SewagePipeRvwColumn";
|
||||
import type { ColumnInfoList, ColumnConfig } from "@/components/type/DataGrid.type";
|
||||
import type { SearchFormValues } from "@/components/type/SearchForm.type";
|
||||
import { toGridRows } from "@/components/util/grid/gridFunction";
|
||||
|
||||
// 하수도 통계 검토 02.하수관로
|
||||
const SewagePipeRvw = () => {
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [activeTab, setActiveTab] = useState<string>('a');
|
||||
|
||||
const searchParamRef = useRef<SearchFormValues | null>(null);
|
||||
|
||||
const columnInfo = useMemo(() => {
|
||||
return SewagePipeColumnInfoListRvw.map((tab: ColumnInfoList) => ({
|
||||
...tab,
|
||||
columns: (tab.columns ?? []).map((col: ColumnConfig) => ({
|
||||
...col,
|
||||
editable: false as const,
|
||||
styleName: col.styleName ?? ("rg-cell-readonly" as const),
|
||||
})),
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const handleReset = () => {
|
||||
setRowDataMap(new Map());
|
||||
setActiveTab('a');
|
||||
};
|
||||
|
||||
const handleSearch = async (values: SearchFormValues) => {
|
||||
if (!values.sido || values.sido === 'ALL') {
|
||||
alert('시도를 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
setActiveTab('a');
|
||||
|
||||
setRowDataMap(new Map());
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
const searchParam = {
|
||||
sido: values.sido,
|
||||
gugun: values.gugun === 'ALL' ? '' : values.gugun,
|
||||
bsnmCd: values.bsnmCd,
|
||||
yr: values.year,
|
||||
};
|
||||
|
||||
searchParamRef.current = searchParam;
|
||||
const response = await statisticsManagementApi.getSewagePipeReviewRegionalList(searchParam);
|
||||
|
||||
if (response?.status === 'success' && response.data) {
|
||||
const newRowDataMap = new Map<string, Record<string, string | number>[]>();
|
||||
newRowDataMap.set('a', toGridRows(response.data as object[]));
|
||||
setRowDataMap(newRowDataMap);
|
||||
} else {
|
||||
alert(response?.message || "데이터가 없습니다.");
|
||||
}
|
||||
} catch (error) {
|
||||
alert('데이터 조회 중 오류가 발생했습니다.');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleActiveTabChange = async (tabKey: string) => {
|
||||
setActiveTab(tabKey);
|
||||
|
||||
const existingAData = rowDataMap.get('a');
|
||||
const activeTabData = rowDataMap.get(tabKey);
|
||||
|
||||
const hasAData = Array.isArray(existingAData) && existingAData.length > 0;
|
||||
const hasActiveTabData = Array.isArray(activeTabData) && activeTabData.length > 0;
|
||||
|
||||
if (hasAData && !hasActiveTabData && searchParamRef.current) {
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
let response;
|
||||
|
||||
if (tabKey === 'b') {
|
||||
response = await statisticsManagementApi.getSewagePipeFacilityList(searchParamRef.current);
|
||||
}
|
||||
|
||||
if (response?.status === 'success' && response.data) {
|
||||
setRowDataMap(prev => {
|
||||
const next = new Map(prev);
|
||||
next.set(tabKey, toGridRows(response.data as object[]));
|
||||
return next;
|
||||
});
|
||||
} else {
|
||||
alert(response?.message || "데이터가 없습니다.");
|
||||
}
|
||||
} catch {
|
||||
alert('데이터 조회 중 오류가 발생했습니다.');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
<div className="relative">
|
||||
<SearchForm onSubmit={handleSearch} onReset={handleReset} />
|
||||
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={() => { }} />
|
||||
<ApproveButton approveFunc={() => { }} />
|
||||
<ReturnButton returnFunc={() => { }} />
|
||||
<SaveButton saveFunc={() => { }} />
|
||||
</div>
|
||||
</div>
|
||||
{isLoading && (
|
||||
<div className="absolute inset-0 z-50 [data-theme='black']:bg-transparent rounded-lg p-10 flex justify-center items-center">
|
||||
<div className="relative size-[5rem]">
|
||||
<LoadingWithAnimation color="primary" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<TabDataGrid
|
||||
columnInfo={columnInfo}
|
||||
isExcelImport={false}
|
||||
rowDataMap={rowDataMap}
|
||||
setRowDataMap={setRowDataMap}
|
||||
activeTab={activeTab}
|
||||
onActiveTabChange={handleActiveTabChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default SewagePipeRvw;
|
||||
@@ -1,11 +1,52 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import { useState } from "react";
|
||||
|
||||
import { TabDataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
|
||||
import { SewageReservoirPumpInfoListRvw } from "@/components/util/column/review/SewageReservoirPumpRvwColumn";
|
||||
|
||||
// 하수도 통계 관리 04. 하수저류 시설 및 빗물 펌프장
|
||||
const SewageReservoirPumpRvw = () => {
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
const approveFunc = () => {
|
||||
console.log('approveFunc');
|
||||
// 승인 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('submit');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const reviewOpinionFunc = () => {
|
||||
console.log('reviewOpinionFunc');
|
||||
// 검토의견 작성
|
||||
};
|
||||
|
||||
const returnFunc = () => {
|
||||
console.log('returnFunc');
|
||||
// 반려
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid columnInfo={SewageReservoirPumpInfoListRvw} isExcelImport={false} rowDataMap={rowDataMap} setRowDataMap={setRowDataMap} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default SewageReservoirPumpRvw;
|
||||
export default SewageReservoirPumpRvw;
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { TabDataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
|
||||
import { SewerageFinanceInfoListRvw } from "@/components/util/column/review/SewerageFinanceRvwColumn";
|
||||
|
||||
|
||||
// 하수도 통계 관리 09. 하수도 재정
|
||||
const SewerageFinanceRvw = () => {
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
const approveFunc = () => {
|
||||
console.log('approveFunc');
|
||||
// 승인 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('submit');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const reviewOpinionFunc = () => {
|
||||
console.log('reviewOpinionFunc');
|
||||
// 검토의견 작성
|
||||
};
|
||||
|
||||
const returnFunc = () => {
|
||||
console.log('returnFunc');
|
||||
// 반려
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid columnInfo={SewerageFinanceInfoListRvw} isExcelImport={false} rowDataMap={rowDataMap} setRowDataMap={setRowDataMap} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default SewerageFinanceRvw;
|
||||
@@ -1,11 +1,115 @@
|
||||
import { useState, useMemo } from "react";
|
||||
import DataGrid from "@/components/module/DataGrid";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
import { LoadingWithAnimation } from "@common/components";
|
||||
|
||||
import { useAlertStore } from "@/shared/lib";
|
||||
import { SeweragePenetrationRateInfoList } from "@/components/util/column/review/SeweragePenetrationRateRvwColumn";
|
||||
import type { SewerageSupplyRateReviewItem } from "@/entities/statistics/model/statistics-sewerage-penetration-review-interface";
|
||||
import { statisticsManagementApi } from "@/entities/statistics/api/statistics-management-service";
|
||||
import type { SearchFormValues } from "@/components/type/SearchForm.type";
|
||||
import { toGridRows } from "@/components/util/grid/gridFunction";
|
||||
|
||||
// 하수도 통계 검토 01.하수도 보급률
|
||||
const SeweragePenetrationRateRvw = () => {
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
const [rowData, setRowData] = useState<any[]>([]);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
|
||||
const columnInfo = useMemo(() => {
|
||||
const { columns, columnLayout, fixedColumns, rowStartNum } = SeweragePenetrationRateInfoList;
|
||||
return {
|
||||
columnLayout,
|
||||
fixedColumns,
|
||||
rowStartNum,
|
||||
columns: columns.map((col) => ({
|
||||
...col,
|
||||
editable: false as const,
|
||||
styleName: col.styleName ?? ("rg-cell-readonly" as const),
|
||||
})),
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleReset = () => {
|
||||
setRowData([]);
|
||||
};
|
||||
|
||||
const handleSearch = async (values: SearchFormValues) => {
|
||||
if (values.sido === '' || values.sido === 'ALL') {
|
||||
alert('시도를 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
const response = await statisticsManagementApi.getSewerageSupplyRateReviewList({
|
||||
sido: values.sido,
|
||||
gugun: values.gugun === 'ALL' ? '' : values.gugun,
|
||||
bsnmCd: values.bsnmCd,
|
||||
yr: values.year,
|
||||
});
|
||||
|
||||
if (response.status === 'success' && response.data) {
|
||||
const rawList = response.data.sewerageSupplyRateList;
|
||||
const convertedData: SewerageSupplyRateReviewItem[] = rawList.map((item) => ({
|
||||
...item,
|
||||
speclCntrplnAr: !item.speclCntrplnAr ? '해당없음' : item.speclCntrplnAr,
|
||||
}));
|
||||
|
||||
setRowData(toGridRows(convertedData));
|
||||
} else {
|
||||
setRowData([]);
|
||||
alert(response.message || "데이터가 없습니다.");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("조회 중 에러 발생:", error);
|
||||
alert('데이터 조회 중 오류가 발생했습니다.');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const approveFunc = () => console.log('approveFunc');
|
||||
const saveFunc = () => console.log('submit');
|
||||
const reviewOpinionFunc = () => console.log('reviewOpinionFunc');
|
||||
const returnFunc = () => console.log('returnFunc');
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
<div className="relative">
|
||||
<SearchForm onSubmit={handleSearch} onReset={handleReset} />
|
||||
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isLoading && (
|
||||
<div className="absolute inset-0 z-50 [data-theme='black']:bg-transparent rounded-lg p-10 flex justify-center items-center">
|
||||
<div className="relative size-[5rem]">
|
||||
<LoadingWithAnimation color="primary" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<DataGrid
|
||||
columnInfo={columnInfo}
|
||||
isExcelImport={false}
|
||||
fixedColumns={columnInfo.fixedColumns}
|
||||
rowStartNum={columnInfo.rowStartNum}
|
||||
rowData={rowData}
|
||||
setRowData={setRowData}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default SeweragePenetrationRateRvw;
|
||||
@@ -0,0 +1,53 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { TabDataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
|
||||
import { SewerageServiceLevelInfoListRvw } from "@/components/util/column/review/SewerageServiceLevelRvwColumn";
|
||||
|
||||
// 하수도 통계 관리 13. 하수도 서비스 수준
|
||||
const SewerageServiceLevelRvw = () => {
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
const approveFunc = () => {
|
||||
console.log('approveFunc');
|
||||
// 승인 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('submit');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const reviewOpinionFunc = () => {
|
||||
console.log('reviewOpinionFunc');
|
||||
// 검토의견 작성
|
||||
};
|
||||
|
||||
const returnFunc = () => {
|
||||
console.log('returnFunc');
|
||||
// 반려
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid columnInfo={SewerageServiceLevelInfoListRvw} isExcelImport={false} rowDataMap={rowDataMap} setRowDataMap={setRowDataMap} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default SewerageServiceLevelRvw;
|
||||
@@ -1,11 +0,0 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const StatsInputSatusRvw = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default StatsInputSatusRvw;
|
||||
@@ -0,0 +1,113 @@
|
||||
import { useState, useMemo } from "react";
|
||||
import { DataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
import { LoadingWithAnimation } from "@common/components";
|
||||
|
||||
import { useAlertStore } from "@/shared/lib";
|
||||
import { StatsInputStatusInfoList } from "@/components/util/column/review/StatsInputStatusRvwColumn";
|
||||
import { statisticsManagementApi } from "@/entities/statistics/api/statistics-management-service";
|
||||
import type { StatsInputStatusReviewItem } from "@/entities/statistics/model/statistics-input-review-interface";
|
||||
import { toGridRows } from "@/components/util/grid/gridFunction";
|
||||
|
||||
// 하수도 통계 검토 00. 통계 입력 현황
|
||||
const StatsInputStatusRvw = () => {
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
const [rowData, setRowData] = useState<any[]>([]);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
|
||||
const columnInfo = useMemo(() => {
|
||||
const { columns, columnLayout } = StatsInputStatusInfoList;
|
||||
return {
|
||||
columnLayout,
|
||||
columns: columns.map((col) => ({
|
||||
...col,
|
||||
editable: false as const,
|
||||
})),
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleReset = () => {
|
||||
setRowData([]);
|
||||
};
|
||||
|
||||
const handleSearch = async (values: any) => {
|
||||
if (!values.sido || values.sido === 'ALL') {
|
||||
alert('시도를 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
const response = await statisticsManagementApi.getStatsInputStatusList({
|
||||
sido: values.sido,
|
||||
gugun: values.gugun === 'ALL' ? '' : values.gugun,
|
||||
yr: values.year || values.yr,
|
||||
bsnmCd: values.bsnmCd
|
||||
});
|
||||
|
||||
if (response.status === 'success' && response.data) {
|
||||
const rawList = response.data.sewerageSupplyRateList || response.data;
|
||||
|
||||
const convertedData: StatsInputStatusReviewItem[] = rawList.map((item: any) => ({
|
||||
...item,
|
||||
status: item.status || '미확인',
|
||||
}));
|
||||
|
||||
setRowData(toGridRows(convertedData));
|
||||
} else {
|
||||
setRowData([]);
|
||||
alert(response.message || "조회된 데이터가 없습니다.");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("입력현황 조회 중 에러 발생:", error);
|
||||
alert('데이터 조회 중 오류가 발생했습니다.');
|
||||
setRowData([]);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const approveFunc = () => console.log('approveFunc');
|
||||
const saveFunc = () => console.log('submit');
|
||||
const reviewOpinionFunc = () => console.log('reviewOpinionFunc');
|
||||
const returnFunc = () => console.log('returnFunc');
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<SearchForm onSubmit={handleSearch} onReset={handleReset} />
|
||||
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isLoading && (
|
||||
<div className="absolute inset-0 z-50 [data-theme='black']:bg-transparent rounded-lg p-10 flex justify-center items-center">
|
||||
<div className="relative size-[5rem]">
|
||||
<LoadingWithAnimation color="primary" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<DataGrid
|
||||
columnInfo={columnInfo}
|
||||
isExcelImport={false}
|
||||
rowStartNum={2}
|
||||
fixedColumns={2}
|
||||
rowData={rowData}
|
||||
setRowData={setRowData}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatsInputStatusRvw;
|
||||
@@ -0,0 +1,51 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { TabDataGrid } from "@rsone/components";
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
import SaveButton from "@/components/button/SaveButton";
|
||||
import ApproveButton from "@/components/button/ApproveButton";
|
||||
import ReviewOpinionButton from "@/components/button/ReviewOpinionButton";
|
||||
import ReturnButton from "@/components/button/ReturnButton";
|
||||
|
||||
import { WaterReuseInfoList } from "@/components/util/column/review/WaterReuseRvwColumn";
|
||||
|
||||
const WaterReuseRvw = () => {
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
|
||||
const approveFunc = () => {
|
||||
console.log('approveFunc');
|
||||
// 승인 로직
|
||||
};
|
||||
|
||||
const saveFunc = () => {
|
||||
console.log('submit');
|
||||
// 저장 로직
|
||||
};
|
||||
|
||||
const reviewOpinionFunc = () => {
|
||||
console.log('reviewOpinionFunc');
|
||||
// 검토의견 작성
|
||||
};
|
||||
|
||||
const returnFunc = () => {
|
||||
console.log('returnFunc');
|
||||
// 반려
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchForm fctName={true} />
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
<ReviewOpinionButton reviewOpinionFunc={reviewOpinionFunc} />
|
||||
<ApproveButton approveFunc={approveFunc} />
|
||||
<ReturnButton returnFunc={returnFunc} />
|
||||
<SaveButton saveFunc={saveFunc} />
|
||||
</div>
|
||||
</div>
|
||||
<TabDataGrid columnInfo={WaterReuseInfoList} isExcelImport={false} rowDataMap={rowDataMap} setRowDataMap={setRowDataMap} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default WaterReuseRvw;
|
||||
@@ -0,0 +1,11 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const ExcretaTreatmentFacilityTot = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExcretaTreatmentFacilityTot;
|
||||
@@ -0,0 +1,11 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const PrivateSewageFacilityTot = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PrivateSewageFacilityTot;
|
||||
@@ -0,0 +1,11 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const PublicSewageFacilityTot = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PublicSewageFacilityTot;
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const SewagePipeMng = () => {
|
||||
const PumpingStationTot = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm userMenual={true} />
|
||||
<SearchForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewagePipeMng;
|
||||
export default PumpingStationTot;
|
||||
@@ -0,0 +1,11 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const SewageExcretaRelatedTot = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewageExcretaRelatedTot;
|
||||
@@ -0,0 +1,11 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const SewageExcretaSlurgeTot = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewageExcretaSlurgeTot;
|
||||
@@ -0,0 +1,11 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const SewagePipeMaintainTot = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewagePipeMaintainTot;
|
||||
@@ -0,0 +1,11 @@
|
||||
import SearchForm from "@/components/module/SearchForm";
|
||||
|
||||
const SewagePipeTot = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SewagePipeTot;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user