diff --git a/docs/git commit message Convention.pdf b/docs/git commit message Convention.pdf
new file mode 100644
index 00000000..1df33833
Binary files /dev/null and b/docs/git commit message Convention.pdf differ
diff --git a/src/app/QcastProvider.js b/src/app/QcastProvider.js
new file mode 100644
index 00000000..f9431eb6
--- /dev/null
+++ b/src/app/QcastProvider.js
@@ -0,0 +1,35 @@
+'use client'
+
+import { useEffect } from 'react'
+import { useRecoilState, useRecoilValue } from 'recoil'
+import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
+import { ErrorBoundary } from 'next/dist/client/components/error-boundary'
+import ServerError from './error'
+
+import '@/styles/common.scss'
+
+import KO from '@/locales/ko.json'
+import JA from '@/locales/ja.json'
+
+export const QcastProvider = ({ children }) => {
+ const globalLocale = useRecoilValue(globalLocaleStore)
+ const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
+
+ useEffect(() => {
+ console.log(sessionStorage.getItem('hi'))
+ console.log(Object.keys(appMessageState).length)
+ // if (Object.keys(appMessageState).length === 0) {
+ if (globalLocale === 'ko') {
+ setAppMessageState(KO)
+ } else {
+ setAppMessageState(JA)
+ }
+ // }
+ }, [globalLocale])
+
+ return (
+ <>
+ }>{children}
+ >
+ )
+}
diff --git a/src/app/[locale]/management/stuff/detail/page.jsx b/src/app/[locale]/management/stuff/detail/page.jsx
index 8b84287a..6759b282 100644
--- a/src/app/[locale]/management/stuff/detail/page.jsx
+++ b/src/app/[locale]/management/stuff/detail/page.jsx
@@ -1,11 +1,15 @@
import React from 'react'
import Hero from '@/components/Hero'
import StuffDetail from '@/components/management/StuffDetail'
+import Link from 'next/link'
export default function ManagementStuffDetailPage() {
return (
<>
diff --git a/src/app/[locale]/management/stuff/tempdetail/page.jsx b/src/app/[locale]/management/stuff/tempdetail/page.jsx
new file mode 100644
index 00000000..8b84287a
--- /dev/null
+++ b/src/app/[locale]/management/stuff/tempdetail/page.jsx
@@ -0,0 +1,15 @@
+import React from 'react'
+import Hero from '@/components/Hero'
+import StuffDetail from '@/components/management/StuffDetail'
+export default function ManagementStuffDetailPage() {
+ return (
+ <>
+
+
물건정보
+
+
+
+
+ >
+ )
+}
diff --git a/src/app/[locale]/page.js b/src/app/[locale]/page.js
index bbdcd96d..1b8f2258 100644
--- a/src/app/[locale]/page.js
+++ b/src/app/[locale]/page.js
@@ -1,21 +1,16 @@
import { getSession } from '@/lib/authActions'
-import { getCurrentLocale } from '@/locales/server'
import MainPage from '@/components/Main'
export default async function page() {
const session = await getSession()
- const currentLocale = getCurrentLocale()
-
const mainPageProps = {
- currentLocale,
isLoggedIn: session?.isLoggedIn,
}
return (
<>
-
Main
>
diff --git a/src/app/community/archive/page.jsx b/src/app/community/archive/page.jsx
new file mode 100644
index 00000000..6917f228
--- /dev/null
+++ b/src/app/community/archive/page.jsx
@@ -0,0 +1,16 @@
+import Hero from '@/components/Hero'
+import Archive from '@/components/community/Archive'
+import { initCheck } from '@/util/session-util'
+
+export default async function CommunityArchivePage() {
+ await initCheck()
+
+ return (
+ <>
+
+
+ >
+ )
+}
diff --git a/src/app/community/faq/page.jsx b/src/app/community/faq/page.jsx
new file mode 100644
index 00000000..2b9d5452
--- /dev/null
+++ b/src/app/community/faq/page.jsx
@@ -0,0 +1,16 @@
+import Hero from '@/components/Hero'
+import Faq from '@/components/community/Faq'
+import { initCheck } from '@/util/session-util'
+
+export default async function CommunityFaqPage() {
+ await initCheck()
+
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
diff --git a/src/app/community/notice/page.jsx b/src/app/community/notice/page.jsx
new file mode 100644
index 00000000..d2157b20
--- /dev/null
+++ b/src/app/community/notice/page.jsx
@@ -0,0 +1,16 @@
+import Hero from '@/components/Hero'
+import Notice from '@/components/community/Notice'
+import { initCheck } from '@/util/session-util'
+
+export default async function CommunityNoticePage() {
+ await initCheck()
+
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
diff --git a/src/app/floor-plan/page.jsx b/src/app/floor-plan/page.jsx
new file mode 100644
index 00000000..f503099e
--- /dev/null
+++ b/src/app/floor-plan/page.jsx
@@ -0,0 +1,9 @@
+import FloorPlan from '@/components/floor-plan/FloorPlan'
+
+export default function FloorPlanPage() {
+ return (
+ <>
+
+ >
+ )
+}
diff --git a/src/app/initSettingsModal/page.jsx b/src/app/initSettingsModal/page.jsx
new file mode 100644
index 00000000..a081ef47
--- /dev/null
+++ b/src/app/initSettingsModal/page.jsx
@@ -0,0 +1,16 @@
+import Hero from '@/components/Hero'
+import InitSettingsModal from '@/components/InitSettingsModal'
+import { initCheck } from '@/util/session-util'
+
+export default async function InitSettingsModalPage() {
+ await initCheck()
+
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
diff --git a/src/app/intro/page.jsx b/src/app/intro/page.jsx
new file mode 100644
index 00000000..8d560ce5
--- /dev/null
+++ b/src/app/intro/page.jsx
@@ -0,0 +1,14 @@
+import Intro from '@/components/Intro'
+import { initCheck } from '@/util/session-util'
+
+export default async function IntroPage() {
+ await initCheck()
+
+ return (
+ <>
+
+
+
+ >
+ )
+}
diff --git a/src/app/join/complete/page.jsx b/src/app/join/complete/page.jsx
new file mode 100644
index 00000000..3f9fc462
--- /dev/null
+++ b/src/app/join/complete/page.jsx
@@ -0,0 +1,19 @@
+'use client'
+
+import { useMessage } from '@/hooks/useMessage'
+
+export default function CompletePage() {
+ const { getMessage } = useMessage()
+
+ return (
+ <>
+
+
{getMessage('join.complete.title')}
+
{getMessage('join.complete.contents')}
+
+ {getMessage('join.complete.email_comment')} : {getMessage('join.complete.email')}
+
+
+ >
+ )
+}
diff --git a/src/app/join/page.jsx b/src/app/join/page.jsx
new file mode 100644
index 00000000..118a25b4
--- /dev/null
+++ b/src/app/join/page.jsx
@@ -0,0 +1,5 @@
+import Join from '@/components/auth/Join'
+
+export default function JoinPage() {
+ return <>{
}>
+}
diff --git a/src/app/layout.js b/src/app/layout.js
index 4d4a4f21..30a6e8ee 100644
--- a/src/app/layout.js
+++ b/src/app/layout.js
@@ -1,13 +1,19 @@
import { Inter } from 'next/font/google'
+import { headers } from 'next/headers'
+import { redirect } from 'next/navigation'
+import { getSession } from '@/lib/authActions'
import RecoilRootWrapper from './RecoilWrapper'
import UIProvider from './UIProvider'
import { ToastContainer } from 'react-toastify'
+import Header from '@/components/header/Header'
+import QModal from '@/components/common/modal/QModal'
+import { QcastProvider } from './QcastProvider'
+
import './globals.css'
import '../styles/style.scss'
-import Header from '@/components/header/Header'
const inter = Inter({ subsets: ['latin'] })
@@ -16,20 +22,33 @@ export const metadata = {
description: 'Generated by create next app',
}
-export default function RootLayout({ children }) {
+export default async function RootLayout({ children }) {
+ const headersList = headers()
+ const headerPathname = headersList.get('x-pathname') || ''
+
+ // console.log('headerPathname:', headerPathname)
+ // const isLoggedIn = await checkSession()
+ const session = await getSession()
+ console.log('session[layout]:', session)
+ if (!headerPathname.includes('/login') && !session.isLoggedIn) {
+ redirect('/login')
+ }
+
return (
{/*{headerPathname !== '/login' &&
}*/}
-
+
- {children}
+
+ {children}
+
- {/**/}
+
diff --git a/src/app/login/page.jsx b/src/app/login/page.jsx
new file mode 100644
index 00000000..0686da2e
--- /dev/null
+++ b/src/app/login/page.jsx
@@ -0,0 +1,9 @@
+import Login from '@/components/auth/Login'
+
+export default function LoginPage() {
+ return (
+ <>
+
+ >
+ )
+}
diff --git a/src/app/management/plan/page.jsx b/src/app/management/plan/page.jsx
new file mode 100644
index 00000000..5fefa62a
--- /dev/null
+++ b/src/app/management/plan/page.jsx
@@ -0,0 +1,16 @@
+import Hero from '@/components/Hero'
+import Plan from '@/components/management/Plan'
+import { initCheck } from '@/util/session-util'
+
+export default async function ManagementPlanPage() {
+ await initCheck()
+
+ return (
+ <>
+
+
+ >
+ )
+}
diff --git a/src/app/management/stuff/detail/page.jsx b/src/app/management/stuff/detail/page.jsx
new file mode 100644
index 00000000..6759b282
--- /dev/null
+++ b/src/app/management/stuff/detail/page.jsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import Hero from '@/components/Hero'
+import StuffDetail from '@/components/management/StuffDetail'
+import Link from 'next/link'
+export default function ManagementStuffDetailPage() {
+ return (
+ <>
+
+
물건정보
+
+ 도면작성
+
+
+
+
+
+ >
+ )
+}
diff --git a/src/app/management/stuff/page.jsx b/src/app/management/stuff/page.jsx
new file mode 100644
index 00000000..7590a7cf
--- /dev/null
+++ b/src/app/management/stuff/page.jsx
@@ -0,0 +1,21 @@
+import StuffSearchCondition from '@/components/management/StuffSearchCondition'
+import Stuff from '@/components/management/Stuff'
+import { initCheck } from '@/util/session-util'
+import Hero from '@/components/Hero'
+export default async function ManagementStuffPage() {
+ await initCheck()
+
+ return (
+ <>
+
+
+
+
+
+ >
+ )
+}
diff --git a/src/app/management/stuff/tempdetail/page.jsx b/src/app/management/stuff/tempdetail/page.jsx
new file mode 100644
index 00000000..8b84287a
--- /dev/null
+++ b/src/app/management/stuff/tempdetail/page.jsx
@@ -0,0 +1,15 @@
+import React from 'react'
+import Hero from '@/components/Hero'
+import StuffDetail from '@/components/management/StuffDetail'
+export default function ManagementStuffDetailPage() {
+ return (
+ <>
+
+
물건정보
+
+
+
+
+ >
+ )
+}
diff --git a/src/app/master/company/page.jsx b/src/app/master/company/page.jsx
new file mode 100644
index 00000000..15eda41c
--- /dev/null
+++ b/src/app/master/company/page.jsx
@@ -0,0 +1,16 @@
+import Hero from '@/components/Hero'
+import Company from '@/components/master/Company'
+import { initCheck } from '@/util/session-util'
+
+export default async function MasterCompanyPage() {
+ await initCheck()
+
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
diff --git a/src/app/master/price/page.jsx b/src/app/master/price/page.jsx
new file mode 100644
index 00000000..a641d6bb
--- /dev/null
+++ b/src/app/master/price/page.jsx
@@ -0,0 +1,16 @@
+import Hero from '@/components/Hero'
+import Price from '@/components/master/Price'
+import { initCheck } from '@/util/session-util'
+
+export default async function MasterPricePage() {
+ await initCheck()
+
+ return (
+ <>
+
+
+ >
+ )
+}
diff --git a/src/app/page.js b/src/app/page.js
index 9c905040..25cd8640 100644
--- a/src/app/page.js
+++ b/src/app/page.js
@@ -1,5 +1,16 @@
-import Main from '@/components/Main'
+import MainPage from '@/components/Main'
+import { getSession } from '@/lib/authActions'
-export default function Home() {
- return
+export default async function Home() {
+ const session = await getSession()
+
+ const mainPageProps = {
+ isLoggedIn: session?.isLoggedIn,
+ }
+
+ return (
+ <>
+
+ >
+ )
}
diff --git a/src/app/playground/page.jsx b/src/app/playground/page.jsx
new file mode 100644
index 00000000..66d83c34
--- /dev/null
+++ b/src/app/playground/page.jsx
@@ -0,0 +1,17 @@
+import Playground from '@/components/Playground'
+import { initCheck } from '@/util/session-util'
+
+export default async function PlaygroundPage() {
+ // const { session } = await checkSession()
+
+ // if (!session.isLoggedIn) {
+ // redirect('/login')
+ // }
+ await initCheck()
+
+ return (
+ <>
+
+ >
+ )
+}
diff --git a/src/app/roof/page.jsx b/src/app/roof/page.jsx
new file mode 100644
index 00000000..f5b8e611
--- /dev/null
+++ b/src/app/roof/page.jsx
@@ -0,0 +1,16 @@
+import Hero from '@/components/Hero'
+import Roof from '@/components/Roof'
+import { initCheck } from '@/util/session-util'
+
+export default async function RoofPage() {
+ await initCheck()
+
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
diff --git a/src/app/roof2/RoofSelect.jsx b/src/app/roof2/RoofSelect.jsx
new file mode 100644
index 00000000..d759398b
--- /dev/null
+++ b/src/app/roof2/RoofSelect.jsx
@@ -0,0 +1,128 @@
+'use client'
+
+import { Select, SelectItem } from '@nextui-org/react'
+import { useEffect, useState } from 'react'
+import { useAxios } from '@/hooks/useAxios'
+
+export default function RoofSelect() {
+ const [roofMaterials, setRoofMaterials] = useState([])
+ const [manufacturers, setManufacturers] = useState([])
+ const [trestles, setTrestles] = useState([])
+ const [modules, setModules] = useState([])
+ const [originTrestles, setOriginTrestles] = useState([])
+
+ const [roofMaterialId, setRoofMaterialId] = useState(null)
+ const [manufacturerId, setManufacturerId] = useState(null)
+ const [trestleId, setTrestleId] = useState(null)
+
+ const { get } = useAxios()
+
+ useEffect(() => {
+ get({ url: '/api/roof-material/roof-material-infos' }).then((res) => {
+ //TODO: error handling
+ if (!res) return
+
+ setRoofMaterials(res)
+ })
+ }, [])
+
+ useEffect(() => {
+ if (!roofMaterialId) {
+ return
+ }
+
+ get({ url: `/api/roof-material/roof-material-infos/${roofMaterialId}/trestles` }).then((res) => {
+ if (res.length === 0) {
+ return
+ }
+ setOriginTrestles(res)
+ const manufactural = res.map((trestle) => {
+ return { id: trestle.manufacturerId, name: trestle.manufacturerName }
+ })
+ // Remove duplicates
+ const uniqueManufactural = Array.from(new Set(manufactural.map((a) => a.id))).map((id) => {
+ return manufactural.find((a) => a.id === id)
+ })
+
+ setManufacturers(uniqueManufactural)
+ })
+ }, [roofMaterialId])
+
+ useEffect(() => {
+ if (!manufacturerId) {
+ return
+ }
+
+ const trestles = originTrestles.filter((trestle) => trestle.manufacturerId === manufacturerId)
+ setTrestles(trestles)
+ }, [manufacturerId])
+
+ useEffect(() => {
+ if (!trestleId) {
+ return
+ }
+ get({ url: `/api/module/module-infos?roofMaterialId=${roofMaterialId}&trestleId=${trestleId}` }).then((res) => {
+ if (res.length === 0) {
+ return
+ }
+ setModules(res)
+ })
+ }, [trestleId])
+
+ const handleRoofMaterialOnChange = (e) => {
+ const roofMaterialId = e.target.value
+ setRoofMaterialId(roofMaterialId)
+ setManufacturers([])
+ setManufacturerId(null)
+ setTrestleId(null)
+ setTrestles([])
+ setModules([])
+ }
+
+ const handleManufacturersOnChange = (e) => {
+ const manufacturerId = Number(e.target.value)
+ setTrestles([])
+ setManufacturerId(manufacturerId)
+ setTrestleId(null)
+ setModules([])
+ }
+
+ const handleTrestlesOnChange = (e) => {
+ const trestleId = Number(e.target.value)
+ setTrestleId(trestleId)
+ setModules([])
+ }
+
+ return (
+
+ {roofMaterials.length > 0 && (
+
+ )}
+ {manufacturers.length > 0 && (
+
+ )}
+ {trestles.length > 0 && (
+
+ )}
+ {modules.length > 0 && (
+
+ )}
+
+ )
+}
diff --git a/src/app/roof2/page.jsx b/src/app/roof2/page.jsx
new file mode 100644
index 00000000..72881d11
--- /dev/null
+++ b/src/app/roof2/page.jsx
@@ -0,0 +1,26 @@
+import Roof2 from '@/components/Roof2'
+import RoofSelect from '@/app/[locale]/roof2/RoofSelect'
+import { initCheck } from '@/util/session-util'
+
+export default async function Roof2Page() {
+ const session = await initCheck()
+ const roof2Props = {
+ name: session.name || '',
+ userId: session.userId || '',
+ email: session.email || '',
+ isLoggedIn: session.isLoggedIn,
+ }
+
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
diff --git a/src/app/settings/page.jsx b/src/app/settings/page.jsx
new file mode 100644
index 00000000..797c024c
--- /dev/null
+++ b/src/app/settings/page.jsx
@@ -0,0 +1,16 @@
+import Hero from '@/components/Hero'
+import Settings from '@/components/Settings'
+import { initCheck } from '@/util/session-util'
+
+export default async function SettingsPage() {
+ await initCheck()
+
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
diff --git a/src/common/common.js b/src/common/common.js
index aaba3f45..c78673ee 100644
--- a/src/common/common.js
+++ b/src/common/common.js
@@ -1,19 +1,22 @@
-export const STEP = {
+export const MENU = {
INITIAL_CANVAS_SETTING: 'initialCanvasSetting', // 배치면 초기설정
ROOF_COVERING: {
EXTERIOR_WALL_LINE: 'exteriorWallLine', // 외벽선 그리기
ROOF_SHAPE_SETTINGS: 'roofShapeSettings', // 지붕형상 설정
ROOF_SHAPE_EDITING: 'roofShapeEditing', // 지붕형상 편집
HELP_LINE_DRAWING: 'helpLineDrawing', // 보조선 그리기
+ DEFAULT: 'roofCoveringDefault', // 아무것도 선택 안할 경우
}, // 지붕덮개
BATCH_CANVAS: {
BATCH_DRAWING: 'batchDrawing', // 배치면 그리기
SURFACE_SHAPE_BATCH: 'surfaceShapeBatch', // 면형상 배치
OBJECT_BATCH: 'objectBatch', // 오브젝트 배치
+ DEFAULT: 'batchCanvasDefault', // default
}, // 배치면
MODULE_CIRCUIT_SETTING: {
BASIC_SETTING: 'basicSetting', // 기본설정
CIRCUIT_TRESTLE_SETTING: 'circuitTrestleSetting', // 회로가대설정
+ DEFAULT: 'moduleCircuitSettingDefault',
}, // 모듈회로구성
ESTIMATE: 'estimate', // todo 견적서
POWER_GENERATION_SIMULATION: 'powerGenerationSimulation', // todo 발전 시뮬레이션
diff --git a/src/components/Main.jsx b/src/components/Main.jsx
index 224ce1ea..4546f32d 100644
--- a/src/components/Main.jsx
+++ b/src/components/Main.jsx
@@ -1,62 +1,9 @@
'use client'
-import { logout } from '@/lib/authActions'
-import { useChangeLocale, useI18n } from '@/locales/client'
-import { Button, Chip } from '@nextui-org/react'
-import Link from 'next/link'
-
export default function MainPage(props) {
- const { currentLocale, isLoggedIn } = props
- const t = useI18n()
- const changeLocale = useChangeLocale()
-
- const handleChangeLocale = () => {
- currentLocale === 'ja' ? changeLocale('ko') : changeLocale('ja')
- }
-
- // console.log('MainPage', currentLocale)
-
- const handleLogout = async () => {
- await logout()
- }
-
return (
<>
-
{t('locale', { locale: {currentLocale} })}
-
{t('hello')}
-
{t('welcome', { name: '효준' })}
-
-
-
- {isLoggedIn && (
-
-
-
- )}
- {!isLoggedIn && (
-
-
-
-
-
- )}
-
font-test
- {/*
{t('locale', { locale: {currentLocale} })}
*/}
- {/*
{t('hello')}
*/}
- {/*
{t('welcome', { name: '효준' })}
*/}
- {/*
*/}
- {/* */}
- {/*
*/}
- {/*{isLoggedIn && (*/}
- {/*
*/}
- {/* */}
- {/*
*/}
- {/*)}*/}
- {/*
font-test
*/}
+
Main page
>
)
}
diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx
index f57f62ae..8e326c7f 100644
--- a/src/components/Roof2.jsx
+++ b/src/components/Roof2.jsx
@@ -42,6 +42,7 @@ import { SurfaceShapeModal } from '@/components/ui/SurfaceShape'
import { changeAllGableRoof, drawDirectionStringToArrow } from '@/util/qpolygon-utils'
import ThumbnailList from '@/components/ui/ThumbnailLIst'
import ObjectPlacement from '@/components/ui/ObjectPlacement'
+import { globalLocaleStore } from '@/store/localeAtom'
export default function Roof2(props) {
const { name, userId, email, isLoggedIn } = props
@@ -58,7 +59,9 @@ export default function Roof2(props) {
setBackImg,
} = useCanvas('canvas')
- const { get } = useAxios()
+ const globalLocaleState = useRecoilValue(globalLocaleStore)
+
+ const { get } = useAxios(globalLocaleState)
const canvasRef = useRef(null)
diff --git a/src/components/auth/Login.jsx b/src/components/auth/Login.jsx
index 44d163a0..d71870e2 100644
--- a/src/components/auth/Login.jsx
+++ b/src/components/auth/Login.jsx
@@ -1,6 +1,7 @@
'use client'
-import { post, patch } from '@/lib/Axios'
+import { useState } from 'react'
+import { useAxios } from '@/hooks/useAxios'
import { setSession } from '@/lib/authActions'
import { redirect } from 'next/navigation'
import { useMessage } from '@/hooks/useMessage'
@@ -9,10 +10,10 @@ import { Button, Switch } from '@nextui-org/react'
import { useRecoilState } from 'recoil'
import { globalLocaleStore } from '@/store/localeAtom'
import { modalContent, modalState } from '@/store/modalAtom'
-import { useState } from 'react'
-export default function Login(props) {
- const { currentLocale } = props
+export default function Login() {
+ const { patch } = useAxios()
+
const { getMessage } = useMessage()
const [globalLocaleState, setGlbalLocaleState] = useRecoilState(globalLocaleStore)
const [isSelected, setIsSelected] = useState(globalLocaleState === 'ko' ? true : false)
diff --git a/src/components/common/draggable/withDraggable.jsx b/src/components/common/draggable/withDraggable.jsx
index 9f322583..b6c2920b 100644
--- a/src/components/common/draggable/withDraggable.jsx
+++ b/src/components/common/draggable/withDraggable.jsx
@@ -1,15 +1,19 @@
'use client'
-import { useState } from 'react'
+import { useEffect, useState } from 'react'
import Draggable from 'react-draggable'
-export default function WithDraggable({ isShow, children }) {
+export default function WithDraggable({ isShow, children, pos }) {
const [position, setPosition] = useState({ x: 0, y: 0 })
const handleOnDrag = (data) => {
setPosition({ x: data.x, y: data.y })
}
+ useEffect(() => {
+ setPosition({ ...pos })
+ }, [])
+
return (
<>
{isShow && (
diff --git a/src/components/common/select/QSelectBox.jsx b/src/components/common/select/QSelectBox.jsx
index 6e77a539..bcc0979d 100644
--- a/src/components/common/select/QSelectBox.jsx
+++ b/src/components/common/select/QSelectBox.jsx
@@ -1,16 +1,22 @@
'use client'
import { useState } from 'react'
-export default function QSelectBox({ title, option }) {
- const [selectAct, setSelectAct] = useState(false)
+export default function QSelectBox({ title = '', options, onChange }) {
+ const [openSelect, setOpenSelect] = useState(false)
+ const [selected, setSelected] = useState(title === '' ? options[0].name : title)
+
+ const handleClickSelectOption = (option) => {
+ setSelected(option.name)
+ onChange?.(option)
+ }
return (
-
setSelectAct(!selectAct)}>
-
{title}
+
setOpenSelect(!openSelect)}>
+
{selected}
- {option.map((el, idx) => (
- -
-
+ {options?.map((option) => (
+
-
+
))}
diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx
index 5be6a114..9990aa21 100644
--- a/src/components/floor-plan/CanvasLayout.jsx
+++ b/src/components/floor-plan/CanvasLayout.jsx
@@ -1,45 +1,53 @@
'use client'
-import { useState } from "react"
-import CanvasFrame from "./CanvasFrame";
+import { useEffect, useState } from 'react'
+import CanvasFrame from './CanvasFrame'
+import { useRecoilState, useRecoilValue } from 'recoil'
+import { currentMenuState, stepState } from '@/store/canvasAtom'
-export default function CanvasLayout () {
- const [plans, setPlans] = useState([{ id: 0, name: 'Plan 1' }, { id: 1, name: 'Plan 2' }, { id: 2, name: 'Plan 3' }]);
- const [idxNum, setIdxNum] = useState(null);
+export default function CanvasLayout() {
+ const [plans, setPlans] = useState([
+ { id: 0, name: 'Plan 1', isCurrent: false },
+ { id: 1, name: 'Plan 2', isCurrent: false },
+ { id: 2, name: 'Plan 3', isCurrent: false },
+ ])
+ const [idxNum, setIdxNum] = useState(null)
- const onClickPlane = (num) => {
- setIdxNum(num);
+ const onClickPlane = (num) => {
+ setIdxNum(num)
+ }
+
+ const handleDeletePlan = (e, id) => {
+ e.stopPropagation() // 이벤트 버블링 방지
+ setPlans(plans.filter((plan) => plan.id !== id)) // 삭제할 아이디와 다른 아이템만 남김
+ }
+
+ const addNewPlan = () => {
+ setPlans([...plans, { id: plans.length, name: `Plan ${plans.length + 1}` }])
+ }
+
+ useEffect(() => {
+ if (plans.length === 1) {
+ setPlans([{ id: 0, name: 'Plan 1', isCurrent: false }])
}
+ }, [])
- const handleDeletePlan = (e, id) => {
- e.stopPropagation(); // 이벤트 버블링 방지
- setPlans(plans.filter(plan => plan.id !== id)); // 삭제할 아이디와 다른 아이템만 남김
- }
-
- const addNewPlan = () => {
- setPlans([...plans, { id: plans.length, name: `Plan ${plans.length + 1}` }]);
- }
-
- return(
-
-
-
- {plans.map((plan, idx) => (
-
- ))}
-
-
-
-
+ return (
+
+
+
+ {plans.map((plan, idx) => (
+
+ ))}
- )
-}
\ No newline at end of file
+
+
+
+
+ )
+}
diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx
index 45896d96..c916a0fc 100644
--- a/src/components/floor-plan/CanvasMenu.jsx
+++ b/src/components/floor-plan/CanvasMenu.jsx
@@ -1,23 +1,96 @@
'use client'
-import { useState } from 'react'
+
+import { useEffect, useState } from 'react'
import MenuDepth01 from './MenuDepth01'
-import { useRecoilState } from 'recoil'
-import { modalState } from '@/store/modalAtom'
import QSelectBox from '@/components/common/select/QSelectBox'
import { useMessage } from '@/hooks/useMessage'
+import { post } from '@/lib/Axios'
+import { useRecoilState, useRecoilValue } from 'recoil'
+import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
+import { canvasZoomState, verticalHorizontalModeState } from '@/store/canvasAtom'
-export default function CanvasMenu() {
- const [modalOption, setModalOption] = useRecoilState(modalState) //modal 열림닫힘 state
+export default function CanvasMenu(props) {
+ const [objectNo] = useState('test123240912001') // 이후 삭제 필요
+ const { setShowCanvasSettingModal, showOutlineModal, setShowOutlineModal } = props
const [menuNumber, setMenuNumber] = useState(null)
+ const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
const [vertical, setVertical] = useState(true)
+ const [type, setType] = useState('')
const { getMessage } = useMessage()
+ const canvasZoom = useRecoilValue(canvasZoomState)
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
const onClickNav = (number) => {
setMenuNumber(number)
- if (menuNumber === number) {
- setMenuNumber(null)
+ if (number === 2) setType('outline')
+ if (number === 3) setType('surface')
+ if (number === 4) setType('module')
+ }
+ const menuProps = {
+ setShowOutlineModal,
+ type,
+ }
+
+ const firstOptions = useRecoilState(settingModalFirstOptionsState)
+ const secondOptions = useRecoilState(settingModalSecondOptionsState)
+
+ useEffect(() => {}, [menuNumber, type])
+
+ // 저장버튼(btn08) 클릭 시 호출되는 함수
+ const handleSaveSettings = async () => {
+ try {
+ // 서버에 전송할 데이터
+ const dataToSend = {
+ firstOption1: firstOptions[0].option1.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ firstOption2: firstOptions[0].option2.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ // secondOption1: secondOptions[0].option1.map((item) => ({
+ // name: item.name,
+ // // 필요한 경우 추가 데이터 항목
+ // })),
+ secondOption2: secondOptions[0].option2.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ }
+
+ const patternData = {
+ objectNo,
+ assignDisplay: dataToSend.firstOption1[0].selected,
+ drawDisplay: dataToSend.firstOption1[1].selected,
+ gridDisplay: dataToSend.firstOption1[2].selected,
+ charDisplay: dataToSend.firstOption1[3].selected,
+ flowDisplay: dataToSend.firstOption1[4].selected,
+ hallwayDimenDisplay: dataToSend.firstOption1[5].selected,
+ actualDimenDisplay: dataToSend.firstOption1[6].selected,
+ noDimenDisplay: dataToSend.firstOption1[7].selected,
+ trestleDisplay: dataToSend.firstOption1[8].selected,
+ coordiDisplay: dataToSend.firstOption1[9].selected,
+ drawConverDisplay: dataToSend.firstOption1[10].selected,
+ onlyBorder: dataToSend.firstOption2[0].selected,
+ lineHatch: dataToSend.firstOption2[1].selected,
+ allPainted: dataToSend.firstOption2[2].selected,
+ adsorpRangeSmall: dataToSend.secondOption2[0].selected,
+ adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
+ adsorpRangeMedium: dataToSend.secondOption2[2].selected,
+ adsorpRangeLarge: dataToSend.secondOption2[3].selected,
+ }
+
+ // HTTP POST 요청 보내기
+ await post({ url: `/api/canvas-management/canvas-settings`, data: patternData })
+
+ // 응답 처리
+ alert('설정이 저장되었습니다.')
+ } catch (error) {
+ console.error('설정을 저장하는 동안 오류가 발생했습니다:', error)
+ alert('설정을 저장하는 중 오류가 발생했습니다.')
}
}
+
return (
@@ -37,13 +110,12 @@ export default function CanvasMenu() {
{
- setModalOption({ ...modalOption, outerwall: true })
onClickNav(2)
}}
>
onClickNav(3)}>
@@ -79,26 +151,28 @@ export default function CanvasMenu() {
-
- {getMessage('plan.mode.vertical.horizontal')}
-
-
+ {menuNumber !== 4 && (
+
+ {getMessage('plan.mode.vertical.horizontal')}
+
+
+ )}
-
+
- 100%
+ {canvasZoom}%
-
+
>
@@ -143,9 +217,7 @@ export default function CanvasMenu() {
- {menuNumber === 2 && }
- {menuNumber === 3 && }
- {menuNumber === 4 && }
+ {(menuNumber === 2 || menuNumber === 3 || menuNumber === 4) && }
)
diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx
index 1577227d..33e522ee 100644
--- a/src/components/floor-plan/FloorPlan.jsx
+++ b/src/components/floor-plan/FloorPlan.jsx
@@ -4,20 +4,42 @@ import CanvasMenu from '@/components/floor-plan/CanvasMenu'
import SettingModal01 from '@/components/floor-plan/modal/setting01/SettingModal01'
import CanvasLayout from '@/components/floor-plan/CanvasLayout'
import '@/styles/contents.scss'
-import { modalState } from '@/store/modalAtom'
-import { useRecoilValue } from 'recoil'
import OuterLineWall from '@/components/floor-plan/modal/outerlinesetting/OuterLineWall'
+import { useEffect, useState } from 'react'
+import { globalLocaleStore } from '@/store/localeAtom'
+import { useRecoilValue } from 'recoil'
+import { useAxios } from '@/hooks/useAxios'
export default function FloorPlan() {
- const modalOption = useRecoilValue(modalState)
+ const [showCanvasSettingModal, setShowCanvasSettingModal] = useState(false)
+ const [showOutlineModal, setShowOutlineModal] = useState(false)
+ const globalLocaleState = useRecoilValue(globalLocaleStore)
+ const { get } = useAxios(globalLocaleState)
+
+ const canvasSettingProps = {
+ setShowCanvasSettingModal,
+ }
+
+ const outlineProps = {
+ setShowOutlineModal,
+ }
+
+ const modalProps = {
+ setShowCanvasSettingModal,
+ showOutlineModal,
+ setShowOutlineModal,
+ }
+
+ useEffect(() => {}, [showOutlineModal])
+
return (
<>
-
+
- {modalOption.option && }
- {modalOption.outerwall && }
+ {showCanvasSettingModal && }
+ {showOutlineModal && }
>
diff --git a/src/components/floor-plan/MenuDepth01.jsx b/src/components/floor-plan/MenuDepth01.jsx
index ce4bd6a4..cf0ad1e8 100644
--- a/src/components/floor-plan/MenuDepth01.jsx
+++ b/src/components/floor-plan/MenuDepth01.jsx
@@ -2,33 +2,63 @@
import { ToggleonMouse } from '@/components/header/Header'
import { useMessage } from '@/hooks/useMessage'
+import { useEffect, useState } from 'react'
-export default function MenuDepth01() {
+export default function MenuDepth01(props) {
+ const { setShowOutlineModal, type } = props
const { getMessage } = useMessage()
+ const [activeMenu, setActiveMenu] = useState()
+ const onClickMenu = (menuNum) => {
+ setActiveMenu(menuNum)
+ setShowOutlineModal(menuNum === 0)
+ }
+
+ const menus = [
+ { id: 0, name: '外壁線を描' },
+ { id: 1, name: '補助線を描' },
+ { id: 2, name: '屋根形状設定' },
+ { id: 3, name: '軒下変更' },
+ { id: 4, name: '外壁線の上げ下げ' },
+ { id: 5, name: '銅線移動' },
+ { id: 6, name: '特殊コーナー形状' },
+ ]
+
+ const menuInfo = {
+ outline: [
+ // 지붕덮개
+ { id: 0, name: 'plan.menu.roof.cover.outline.drawing' },
+ { id: 1, name: 'plan.menu.roof.cover.roof.shape.setting' },
+ { id: 2, name: 'plan.menu.roof.cover.roof.shape.edit' },
+ { id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing' },
+ ],
+ surface: [
+ // 배치면
+ { id: 0, name: 'plan.menu.placement.surface.drawing' },
+ { id: 1, name: 'plan.menu.placement.surface.surface' },
+ { id: 2, name: 'plan.menu.placement.surface.object' },
+ ],
+ module: [
+ // 모듈, 회로 구성
+ { id: 0, name: 'plan.menu.module.circuit.setting.default' },
+ { id: 1, name: 'plan.menu.module.circuit.setting.circuit.trestle.setting' },
+ ],
+ }
+
+ useEffect(() => {
+ menus.forEach((menu) => {
+ menu.isActive = menu.id === activeMenu
+ })
+ }, [menus, activeMenu])
return (
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
+ {menuInfo[type].map((menu) => {
+ return (
+ -
+
+
+ )
+ })}
- ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
diff --git a/src/components/floor-plan/RoofCoveringMenu.jsx b/src/components/floor-plan/RoofCoveringMenu.jsx
new file mode 100644
index 00000000..26da4bda
--- /dev/null
+++ b/src/components/floor-plan/RoofCoveringMenu.jsx
@@ -0,0 +1,54 @@
+'use client'
+
+import { useMessage } from '@/hooks/useMessage'
+import { useRecoilState, useSetRecoilState } from 'recoil'
+import { currentMenuState } from '@/store/canvasAtom'
+import { MENU } from '@/common/common'
+import { modalState } from '@/store/modalAtom'
+import { ToggleonMouse } from '@/components/header/Header'
+
+export default function RoofCoveringMenu() {
+ const { getMessage } = useMessage()
+ const [currentMenu, setCurrentMenu] = useRecoilState(currentMenuState)
+
+ const setModalState = useSetRecoilState(modalState)
+
+ const onClickNav = (menu) => {
+ setCurrentMenu(menu)
+ if (menu === MENU.ROOF_COVERING.EXTERIOR_WALL_LINE) {
+ setModalState((prev) => ({ ...prev, outerwall: true }))
+ } else {
+ setModalState((prev) => ({ ...prev, outerwall: false }))
+ }
+ }
+
+ return (
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ - ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
+
+
+ - ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
+
+
+ - ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
+
+
+
+
+ )
+}
diff --git a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx
index 1ba1c597..05d7cb0c 100644
--- a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx
+++ b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx
@@ -1,68 +1,561 @@
'use client'
-import { useState } from 'react'
+import { useEffect, useRef } from 'react'
import WithDraggable from '@/components/common/draggable/withDraggable'
-import { modalState } from '@/store/modalAtom'
-import { useRecoilState } from 'recoil'
+import { useRecoilState, useRecoilValue } from 'recoil'
import { useMessage } from '@/hooks/useMessage'
+import { useEvent } from '@/hooks/useEvent'
+import { canvasState, verticalHorizontalModeState } from '@/store/canvasAtom'
+import {
+ OUTER_LINE_TYPE,
+ outerLineArrow1State,
+ outerLineArrow2State,
+ outerLineLength1State,
+ outerLineLength2State,
+ outerLinePointsState,
+ outerLineTypeState,
+} from '@/store/outerLineAtom'
+import { QLine } from '@/components/fabric/QLine'
+import { useLine } from '@/hooks/useLine'
+import { distanceBetweenPoints } from '@/util/canvas-util'
-export default function OuterLineWall() {
- const [modalOption, setModalOption] = useRecoilState(modalState) //modal 열림닫힘 state
- const [buttonAct, setButtonAct] = useState(1)
- const [close, setClose] = useState(false)
+export default function OuterLineWall(props) {
+ const { setShowOutlineModal } = props
const { getMessage } = useMessage()
- const HandleClickClose = () => {
- setClose(true)
- setTimeout(() => {
- setModalOption({ ...modalOption, outerwall: false })
- setClose(false)
- }, 180)
+ const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners } = useEvent()
+ const { addLineText, removeLineText } = useLine()
+ const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
+
+ const length1Ref = useRef(null)
+ const length2Ref = useRef(null)
+ const [length1, setLength1] = useRecoilState(outerLineLength1State)
+ const [length2, setLength2] = useRecoilState(outerLineLength2State)
+ const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State)
+ const [arrow2, setArrow2] = useRecoilState(outerLineArrow2State)
+ const [points, setPoints] = useRecoilState(outerLinePointsState)
+ const [type, setType] = useRecoilState(outerLineTypeState)
+ const arrow1Ref = useRef(arrow1)
+ const arrow2Ref = useRef(arrow2)
+
+ const canvas = useRecoilValue(canvasState)
+
+ useEffect(() => {
+ removeAllMouseEventListeners()
+ addCanvasMouseEventListener('mouse:down', mouseDown)
+ }, [verticalHorizontalMode, points])
+
+ useEffect(() => {
+ arrow1Ref.current = arrow1
+ }, [arrow1])
+
+ useEffect(() => {
+ arrow2Ref.current = arrow2
+ }, [arrow2])
+
+ useEffect(() => {
+ removeAllDocumentEventListeners()
+ addDocumentEventListener('keydown', document, keydown[type])
+ clear()
+ }, [type])
+
+ const clear = () => {
+ setLength1(0)
+ setLength2(0)
+
+ setArrow1('')
+ setArrow2('')
+ }
+
+ const mouseDown = (e) => {
+ const pointer = canvas.getPointer(e.e)
+ if (points.length === 0) {
+ setPoints((prev) => [...prev, pointer])
+ } else {
+ const lastPoint = points[points.length - 1]
+ let newPoint = { x: pointer.x, y: pointer.y }
+ const length = distanceBetweenPoints(lastPoint, newPoint)
+ if (verticalHorizontalMode) {
+ const vector = {
+ x: pointer.x - points[points.length - 1].x,
+ y: pointer.y - points[points.length - 1].y,
+ }
+ const slope = Math.abs(vector.y / vector.x) // 기울기 계산
+
+ let scaledVector
+ if (slope >= 1) {
+ // 기울기가 1 이상이면 x축 방향으로 그림
+ scaledVector = {
+ x: 0,
+ y: vector.y >= 0 ? Number(length) : -Number(length),
+ }
+ } else {
+ // 기울기가 1 미만이면 y축 방향으로 그림
+ scaledVector = {
+ x: vector.x >= 0 ? Number(length) : -Number(length),
+ y: 0,
+ }
+ }
+
+ const verticalLength = scaledVector.y
+ const horizontalLength = scaledVector.x
+
+ newPoint = {
+ x: lastPoint.x + horizontalLength,
+ y: lastPoint.y + verticalLength,
+ }
+ }
+ setPoints((prev) => [...prev, newPoint])
+ }
+ }
+
+ useEffect(() => {
+ canvas
+ ?.getObjects()
+ .filter((obj) => obj.name === 'outerLine')
+ .forEach((obj) => {
+ canvas?.remove(obj)
+ removeLineText(obj)
+ })
+
+ canvas
+ ?.getObjects()
+ .filter((obj) => obj.name === 'helpGuideLine' || (obj.name === 'lengthTxt' && obj.parent?.name === 'helpGuideLine'))
+ .forEach((obj) => canvas?.remove(obj))
+
+ canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'startPoint'))
+
+ // point가 변경 될때마다 이벤트 리스너를 제거하고 다시 등록
+ removeAllDocumentEventListeners()
+ addDocumentEventListener('keydown', document, keydown[type])
+
+ if (points.length === 0) {
+ return
+ }
+
+ if (points.length === 1) {
+ const point = new fabric.Circle({
+ radius: 5,
+ fill: 'transparent',
+ stroke: 'red',
+ left: points[0].x - 5,
+ top: points[0].y - 5,
+ selectable: false,
+ name: 'startPoint',
+ })
+
+ canvas?.add(point)
+ } else {
+ points.forEach((point, idx) => {
+ if (idx === 0) {
+ return
+ }
+ drawLine(points[idx - 1], point, idx)
+ })
+
+ const lastPoint = points[points.length - 1]
+ const firstPoint = points[0]
+
+ if (points.length < 3) {
+ return
+ }
+
+ if (lastPoint.x === firstPoint.x && lastPoint.y === firstPoint.y) {
+ return
+ }
+
+ if (lastPoint.x === firstPoint.x || lastPoint.y === firstPoint.y) {
+ const line = new QLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], {
+ stroke: 'grey',
+ strokeWidth: 1,
+ selectable: false,
+ name: 'helpGuideLine',
+ })
+
+ canvas?.add(line)
+ addLineText(line)
+ } else {
+ const guideLine1 = new QLine([lastPoint.x, lastPoint.y, lastPoint.x, firstPoint.y], {
+ stroke: 'grey',
+ strokeWidth: 1,
+ strokeDashArray: [1, 1, 1],
+ name: 'helpGuideLine',
+ })
+
+ const guideLine2 = new QLine([guideLine1.x2, guideLine1.y2, firstPoint.x, firstPoint.y], {
+ stroke: 'grey',
+ strokeWidth: 1,
+ strokeDashArray: [1, 1, 1],
+ name: 'helpGuideLine',
+ })
+ if (guideLine1.length > 0) {
+ canvas?.add(guideLine1)
+ addLineText(guideLine1)
+ }
+
+ canvas?.add(guideLine2)
+
+ addLineText(guideLine2)
+ }
+ }
+ }, [points])
+
+ const drawLine = (point1, point2, idx) => {
+ const line = new QLine([point1.x, point1.y, point2.x, point2.y], {
+ stroke: 'black',
+ strokeWidth: 3,
+ idx: idx,
+ selectable: false,
+ name: 'outerLine',
+ })
+
+ canvas?.add(line)
+ addLineText(line)
+ }
+
+ // 직각 완료될 경우 확인
+ const checkRightAngle = () => {
+ const length1Num = Number(length1Ref.current.value) / 10
+ const length2Num = Number(length2Ref.current.value) / 10
+
+ if (points.length === 0) {
+ return
+ }
+
+ if (length1Num === 0 || length2Num === 0 || arrow1Ref.current === '' || arrow2Ref.current === '') {
+ return
+ }
+
+ if (arrow1Ref.current === '↓' && arrow2Ref.current === '→') {
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[prev.length - 1].x + length2Num, y: prev[prev.length - 1].y + length1Num }]
+ })
+ } else if (arrow1Ref.current === '↓' && arrow2Ref.current === '←') {
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[prev.length - 1].x - length2Num, y: prev[prev.length - 1].y + length1Num }]
+ })
+ } else if (arrow1Ref.current === '↑' && arrow2Ref.current === '→') {
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[prev.length - 1].x + length2Num, y: prev[prev.length - 1].y - length1Num }]
+ })
+ } else if (arrow1Ref.current === '↑' && arrow2Ref.current === '←') {
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[prev.length - 1].x - length2Num, y: prev[prev.length - 1].y - length1Num }]
+ })
+ } else if (arrow1Ref.current === '→' && arrow2Ref.current === '↓') {
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[prev.length - 1].x + length1Num, y: prev[prev.length - 1].y + length2Num }]
+ })
+ } else if (arrow1Ref.current === '→' && arrow2Ref.current === '↑') {
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[prev.length - 1].x + length1Num, y: prev[prev.length - 1].y - length2Num }]
+ })
+ } else if (arrow1Ref.current === '←' && arrow2Ref.current === '↓') {
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[prev.length - 1].x - length1Num, y: prev[prev.length - 1].y + length2Num }]
+ })
+ } else if (arrow1Ref.current === '←' && arrow2Ref.current === '↑') {
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[prev.length - 1].x - length1Num, y: prev[prev.length - 1].y - length2Num }]
+ })
+ }
+ }
+
+ const keydown = {
+ outerLine: (e) => {
+ if (points.length === 0) {
+ return
+ }
+ const key = e.key
+
+ if (!length1Ref.current) {
+ return
+ }
+
+ const lengthNum = Number(length1Ref.current.value) / 10
+ if (lengthNum === 0) {
+ return
+ }
+ switch (key) {
+ case 'Down': // IE/Edge에서 사용되는 값
+ case 'ArrowDown': {
+ setArrow1('↓')
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[prev.length - 1].x, y: prev[prev.length - 1].y + lengthNum }]
+ })
+ break
+ }
+ case 'Up': // IE/Edge에서 사용되는 값
+ case 'ArrowUp':
+ setArrow1('↑')
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[prev.length - 1].x, y: prev[prev.length - 1].y - lengthNum }]
+ })
+ break
+ case 'Left': // IE/Edge에서 사용되는 값
+ case 'ArrowLeft':
+ setArrow1('←')
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[prev.length - 1].x - lengthNum, y: prev[prev.length - 1].y }]
+ })
+ break
+ case 'Right': // IE/Edge에서 사용되는 값
+ case 'ArrowRight':
+ setArrow1('→')
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[prev.length - 1].x + lengthNum, y: prev[prev.length - 1].y }]
+ })
+ break
+ }
+ },
+ rightAngle: (e) => {
+ if (points.length === 0) {
+ return
+ }
+ const key = e.key
+
+ const activeElem = document.activeElement
+
+ switch (key) {
+ case 'Down': // IE/Edge에서 사용되는 값
+ case 'ArrowDown': {
+ if (activeElem === length1Ref.current) {
+ setArrow1('↓')
+ arrow1Ref.current = '↓'
+ length2Ref.current.focus()
+ } else if (activeElem === length2Ref.current) {
+ if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') {
+ break
+ }
+ setArrow2('↓')
+ arrow2Ref.current = '↓'
+ checkRightAngle()
+ }
+
+ break
+ }
+ case 'Up': // IE/Edge에서 사용되는 값
+ case 'ArrowUp':
+ if (activeElem === length1Ref.current) {
+ setArrow1('↑')
+ arrow1Ref.current = '↑'
+ length2Ref.current.focus()
+ } else if (activeElem === length2Ref.current) {
+ if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') {
+ break
+ }
+ setArrow2('↑')
+ arrow2Ref.current = '↑'
+ checkRightAngle()
+ }
+
+ break
+ case 'Left': // IE/Edge에서 사용되는 값
+ case 'ArrowLeft':
+ if (activeElem === length1Ref.current) {
+ setArrow1('←')
+ arrow1Ref.current = '←'
+ length2Ref.current.focus()
+ } else if (activeElem === length2Ref.current) {
+ if (arrow1Ref.current === '←' || arrow1Ref.current === '→') {
+ break
+ }
+ setArrow2('←')
+ arrow2Ref.current = '←'
+ checkRightAngle()
+ }
+
+ break
+ case 'Right': // IE/Edge에서 사용되는 값
+ case 'ArrowRight':
+ if (activeElem === length1Ref.current) {
+ setArrow1('→')
+ arrow1Ref.current = '→'
+ length2Ref.current.focus()
+ } else if (activeElem === length2Ref.current) {
+ if (arrow1Ref.current === '←' || arrow1Ref.current === '→') {
+ break
+ }
+ setArrow2('→')
+ arrow2Ref.current = '→'
+ checkRightAngle()
+ }
+
+ break
+ }
+ },
+ leeGubae: (e) => {
+ console.log('leegubae')
+ },
+ angle: (e) => {
+ console.log('angle')
+ },
+ diagonalLine: (e) => {
+ console.log('diagonalLine')
+ },
+ }
+
+ /**
+ * 일변전으로 돌아가기
+ */
+ const handleRollback = () => {
+ //points의 마지막 요소를 제거
+ setPoints((prev) => prev.slice(0, prev.length - 1))
+ }
+
+ const handleFix = () => {
+ if (points.length < 3) {
+ return
+ }
+ setPoints((prev) => {
+ if (prev.length === 0) {
+ return []
+ }
+ return [...prev, { x: prev[0].x, y: prev[0].y }]
+ })
}
return (
-
-
+
+
{getMessage('modal.cover.outline.drawing')}
-
- setButtonAct(1)}>
+ setType(OUTER_LINE_TYPE.OUTER_LINE)}
+ >
{getMessage('modal.cover.outline')}
- setButtonAct(2)}>
+ setType(OUTER_LINE_TYPE.RIGHT_ANGLE)}
+ >
{getMessage('modal.cover.outline.right.angle')}
- setButtonAct(3)}>
+ setType(OUTER_LINE_TYPE.LEE_GUBAE)}
+ >
{getMessage('modal.cover.outline2')}
- setButtonAct(4)}>
+ setType(OUTER_LINE_TYPE.ANGLE)}>
{getMessage('modal.cover.outline.angle')}
- setButtonAct(5)}>
+ setType(OUTER_LINE_TYPE.DIAGONAL_LINE)}
+ >
{getMessage('modal.cover.outline.diagonal')}
{getMessage('modal.cover.outline.setting')}
-
-
-
-
+ {type === OUTER_LINE_TYPE.OUTER_LINE ? (
+
-
-
-
+ ) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? (
+
-
+ ) : (
+ <>>
+ )}
-
+ = 3 ? 'act' : ''}`} onClick={handleFix}>
{getMessage('modal.cover.outline.fix')}
-
+ = 1 ? 'act' : ''}`} onClick={handleRollback}>
{getMessage('modal.cover.outline.rollback')}
diff --git a/src/components/floor-plan/modal/setting01/FirstOption.jsx b/src/components/floor-plan/modal/setting01/FirstOption.jsx
index cddab6c0..8c292a05 100644
--- a/src/components/floor-plan/modal/setting01/FirstOption.jsx
+++ b/src/components/floor-plan/modal/setting01/FirstOption.jsx
@@ -1,11 +1,61 @@
import { useRecoilState } from 'recoil'
import { settingModalFirstOptionsState } from '@/store/settingAtom'
import { useMessage } from '@/hooks/useMessage'
+import React, { useEffect, useState } from 'react'
+import { get } from '@/lib/Axios'
export default function FirstOption() {
+ const [objectNo] = useState('test123240912001') // 이후 삭제 필요
const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalFirstOptionsState)
const { option1, option2 } = settingsModalOptions
const { getMessage } = useMessage()
+
+ const [isFetched, setIsFetched] = useState(false) // 조회 여부 상태
+
+ // 데이터를 최초 한 번만 조회
+ useEffect(() => {
+ console.log('FirstOption useEffect 실행')
+ if (!isFetched) {
+ // 조회가 안 되었을 때만 fetchSettings 실행
+ fetchSettings()
+ }
+ }, [isFetched]) // isFetched 상태가 변할 때마다 확인
+
+ // Canvas Setting 조회 및 초기화
+ const fetchSettings = async () => {
+ try {
+ const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
+
+ const options1 = [
+ 'assignDisplay',
+ 'drawDisplay',
+ 'gridDisplay',
+ 'charDisplay',
+ 'flowDisplay',
+ 'hallwayDimenDisplay',
+ 'actualDimenDisplay',
+ 'noDimenDisplay',
+ 'trestleDisplay',
+ 'coordiDisplay',
+ 'drawConverDisplay',
+ ]
+ const option1 = settingsModalOptions.option1.map((item, index) => ({ ...item, selected: res[options1[index]] }))
+
+ const options2 = ['onlyBorder', 'lineHatch', 'allPainted']
+ const option2 = settingsModalOptions.option2.map((item, index) => ({ ...item, selected: res[options2[index]] }))
+
+ // 데이터 설정
+ setSettingModalOptions({
+ option1,
+ option2,
+ })
+
+ setIsFetched(true) // 조회가 완료되면 isFetched를 true로 설정
+ } catch (error) {
+ console.error('Data fetching error:', error)
+ }
+ }
+
const onClickOption = (option) => {
option.selected = !option.selected
diff --git a/src/components/floor-plan/modal/setting01/SecondOption.jsx b/src/components/floor-plan/modal/setting01/SecondOption.jsx
index 499b316c..0a568b67 100644
--- a/src/components/floor-plan/modal/setting01/SecondOption.jsx
+++ b/src/components/floor-plan/modal/setting01/SecondOption.jsx
@@ -1,23 +1,61 @@
import { useRecoilState } from 'recoil'
import { settingModalSecondOptionsState } from '@/store/settingAtom'
import { useMessage } from '@/hooks/useMessage'
+import React, { useEffect, useState } from 'react'
+import { get } from '@/lib/Axios'
export default function SecondOption() {
+ const [objectNo] = useState('test123240912001') // 이후 삭제 필요
const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalSecondOptionsState)
const { option1, option2 } = settingsModalOptions
const { getMessage } = useMessage()
- const onClickOption = (option) => {
- option.selected = !option.selected
- setSettingModalOptions({ option1: option1, option2: option2 })
+ const [isFetched, setIsFetched] = useState(false) // 조회 여부 상태
+
+ // 데이터를 최초 한 번만 조회
+ useEffect(() => {
+ console.log('SecondOption useEffect 실행')
+ if (!isFetched) {
+ // 조회가 안 되었을 때만 fetchSettings 실행
+ fetchSettings()
+ }
+ }, [isFetched]) // isFetched 상태가 변할 때마다 확인
+
+ const fetchSettings = async () => {
+ try {
+ const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
+
+ //const options1 = ['1', '2', '3', '4']
+ //const option1 = settingsModalOptions.option1.map((item, index) => ({ ...item, selected: res[options1[index]] }))
+
+ const options2 = ['adsorpRangeSmall', 'adsorpRangeSmallSemi', 'adsorpRangeMedium', 'adsorpRangeLarge']
+ const option2 = settingsModalOptions.option2.map((item, index) => ({ ...item, selected: res[options2[index]] }))
+
+ // 데이터 설정
+ setSettingModalOptions({
+ option1,
+ option2,
+ })
+
+ setIsFetched(true) // 조회가 완료되면 isFetched를 true로 설정
+ } catch (error) {
+ console.error('Data fetching error:', error)
+ }
+ }
+
+ const onClickOption = (option) => {
+ // option2에서 한 개만 선택 가능하도록 처리
+ const updatedOption2 = option2.map((item) => (item.id === option.id ? { ...item, selected: true } : { ...item, selected: false }))
+
+ setSettingModalOptions({ option1, option2: updatedOption2 })
}
return (
<>
{getMessage('modal.canvas.setting.font.plan.edit')}
- {settingsModalOptions.option1.map((item) => (
-
+ {settingsModalOptions.option1.map((item, index) => (
+
{getMessage(item.name)}
))}
@@ -26,8 +64,8 @@ export default function SecondOption() {
{getMessage('modal.canvas.setting.font.plan.absorption')}
- {settingsModalOptions.option2.map((item) => (
-
onClickOption(item)}>
+ {settingsModalOptions.option2.map((item, index) => (
+ onClickOption(item)}>
{getMessage(item.name)}
diff --git a/src/components/floor-plan/modal/setting01/SettingModal01.jsx b/src/components/floor-plan/modal/setting01/SettingModal01.jsx
index 6b720cae..6ce186b7 100644
--- a/src/components/floor-plan/modal/setting01/SettingModal01.jsx
+++ b/src/components/floor-plan/modal/setting01/SettingModal01.jsx
@@ -5,28 +5,18 @@ import FirstOption from './FirstOption'
import WithDraggable from '@/components/common/draggable/withDraggable'
import SecondOption from '@/components/floor-plan/modal/setting01/SecondOption'
import { useMessage } from '@/hooks/useMessage'
-import { modalState } from '@/store/modalAtom'
-import { useRecoilState } from 'recoil'
-export default function SettingModal01() {
- const [modalOption, setModalOption] = useRecoilState(modalState) //modal 열림닫힘 state
+export default function SettingModal01(props) {
+ const { setShowCanvasSettingModal } = props
const [buttonAct, setButtonAct] = useState(1)
- const [close, setClose] = useState(false)
- const HandleClickClose = () => {
- setClose(true)
- setTimeout(() => {
- setModalOption({ ...modalOption, option: false })
- setClose(false)
- }, 180)
- }
const { getMessage } = useMessage()
return (
-
-
+
+
{getMessage('modal.canvas.setting')}
-
+ setShowCanvasSettingModal(false)}>
닫기
diff --git a/src/components/header/Header.jsx b/src/components/header/Header.jsx
index f81a0ca7..e8a4e872 100644
--- a/src/components/header/Header.jsx
+++ b/src/components/header/Header.jsx
@@ -1,8 +1,11 @@
'use client'
+import { Fragment, useState } from 'react'
import Link from 'next/link'
-import QSelectBox from '@/components/common/select/QSelectBox'
-import { usePathname } from 'next/navigation'
+import { usePathname, useRouter } from 'next/navigation'
import { useMessage } from '@/hooks/useMessage'
+import { logout } from '@/lib/authActions'
+
+import QSelectBox from '@/components/common/select/QSelectBox'
export const ToggleonMouse = (e, act, target) => {
const listWrap = e.target.closest(target)
@@ -19,101 +22,122 @@ export const ToggleonMouse = (e, act, target) => {
}
}
-export default function Header() {
+export default function Header(props) {
+ const { loginedUserNm } = props
const { getMessage } = useMessage()
const pathName = usePathname()
- if (pathName.includes('login') || pathName.includes('join')) {
- return null
+ // if (pathName.includes('login') || pathName.includes('join')) {
+ // return null
+ // }
+ const [selected, setSelected] = useState('')
+
+ const SelectOptions = [
+ { id: 0, name: 'オンライン保証シ', link: '' },
+ { id: 1, name: 'ステム', link: '' },
+ { id: 2, name: 'TEST1', link: 'https://www.weather.go.kr/w/index.do' },
+ { id: 3, name: 'TEST2', link: 'https://www.google.com' },
+ ]
+ const menus = [
+ { id: 0, name: 'header.menus.home', url: '/', children: [] },
+ {
+ id: 1,
+ name: 'header.menus.management',
+ url: '',
+ children: [
+ { id: 3, name: 'header.menus.management.stuff', url: '/management/stuff', children: [] },
+ { id: 4, name: 'header.menus.management.plan', url: '/floor-plan', children: [] },
+ ],
+ },
+ {
+ id: 2,
+ name: 'header.menus.community',
+ url: '',
+ children: [
+ { id: 5, name: 'header.menus.community.notice', url: '/community/notice', children: [] },
+ { id: 6, name: 'header.menus.community.faq', url: '/community/faq', children: [] },
+ { id: 7, name: 'header.menus.community.archive', url: '/community/archive', children: [] },
+ ],
+ },
+ ]
+
+ const onChangeSelect = (option) => {
+ setSelected(option)
+ }
+ const navPage = () => {
+ if (selected.link) {
+ location.href = selected.link
+ }
+ }
+
+ const getMenuTemplate = (menus) => {
+ return menus.map((menu) => {
+ return (
+
- ToggleonMouse(e, 'add', 'nav > ul')}
+ onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'nav > ul')}
+ >
+ {menu.children.length === 0 ? (
+
+ {getMessage(menu.name)}
+
+ ) : (
+
+ {getMessage(menu.name)}
+
+ {menu.children.map((m) => {
+ return (
+ - ToggleonMouse(e, 'add', 'li > ul')}
+ onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'li > ul')}
+ >
+ {getMessage(m.name)}
+
+ )
+ })}
+
+
+ )}
+
+ )
+ })
}
- const SelectOption = [{ name: 'オンライン保証シ' }, { name: 'ステム' }]
return (
-
-
-
-
-
-
-
-
-
-
-
Kim Ji Young
+ !(pathName.includes('login') || pathName.includes('join')) && (
+
+
+ )
)
}
diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx
index cf427814..6f615c3c 100644
--- a/src/components/management/Stuff.jsx
+++ b/src/components/management/Stuff.jsx
@@ -6,7 +6,7 @@ import { Button } from '@nextui-org/react'
import { useAxios } from '@/hooks/useAxios'
import { useMessage } from '@/hooks/useMessage'
import StuffQGrid from './StuffQGrid'
-import { useRecoilValue } from 'recoil'
+import { useRecoilValue, useRecoilState } from 'recoil'
import { stuffSearchState } from '@/store/stuffAtom'
import { queryStringFormatter, isEmptyArray } from '@/util/common-utils'
import dayjs from 'dayjs'
@@ -15,10 +15,12 @@ dayjs.extend(isLeapYear)
export default function Stuff() {
const stuffSearchParams = useRecoilValue(stuffSearchState)
+ const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState)
const { getMessage } = useMessage()
const [curPage, setCurPage] = useState(1) //현재 페이지 번호
- const [size, setSize] = useState(100) //페이지 당 게시물 수
- const { get, del } = useAxios()
+ const [defaultSize, setDefaultSize] = useState(100) //페이지 당 게시물 수
+ const [defaultSortType, setDefaultSortType] = useState('R')
+ const { get } = useAxios()
const gridRef = useRef()
const [gridCount, setGridCount] = useState(0)
@@ -38,13 +40,26 @@ export default function Stuff() {
}
}
+ //물건번호 복사버튼 옆에 영역
+ const onDoubleClick = (e) => {
+ let objectNo = e.target.innerText
+ console.log(objectNo)
+ if (objectNo.substring(0, 1) === 'R') {
+ console.log('진짜')
+ router.push(`${pathname}/detail?objectNo=${objectNo.toString()}`)
+ } else {
+ console.log('임시')
+ router.push(`${pathname}/tempdetail?objectNo=${objectNo.toString()}`)
+ }
+ }
+
const [gridProps, setGridProps] = useState({
gridData: [],
isPageable: false,
// sets 10 rows per page (default is 100)
- paginationPageSize: 100,
+ // paginationPageSize: 100,
// allows the user to select the page size from a predefined list of page sizes
- paginationPageSizeSelector: [100, 200, 300, 400],
+ // paginationPageSizeSelector: [100, 200, 300, 400],
gridColumns: [
{
field: 'lastEditDatetime',
@@ -82,7 +97,6 @@ export default function Stuff() {
{
copyNo(params.value)
@@ -90,7 +104,7 @@ export default function Stuff() {
>
복사
- {params.value}
+ {params.value}
)
}
@@ -148,8 +162,15 @@ export default function Stuff() {
return
} else {
console.log(' 상세이동::::::::', event.data)
+ //T 면 임시 R은 진짜
if (event.data.objectNo) {
- router.push(`${pathname}/detail?objectNo=${event.data.objectNo.toString()}`)
+ if (event.data.objectNo.substring(0, 1) === 'R') {
+ console.log('진짜:::::::::')
+ router.push(`${pathname}/detail?objectNo=${event.data.objectNo.toString()}`)
+ } else {
+ console.log('임시:::::::::::::::::')
+ router.push(`${pathname}/tempdetail?objectNo=${event.data.objectNo.toString()}`)
+ }
}
}
}
@@ -175,45 +196,6 @@ export default function Stuff() {
errCount++
}
})
-
- async function fetchDelete(data) {
- console.log('물건삭제API호출!!!!!!!!!', data)
- //행추가말고 api데이터만 보냄
- // let newData = data.filter((item) => item.company != null)
- // console.log('삭제에 전송되는 데이타::', newData)
- // await del({ url: '', data:newData })
- await get({ url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' })
- // try {
- // const res = await del({url:'', data:newData})
-
- // if(!res || res.length === 0) {
-
- // } else {
- fetchData()
- // }
- // } catch (error) {
- // console.error('Data Delete error:', error);
- // }
- }
-
- // 삭제API 완료 후 fetchData Api호출
- async function fetchData() {
- console.log('물건삭제후 조회API호출!!!!!!!!!!!!!', stuffSearchParams)
- const data = await get({ url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' })
- setGridProps({ ...gridProps, gridData: data, count: data.length })
- setGridCount(data.length)
- //data.length = 10
- //setGridProps({ ...gridProps, gridData: data, count: data.length-1})
- //setGridCount(data.length - 1 )
- }
-
- if (errCount === 0) {
- // console.log('errCount::::::::', errCount)
- fetchDelete(data)
- // fetchData()
- } else {
- alert('물건정보가 있는 행만 선택해주세요')
- }
}
//행추가
@@ -265,15 +247,14 @@ export default function Stuff() {
schDateType: 'U',
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
- startRow: (curPage - 1) * size + 1,
- endRow: curPage * size,
+ startRow: (curPage - 1) * defaultSize + 1,
+ endRow: curPage * defaultSize,
+ schSelSaleStoreId: '',
+ schSortType: 'R',
}
async function fetchData() {
console.log('화면진입:::::::::::::', params)
- console.log('현재페이지::::::', curPage)
- console.log('페이지당 게시물수::::::', size)
-
//api에 넘길값 startRow, endRow
// let startRow
// let endRow
@@ -288,7 +269,8 @@ export default function Stuff() {
// let size
// let pageCount
- const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(params)}`
+ // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(params)}`
+ const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(params)}`
await get({
url: apiUrl,
@@ -306,14 +288,21 @@ export default function Stuff() {
useEffect(() => {
if (stuffSearchParams?.code === 'E') {
+ stuffSearchParams.startRow = (curPage - 1) * defaultSize + 1
+ stuffSearchParams.endRow = curPage * defaultSize
+ stuffSearchParams.schSortType = defaultSortType
console.log('조회 눌럿을때 ::::::::::::::', stuffSearchParams)
async function fetchData() {
- const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}`
+ // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}`
+ const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}`
await get({ url: apiUrl }).then((res) => {
console.log('API결과:::::::', res)
if (!isEmptyArray(res)) {
setGridProps({ ...gridProps, gridData: res, count: res.length })
setGridCount(res.length)
+ } else {
+ setGridProps({ ...gridProps, gridData: [], count: 0 })
+ setGridCount(0)
}
})
}
@@ -321,6 +310,58 @@ export default function Stuff() {
}
}, [stuffSearchParams])
+ //페이지 갯수 변경 이벤트
+ const onChangePerPage = (e) => {
+ let startRow = (curPage - 1) * e.target.value + 1
+ stuffSearchParams.startRow = startRow
+ stuffSearchParams.endRow = curPage * e.target.value
+ setDefaultSize(e.target.value)
+ setStuffSearch({
+ ...stuffSearch,
+ code: 'S',
+ startRow: startRow,
+ endRow: curPage * e.target.value,
+ })
+ console.log('셋팅된 검색조건:::', stuffSearchParams)
+ //조회API호출
+ // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}`
+ const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}`
+ get({ url: apiUrl }).then((res) => {
+ console.log('보여줄개수바꿨을때 조회 ::::::::::', res)
+ if (!isEmptyArray(res)) {
+ setGridProps({ ...gridProps, gridData: res, count: res.length })
+ setGridCount(res.length)
+ } else {
+ setGridProps({ ...gridProps, gridData: [], count: 0 })
+ setGridCount(0)
+ }
+ })
+ }
+
+ //최근 등록일 수정일 정렬 이벤트
+ const onChangeSortType = (e) => {
+ stuffSearchParams.schSortType = e.target.value
+ console.log('셋팅된 검색조건:::', stuffSearchParams)
+ setDefaultSortType(e.target.value)
+ setStuffSearch({
+ ...stuffSearch,
+ code: 'S',
+ schSortType: e.target.value,
+ })
+ // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}`
+ const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}`
+ // console.log('apiUrl::', apiUrl)
+ get({ url: apiUrl }).then((res) => {
+ console.log('정렬바꿨을때 조회 ::::::::::', res)
+ if (!isEmptyArray(res)) {
+ setGridProps({ ...gridProps, gridData: res, count: res.length })
+ setGridCount(res.length)
+ } else {
+ setGridProps({ ...gridProps, gridData: [], count: 0 })
+ setGridCount(0)
+ }
+ })
+ }
return (
<>
@@ -328,6 +369,15 @@ export default function Stuff() {
전체 : {gridCount} // 선택 : {selectedRowDataCount}
+
+
{/*
{
- get({ url: '/api/object/prefecture/list' }).then((res) => {
- if (!isEmptyArray(res)) {
- console.log('도도부현API 결과:::', res)
- setPrefCodeList(res)
- }
- })
- // console.log('상세화면진입:::::::::', searchParams.get('objectNo'))
- // console.log('물건번호::::', objectNo)
-
if (objectNo) {
+ console.log('수정화면')
setEditMode('EDIT')
+
if (objectNo.substring(0, 1) === 'R') {
+ //진짜
setIsFormValid(true)
}
get({ url: `/api/object/${objectNo}/detail` }).then((res) => {
+ // console.log('물건번호로 상세 API 호출')
if (res != null) {
- // console.log('res:::::::', res)
+ // console.log('상세res:::::::', res)
setDetailData(res)
+
+ // 신규 상세 공통APi
+ // 도도부현API
+ get({ url: '/api/object/prefecture/list' }).then((res) => {
+ if (!isEmptyArray(res)) {
+ //console.log('도도부현API 결과:::', res)
+ setPrefCodeList(res)
+ }
+ })
+ // 판매점목록 API /api/object/saleStore/판매점코드/list - 판매점 목록 조회
+ // 임시 1차점 판매점코드 saleStoreId=201TES01
+ // T01
+ //1차점 : X167
+ get({ url: `/api/object/saleStore/X167/list` }).then((res) => {
+ if (!isEmptyArray(res)) {
+ console.log('판매점 결과:::::', res)
+ setSaleStoreList(res)
+ //1차 판매점 자동완성 값 셋팅
+ form.setValue('saleStoreId', res[0].saleStoreId)
+ //1차 판매점 번호 셋팅
+ form.setValue('saleStoreName', res[0].saleStoreId)
+ setOtherSaleStoreList([])
+ }
+ })
+ } else {
+ alert('삭제된 물건입니다')
+ router.push('/management/stuff')
+ }
+ })
+ } else {
+ console.log('신규화면')
+ // 신규 상세 공통APi
+ // 도도부현API
+ get({ url: '/api/object/prefecture/list' }).then((res) => {
+ if (!isEmptyArray(res)) {
+ //console.log('도도부현API 결과:::', res)
+ setPrefCodeList(res)
+ }
+ })
+ // 판매점목록 API /api/object/saleStore/판매점코드/list - 판매점 목록 조회
+ // 임시 1차점 판매점코드 saleStoreId=201TES01
+ // T01
+ //1차점 : X167
+ get({ url: `/api/object/saleStore/X167/list` }).then((res) => {
+ if (!isEmptyArray(res)) {
+ console.log('판매점 결과:::::', res)
+ const firstList = res.filter((row) => row.saleStoreLevel === '1')
+ const otherList = res.filter((row) => row.saleStoreLevel !== '1')
+ console.log('first:::::', firstList)
+ console.log('otherList:::::', otherList)
+ //1차점 셀렉트박스
+ setSaleStoreList(firstList)
+ //1차 판매점 자동완성 값 셋팅
+ form.setValue('saleStoreId', firstList[0].saleStoreId)
+ //1차 판매점 번호 셋팅
+ form.setValue('saleStoreName', firstList[0].saleStoreId)
+
+ //1차점 아닌 판매점 셀렉트박스
+ setOtherSaleStoreList(otherList)
}
})
}
}, [objectNo])
- useEffect(() => {
- // validateForm()
- }, [receiveUser, name2, name3, gubun, sel, autoSelectValue, zipCode, sel2, sel3, name5, sel4])
+ //1차점 변경 이벤트
+ const onSelectionChange = (key) => {
+ if (key == null) {
+ form.setValue('saleStoreId', '')
+ form.setValue('saleStoreName', '')
+ } else {
+ form.setValue('saleStoreId', key)
+ form.setValue('saleStoreName', key)
+ }
+ }
+ //2차점 변경 이벤트
+ const onSelectionChange2 = (key) => {
+ console.log(key)
+ }
// 우편번호 숫자만 체크
const _zipNo = watch('zipNo')
useEffect(() => {
@@ -114,62 +164,87 @@ export default function StuffDetail() {
}
}, [_zipNo])
- // 수직적설량 숫자만
- const textTypeHandler2 = (e) => {
- if (!e.target.value.match(/[^0-9]/g)) {
- setName5(e.target.value)
- }
- }
- const validateForm = () => {
- let errors = {}
+ //임시저장 저장 버튼 컨트롤
+ // dispCompanyName: '', //담당자
+ // objectName: '', //물건명
+ // objectNameOmit: '', //경칭선택
+ // saleStoreId: '', //판매점ID
+ // zipNo: '', //우편번호
+ // prefId: '', //도도부현
+ // address: '', //주소
+ // powerSimArea: '', //발전량시뮬레이션지역
+ // windSpeed: '', //기준풍속
+ // snowCover: '', //수직적설량
+ // coldAreaChk: false, //한랭지대책시행
+ // surfaceType: 'Ⅲ・Ⅳ', //면조도구분(Ⅲ・Ⅳ / Ⅱ)
+ // saltAreaChk: false, //염해지역용아이템사용
+ // installHeight: '', //설치높이
+ // powerConTerms: '0', //계약조건(잉여 / 전량)
+ // remarks: '', //메모
+ // tempFlag: 'T', //임시저장(1) 저장(0)
+ const _dispCompanyName = watch('dispCompanyName')
+ const _objectName = watch('objectName')
+ const _objectNameOmit = watch('objectNameOmit')
+ const _saleStoreId = watch('saleStoreId')
+ const _prefId = watch('prefId')
+ const _address = watch('address')
+ const _powerSimArea = watch('powerSimArea')
+ const _windSpeed = watch('windSpeed')
+ const _snowCover = watch('snowCover')
+ const _installHeight = watch('installHeight')
+ useEffect(() => {
+ // console.log('mode:::::', editMode)
+ if (editMode === 'NEW') {
+ const formData = form.getValues()
+ // console.log('폼::::::::::::', formData)
+ let errors = {}
+ if (!_dispCompanyName || _dispCompanyName.trim().length === 0) {
+ errors.dispCompanyName = true
+ }
+ if (!_objectName || _objectName.trim().length === 0) {
+ errors.objectName = true
+ }
+ if (!_objectNameOmit) {
+ errors.objectNameOmit = true
+ }
+ if (!_saleStoreId) {
+ errors.saleStoreId = true
+ }
- if (!receiveUser || receiveUser.trim().length === 0) {
- errors.receiveUser = '담당자 is required.'
- }
+ if (!_zipNo || _zipNo.length != 7) {
+ errors.zipCode = true
+ }
- if (!name2 || name2.trim().length === 0) {
- errors.name2 = '물건명 is required.'
- }
+ if (!_prefId) {
+ errors.prefId = true
+ }
- if (!name3 || name3.trim().length === 0) {
- errors.name3 = '물건명후리가나 is required.'
- }
+ if (!_address.trim().length === 0) {
+ errors.address = true
+ }
- if (!sel) {
- errors.sel = '경칭선택 is required'
- }
+ if (!_powerSimArea) {
+ errors.powerSimArea = true
+ }
- if (!sel2) {
- errors.sel2 = '발전량시뮬레이션지역 is required'
- }
+ if (!_windSpeed) {
+ errors.windSpeed = true
+ }
- if (!sel3) {
- errors.sel3 = '기준풍속 is required'
- }
+ if (!_snowCover) {
+ errors.snowCover = true
+ }
- if (!sel4) {
- errors.sel4 = '설치높이 is required'
- }
+ if (!_installHeight) {
+ errors.installHeight = true
+ }
- if (!autoSelectValue) {
- errors.autoSelectValue = '판매점ID자동완성 is required'
- }
-
- if (!zipCode || zipCode.length != 7) {
- errors.zipCode = '우편번호 is required.'
- setButtonValid(true)
+ // console.log('errors::', errors)
+ setIsFormValid(Object.keys(errors).length === 0)
} else {
- setButtonValid(false)
+ // console.log('상세일때 폼체크')
}
-
- if (!name5) {
- errors.name5 = '수직적설량 is required.'
- }
-
- console.log('errors::', errors)
- setErrors(errors)
- setIsFormValid(Object.keys(errors).length === 0)
- }
+ }, [_dispCompanyName, _objectName, _objectNameOmit, _saleStoreId, _zipNo, _prefId, _address, _powerSimArea, _windSpeed, _snowCover, _installHeight])
// 주소검색 API
const onSearchPostNumber = () => {
@@ -178,22 +253,25 @@ export default function StuffDetail() {
}
get({ url: `https://zipcloud.ibsnet.co.jp/api/search?${queryStringFormatter(params)}` }).then((res) => {
//7830060
+ //9302226
if (res.status === 200) {
- console.log('res.results::', res.results)
if (res.results != null) {
- console.log('res.results::', res.results)
- // prefId: '', //도도부현
- // address: '', //주소
- console.log('prefcode::', res.results[0].prefcode)
- console.log('address::', res.results[0].address2 + res.results[0].address3)
+ // console.log('주소검색::', res.results)
+ // console.log('prefcode::', res.results[0].prefcode)
+ // console.log('address::', res.results[0].address2 + res.results[0].address3)
setPrefValue(res.results[0].prefcode)
form.setValue('prefId', res.results[0].prefcode)
+ form.setValue('prefName', res.results[0].address1)
form.setValue('address', res.results[0].address2 + res.results[0].address3)
} else {
alert('등록된 우편번호에서 주소를 찾을 수 없습니다. 다시 입력해주세요.')
form.setValue('prefId', '')
+ form.setValue('prefName', '')
form.setValue('address', '')
+ form.setValue('zipNo', '')
setPrefValue('')
+ setPowerSimAreaList([])
+ form.setValue('powerSimArea', '')
}
} else {
alert(res.message)
@@ -201,58 +279,118 @@ export default function StuffDetail() {
})
}
- const onTempSave = () => {
- console.log('임시저장::', isFormValid)
- }
-
- const onSave = () => {
- console.log('진짜저장isFormValid:::', isFormValid)
- }
-
- const moveList = () => {
- router.push('/management/stuff')
- }
-
- const changeAddress2 = (e) => {
- console.log('e:::::::', e.target.value)
- }
+ useEffect(() => {
+ if (prefValue !== '') {
+ // console.log('우편번호 검색해서 도도부현골랐을때::::', prefValue)
+ // 발전량시뮬레이션 지역 목록
+ // /api/object/prefecture/도도부현코드/list
+ get({ url: `/api/object/prefecture/${prefValue}/list` }).then((res) => {
+ if (!isEmptyArray(res)) {
+ // console.log('발전시뮬레이션::::::::', res)
+ setPowerSimAreaList(res)
+ }
+ })
+ }
+ }, [prefValue])
//필수값 다 입력했을때
const onValid = (data) => {
- console.log('data::::::', data)
+ // 수정모드일때는 PUT
+ // console.log('필수값 다 있고 저장')
+ // console.log('data::::::', data)
const formData = form.getValues()
- //console.log('formData::::', formData)
- const _dispCompanyName = watch('dispCompanyName')
- const _objectStatusId = watch('objectStatusId')
- const _objectNameOmit = watch('objectNameOmit')
- const _zipNo = watch('zipNo')
- const _prefId = watch('prefId')
- const _address = watch('address')
- const _coldAreaChk = watch('coldAreaChk')
- console.log(_dispCompanyName)
- console.log(_objectStatusId)
- console.log(_objectNameOmit)
- console.log(_zipNo)
- console.log(_prefId)
- console.log('prefValue::', prefValue)
- console.log(_address)
- console.log('_coldAreaChk::', _coldAreaChk)
+ // console.log('formData::::', formData)
+ // const _dispCompanyName = watch('dispCompanyName')
+ // const _objectStatusId = watch('objectStatusId')
+ // const _objectNameOmit = watch('objectNameOmit')
+ // const _zipNo = watch('zipNo')
+ // const _prefId = watch('prefId')
+ // const _address = watch('address')
+ // const _coldAreaChk = watch('coldAreaChk')
+ // console.log(_dispCompanyName)
+ // console.log(_objectStatusId)
+ // console.log(_objectNameOmit)
+ // console.log(_zipNo)
+ // console.log(_prefId)
+ // console.log('prefValue::', prefValue)
+ // console.log(_address)
+ // console.log('_coldAreaChk::', _coldAreaChk)
}
- //필수값 안넣었을때
- const onInvalid = (errors) => {
- console.log('실패', errors)
+ //필수값 안넣었을때 임시저장 form required사용시
+ // const onInvalid = (errors) => {
+ // console.log('22222222222222222222222')
+ // const formData = form.getValues()
+ // console.log('임시저장formData::::', formData)
+ // }
+
+ // 임시저장
+ const onTempSave = async () => {
+ const formData = form.getValues()
+ //console.log('임시저장::::::::', formData)
+
+ const params = {
+ saleStoreId: formData.saleStoreId,
+ saleStoreName: formData.saleStoreName,
+ objectStatusId: formData.objectStatusId,
+ objectName: formData.objectName,
+ objectNameOmit: formData.objectNameOmit,
+ objectNameKana: formData.objectNameKana,
+ zipNo: formData.zipNo,
+ prefId: formData.prefId,
+ prefName: formData.prefName,
+ address: formData.address,
+ powerSimArea: formData.powerSimArea,
+ receiveUser: formData.dispCompanyName,
+ installHeight: formData.installHeight,
+ windSpeed: formData.windSpeed,
+ snowCover: formData.snowCover,
+ surfaceType: formData.surfaceType,
+ powerConTerms: formData.powerConTerms,
+ saltAreaChk: formData.saltAreaChk,
+ coldAreaChk: formData.coldAreaChk,
+ tempFlg: '1',
+ workNo: null,
+ workName: null,
+ }
+ console.log('임시저장params::', params)
+ return
+ await post({ url: '/api/object/save-object', data: params }).then((res) => {
+ console.log('res::::::', res)
+ })
+ }
+
+ // 발전량 시뮬레이션 변경
+ const handlePowerSimAreaOnChange = (e) => {
+ // console.log('가지고있는 도도부현코드:::::::::', prefValue)
+ // console.log('발전량시뮬레이션변경:::::::::', e.target.value)
+ //값 set해주고 그거 useEffect로 api호출
+ }
+
+ // 물건삭제
+ const onDelete = () => {
+ //http://localhost:8080/api/object/R201TES01240910023
+ // console.log('물건번호::::::::', objectNo)
+ alert('사양확정일이 있으면 삭제 불가')
+ if (confirm(getMessage('common.message.data.delete'))) {
+ let testobj = '10'
+
+ del({ url: `/api/object/${testobj}` }).then((res) => {
+ // console.log('삭제 결과:::', res)
+ router.push('/management/stuff')
+ })
+ }
}
return (
<>
{(editMode === 'NEW' && (
-