Merge commit '268c45ed05efa45f966d33556a6ea974472b4b81'

This commit is contained in:
truthwing
2025-07-22 21:26:32 +09:00
21 changed files with 167 additions and 80 deletions
+19
View File
@@ -0,0 +1,19 @@
NEXT_PUBLIC_SITE_ID = DM
NEXT_PUBLIC_PORT = 3000
NEXT_PUBLIC_PROXY_HOST = http://localhost:3000
NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1
NEXT_PUBLIC_FO_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1
NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_CS_TUS_UPLOAD = /attach-service/api/v1/tus/upload
NEXT_PUBLIC_CLAIM_NAME = Authorization
NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
# NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883/sewerage-service/api # 박이정
+19
View File
@@ -0,0 +1,19 @@
NEXT_PUBLIC_SITE_ID = DM
NEXT_PUBLIC_PORT = 3000
NEXT_PUBLIC_PROXY_HOST = http://localhost:3000
NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1
NEXT_PUBLIC_FO_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1
NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_CS_TUS_UPLOAD = /attach-service/api/v1/tus/upload
NEXT_PUBLIC_CLAIM_NAME = Authorization
NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
# NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883/sewerage-service/api # 박이정
+17
View File
@@ -0,0 +1,17 @@
NEXT_PUBLIC_SITE_ID = DM
NEXT_PUBLIC_PORT = 3000
NEXT_PUBLIC_PROXY_HOST = http://wr.hasuon.or.kr
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000/api/v1
NEXT_PUBLIC_FO_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000/operation-service/api/v1
NEXT_PUBLIC_CS_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000
NEXT_PUBLIC_CS_TUS_UPLOAD = /attach-service/api/v1/tus/upload
NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl
NEXT_PUBLIC_CLAIM_NAME = Authorization
NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_SEWERAGE_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000/sewerage-service/api
-2
View File
@@ -1,7 +1,6 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
@@ -31,7 +30,6 @@ yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
+22
View File
@@ -0,0 +1,22 @@
"use client";
import { BaseLayout } from "@common/components";
import type { MenuItem } from "./store/common";
import { useDmStore } from "./store";
import { useRouter } from "next/navigation";
export default function Base({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const { getMenuAuth } = useDmStore((state) => state);
const router = useRouter();
const handleClick = (id:MenuItem) =>{
getMenuAuth(id.menuCd);
router.push(id.urlPath);
}
return <BaseLayout handleMenuClick={handleClick}>{children}</BaseLayout>;
}
+4 -7
View File
@@ -1,6 +1,5 @@
"use client";
import { BaseLayout } from "@common/components";
"use client"
import Base from "./base";
import "./globals.css";
import { StoreProvider } from "./store";
@@ -13,11 +12,9 @@ export default function RootLayout({
<html lang="en">
<body>
<StoreProvider>
<BaseLayout>
{children}
</BaseLayout>
<Base>{children}</Base>
</StoreProvider>
</body>
</html>
);
}
}
@@ -52,7 +52,7 @@ export default function ModalSimilarPage({ sply = 0, usageCd = '', money = 0 }:
return spans;
}, [similarCaseList]);
const handleCellClick = (index: number, headId: string) => {
const handleCellClick = (index: number) => {
setMoneyDetailList([{
reqBizGrssCst: similarCaseList[index]?.reqBizGrssCst ?? '',
reqBizReuseFcltCst: similarCaseList[index]?.reqBizReuseFcltCst ?? '',
@@ -124,10 +124,10 @@ export default function ModalSimilarPage({ sply = 0, usageCd = '', money = 0 }:
key={`similar-case-cell-${head.id}-${index}-${el.ruseBizNm}`}
rowSpan={(head.id === 'businessName' || head.id ==='businessDuration' || head.id === 'money') ? rowSpans[index] : undefined}
style={(head.id === 'businessName' || head.id === 'businessDuration' || head.id === 'money') && index > 0 && similarCaseList[index - 1]?.ruseBizNm === el.ruseBizNm ? { display: 'none' } : undefined}
onClick={() => handleCellClick(index, head.id)}
onClick={() => handleCellClick(index)}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
handleCellClick(index, head.id);
handleCellClick(index);
}
}}
>
@@ -9,7 +9,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { useSearchParams } from "next/navigation";
import { Suspense, useEffect, useState } from "react";
import { FormProvider, useForm, type SubmitHandler } from "react-hook-form";
import { Toaster, toast } from "react-hot-toast";
import { Toaster } from "react-hot-toast";
import * as z from "zod";
import SdmLogin from "../sdmLogin/page";
+4 -13
View File
@@ -1,8 +1,7 @@
'use client';
import React, { useState, useEffect, useRef } from 'react';
import Image from 'next/image';
import { CHART_FORM, MainChart, type ChartConfig } from '@common/business_components';
import React, { useEffect, useRef, useState } from 'react';
interface RegionData {
name: string;
@@ -22,12 +21,10 @@ interface TableData {
const WrStatusPage: React.FC = () => {
const [selectedRegion, setSelectedRegion] = useState<string | null>(null);
const [originalFills, setOriginalFills] = useState<Record<string, string>>({});
const [hoveredRegion, setHoveredRegion] = useState<string | null>(null);
const [tooltipPosition, setTooltipPosition] = useState<{ x: number; y: number } | null>(null);
const [favorites, setFavorites] = useState<Record<string, boolean>>({});
const svgContainerRef = useRef<HTMLDivElement>(null);
const [chartData, setChartData] = useState<any[]>([
const [chartData] = useState<any[]>([
{
label : '서울',
하수 : 4,
@@ -244,12 +241,6 @@ const WrStatusPage: React.FC = () => {
}
};
const handleFavoriteClick = (region: string) => {
setFavorites(prev => ({
...prev,
[region]: !prev[region]
}));
};
const createDonutMarker = (svg: SVGSVGElement, x: number, y: number, name: string, values: number[]) => {
const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FED16A'];
@@ -395,13 +386,13 @@ const WrStatusPage: React.FC = () => {
if (selectedRegion === pathId) {
path.setAttribute('fill', '#2563eb');
} else {
const original = originalFills[pathId] || '#ffffff';
const original = '#ffffff';
path.setAttribute('fill', original);
}
}
});
}
}, [selectedRegion, originalFills]);
}, [selectedRegion]);
return (
<div className="flex h-screen bg-[#F4F7FB] text-gray-800">
+39
View File
@@ -14,6 +14,26 @@ export type SelectDataType = {
val: string;
}
export interface MenuItem {
menuCd: number;
menuKornNm: string;
menuEngNm: string;
parentId: number | null;
sortSeq: number;
iconNm?: string;
children: MenuItem[] | null;
levelNo: number;
urlPath: string;
menuLnkgTypeCd: string;
menuLnkgSn: number;
menuPath: string;
qrcd: string;
useYn: string;
otptYn: string;
newWndwYn: string;
requiredUrlPath: boolean;
}
// grid header
export type TableUpperProps = {
id: string;
@@ -312,6 +332,7 @@ const fetchEnvPartData = async (): Promise<envPartSelectDataType[]> => {
====================================*/
export type CommonAction = {
initializeCommonData: () => Promise<void>;
getMenuAuth: (menuCd:number) => Promise<void>;
}
export type CommonType = {
@@ -358,6 +379,24 @@ export const CommonState:CommonType = {
export const CommonReducer:(set:any)=>CommonAction=(set: any) => {
return {
getMenuAuth : async (menuCd : number) =>{
const response = await getFetch(
"local",
`/cms-service/api/v1/menu-authrts/pageinfo/${menuCd}`
);
set((state: CommonType) => {
return {
...state,
auth: {
mngAuthrtYn: response[0].mngAuthrtYn,
inqAuthrtYn: response[0].mngAuthrtYn,
regAuthrtYn: response[0].mngAuthrtYn,
mdfcnAuthrtYn: response[0].mngAuthrtYn,
delAuthrtYn: response[0].mngAuthrtYn,
},
};
});
},
// 시도 변경 이벤트
initializeCommonData: async () => {
const promiseSet = await Promise.all([fetchSidoData(), fetchSigunData(), fetchRegionData(), fetchUnitWaterShedData(), fetchMiddleRegionData(), fetchEnvPartData()]);
-2
View File
@@ -253,8 +253,6 @@ export const upHeadSdmInfoStatus: TableUpperProps[] = [
]
// 수요정보 신청현황 데이터
const sdmInfoStatusList : DemandCompType[] = [
]
/**====================================
* Store - Api
+4 -12
View File
@@ -1,13 +1,5 @@
const LOCAL_PORT = "3000";
const DEV_PORT = "11080";
const DEV_PORT_FO = "11082";
import { PROXY_HOST, SERVER_API_FO_URL, SERVER_API_WR_URL } from "@/src/shared/config/env";
export const LOCAL_URL_WR = `http://localhost:${LOCAL_PORT}/api/v1`;
export const DEV_URL_WR = `http://con.mind-one.co.kr:${DEV_PORT}/api/v1`;
//export const DEV_URL_FO = `http://con.mind-one.co.kr:${DEV_PORT_FO}/api/v1`;
export const LOCAL_URL_FO = `http://192.168.1.129:${DEV_PORT_FO}/api/v1`;
export const DEV_URL_FO = `http://con.mind-one.co.kr:${DEV_PORT_FO}/api/v1`;
export const CS_URL= 'http://dev.onasys.co.kr:8000'
export const CS_TUS_UPLOAD= "/attach-service/api/v1/tus/upload";
export const LOCAL_URL = PROXY_HOST;
export const DEV_URL_FO = SERVER_API_FO_URL;
export const DEV_URL_WR = SERVER_API_WR_URL;
@@ -12,7 +12,6 @@ interface AccessibleFormFieldProps<T extends FieldValues> {
}
export function AccessibleFormField<T extends FieldValues>({
field,
label,
required = false,
error,
+4
View File
@@ -11,6 +11,10 @@ const compat = new FlatCompat({
const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"),
{rules:{
// other rules..
"@typescript-eslint/no-explicit-any": "off",
}},
];
export default eslintConfig;
+1 -2
View File
@@ -1,10 +1,9 @@
import { NextRequest, NextResponse } from "next/server";
import { CS_URL } from "./components/ui/config";
import { CLAIM_NAME, AUTH_USER_ID } from "./src/shared/config";
// const CLAIM_NAME = "Authorization";
// const AUTH_USER_ID = "token-id";
const serverApiUrl = CS_URL;
const serverApiUrl = process.env.NEXT_PUBLIC_CS_SERVER_API_URL;
const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || "";
const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || "";
const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
+26 -34
View File
@@ -1,41 +1,33 @@
import type { NextConfig } from "next";
import webpack from "webpack";
const subDomain =
process.env.NEXT_PUBLIC_SUB_DOMAIN || "http://localhost:3000";
const nextConfig: NextConfig = {
output: "standalone",
eslint: {
ignoreDuringBuilds: true,
},
webpack: (config) => {
config.plugins.push(
new webpack.DefinePlugin({
"import.meta.env.VITE_PORT": JSON.stringify(
process.env.NEXT_PUBLIC_PORT
),
"import.meta.env.VITE_PROXY_HOST": JSON.stringify(
process.env.NEXT_PUBLIC_PROXY_HOST
),
"import.meta.env.VITE_SERVER_API_URL": JSON.stringify(
process.env.NEXT_PUBLIC_SERVER_API_URL
),
"import.meta.env.VITE_SITE_ID": JSON.stringify(process.env.SITE_ID),
"import.meta.env.VITE_CLAIM_NAME": JSON.stringify(
process.env.NEXT_PUBLIC_CLAIM_NAME
),
"import.meta.env.VITE_ACCESS_TOKEN": JSON.stringify(
process.env.NEXT_PUBLIC_ACCESS_TOKEN
),
"import.meta.env.VITE_REFRESH_TOKEN": JSON.stringify(
process.env.NEXT_PUBLIC_REFRESH_TOKEN
),
"import.meta.env.VITE_AUTH_USER_ID": JSON.stringify(
process.env.NEXT_PUBLIC_AUTH_USER_ID
),
"process.env.SITE_ID": JSON.stringify(process.env.NEXT_PUBLIC_SITE_ID),
})
);
return config;
async rewrites() {
return {
beforeFiles: [
{
source: "/_next/static/:path*",
destination: `${subDomain}/_next/static/:path*`,
has: [
{
type: "header",
key: "referer",
value: "(.*)/pst(.*)",
},
],
},
],
afterFiles: [
{
source: "/pst/:path*",
destination: `${subDomain}/pst/:path*`,
},
],
fallback: [],
};
},
};
+2
View File
@@ -9,11 +9,13 @@
"lint": "next lint"
},
"dependencies": {
"@common/assets": "workspace:*",
"@common/business_components": "workspace:*",
"@common/components": "workspace:*",
"@hookform/resolvers": "^4.1.3",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"js-cookie": "^3.0.5",
"js-sha512": "^0.9.0",
"lucide-react": "^0.474.0",
"next": "15.1.7",
@@ -1,4 +1,3 @@
import type { LoginService, ILogin } from "../model/login-interface";
import { tokenManager } from "../lib/token-manager";
import {PROXY_HOST, ACCESS_TOKEN, AUTH_USER_ID,SITE_ID, CLAIM_NAME, ENDPOINT, JWT_EXPIRATION_TIME } from "../../../shared/config";
+1 -1
View File
@@ -1,2 +1,2 @@
export * from "./api";
export * from "./env";
export * from "./env";
-1
View File
@@ -1,4 +1,3 @@
import Cookies from "js-cookie";
+1
View File
@@ -2,6 +2,7 @@
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"noImplicitAny": false,
"baseUrl": ".",
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],