diff --git a/package.json b/package.json index 4dfef6dd..303e4864 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ }, "dependencies": { "@nextui-org/react": "^2.4.2", - "@prisma/client": "^5.18.0", "ag-grid-react": "^32.0.2", "axios": "^1.7.3", "fabric": "^5.3.0", @@ -30,7 +29,6 @@ "react-hook-form": "^7.53.0", "react-icons": "^5.3.0", "react-responsive-modal": "^6.4.2", - "react-toastify": "^10.0.5", "recoil": "^0.7.7", "sweetalert2": "^11.14.1", "sweetalert2-react-content": "^5.0.7", @@ -42,7 +40,6 @@ "dayjs": "^1.11.13", "postcss": "^8", "prettier": "^3.3.3", - "prisma": "^5.18.0", "react-color-palette": "^7.2.2", "react-select": "^5.8.1", "sass": "^1.77.8", diff --git a/src/app/QcastProvider.js b/src/app/QcastProvider.js index 84a5638e..bdaa72c6 100644 --- a/src/app/QcastProvider.js +++ b/src/app/QcastProvider.js @@ -1,24 +1,19 @@ 'use client' import { ErrorBoundary } from 'next/dist/client/components/error-boundary' +import { useCommonCode } from '@/hooks/common/useCommonCode' 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) + const { commonCode, findCommonCode } = useCommonCode() // useEffect(() => { - // if (globalLocale === 'ko') { - // setAppMessageState(KO) - // } else { - // setAppMessageState(JA) - // } - // }, [globalLocale]) + // console.log('commonCode', commonCode) + // console.log(findCommonCode(100200)) + // console.log(findCommonCode(115800)) + // }, [commonCode]) return ( <> diff --git a/src/app/[locale]/LocaleProvider.js b/src/app/[locale]/LocaleProvider.js deleted file mode 100644 index cb4aa5d6..00000000 --- a/src/app/[locale]/LocaleProvider.js +++ /dev/null @@ -1,11 +0,0 @@ -'use client' - -import { I18nProviderClient } from '@/locales/client' - -export function LocaleProvider({ locale, children }) { - return ( - - {children} - - ) -} diff --git a/src/app/[locale]/community/archive/page.jsx b/src/app/[locale]/community/archive/page.jsx deleted file mode 100644 index 6917f228..00000000 --- a/src/app/[locale]/community/archive/page.jsx +++ /dev/null @@ -1,16 +0,0 @@ -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/[locale]/community/faq/page.jsx b/src/app/[locale]/community/faq/page.jsx deleted file mode 100644 index 2b9d5452..00000000 --- a/src/app/[locale]/community/faq/page.jsx +++ /dev/null @@ -1,16 +0,0 @@ -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/[locale]/community/notice/page.jsx b/src/app/[locale]/community/notice/page.jsx deleted file mode 100644 index d2157b20..00000000 --- a/src/app/[locale]/community/notice/page.jsx +++ /dev/null @@ -1,16 +0,0 @@ -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/[locale]/error.jsx b/src/app/[locale]/error.jsx deleted file mode 100644 index 07d75e7e..00000000 --- a/src/app/[locale]/error.jsx +++ /dev/null @@ -1,15 +0,0 @@ -'use client' - -export default function ServerError() { - return ( -
-
-
-

500

-

Internal Server Error.

-

We are already working to solve the problem.

-
-
-
- ) -} diff --git a/src/app/[locale]/floor-plan/page.jsx b/src/app/[locale]/floor-plan/page.jsx deleted file mode 100644 index f503099e..00000000 --- a/src/app/[locale]/floor-plan/page.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import FloorPlan from '@/components/floor-plan/FloorPlan' - -export default function FloorPlanPage() { - return ( - <> - - - ) -} diff --git a/src/app/[locale]/initSettingsModal/page.jsx b/src/app/[locale]/initSettingsModal/page.jsx deleted file mode 100644 index a081ef47..00000000 --- a/src/app/[locale]/initSettingsModal/page.jsx +++ /dev/null @@ -1,16 +0,0 @@ -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/[locale]/intro/page.jsx b/src/app/[locale]/intro/page.jsx deleted file mode 100644 index 8d560ce5..00000000 --- a/src/app/[locale]/intro/page.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import Intro from '@/components/Intro' -import { initCheck } from '@/util/session-util' - -export default async function IntroPage() { - await initCheck() - - return ( - <> -
- -
- - ) -} diff --git a/src/app/[locale]/join/complete/page.jsx b/src/app/[locale]/join/complete/page.jsx deleted file mode 100644 index 3f9fc462..00000000 --- a/src/app/[locale]/join/complete/page.jsx +++ /dev/null @@ -1,19 +0,0 @@ -'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/[locale]/join/page.jsx b/src/app/[locale]/join/page.jsx deleted file mode 100644 index 118a25b4..00000000 --- a/src/app/[locale]/join/page.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import Join from '@/components/auth/Join' - -export default function JoinPage() { - return <>{} -} diff --git a/src/app/[locale]/layout.js b/src/app/[locale]/layout.js deleted file mode 100644 index 018f1ef5..00000000 --- a/src/app/[locale]/layout.js +++ /dev/null @@ -1,42 +0,0 @@ -'use client' - -import { useEffect } from 'react' -import { useRecoilState, useRecoilValue } from 'recoil' -import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' -import { LocaleProvider } from './LocaleProvider' -import { useCurrentLocale } from '@/locales/client' -import ServerError from './error' -import { ErrorBoundary } from 'next/dist/client/components/error-boundary' -import '@/styles/common.scss' - -import KO from '@/locales/ko.json' -import JA from '@/locales/ja.json' - -export default function LocaleLayout({ children }) { - const locale = useCurrentLocale() - const globalLocale = useRecoilValue(globalLocaleStore) - const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore) - - useEffect(() => { - console.log(globalLocale) - 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]/login/page.jsx b/src/app/[locale]/login/page.jsx deleted file mode 100644 index 47a23986..00000000 --- a/src/app/[locale]/login/page.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import Login from '@/components/auth/Login' -import { getCurrentLocale } from '@/locales/server' - -export default function LoginPage() { - const currentLocale = getCurrentLocale() - - const loginPageProps = { - currentLocale, - } - - return ( - <> - - - ) -} diff --git a/src/app/[locale]/management/plan/page.jsx b/src/app/[locale]/management/plan/page.jsx deleted file mode 100644 index 5fefa62a..00000000 --- a/src/app/[locale]/management/plan/page.jsx +++ /dev/null @@ -1,16 +0,0 @@ -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/[locale]/management/stuff/detail/page.jsx b/src/app/[locale]/management/stuff/detail/page.jsx deleted file mode 100644 index 6759b282..00000000 --- a/src/app/[locale]/management/stuff/detail/page.jsx +++ /dev/null @@ -1,19 +0,0 @@ -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/page.jsx b/src/app/[locale]/management/stuff/page.jsx deleted file mode 100644 index 7590a7cf..00000000 --- a/src/app/[locale]/management/stuff/page.jsx +++ /dev/null @@ -1,21 +0,0 @@ -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/[locale]/management/stuff/tempdetail/page.jsx b/src/app/[locale]/management/stuff/tempdetail/page.jsx deleted file mode 100644 index 8b84287a..00000000 --- a/src/app/[locale]/management/stuff/tempdetail/page.jsx +++ /dev/null @@ -1,15 +0,0 @@ -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]/master/company/page.jsx b/src/app/[locale]/master/company/page.jsx deleted file mode 100644 index 15eda41c..00000000 --- a/src/app/[locale]/master/company/page.jsx +++ /dev/null @@ -1,16 +0,0 @@ -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/[locale]/master/price/page.jsx b/src/app/[locale]/master/price/page.jsx deleted file mode 100644 index a641d6bb..00000000 --- a/src/app/[locale]/master/price/page.jsx +++ /dev/null @@ -1,16 +0,0 @@ -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/[locale]/not-found.jsx b/src/app/[locale]/not-found.jsx deleted file mode 100644 index 8127943b..00000000 --- a/src/app/[locale]/not-found.jsx +++ /dev/null @@ -1,25 +0,0 @@ -'use client' - -import Link from 'next/link' - -export default function NotFound() { - return ( -
-
-
-

404

-

Something's missing.

-

- Sorry, we can't find that page. You'll find lots to explore on the home page.{' '} -

- - Back to Homepage - -
-
-
- ) -} diff --git a/src/app/[locale]/page.js b/src/app/[locale]/page.js deleted file mode 100644 index 1b8f2258..00000000 --- a/src/app/[locale]/page.js +++ /dev/null @@ -1,18 +0,0 @@ -import { getSession } from '@/lib/authActions' -import MainPage from '@/components/Main' - -export default async function page() { - const session = await getSession() - - const mainPageProps = { - isLoggedIn: session?.isLoggedIn, - } - - return ( - <> -
- -
- - ) -} diff --git a/src/app/[locale]/playground/page.jsx b/src/app/[locale]/playground/page.jsx deleted file mode 100644 index 66d83c34..00000000 --- a/src/app/[locale]/playground/page.jsx +++ /dev/null @@ -1,17 +0,0 @@ -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/[locale]/roof/page.jsx b/src/app/[locale]/roof/page.jsx deleted file mode 100644 index f5b8e611..00000000 --- a/src/app/[locale]/roof/page.jsx +++ /dev/null @@ -1,16 +0,0 @@ -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/[locale]/roof2/RoofSelect.jsx b/src/app/[locale]/roof2/RoofSelect.jsx deleted file mode 100644 index d759398b..00000000 --- a/src/app/[locale]/roof2/RoofSelect.jsx +++ /dev/null @@ -1,128 +0,0 @@ -'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/[locale]/roof2/page.jsx b/src/app/[locale]/roof2/page.jsx deleted file mode 100644 index 72881d11..00000000 --- a/src/app/[locale]/roof2/page.jsx +++ /dev/null @@ -1,26 +0,0 @@ -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/[locale]/settings/page.jsx b/src/app/[locale]/settings/page.jsx deleted file mode 100644 index 797c024c..00000000 --- a/src/app/[locale]/settings/page.jsx +++ /dev/null @@ -1,16 +0,0 @@ -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/app/community/archive/page.jsx b/src/app/community/archive/page.jsx index 308e02f3..eee23c36 100644 --- a/src/app/community/archive/page.jsx +++ b/src/app/community/archive/page.jsx @@ -1,10 +1,7 @@ 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 index 054f9007..cf1c1941 100644 --- a/src/app/community/faq/page.jsx +++ b/src/app/community/faq/page.jsx @@ -1,9 +1,6 @@ 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 index a3453e64..c6d407e2 100644 --- a/src/app/community/notice/page.jsx +++ b/src/app/community/notice/page.jsx @@ -1,9 +1,6 @@ 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/initSettingsModal/page.jsx b/src/app/initSettingsModal/page.jsx index a081ef47..fc51b5cc 100644 --- a/src/app/initSettingsModal/page.jsx +++ b/src/app/initSettingsModal/page.jsx @@ -1,10 +1,7 @@ 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 index 8d560ce5..ebf1081b 100644 --- a/src/app/intro/page.jsx +++ b/src/app/intro/page.jsx @@ -2,8 +2,6 @@ import Intro from '@/components/Intro' import { initCheck } from '@/util/session-util' export default async function IntroPage() { - await initCheck() - return ( <>
diff --git a/src/app/layout.js b/src/app/layout.js index 64b374e8..32803812 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -1,24 +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 { ToastContainer } from 'react-toastify' - import { QcastProvider } from './QcastProvider' import Header from '@/components/header/Header' import QModal from '@/components/common/modal/QModal' +import Dimmed from '@/components/ui/Dimmed' +import SessionProvider from './SessionProvider' +import LocaleSwitch from '@/components/LocaleSwitch' +import PopupManager from '@/components/common/popupManager/PopupManager' import './globals.css' import '../styles/style.scss' import '../styles/contents.scss' -import Dimmed from '@/components/ui/Dimmed' -import SessionProvider from './SessionProvider' -import LocaleSwitch from '@/components/LocaleSwitch' - -// const inter = Inter({ subsets: ['latin'] }) export const metadata = { title: 'Create Next App', @@ -29,8 +24,6 @@ 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) @@ -84,8 +77,8 @@ export default async function RootLayout({ children }) {
)} - + diff --git a/src/app/management/plan/page.jsx b/src/app/management/plan/page.jsx index 5fefa62a..51d67116 100644 --- a/src/app/management/plan/page.jsx +++ b/src/app/management/plan/page.jsx @@ -1,10 +1,7 @@ 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 index 8783e17e..8c7dd731 100644 --- a/src/app/management/stuff/detail/page.jsx +++ b/src/app/management/stuff/detail/page.jsx @@ -1,36 +1,12 @@ import React from 'react' -import Link from 'next/link' -import Image from 'next/image' import '@/styles/contents.scss' +import StuffSubHeader from '@/components/management/StuffSubHeader' import StuffHeader from '@/components/management/StuffHeader' import StuffDetail from '@/components/management/StuffDetail' export default function ManagementStuffDetailPage() { return ( <> -
-
-
    -
  • - - 商品情報 - -
  • -
-
    -
  • - - react - -
  • -
  • - 物品及び図面管理 -
  • -
  • - 商品情報 -
  • -
-
-
+
diff --git a/src/app/management/stuff/page.jsx b/src/app/management/stuff/page.jsx index 9c1abdfb..eb852712 100644 --- a/src/app/management/stuff/page.jsx +++ b/src/app/management/stuff/page.jsx @@ -1,31 +1,11 @@ import StuffSearchCondition from '@/components/management/StuffSearchCondition' import Stuff from '@/components/management/Stuff' -import { initCheck } from '@/util/session-util' -import Image from 'next/image' +import StuffSubHeader from '@/components/management/StuffSubHeader' import '@/styles/contents.scss' export default async function ManagementStuffPage() { - await initCheck() - return ( <> -
-
-

物品及び図面管理

-
    -
  • - - react - -
  • -
  • - 物品及び図面管理 -
  • -
  • - 新規物件登録 -
  • -
-
-
+
diff --git a/src/app/management/stuff/tempdetail/page.jsx b/src/app/management/stuff/tempdetail/page.jsx index d122d717..447194fc 100644 --- a/src/app/management/stuff/tempdetail/page.jsx +++ b/src/app/management/stuff/tempdetail/page.jsx @@ -1,35 +1,11 @@ import React from 'react' -import Link from 'next/link' -import Image from 'next/image' +import StuffSubHeader from '@/components/management/StuffSubHeader' import '@/styles/contents.scss' import StuffDetail from '@/components/management/StuffDetail' export default function ManagementStuffDetailPage() { return ( <> -
-
-
    -
  • - - 商品情報 - -
  • -
-
    -
  • - - react - -
  • -
  • - 物品及び図面管理 -
  • -
  • - 商品情報 -
  • -
-
-
+
diff --git a/src/app/master/company/page.jsx b/src/app/master/company/page.jsx index 15eda41c..968452e8 100644 --- a/src/app/master/company/page.jsx +++ b/src/app/master/company/page.jsx @@ -1,10 +1,7 @@ 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 index a641d6bb..57fa0bd2 100644 --- a/src/app/master/price/page.jsx +++ b/src/app/master/price/page.jsx @@ -1,10 +1,7 @@ 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/playground/page.jsx b/src/app/playground/page.jsx index 66d83c34..3a3ad1d1 100644 --- a/src/app/playground/page.jsx +++ b/src/app/playground/page.jsx @@ -1,14 +1,6 @@ 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 index f5b8e611..960ffa89 100644 --- a/src/app/roof/page.jsx +++ b/src/app/roof/page.jsx @@ -1,10 +1,7 @@ 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/settings/page.jsx b/src/app/settings/page.jsx index 797c024c..ab714682 100644 --- a/src/app/settings/page.jsx +++ b/src/app/settings/page.jsx @@ -1,10 +1,7 @@ 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/components/Roof2.jsx b/src/components/Roof2.jsx index fbe61038..cc690ba9 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -39,7 +39,7 @@ import QEmptyContextMenu from '@/components/common/context-menu/QEmptyContextMen import InitSettingsModal from './InitSettingsModal' import GridSettingsModal from './GridSettingsModal' import { SurfaceShapeModal } from '@/components/ui/SurfaceShape' -import { changeAllHipAndGableRoof, drawDirectionStringToArrow } from '@/util/qpolygon-utils' +import { drawDirectionStringToArrow } from '@/util/qpolygon-utils' import ThumbnailList from '@/components/ui/ThumbnailLIst' import ObjectPlacement from '@/components/ui/ObjectPlacement' import { globalLocaleStore } from '@/store/localeAtom' diff --git a/src/components/common/color-picker/ColorPicker.jsx b/src/components/common/color-picker/ColorPicker.jsx index 7e774259..fe48272b 100644 --- a/src/components/common/color-picker/ColorPicker.jsx +++ b/src/components/common/color-picker/ColorPicker.jsx @@ -1,11 +1,30 @@ import { HexColorPicker } from 'react-colorful' +import { useMessage } from '@/hooks/useMessage' export default function ColorPicker(props) { const { color, setColor } = props - + const { getMessage } = useMessage() + const defaultColors = ['#EA575D', '#F29955', '#F2C957', '#32975D', '#3D7FED', '#828282', '#ffffff', '#000000'] return ( <> - +
+ +
+
+
HEX
+
+ setColor(e.target.value)} /> +
+
+
+
+
{getMessage('modal.color.picker.default.color')}
+
+ {defaultColors.map((color, index) => ( + + ))} +
+
) } diff --git a/src/components/common/color-picker/ColorPickerModal.jsx b/src/components/common/color-picker/ColorPickerModal.jsx new file mode 100644 index 00000000..fe16896f --- /dev/null +++ b/src/components/common/color-picker/ColorPickerModal.jsx @@ -0,0 +1,56 @@ +import WithDraggable from '@/components/common/draggable/WithDraggable' +import ColorPicker from '@/components/common/color-picker/ColorPicker' +import { useMessage } from '@/hooks/useMessage' +import { useEffect, useState } from 'react' +import { usePopup } from '@/hooks/usePopup' + +export default function ColorPickerModal(props) { + const { isShow, setIsShow, pos = { x: 770, y: -815 }, color = '#ff0000', setColor, id } = props + const { getMessage } = useMessage() + const [originColor, setOriginColor] = useState(color) + const { closePopup } = usePopup() + + console.log(props) + useEffect(() => { + setOriginColor(color) + }, [isShow]) + + return ( + +
+
+

{getMessage('modal.color.picker.title')}

+ +
+
+
+
COLOR PICKER
+
+ +
+
+
+ +
+
+
+
+ ) +} diff --git a/src/components/common/font/FontSetting.jsx b/src/components/common/font/FontSetting.jsx new file mode 100644 index 00000000..0e4754b0 --- /dev/null +++ b/src/components/common/font/FontSetting.jsx @@ -0,0 +1,129 @@ +import WithDraggable from '@/components/common/draggable/withDraggable' +import QSelectBox from '@/components/common/select/QSelectBox' +import { usePopup } from '@/hooks/usePopup' +import { useState } from 'react' + +const fonts = [ + { name: 'MS PGothic', value: 'MS PGothic' }, + { name: '@Yu Gothic', value: '@Yu Gothic' }, + { name: 'Yu Gothic', value: 'Yu Gothic' }, + { name: '@Yu Gothic UI', value: '@Yu Gothic UI' }, + { name: 'Yu Gothic UI', value: 'Yu Gothic UI' }, +] +const fontOptions = [ + { name: '보통', value: 'normal' }, + { name: '기울임꼴', value: 'italic' }, + { + name: '굵게', + value: 'bold', + }, + { name: '굵은 기울임꼴', value: 'boldAndItalic' }, +] +const fontSizes = [ + ...Array.from({ length: 4 }).map((_, index) => { + return { name: index + 8, value: index + 8 } + }), + ...Array.from({ length: 9 }).map((_, index) => { + return { name: (index + 6) * 2, value: (index + 6) * 2 } + }), + { name: 36, value: 36 }, + { name: 48, value: 48 }, + { name: 72, value: 72 }, +] +const fontColors = [ + { name: '검정색', value: 'black' }, + { name: '빨강색', value: 'red' }, + { name: '파랑색', value: 'blue' }, + { name: '회색', value: 'gray' }, + { name: '황색', value: 'yellow' }, + { name: '녹색', value: 'green' }, + { name: '분홍색', value: 'pink' }, + { name: '황금색', value: 'gold' }, + { name: '남색', value: 'darkblue' }, +] +export default function FontSetting(props) { + const { id, setIsShow, font, setFont, fontSize, setFontSize } = props + const { closePopup } = usePopup() + const [originFont, setOriginFont] = useState(font) + const [originFontSize, setOriginFontSize] = useState(fontSize) + const [selectedFont, setSelectedFont] = useState(font ? font : fonts[0]) + const [selectedFontSize, setSelectedFontSize] = useState(fontSize ? fontSize : fontSizes[0]) + const [selectedFontColor, setSelectedFontColor] = useState(null) + return ( + +
+
+

フォント

+ +
+
+
+
+
+
文字(F)
+
+ setSelectedFont(e)} /> +
+
+
+
フォントスタイル(Y)
+
+ setSelectedFont(e)} /> +
+
+
+
サイズ(S)
+
+ setSelectedFontSize(e)} /> +
+
+
+
フォン
+
+ setSelectedFontColor(e)} /> +
+
+
+
+
見る
+
+ + Aaあぁアァ + +
+
+
ントです。プリンタと画面 でも同じフォントを使用します.
+
+
+ +
+
+
+
+ ) +} diff --git a/src/components/common/popupManager/PopupManager.jsx b/src/components/common/popupManager/PopupManager.jsx new file mode 100644 index 00000000..aa4b6cae --- /dev/null +++ b/src/components/common/popupManager/PopupManager.jsx @@ -0,0 +1,9 @@ +'use client' +import { useRecoilState } from 'recoil' +import { popupState } from '@/store/popupAtom' +import { Fragment } from 'react' + +export default function PopupManager() { + const [popup, setPopup] = useRecoilState(popupState) + return popup.children?.map((child) => {child.component}) +} diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index ad08e884..d982a49a 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -2,7 +2,7 @@ import { fabric } from 'fabric' import { v4 as uuidv4 } from 'uuid' import { QLine } from '@/components/fabric/QLine' import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util' -import { calculateAngle, drawDirectionArrow, drawHippedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' +import { calculateAngle, drawHippedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' import * as turf from '@turf/turf' export const QPolygon = fabric.util.createClass(fabric.Polygon, { @@ -121,13 +121,9 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { this.on('modified', (e) => { this.addLengthText() - // if (this.arrow) { - // drawDirectionArrow(this) - // } }) this.on('selected', () => { - // drawDirectionArrow(this) Object.keys(this.controls).forEach((controlKey) => { if (controlKey !== 'ml' && controlKey !== 'mr') { this.setControlVisible(controlKey, false) diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx index b35066b7..b7d9a5da 100644 --- a/src/components/floor-plan/CanvasFrame.jsx +++ b/src/components/floor-plan/CanvasFrame.jsx @@ -4,13 +4,24 @@ import { useEffect, useRef } from 'react' import { useCanvas } from '@/hooks/useCanvas' import { useEvent } from '@/hooks/useEvent' -import QContextMenu from '@/components/common/context-menu/QContextMenu' import { useContextMenu } from '@/hooks/useContextMenu' +import { useRecoilValue } from 'recoil' +import { currentObjectState } from '@/store/canvasAtom' +import { useCanvasEvent } from '@/hooks/useCanvasEvent' +import QContextMenu from '@/components/common/context-menu/QContextMenu' export default function CanvasFrame({ plan }) { const canvasRef = useRef(null) + console.log(canvasRef) const { canvas } = useCanvas('canvas') - const { contextMenu, currentContextMenu, setCurrentContextMenu } = useContextMenu() + const { handleZoomClear } = useCanvasEvent() + const { contextMenu, currentContextMenu, setCurrentContextMenu } = useContextMenu({ + externalFn: { + handleZoomClear, + }, + }) + + const currentObject = useRecoilValue(currentObjectState) useEvent() @@ -32,16 +43,22 @@ export default function CanvasFrame({ plan }) { const onClickContextMenu = (index) => {} return ( -
-
- -
+
+ {contextMenu.map((menus, index) => (
    - {menus.map((menu, idx) => ( -
  • setCurrentContextMenu(menu)}> + {menus.map((menu) => ( +
  • { + if (menu.fn) { + menu.fn() + } + setCurrentContextMenu(menu) + }} + > {menu.name}
  • ))} diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index 84cbdca2..c2f70f1d 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -6,7 +6,7 @@ import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import MenuDepth01 from './MenuDepth01' import QSelectBox from '@/components/common/select/QSelectBox' - +import { v4 as uuidv4 } from 'uuid' import { useMessage } from '@/hooks/useMessage' import { usePlan } from '@/hooks/usePlan' import { useSwal } from '@/hooks/useSwal' @@ -23,6 +23,10 @@ import { checkLineOrientation, getDistance } from '@/util/canvas-util' import KO from '@/locales/ko.json' import JA from '@/locales/ja.json' import { settingModalFirstOptionsState } from '@/store/settingAtom' +import { useCanvasEvent } from '@/hooks/useCanvasEvent' +import { popupState } from '@/store/popupAtom' +import SettingModal01 from '@/components/floor-plan/modal/setting01/SettingModal01' +import { usePopup } from '@/hooks/usePopup' import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom' import { lineSegment } from '@turf/turf' @@ -60,6 +64,7 @@ export default function CanvasMenu(props) { setShowPropertiesSettingModal, } = props + const { addPopup, closePopup } = usePopup() const [type, setType] = useState('') const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState) @@ -69,6 +74,7 @@ export default function CanvasMenu(props) { const setPlacementPoints = useSetRecoilState(placementShapeDrawingPointsState) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) + const { handleZoomClear } = useCanvasEvent() const globalLocale = useRecoilValue(globalLocaleStore) const canvas = useRecoilValue(canvasState) @@ -78,16 +84,30 @@ export default function CanvasMenu(props) { const { getMessage } = useMessage() const { saveCanvas } = usePlan() const { swalFire } = useSwal() - const { addCanvasMouseEventListener, initEvent, addDocumentEventListener } = useEvent() - const [commonFunction, setCommonFunction] = useState(null) + const [commonFunctionState, setCommonFunctionState] = useState({ text: false, dimension: false, distance: false, }) + const [popup, setPopup] = useRecoilState(popupState) + const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }] + useEffect(() => { + console.log(canvas) + if (canvas) { + const circle = new fabric.Circle({ + left: 300, + top: 300, + radius: 5, + stroke: 'black', + }) + canvas.add(circle) + canvas.renderAll() + } + }, []) const onClickNav = (menu) => { setMenuNumber(menu.index) setCurrentMenu(menu.title) @@ -161,12 +181,17 @@ export default function CanvasMenu(props) { setPlacementPoints([]) canvas?.clear() } + // + // const handleZoomClear = () => { + // setCanvasZoom(100) + // canvas.set({ zoom: 1 }) + // canvas.viewportTransform = [1, 0, 0, 1, 0, 0] + // canvas.renderAll() + // } - const handleZoomClear = () => { - setCanvasZoom(100) - canvas.set({ zoom: 1 }) - canvas.viewportTransform = [1, 0, 0, 1, 0, 0] - canvas.renderAll() + const handlePopup = () => { + const id = uuidv4() + addPopup(id, 1, ) } const commonTextMode = () => { @@ -565,7 +590,8 @@ export default function CanvasMenu(props) {
- + {/**/} +
diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx index a5b7ea41..21b90616 100644 --- a/src/components/floor-plan/FloorPlan.jsx +++ b/src/components/floor-plan/FloorPlan.jsx @@ -1,19 +1,16 @@ 'use client' import { useEffect, useState } from 'react' -import { useRecoilState, useRecoilValue } from 'recoil' +import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { useAxios } from '@/hooks/useAxios' import { globalLocaleStore } from '@/store/localeAtom' -import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom' +import { settingModalFirstOptionsState, settingModalGridOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom' import '@/styles/contents.scss' import CanvasMenu from '@/components/floor-plan/CanvasMenu' -import SettingModal01 from '@/components/floor-plan/modal/setting01/SettingModal01' import CanvasLayout from '@/components/floor-plan/CanvasLayout' -import DotLineGrid from '@/components/floor-plan/modal/grid/DotLineGrid' import WallLineSetting from '@/components/floor-plan/modal/outerlinesetting/WallLineSetting' import PropertiesSetting from '@/components/floor-plan/modal/outerlinesetting/PropertiesSetting' import PlacementShapeSetting from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting' -import GridColorSetting from './modal/grid/GridColorSetting' import RoofShapeSetting from '@/components/floor-plan/modal/roofShape/RoofShapeSetting' import PlacementShapeDrawing from '@/components/floor-plan/modal/placementShape/PlacementShapeDrawing' import Slope from '@/components/floor-plan/modal/Slope' @@ -28,6 +25,7 @@ import MovementSetting from '@/components/floor-plan/modal/movement/MovementSett import RoofAllocationSetting from '@/components/floor-plan/modal/roofAllocation/RoofAllocationSetting' import BasicSetting from '@/components/floor-plan/modal/basic/BasicSetting' import CircuitTrestleSetting from '@/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting' +import { gridColorState } from '@/store/gridAtom' export default function FloorPlan() { const [showCanvasSettingModal, setShowCanvasSettingModal] = useState(false) @@ -53,16 +51,13 @@ export default function FloorPlan() { const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState) const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요 + const [menuNumber, setMenuNumber] = useState(null) const [showDotLineGridModal, setShowDotLineGridModal] = useState(false) const [showGridCopyModal, setShowGridCopyModal] = useState(false) const [showGridMoveModal, setShowGridMoveModal] = useState(false) - const [showColorPickerModal, setShowColorPickerModal] = useState(false) - const canvasSettingProps = { - setShowCanvasSettingModal, - setShowDotLineGridModal, - setShowColorPickerModal, - } + const [color, setColor] = useRecoilState(gridColorState) + const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState) const outlineProps = { setShowOutlineModal, @@ -122,14 +117,6 @@ export default function FloorPlan() { console.error('Data fetching error:', error) } } - const dotLineProps = { - showDotLineGridModal, - setShowDotLineGridModal, - } - - const gridColorProps = { - setShowColorPickerModal, - } const propertiesSettingProps = { setShowPropertiesSettingModal, @@ -138,33 +125,31 @@ export default function FloorPlan() { useEffect(() => {}, [showOutlineModal]) return ( -
- -
- - {showCanvasSettingModal && } - {showOutlineModal && } - {showDotLineGridModal && } - {showColorPickerModal && } - {showPropertiesSettingModal && } - - {showPlaceShapeModal && } - {showRoofShapeSettingModal && } - {showRoofShapePassivitySettingModal && ( - - )} - {showAuxiliaryModal && } - {showSlopeSettingModal && } - {showPlaceShapeDrawingModal && } - {showEavesGableEditModal && } - {showMovementModal && } - {showRoofAllocationSettingModal && } - {showWallLineOffsetSettingModal && } - {showObjectSettingModal && } - {showPlacementSurfaceSettingModal && } - {showBasicSettingModal && } - {showCircuitTrestleSettingModal && } + <> +
+ +
+ + {showOutlineModal && } + {showPropertiesSettingModal && } + {showPlaceShapeModal && } + {showRoofShapeSettingModal && } + {showRoofShapePassivitySettingModal && ( + + )} + {showAuxiliaryModal && } + {showSlopeSettingModal && } + {showPlaceShapeDrawingModal && } + {showEavesGableEditModal && } + {showMovementModal && } + {showRoofAllocationSettingModal && } + {showWallLineOffsetSettingModal && } + {showObjectSettingModal && } + {showPlacementSurfaceSettingModal && } + {showBasicSettingModal && } + {showCircuitTrestleSettingModal && } +
-
+ ) } diff --git a/src/components/floor-plan/modal/Slope.jsx b/src/components/floor-plan/modal/Slope.jsx index ba9ede2a..4e6d63aa 100644 --- a/src/components/floor-plan/modal/Slope.jsx +++ b/src/components/floor-plan/modal/Slope.jsx @@ -9,7 +9,7 @@ export default function Slope({ setShowSlopeSettingModal }) { const [globalPitch, setGlobalPitch] = useRecoilState(globalPitchState) const inputRef = useRef() return ( - +

{getMessage('plan.menu.placement.surface.slope.setting')}

diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx index d0f87114..8ce885c4 100644 --- a/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx +++ b/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx @@ -1,4 +1,3 @@ -import { useState } from 'react' import { useMessage } from '@/hooks/useMessage' import WithDraggable from '@/components/common/draggable/WithDraggable' import RightAngle from '@/components/floor-plan/modal/lineTypes/RightAngle' @@ -6,7 +5,6 @@ import DoublePitch from '@/components/floor-plan/modal/lineTypes/DoublePitch' import Angle from '@/components/floor-plan/modal/lineTypes/Angle' import Diagonal from '@/components/floor-plan/modal/lineTypes/Diagonal' import { OUTER_LINE_TYPE } from '@/store/outerLineAtom' -import { useOuterLineWall } from '@/hooks/roofcover/useOuterLineWall' import OuterLineWall from '@/components/floor-plan/modal/lineTypes/OuterLineWall' import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing' @@ -123,7 +121,7 @@ export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) { setType(button.type) } return ( - +

{getMessage('modal.auxiliary.drawing')}

@@ -152,7 +150,7 @@ export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) { {getMessage('modal.cover.outline.rollback')}
diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index 555cdfcb..94ad7317 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -14,7 +14,7 @@ export default function BasicSetting({ setShowBasicSettingModal }) { const [tabNum, setTabNum] = useState(1) const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) return ( - +

{getMessage('plan.menu.module.circuit.setting.default')}

diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx index f165bde0..6daf04b2 100644 --- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx @@ -14,7 +14,7 @@ export default function CircuitTrestleSetting({ setShowCircuitTrestleSettingModa setCircuitAllocationType, } return ( - +

{getMessage('modal.circuit.trestle.setting')}

diff --git a/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx b/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx index bab1e696..b19f435e 100644 --- a/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx +++ b/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx @@ -1,6 +1,5 @@ import { useMessage } from '@/hooks/useMessage' import WithDraggable from '@/components/common/draggable/WithDraggable' -import { useState } from 'react' import Eaves from '@/components/floor-plan/modal/eavesGable/type/Eaves' import Gable from '@/components/floor-plan/modal/eavesGable/type/Gable' import WallMerge from '@/components/floor-plan/modal/eavesGable/type/WallMerge' @@ -35,7 +34,7 @@ export default function EavesGableEdit({ setShowEavesGableEditModal }) { } return ( - +

{getMessage('modal.eaves.gable.edit')}

diff --git a/src/components/floor-plan/modal/grid/DotLineGrid.jsx b/src/components/floor-plan/modal/grid/DotLineGrid.jsx index d9919351..eacb1b34 100644 --- a/src/components/floor-plan/modal/grid/DotLineGrid.jsx +++ b/src/components/floor-plan/modal/grid/DotLineGrid.jsx @@ -10,6 +10,7 @@ import { gridColorState } from '@/store/gridAtom' import { gridDisplaySelector, settingModalGridOptionsState } from '@/store/settingAtom' import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' +import { usePopup } from '@/hooks/usePopup' const TYPE = { DOT: 'DOT', @@ -20,7 +21,7 @@ export default function DotLineGrid(props) { // const [modalOption, setModalOption] = useRecoilState(modalState); //modal 열림닫힘 state const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요 const [close, setClose] = useState(false) - const { setShowDotLineGridModal } = props + const { id, setShowDotLineGridModal } = props const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState) const gridColor = useRecoilValue(gridColorState) const canvas = useRecoilValue(canvasState) @@ -33,6 +34,7 @@ export default function DotLineGrid(props) { const { getMessage } = useMessage() const { get, post } = useAxios() const { swalFire } = useSwal() + const { closePopup } = usePopup() useEffect(() => { return () => { @@ -106,6 +108,10 @@ export default function DotLineGrid(props) { } const handleSave = async () => { + if (!dotLineGridSetting.DOT && !dotLineGridSetting.LINE) { + swalFire({ text: '배치할 그리드를 설정해주세요.' }) + return + } try { const patternData = { objectNo, @@ -247,6 +253,8 @@ export default function DotLineGrid(props) { canvas.renderAll() }) + setShowDotLineGridModal(false) + closePopup(id) } catch (error) { swalFire({ text: getMessage(res.returnMessage), icon: 'error' }) } @@ -307,11 +315,17 @@ export default function DotLineGrid(props) { } return ( - +

{getMessage('modal.canvas.setting.grid.dot.line.setting')}

-
@@ -335,7 +349,8 @@ export default function DotLineGrid(props) { id="ra01" value={1} onChange={handleRadioChange} - checked={dotLineGridSetting.INTERVAL.type === 1} + checked={(dotLineGridSetting.DOT || dotLineGridSetting.LINE) && dotLineGridSetting.INTERVAL.type === 1} + readOnly={!dotLineGridSetting.DOT && !dotLineGridSetting.LINE} />
@@ -374,7 +389,8 @@ export default function DotLineGrid(props) { id="ra02" value={2} onChange={handleRadioChange} - checked={dotLineGridSetting.INTERVAL.type === 2} + checked={(dotLineGridSetting.DOT || dotLineGridSetting.LINE) && dotLineGridSetting.INTERVAL.type === 2} + readOnly={!dotLineGridSetting.DOT && !dotLineGridSetting.LINE} />
diff --git a/src/components/floor-plan/modal/grid/GridColorSetting.jsx b/src/components/floor-plan/modal/grid/GridColorSetting.jsx deleted file mode 100644 index 5b7b2ff6..00000000 --- a/src/components/floor-plan/modal/grid/GridColorSetting.jsx +++ /dev/null @@ -1,39 +0,0 @@ -import WithDraggable from '@/components/common/draggable/WithDraggable' -import ColorPicker from '@/components/common/color-picker/ColorPicker' -import { useRecoilState, useSetRecoilState } from 'recoil' -import { gridColorState } from '@/store/gridAtom' -import { useMessage } from '@/hooks/useMessage' -import { useEffect } from 'react' -import { settingModalGridOptionsState } from '@/store/settingAtom' - -export default function GridColorSetting(props) { - const { setShowColorPickerModal } = props - const [color, setColor] = useRecoilState(gridColorState) - const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState) - const { getMessage } = useMessage() - - useEffect(() => { - return () => { - setSettingModalGridOptions((prev) => { - const newSettingOptions = [...prev] - newSettingOptions[3].selected = false - return [...newSettingOptions] - }) - } - }, []) - return ( - -
-
-

{getMessage('modal.canvas.setting.grid.color.setting')}

- -
-
- -
-
-
- ) -} diff --git a/src/components/floor-plan/modal/movement/MovementSetting.jsx b/src/components/floor-plan/modal/movement/MovementSetting.jsx index 569249d6..2e6bd7ec 100644 --- a/src/components/floor-plan/modal/movement/MovementSetting.jsx +++ b/src/components/floor-plan/modal/movement/MovementSetting.jsx @@ -13,7 +13,7 @@ export default function MovementSetting({ setShowMovementModal }) { ] return ( - +

{getMessage('plan.menu.roof.cover.movement.shape.updown')}

diff --git a/src/components/floor-plan/modal/object/ObjectSetting.jsx b/src/components/floor-plan/modal/object/ObjectSetting.jsx index cb1b0b45..d98b76b0 100644 --- a/src/components/floor-plan/modal/object/ObjectSetting.jsx +++ b/src/components/floor-plan/modal/object/ObjectSetting.jsx @@ -1,9 +1,8 @@ 'use client' -import { useState, useRef, useEffect } from 'react' +import { useEffect, useRef, useState } from 'react' import { useRecoilValue } from 'recoil' import { useMessage } from '@/hooks/useMessage' -import { useEvent } from '@/hooks/useEvent' import { canvasState } from '@/store/canvasAtom' import { useSwal } from '@/hooks/useSwal' import { useObjectBatch } from '@/hooks/object/useObjectBatch' @@ -71,7 +70,7 @@ export default function ObjectSetting({ setShowObjectSettingModal }) { { id: 4, name: getMessage('modal.object.setting.type.pentagon.dormer') }, ] return ( - +

{getMessage('plan.menu.placement.surface.object')}

diff --git a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx index d26b2ef3..a1e848be 100644 --- a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx @@ -9,7 +9,7 @@ export default function PropertiesSetting(props) { const { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } = usePropertiesSetting(setShowPropertiesSettingModal) return ( - +

{getMessage('modal.canvas.setting.wallline.properties.setting')}

diff --git a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx index 975a582a..84e59da4 100644 --- a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx @@ -109,7 +109,7 @@ export default function WallLineSetting(props) { } return ( - +

{getMessage('modal.cover.outline.drawing')}

diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx index 0d2c301c..9374dbf9 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx @@ -5,7 +5,6 @@ import RightAngle from '@/components/floor-plan/modal/lineTypes/RightAngle' import DoublePitch from '@/components/floor-plan/modal/lineTypes/DoublePitch' import Angle from '@/components/floor-plan/modal/lineTypes/Angle' import Diagonal from '@/components/floor-plan/modal/lineTypes/Diagonal' -import { useOuterLineWall } from '@/hooks/roofcover/useOuterLineWall' import { OUTER_LINE_TYPE } from '@/store/outerLineAtom' import OuterLineWall from '@/components/floor-plan/modal/lineTypes/OuterLineWall' import { usePlacementShapeDrawing } from '@/hooks/surface/usePlacementShapeDrawing' @@ -120,7 +119,7 @@ export default function PlacementShapeDrawing({ setShowPlaceShapeDrawingModal }) setType(button.type) } return ( - +

{getMessage('plan.menu.placement.surface.drawing')}

diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 55cfcb6b..bc7ba2b7 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -1,7 +1,6 @@ import SizeGuide from '@/components/floor-plan/modal/placementShape/SizeGuide' import MaterialGuide from '@/components/floor-plan/modal/placementShape/MaterialGuide' import WithDraggable from '@/components/common/draggable/WithDraggable' -import { Button, Checkbox, CheckboxGroup, RadioGroup, Radio, Input, Select, SelectItem } from '@nextui-org/react' import { useRecoilState } from 'recoil' import { Fragment, useEffect, useState } from 'react' import { canvasSettingState } from '@/store/canvasAtom' @@ -18,7 +17,18 @@ export default function PlacementShapeSetting({ setShowPlaceShapeModal }) { const [basicSetting, setBasicSettings] = useState({ roofSizeSet: 1, roofAngleSet: 'slope', - roofs: [{ roofApply: true, roofSeq: 1, roofType: 1, roofWidth: 200, roofHeight: 200, roofHajebichi: 200, roofGap: 0, roofLayout: 'parallel' }], + roofs: [ + { + roofApply: true, + roofSeq: 1, + roofType: 1, + roofWidth: 200, + roofHeight: 200, + roofHajebichi: 200, + roofGap: 0, + roofLayout: 'parallel', + }, + ], }) const { getMessage } = useMessage() @@ -159,7 +169,7 @@ export default function PlacementShapeSetting({ setShowPlaceShapeModal }) { } return ( - +

{getMessage('plan.menu.placement.surface.initial.setting')}

diff --git a/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx b/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx index e667667e..90e05dbf 100644 --- a/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx +++ b/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx @@ -1,6 +1,6 @@ import { useMessage } from '@/hooks/useMessage' import WithDraggable from '@/components/common/draggable/WithDraggable' -import { useEffect, useState, useRef } from 'react' +import { useEffect, useRef, useState } from 'react' import Image from 'next/image' import PlacementSurface from '@/components/floor-plan/modal/placementSurface/PlacementSurface' import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch' @@ -239,7 +239,7 @@ export default function PlacementSurfaceSetting({ setShowPlacementSurfaceSetting }, []) return ( - +

{getMessage('plan.menu.placement.surface.arrangement')}

diff --git a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx index 72599bbe..52ee2e3f 100644 --- a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx +++ b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx @@ -1,6 +1,5 @@ import { useMessage } from '@/hooks/useMessage' import WithDraggable from '@/components/common/draggable/WithDraggable' -import { useState } from 'react' import QSelectBox from '@/components/common/select/QSelectBox' import { useRoofAllocationSetting } from '@/hooks/roofcover/useRoofAllocationSetting' @@ -10,7 +9,7 @@ export default function RoofAllocationSetting({ setShowRoofAllocationSettingModa useRoofAllocationSetting(setShowRoofAllocationSettingModal) return ( - +

{getMessage('plan.menu.estimate.roof.alloc')}

diff --git a/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx b/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx index ec1684a6..9e9dc93f 100644 --- a/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx +++ b/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx @@ -25,7 +25,7 @@ export default function RoofShapePassivitySetting({ setShowRoofShapePassivitySet } return ( - +

{getMessage('plan.menu.roof.cover.roof.shape.passivity.setting')}

diff --git a/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx b/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx index 60355848..d92ed807 100644 --- a/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx +++ b/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx @@ -67,10 +67,19 @@ export default function RoofShapeSetting({ setShowRoofShapeSettingModal }) { handleRollBack, } - const directionProps = { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset, shedWidth, setShedWidth } + const directionProps = { + pitch, + setPitch, + eavesOffset, + setEavesOffset, + gableOffset, + setGableOffset, + shedWidth, + setShedWidth, + } return ( - +

{getMessage('modal.roof.shape.setting')}

diff --git a/src/components/floor-plan/modal/setting01/GridOption.jsx b/src/components/floor-plan/modal/setting01/GridOption.jsx index 39af3a10..7854e9ab 100644 --- a/src/components/floor-plan/modal/setting01/GridOption.jsx +++ b/src/components/floor-plan/modal/setting01/GridOption.jsx @@ -1,69 +1,100 @@ -import React, { useEffect } from 'react' -import { useRecoilState } from 'recoil' +import React, { useEffect, useState } from 'react' +import { useRecoilState, useSetRecoilState } from 'recoil' import { settingModalGridOptionsState } from '@/store/settingAtom' import { useMessage } from '@/hooks/useMessage' import { adsorptionPointAddModeState } from '@/store/canvasAtom' import { useTempGrid } from '@/hooks/useTempGrid' import { gridColorState } from '@/store/gridAtom' import { useColor } from 'react-color-palette' +import ColorPickerModal from '@/components/common/color-picker/ColorPickerModal' +import { usePopup } from '@/hooks/usePopup' +import { v4 as uuidv4 } from 'uuid' +import DotLineGrid from '@/components/floor-plan/modal/grid/DotLineGrid' -export default function GridOption(props) { - const { setShowDotLineGridModal, setShowColorPickerModal } = props +export default function GridOption() { const [gridOptions, setGridOptions] = useRecoilState(settingModalGridOptionsState) - const [gridColor, setGridColor] = useRecoilState(gridColorState) const [adsorptionPointAddMode, setAdsorptionPointAddMode] = useRecoilState(adsorptionPointAddModeState) + const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState) const { getMessage } = useMessage() const { tempGridMode, setTempGridMode } = useTempGrid() - + const [gridColor, setGridColor] = useRecoilState(gridColorState) const [color, setColor] = useColor(gridColor) + const [showColorPickerModal, setShowColorPickerModal] = useState(false) + const [showDotLineGridModal, setShowDotLineGridModal] = useState(false) + const { addPopup, closePopup } = usePopup() + let [colorId, dotLineId] = '' useEffect(() => { - console.log('GridOption useEffect 실행') setGridColor(color.hex) }, [color]) + useEffect(() => { + console.log(showColorPickerModal) + gridOptions[3].selected = showColorPickerModal + setGridOptions([...gridOptions]) + }, [showColorPickerModal]) + + useEffect(() => { + colorId = uuidv4() + dotLineId = uuidv4() + return () => { + setSettingModalGridOptions((prev) => { + const newSettingOptions = [...prev] + newSettingOptions[3].selected = false + return [...newSettingOptions] + }) + } + }, []) + const onClickOption = (option) => { + const { id, name, selected } = option + const newGridOptions = [...gridOptions] - newGridOptions.map((item) => { - if (item.id === option.id) { + + // 초기화 + setShowColorPickerModal(false) + setShowDotLineGridModal(false) + setTempGridMode(false) + setAdsorptionPointAddMode(false) + closePopup(dotLineId) + closePopup(colorId) + // + + newGridOptions.forEach((item) => { + if (item.id === id) { item.selected = !item.selected + } else { + item.selected = false } }) - if (option.id === 1) { - // 점 그리드 - setAdsorptionPointAddMode(false) - setTempGridMode(option.selected) - newGridOptions[2].selected = false - } - - if (option.id === 2) { - // 점.선 그리드 - if (option.selected) { - setShowDotLineGridModal(true) - } else { - setShowDotLineGridModal(false) - } - } - - if (option.name === 'modal.canvas.setting.grid.absorption.add') { - setAdsorptionPointAddMode(!adsorptionPointAddMode) - setTempGridMode(false) - newGridOptions[0].selected = false - } - - if (option.id === 4) { - // 그리드 색 설정 - if (option.selected) { - setShowColorPickerModal(true) - } else { - setShowColorPickerModal(false) - } + const selectedOption = newGridOptions.find((item) => item.id === option.id) + if (selectedOption.id === 1) { + // 임의 그리드 모드 + setTempGridMode(selectedOption.selected) + } else if (selectedOption.id === 2) { + // 점 선 그리드 설정 모달 + setShowDotLineGridModal(selectedOption.selected) + addPopup(dotLineId, 2, ) + } else if (selectedOption.id === 3) { + // 흡착점 모드 + setAdsorptionPointAddMode(selectedOption.selected) + } else if (selectedOption.id === 4) { + // 그리드 색 설정 모달 + setShowColorPickerModal(selectedOption.selected) + addPopup(colorId, 2, ) } setGridOptions(newGridOptions) } + const colorPickerProps = { + color: gridColor, + setColor: setGridColor, + isShow: showColorPickerModal, + setIsShow: setShowColorPickerModal, + } + return ( <>
@@ -77,6 +108,7 @@ export default function GridOption(props) { ))}
+ {/**/} ) } diff --git a/src/components/floor-plan/modal/setting01/SecondOption.jsx b/src/components/floor-plan/modal/setting01/SecondOption.jsx index f6cf6e30..0efb2aab 100644 --- a/src/components/floor-plan/modal/setting01/SecondOption.jsx +++ b/src/components/floor-plan/modal/setting01/SecondOption.jsx @@ -5,6 +5,10 @@ import React, { useEffect, useState } from 'react' import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' import { adsorptionPointModeState, adsorptionRangeState } from '@/store/canvasAtom' +import DimensionLineSetting from '@/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting' +import { usePopup } from '@/hooks/usePopup' +import { v4 as uuidv4 } from 'uuid' +import FontSetting from '@/components/common/font/FontSetting' export default function SecondOption() { const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요 @@ -18,6 +22,9 @@ export default function SecondOption() { const { getMessage } = useMessage() const { get, post } = useAxios() const { swalFire } = useSwal() + const { addPopup } = usePopup() + const [showFontSettingModal, setShowFontSettingModal] = useState(false) + const [showDimensionLineSettingModal, setShowDimensionLineSettingModal] = useState(false) // 데이터를 최초 한 번만 조회 useEffect(() => { @@ -31,7 +38,10 @@ export default function SecondOption() { const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` }) const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] })) const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] })) - const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item, selected: res[item.column] })) + const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ + ...item, + selected: res[item.column], + })) const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item })) const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] })) @@ -51,7 +61,14 @@ export default function SecondOption() { const onClickOption = async (option) => { // option4에서 한 개만 선택 가능하도록 처리 - const updatedOption4 = option4.map((item) => (item.id === option.id ? { ...item, selected: true } : { ...item, selected: false })) + const updatedOption4 = option4.map((item) => + item.id === option.id + ? { ...item, selected: true } + : { + ...item, + selected: false, + }, + ) setSettingModalFirstOptions({ option1, option2, dimensionDisplay }) setSettingModalSecondOptions({ option3, option4: updatedOption4 }) @@ -117,6 +134,46 @@ export default function SecondOption() { } setAdsorptionRange(option.range) } + const dimensionId = uuidv4() + const fontId = uuidv4() + const [pixel, setPixel] = useState(1) + const [color, setColor] = useState('#FF0000') + const [font, setFont] = useState(null) + const [fontSize, setFontSize] = useState('#FF0000') + const [fontColor, setFontColor] = useState('#FF0000') + + const dimensionProps = { + color, + setColor, + pixel, + setPixel, + font, + setFont, + fontSize, + setFontSize, + fontColor, + setFontColor, + id: dimensionId, + isShow: showDimensionLineSettingModal, + setIsShow: setShowDimensionLineSettingModal, + } + + const handlePopup = (type) => { + const id = uuidv4() + + switch (type) { + case 'dimensionLine': + setShowDimensionLineSettingModal(true) + addPopup(dimensionId, 2, ) + break + case 'font1': //문자 글꼴변경 + case 'font2': //흐름 방향 글꼴 변경 + case 'font3': //치수 글꼴변경 + case 'font4': //회로번호 글꼴변경 + addPopup(fontId, 2, ) + } + } + return ( <>
@@ -124,7 +181,7 @@ export default function SecondOption() {
{settingModalSecondOptions && settingModalSecondOptions.option3.map((item) => ( - ))} @@ -142,7 +199,8 @@ export default function SecondOption() { ))}
- -
-
-
- - - - {canGridOptionSeletorValue && ( - - )}
- {buttonAct === 1 && } - {buttonAct === 2 && } - {buttonAct === 3 && } +
+
+ + + + {canGridOptionSeletorValue && ( + + )} +
+ {buttonAct === 1 && } + {buttonAct === 2 && } + {buttonAct === 3 && } +
-
- + + ) } diff --git a/src/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting.jsx b/src/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting.jsx new file mode 100644 index 00000000..0f532ae9 --- /dev/null +++ b/src/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting.jsx @@ -0,0 +1,174 @@ +import WithDraggable from '@/components/common/draggable/withDraggable' +import { usePopup } from '@/hooks/usePopup' +import { v4 as uuidv4 } from 'uuid' +import ColorPickerModal from '@/components/common/color-picker/ColorPickerModal' +import { useEffect, useState } from 'react' +import FontSetting from '@/components/common/font/FontSetting' +import QSelectBox from '@/components/common/select/QSelectBox' +import { useMessage } from '@/hooks/useMessage' +/* + color: 치수선 색 + fontColor: 글꼴 색 + fontSize: 치수선 치수 색 + pixel: 치수선 두깨 +*/ +export default function DimensionLineSetting(props) { + const { + color, + setColor, + font, + setFont, + fontColor, + setFontColor, + fontSize, + setFontSize, + pixel, + setPixel, + setIsShow, + id, + pos = { x: 985, y: 180 }, + } = props + const { addPopup, closePopup } = usePopup() + const pixels = Array.from({ length: 5 }).map((_, index) => { + return { name: index + 1, value: index + 1 } + }) + const [originColor, setOriginColor] = useState(color) + const [originFont, setOriginFont] = useState(font) + const [originFontColor, setOriginFontColor] = useState(fontColor) + const [originFontSize, setOriginFontSize] = useState(fontSize) + const [originPixel, setOriginPixel] = useState(pixel) + const fontModalId = uuidv4() + const colorModalId = uuidv4() + const [showColorPickerModal, setShowColorPickerModal] = useState(false) + const [showFontModal, setShowFontModal] = useState(false) + const { getMessage } = useMessage() + const colorPickerProps = { + isShow: showColorPickerModal, + setIsShow: setShowColorPickerModal, + color: originColor, + setColor: setOriginColor, + id: colorModalId, + pos: { + x: 480, + y: -815, + }, + } + + const fontProps = { + isShow: showFontModal, + setIsShow: setShowFontModal, + color: originColor, + setColor: setOriginColor, + font: originFont, + setFont: setOriginFont, + fontColor: 'black', + setFontColor: setOriginFontColor, + fontSize: originFontSize, + setFontSize: setOriginFontSize, + id: fontModalId, + pos: { + x: 480, + y: -815, + }, + } + const popupHandle = (type) => { + switch (type) { + case 'color': + closePopup(fontModalId) + addPopup(colorModalId, 3, ) + break + case 'font': + closePopup(colorModalId) + addPopup(fontModalId, 3, ) + break + } + } + + useEffect(() => { + console.log(pixel) + if (pixel) { + setOriginPixel(pixels?.filter((data) => data.value === pixel)[0]) + } + }, []) + + return ( + +
+
+

{getMessage('modal.canvas.setting.font.plan.absorption.dimension.line')}

+ +
+
+
+ +
+
+
+ {getMessage('modal.canvas.setting.font.plan.absorption.dimension.line.font.size')} +
+ setOriginPixel(e)} /> +
+ pixel +
+
+ {getMessage('modal.canvas.setting.font.plan.absorption.dimension.line.color')} + +
+
+
+
{getMessage('modal.canvas.setting.font.plan.absorption.dimension.display')}
+
+
+
+ + 9,999 + + +
+
+
+
+
+ +
+
+
+
+ ) +} diff --git a/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx b/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx index 7e5230b1..1e421440 100644 --- a/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx +++ b/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx @@ -1,6 +1,5 @@ import { useMessage } from '@/hooks/useMessage' import WithDraggable from '@/components/common/draggable/WithDraggable' -import { useState } from 'react' import WallLine from '@/components/floor-plan/modal/wallLineOffset/type/WallLine' import Offset from '@/components/floor-plan/modal/wallLineOffset/type/Offset' import { useWallLineOffsetSetting } from '@/hooks/roofcover/useWallLineOffsetSetting' @@ -38,7 +37,7 @@ export default function WallLineOffsetSetting({ setShowWallLineOffsetSettingModa } return ( - +

{getMessage('modal.wallline.offset.setting')}

diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index 6800a5e8..04ba662a 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -30,6 +30,7 @@ export default function StuffDetail() { //form const formInitValue = { // 물건번호 T...(임시) R...(진짜) + planReqNo: '', //설계의뢰No dispCompanyName: '', //담당자 objectStatusId: '0', //물건구분(신축:0 기축 : 1) objectName: '', //물건명 @@ -70,7 +71,6 @@ export default function StuffDetail() { const [areaIdList, setAreaIdList] = useState([]) //발전시뮬레이션 리스트 - // const [windSpeedList, setWindSpeedList] = useState([]) //기준풍속 리스트 팝업으로이동 const [isFormValid, setIsFormValid] = useState(false) //임시저장, 진짜저장 버튼 컨트롤 const [showAddressButtonValid, setShowAddressButtonValid] = useState(false) //주소검색팝업 활성화 컨트롤 const [showDesignRequestButtonValid, setShowDesignRequestButtonValid] = useState(false) //설계의뢰팝업 활성화 컨트롤 @@ -109,7 +109,7 @@ export default function StuffDetail() { // 임시 1차점 판매점코드 saleStoreId=201TES01 // T01 //1차점 : X167 T01 - // get({ url: `/api/object/saleStore/TEMP02/list` }).then((res) => { + // get({ url: `/api/object/saleStore/T01/list` }).then((res) => { get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => { if (!isEmptyArray(res)) { const firstList = res.filter((row) => row.saleStoreLevel === '1') @@ -142,8 +142,8 @@ export default function StuffDetail() { // 임시 1차점 판매점코드 saleStoreId=201TES01 // T01 //1차점 : X167 - get({ url: `/api/object/saleStore/T01/list` }).then((res) => { - // get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => { + // get({ url: `/api/object/saleStore/T01/list` }).then((res) => { + get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => { if (!isEmptyArray(res)) { const firstList = res.filter((row) => row.saleStoreLevel === '1') const otherList = res.filter((row) => row.saleStoreLevel !== '1') @@ -208,7 +208,7 @@ export default function StuffDetail() { //팝업에서 넘어온 우편정보 const setZipInfo = (info) => { - // console.log('팝업에서 넘어온 데이타::::::::', info) + console.log('팝업에서 넘어온 우편 데이타::::::::', info) setPrefValue(info.prefId) form.setValue('prefId', info.prefId) form.setValue('prefName', info.address1) @@ -218,14 +218,33 @@ export default function StuffDetail() { //팝업에서 넘어온 설계의뢰 정보로 바꾸기 const setPlanReqInfo = (info) => { - console.log('팝업에서 넘어온 설계의뢰 정보::: ', info) - //building : 신축 기축 - //planReqName : 물건명 - //zipNo : 우편번호 - //도도부현 :address1 주소 : address2 미세팅 - //기준풍속 팝업열려면 setPrefValue(info.prefId) 필요 - //기준풍속 : - // form.setValue('dispCompanyName', info.planReqName) + form.setValue('planReqNo', info.planReqNo) + form.setValue('objectStatusId', info.building) + form.setValue('objectName', info.planReqName) + form.setValue('zipNo', info.zipNo) + form.setValue('address', info.address2) + // console.log('팝업에서 넘어온 설계의뢰 정보::: ', info) + + prefCodeList.map((row) => { + if (row.prefName == info.address1) { + setPrefValue(row.prefId) + form.setValue('prefId', row.prefId) + form.setValue('prefName', info.address1) + } + }) + + if (info.saleStoreLevel === '1') { + setSelOptions(info.saleStoreId) + form.setValue('saleStoreId', info.saleStoreName) + } else { + console.log('설계의뢰 정보가 2차점인경우::::::::::::', info) + } + form.setValue('windSpeed', info.windSpeed) + form.setValue('verticalSnowCover', info.verticalSnowCover) + form.setValue('surfaceType', info.surfaceType) + //설치 높이 installHeight + + form.setValue('remarks', info.remarks) } //팝업에서 넘어온 바람정보 @@ -475,7 +494,7 @@ export default function StuffDetail() {
- +
@@ -630,13 +654,6 @@ export default function StuffDetail() {
{prefCodeList?.length > 0 && ( - // 0 ? false : true} - onChange={handleAreaIdOnChange} - > - {areaIdList.map((row) => { - return ( - - ) - })} - - */}
- {/*
- -
*/} {getMessage('stuff.detail.windSpeedSpan')} )} - + diff --git a/src/components/management/StuffSubHeader.jsx b/src/components/management/StuffSubHeader.jsx new file mode 100644 index 00000000..1b10a149 --- /dev/null +++ b/src/components/management/StuffSubHeader.jsx @@ -0,0 +1,81 @@ +'use client' + +import { useEffect } from 'react' +import Link from 'next/link' +import Image from 'next/image' +import { useMessage } from '@/hooks/useMessage' +import { useRouter, useSearchParams } from 'next/navigation' +import { stuffSearchState } from '@/store/stuffAtom' +import { useSetRecoilState } from 'recoil' + +export default function StuffSubHeader({ type }) { + const { getMessage } = useMessage() + const router = useRouter() + + const setSchObjectNo = useSetRecoilState(stuffSearchState) + useEffect(() => { + window.scrollTo(0, 0) + }, []) + + const searchParams = useSearchParams() + const objectNo = searchParams.get('objectNo') //url에서 물건번호 꺼내서 바로 set + + // url에 물건번호로 도면작성화면으로 이동 + const moveFloorPlan = () => { + setSchObjectNo(objectNo) + + router.push('/floor-plan') + } + + return ( +
+
+ {type === 'list' && ( + +

{getMessage('header.menus.management')}

+ + )} + {type === 'temp' && ( +
    +
  • + + {getMessage('stuff.temp.subTitle')} + +
  • +
+ )} + {type === 'detail' && ( + + )} + + {type !== 'detail' && ( +
    +
  • + + react + +
  • +
  • + {getMessage('header.menus.management')} +
  • +
  • + {getMessage('header.menus.management.stuff')} +
  • +
+ )} +
+
+ ) +} diff --git a/src/components/management/popup/PlanRequestPop.jsx b/src/components/management/popup/PlanRequestPop.jsx index ab2a836c..53d30447 100644 --- a/src/components/management/popup/PlanRequestPop.jsx +++ b/src/components/management/popup/PlanRequestPop.jsx @@ -1,16 +1,12 @@ -import React, { useState, useRef, useEffect } from 'react' -import { useForm } from 'react-hook-form' +import React, { useState, useRef } from 'react' import { useAxios } from '@/hooks/useAxios' import { globalLocaleStore } from '@/store/localeAtom' -import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' -import FindAddressPopQGrid from './FindAddressPopQGrid' +import { useRecoilValue } from 'recoil' import { useMessage } from '@/hooks/useMessage' import { isNotEmptyArray } from '@/util/common-utils' import SingleDatePicker from '@/components/common/datepicker/SingleDatePicker' import dayjs from 'dayjs' import PlanRequestPopQGrid from './PlanRequestPopQGrid' -import { sessionStore } from '@/store/commonAtom' -import { planReqSearchState } from '@/store/planReqAtom' import { isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils' import Select from 'react-select' @@ -24,7 +20,7 @@ export default function PlanRequestPop(props) { const [planReqObject, setPlanReqObject] = useState({}) - const { get, promiseGet } = useAxios(globalLocaleState) + const { promiseGet } = useAxios(globalLocaleState) const { getMessage } = useMessage() //Select ref @@ -43,9 +39,6 @@ export default function PlanRequestPop(props) { setStartDate: setEndDate, } - const resetPlanReqRecoil = useResetRecoilState(planReqSearchState) - - const [planReqSearch, setPlanReqSearch] = useRecoilState(planReqSearchState) const [schPlanReqNo, setSchPlanReqNo] = useState('') //설계의뢰번호 const [schTitle, setSchTitle] = useState('') //안건명 const [schAddress, setSchAddress] = useState('') //도도부현 @@ -66,7 +59,6 @@ export default function PlanRequestPop(props) { setEndDate(dayjs(new Date()).format('YYYY-MM-DD')) setSchPlanStatCd('') handleClear() //셀렉트 자동완성 초기화 - resetPlanReqRecoil() } //셀렉트 자동완성 초기화 @@ -82,22 +74,12 @@ export default function PlanRequestPop(props) { // console.log('E::::::::', key) if (isObjectNotEmpty(key)) { setSchPlanStatCd(key.value) - setPlanReqSearch({ - ...planReqSearch, - schPlanStatCd: key.value, - }) } else { //X누름 setSchPlanStatCd('') - setPlanReqSearch({ ...planReqSearch, schPlanStatCd: '' }) } } - useEffect(() => { - setStartDate(planReqSearch?.schStartDt ? planReqSearch.schStartDt : dayjs(new Date()).add(-3, 'month').format('YYYY-MM-DD')) - setEndDate(planReqSearch?.schEndDt ? planReqSearch.schEndDt : dayjs(new Date()).format('YYYY-MM-DD')) - }, [planReqSearch]) - // 조회 const onSubmit = (page, type) => { const params = { @@ -105,13 +87,13 @@ export default function PlanRequestPop(props) { // saleStoreLevel: '1', saleStoreId: props?.otherSaleStoreId ? props.otherSaleStoreId : props.saleStoreId, saleStoreLevel: props?.otherSaleStoreLevel ? props.otherSaleStoreLevel : props.saleStoreLevel, - schPlanReqNo: planReqSearch?.schPlanReqNo ? planReqSearch.schPlanReqNo : schPlanReqNo, - schTitle: planReqSearch?.schTitle ? planReqSearch.schTitle : schTitle, - schAddress: planReqSearch?.schAddress ? planReqSearch.schAddress : schAddress, - schSaleStoreName: planReqSearch?.schSaleStoreName ? planReqSearch.schSaleStoreName : schSaleStoreName, - schPlanReqName: planReqSearch?.schPlanReqName ? planReqSearch.schPlanReqName : schPlanReqName, - schPlanStatCd: planReqSearch?.schPlanStatCd ? planReqSearch.schPlanStatCd : schPlanStatCd, - schDateGbn: planReqSearch?.schDateGbn ? planReqSearch.schDateGbn : schDateGbn, + schPlanReqNo: schPlanReqNo, + schTitle: schTitle, + schAddress: schAddress, + schSaleStoreName: schSaleStoreName, + schPlanReqName: schPlanReqName, + schPlanStatCd: schPlanStatCd, + schDateGbn: schDateGbn, schStartDt: dayjs(startDate).format('YYYY-MM-DD'), schEndDt: dayjs(endDate).format('YYYY-MM-DD'), startRow: type === 'S' ? (1 - 1) * pageSize + 1 : (page - 1) * pageSize + 1, @@ -122,7 +104,6 @@ export default function PlanRequestPop(props) { } else { setPageNo(page) } - // console.log(params) const apiUrl = `/api/object/planReq/list?${queryStringFormatter(params)}` promiseGet({ url: apiUrl }).then((res) => { @@ -142,16 +123,51 @@ export default function PlanRequestPop(props) { } // 페이징 현재페이지 변경 const handleChangePage = (page) => { - setPlanReqSearch({ - ...planReqSearch, - startRow: (page - 1) * pageSize + 1, - endRow: page * pageSize, - }) setPageNo(page) onSubmit(page, 'P') } + //페이지 갯수 변경 이벤트 + const onChangePerPage = (e) => { + const params = { + // saleStoreId: 'T100', + // saleStoreLevel: '1', + saleStoreId: props?.otherSaleStoreId ? props.otherSaleStoreId : props.saleStoreId, + saleStoreLevel: props?.otherSaleStoreLevel ? props.otherSaleStoreLevel : props.saleStoreLevel, + schTitle: schTitle, + schAddress: schAddress, + schPlanReqNo: schPlanReqNo, + schSaleStoreName: schSaleStoreName, + schPlanReqName: schPlanReqName, + schPlanStatCd: schPlanStatCd, + schDateGbn: schDateGbn, + schStartDt: dayjs(startDate).format('YYYY-MM-DD'), + schEndDt: dayjs(endDate).format('YYYY-MM-DD'), + startRow: (1 - 1) * e.target.value + 1, + endRow: 1 * e.target.value, + } + + setPageSize(e.target.value) + setPageNo(1) + + const apiUrl = `/api/object/planReq/list?${queryStringFormatter(params)}` + promiseGet({ url: apiUrl }).then((res) => { + if (res.status === 200) { + if (isNotEmptyArray(res.data.data)) { + setGridProps({ ...gridProps, gridData: res.data.data, gridCount: res.data.data[0].totCnt }) + setTotalCount(res.data.data[0].totCnt) + } else { + setGridProps({ ...gridProps, gridData: [], gridCount: 0 }) + setTotalCount(0) + } + } else { + setGridProps({ ...gridProps, gridData: [], gridCount: 0 }) + setTotalCount(0) + } + }) + } + const [gridProps, setGridProps] = useState({ gridData: [], isPageable: false, @@ -292,10 +308,9 @@ export default function PlanRequestPop(props) { { setSchPlanReqNo(e.target.value) - setPlanReqSearch({ ...planReqSearch, schPlanReqNo: e.target.value }) }} />
@@ -306,10 +321,9 @@ export default function PlanRequestPop(props) { { setSchTitle(e.target.value) - setPlanReqSearch({ ...planReqSearch, schTitle: e.target.value }) }} />
@@ -320,10 +334,9 @@ export default function PlanRequestPop(props) { { setSchAddress(e.target.value) - setPlanReqSearch({ ...planReqSearch, schAddress: e.target.value }) }} />
@@ -336,10 +349,9 @@ export default function PlanRequestPop(props) { { setSchSaleStoreName(e.target.value) - setPlanReqSearch({ ...planReqSearch, schSaleStoreName: e.target.value }) }} />
@@ -350,10 +362,9 @@ export default function PlanRequestPop(props) { { setSchPlanReqName(e.target.value) - setPlanReqSearch({ ...planReqSearch, schPlanReqName: e.target.value }) }} />
@@ -386,11 +397,10 @@ export default function PlanRequestPop(props) { type="radio" name="radio04" id="ra07" - checked={planReqSearch?.schDateGbn === 'S' ? true : false} + checked={schDateGbn === 'S' ? true : false} value={'S'} onChange={(e) => { setSchDateGbn(e.target.value) - setPlanReqSearch({ ...planReqSearch, schDateGbn: e.target.value }) }} /> @@ -400,11 +410,10 @@ export default function PlanRequestPop(props) { type="radio" name="radio04" id="ra08" - checked={planReqSearch?.schDateGbn === 'R' ? true : false} + checked={schDateGbn === 'R' ? true : false} value={'R'} onChange={(e) => { setSchDateGbn(e.target.value) - setPlanReqSearch({ ...planReqSearch, schDateGbn: e.target.value }) }} /> @@ -427,7 +436,16 @@ export default function PlanRequestPop(props) {
-
Plan List
+
+
Plan List
+
+ +
+
diff --git a/src/hooks/common/useCommonCode.js b/src/hooks/common/useCommonCode.js new file mode 100644 index 00000000..17c2de8b --- /dev/null +++ b/src/hooks/common/useCommonCode.js @@ -0,0 +1,33 @@ +import { useEffect } from 'react' +import { useRecoilState } from 'recoil' +import { commonCodeState } from '@/store/commonCodeAtom' +import { isObjectNotEmpty } from '@/util/common-utils' +import { useAxios } from '../useAxios' + +export const useCommonCode = () => { + const [commonCode, setCommonCode] = useRecoilState(commonCodeState) + const { promiseGet } = useAxios() + + const findCommonCode = (key) => { + // const arr = commonCode[key] + // return arr.sort((a, b) => a.clPriority - b.clPriority) + return commonCode[key] + } + + useEffect(() => { + const getCommonCode = async () => { + await promiseGet({ url: '/api/commcode/qc-comm-code' }).then((res) => { + setCommonCode(Object.groupBy(res.data, ({ clHeadCd }) => clHeadCd)) + }) + } + + if (!isObjectNotEmpty(commonCode)) { + getCommonCode() + } + }, []) + + return { + commonCode, + findCommonCode, + } +} diff --git a/src/hooks/object/useObjectBatch.js b/src/hooks/object/useObjectBatch.js index e18b13e3..24e4bf07 100644 --- a/src/hooks/object/useObjectBatch.js +++ b/src/hooks/object/useObjectBatch.js @@ -1,14 +1,13 @@ 'use client' import { useMessage } from '@/hooks/useMessage' -import { useRecoilState, useRecoilValue } from 'recoil' +import { useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' -import { INPUT_TYPE, BATCH_TYPE } from '@/common/common' +import { BATCH_TYPE, INPUT_TYPE } from '@/common/common' import { useEvent } from '@/hooks/useEvent' -import { polygonToTurfPolygon, rectToPolygon, triangleToPolygon, pointsToTurfPolygon, setSurfaceShapePattern } from '@/util/canvas-util' +import { pointsToTurfPolygon, polygonToTurfPolygon, rectToPolygon } from '@/util/canvas-util' import { useSwal } from '@/hooks/useSwal' import * as turf from '@turf/turf' -import { QPolygon } from '@/components/fabric/QPolygon' -import { drawDirectionArrow } from '@/util/qpolygon-utils' +import { usePolygon } from '@/hooks/usePolygon' export function useObjectBatch() { const { getMessage } = useMessage() @@ -16,6 +15,8 @@ export function useObjectBatch() { const { addCanvasMouseEventListener, initEvent } = useEvent() const { swalFire } = useSwal() + const { drawDirectionArrow } = usePolygon() + const applyOpeningAndShadow = (objectPlacement, buttonAct, surfaceShapePolygons) => { const selectedType = objectPlacement.typeRef.current.find((radio) => radio.checked).value const isCrossChecked = buttonAct === 1 ? objectPlacement.isCrossRef.current.checked : false diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index bc55c921..6eba271f 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -2,12 +2,14 @@ import { useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' import { useEffect, useState } from 'react' import { setSurfaceShapePattern } from '@/util/canvas-util' -import { drawDirectionArrow, splitPolygonWithLines } from '@/util/qpolygon-utils' +import { splitPolygonWithLines } from '@/util/qpolygon-utils' import { useSwal } from '@/hooks/useSwal' +import { usePolygon } from '@/hooks/usePolygon' // 지붕면 할당 export function useRoofAllocationSetting(setShowRoofAllocationSettingModal) { const canvas = useRecoilValue(canvasState) + const { drawDirectionArrow } = usePolygon() const { swalFire } = useSwal() diff --git a/src/hooks/surface/usePlacementShapeDrawing.js b/src/hooks/surface/usePlacementShapeDrawing.js index 123e991d..40d25bf0 100644 --- a/src/hooks/surface/usePlacementShapeDrawing.js +++ b/src/hooks/surface/usePlacementShapeDrawing.js @@ -14,7 +14,7 @@ import { useTempGrid } from '@/hooks/useTempGrid' import { useEffect, useRef } from 'react' import { distanceBetweenPoints, setSurfaceShapePattern } from '@/util/canvas-util' import { fabric } from 'fabric' -import { calculateAngle, drawDirectionArrow } from '@/util/qpolygon-utils' +import { calculateAngle } from '@/util/qpolygon-utils' import { placementShapeDrawingAngle1State, placementShapeDrawingAngle2State, @@ -37,7 +37,7 @@ export function usePlacementShapeDrawing(setShowPlaceShapeDrawingModal) { useEvent() const { getIntersectMousePoint } = useMouse() const { addLine, removeLine } = useLine() - const { addPolygonByLines } = usePolygon() + const { addPolygonByLines, drawDirectionArrow } = usePolygon() const { tempGridMode } = useTempGrid() const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState) diff --git a/src/hooks/useCanvasEvent.js b/src/hooks/useCanvasEvent.js index cf3b6244..4f041e79 100644 --- a/src/hooks/useCanvasEvent.js +++ b/src/hooks/useCanvasEvent.js @@ -1,15 +1,17 @@ import { useState } from 'react' import { useRecoilState, useRecoilValue } from 'recoil' -import { canvasSizeState, currentObjectState, fontFamilyState, fontSizeState } from '@/store/canvasAtom' +import { canvasSizeState, canvasState, canvasZoomState, currentObjectState, fontFamilyState, fontSizeState } from '@/store/canvasAtom' import { QPolygon } from '@/components/fabric/QPolygon' // 캔버스에 필요한 이벤트 export function useCanvasEvent() { - const [canvas, setCanvasForEvent] = useState(null) + const canvas = useRecoilValue(canvasState) + const [canvasForEvent, setCanvasForEvent] = useState(null) const [currentObject, setCurrentObject] = useRecoilState(currentObjectState) const canvasSize = useRecoilValue(canvasSizeState) const fontSize = useRecoilValue(fontSizeState) const fontFamily = useRecoilValue(fontFamilyState) + const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) // 기본적인 이벤트 필요시 추가 const attachDefaultEventOnCanvas = () => { @@ -167,7 +169,6 @@ export function useCanvasEvent() { const whiteList = ['mouseLine', 'guideLine'] if (whiteList.includes(e.target.name)) { - return } }, } @@ -336,8 +337,16 @@ export function useCanvasEvent() { }) } + const handleZoomClear = () => { + setCanvasZoom(100) + canvas.set({ zoom: 1 }) + canvas.viewportTransform = [1, 0, 0, 1, 0, 0] + canvas.renderAll() + } + return { setCanvasForEvent, attachDefaultEventOnCanvas, + handleZoomClear, } } diff --git a/src/hooks/useContextMenu.js b/src/hooks/useContextMenu.js index 665617ef..3fb6f164 100644 --- a/src/hooks/useContextMenu.js +++ b/src/hooks/useContextMenu.js @@ -1,16 +1,18 @@ import { useRecoilValue } from 'recoil' -import { currentMenuState } from '@/store/canvasAtom' +import { currentMenuState, currentObjectState } from '@/store/canvasAtom' import { useEffect, useState } from 'react' import { MENU } from '@/common/common' import AuxiliaryMove from '@/components/floor-plan/modal/auxiliary/AuxiliaryMove' import AuxiliarySize from '@/components/floor-plan/modal/auxiliary/AuxiliarySize' -export function useContextMenu() { +export function useContextMenu({ externalFn }) { const currentMenu = useRecoilValue(currentMenuState) const [contextMenu, setContextMenu] = useState([[]]) const [currentContextMenu, setCurrentContextMenu] = useState(null) + const currentObject = useRecoilValue(currentObjectState) - useEffect(() => { + const currentMenuSetting = () => { + console.log(currentMenu) switch (currentMenu) { case MENU.PLAN_DRAWING: setContextMenu([ @@ -50,6 +52,13 @@ export function useContextMenu() { case MENU.ROOF_COVERING.DEFAULT: setContextMenu([ [ + { + id: 'refresh', + name: '새로고침', + fn: () => { + externalFn.handleZoomClear() + }, + }, { id: 'roofMaterialPlacement', name: '지붕재 배치', @@ -150,8 +159,121 @@ export function useContextMenu() { setContextMenu([]) break } + } + useEffect(() => { + currentMenuSetting() }, [currentMenu]) + useEffect(() => { + console.log('currentObject', currentObject) + console.log('currentMenu', currentMenu) + if (currentObject?.name) { + console.log(currentObject) + switch (currentObject.name) { + case 'triangleDormer': + setContextMenu([ + [ + { + id: 'sizeEdit', + name: '사이즈 변경', + }, + { + id: 'dormerRemove', + name: '삭제(D)', + }, + { + id: 'dormerMove', + name: '이동(M)', + }, + { + id: 'dormerCopy', + name: '복사(C)', + }, + { + id: 'roofMaterialEdit', + name: '지붕재 변경', + }, + { + id: 'dormerOffset', + name: '도머 오프셋', + }, + ], + ]) + break + case 'roof': + setContextMenu([ + [ + { + id: 'sizeEdit', + name: '사이즈 변경', + }, + { + id: 'roofMaterialRemove', + name: '삭제(D)', + }, + { + id: 'roofMaterialMove', + name: '이동(M)', + }, + { + id: 'roofMaterialCopy', + name: '복사(C)', + }, + ], + [ + { + id: 'roofMaterialEdit', + name: '지붕재 변경', + }, + { + id: 'linePropertyEdit', + name: '각 변 속성 변경', + }, + { + id: 'flowDirectionEdit', + name: '흐름 뱡향 변경', + }, + ], + ]) + break + case 'opening': + setContextMenu([ + [ + { + id: 'sizeEdit', + name: '사이즈 변경', + }, + { + id: 'openingRemove', + name: '삭제(D)', + }, + { + id: 'openingMove', + name: '이동(M)', + }, + { + id: 'openingCopy', + name: '복사(C)', + }, + { + id: 'openingOffset', + name: '개구 오프셋', + }, + ], + ]) + break + default: + currentMenuSetting() + } + } else { + currentMenuSetting() + } + }, [currentObject]) + + useEffect(() => { + console.log(currentContextMenu) + }, [currentContextMenu]) + return { contextMenu, currentContextMenu, diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 7289a0d3..514c6592 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -4,9 +4,11 @@ import { fabric } from 'fabric' import { getDirectionByPoint } from '@/util/canvas-util' import { QPolygon } from '@/components/fabric/QPolygon' import { isSamePoint } from '@/util/qpolygon-utils' +import { flowDisplaySelector } from '@/store/settingAtom' export const usePolygon = () => { const canvas = useRecoilValue(canvasState) + const isFlowDisplay = useRecoilValue(flowDisplaySelector) const fontSize = useRecoilValue(fontSizeState) const fontFamily = useRecoilValue(fontFamilyState) @@ -100,9 +102,323 @@ export const usePolygon = () => { canvas.renderAll() } + /** + * poolygon의 방향에 따라 화살표를 추가한다. + * @param polygon + */ + const drawDirectionArrow = (polygon) => { + const direction = polygon.direction + if (!direction) { + return + } + + polygon.canvas + .getObjects() + .filter((obj) => obj.name === 'directionText' && obj.parent === polygon.arrow) + .forEach((obj) => polygon.canvas.remove(obj)) + + let arrow = null + let points = [] + + if (polygon.arrow) { + polygon.canvas.remove(polygon.arrow) + } + + let centerPoint = { x: polygon.left, y: polygon.top } + let stickeyPoint + + const polygonMaxX = Math.max(...polygon.getCurrentPoints().map((point) => point.x)) + const polygonMinX = Math.min(...polygon.getCurrentPoints().map((point) => point.x)) + const polygonMaxY = Math.max(...polygon.getCurrentPoints().map((point) => point.y)) + const polygonMinY = Math.min(...polygon.getCurrentPoints().map((point) => point.y)) + + switch (direction) { + case 'north': + points = [ + { x: centerPoint.x, y: polygonMinY - 50 }, + { x: centerPoint.x + 20, y: polygonMinY - 50 }, + { x: centerPoint.x + 20, y: polygonMinY - 80 }, + { x: centerPoint.x + 50, y: polygonMinY - 80 }, + { x: centerPoint.x, y: polygonMinY - 110 }, + { x: centerPoint.x - 50, y: polygonMinY - 80 }, + { x: centerPoint.x - 20, y: polygonMinY - 80 }, + { x: centerPoint.x - 20, y: polygonMinY - 50 }, + ] + + stickeyPoint = { x: centerPoint.x, y: polygonMinY - 110 } + break + case 'south': + points = [ + { x: centerPoint.x, y: polygonMaxY + 50 }, + { x: centerPoint.x + 20, y: polygonMaxY + 50 }, + { x: centerPoint.x + 20, y: polygonMaxY + 80 }, + { x: centerPoint.x + 50, y: polygonMaxY + 80 }, + { x: centerPoint.x, y: polygonMaxY + 110 }, + { x: centerPoint.x - 50, y: polygonMaxY + 80 }, + { x: centerPoint.x - 20, y: polygonMaxY + 80 }, + { x: centerPoint.x - 20, y: polygonMaxY + 50 }, + ] + stickeyPoint = { x: centerPoint.x, y: polygonMaxY + 110 } + break + case 'west': + points = [ + { x: polygonMinX - 50, y: centerPoint.y }, + { x: polygonMinX - 50, y: centerPoint.y + 20 }, + { x: polygonMinX - 80, y: centerPoint.y + 20 }, + { x: polygonMinX - 80, y: centerPoint.y + 50 }, + { x: polygonMinX - 110, y: centerPoint.y }, + { x: polygonMinX - 80, y: centerPoint.y - 50 }, + { x: polygonMinX - 80, y: centerPoint.y - 20 }, + { x: polygonMinX - 50, y: centerPoint.y - 20 }, + ] + + stickeyPoint = { x: polygonMinX - 110, y: centerPoint.y } + break + case 'east': + points = [ + { x: polygonMaxX + 50, y: centerPoint.y }, + { x: polygonMaxX + 50, y: centerPoint.y + 20 }, + { x: polygonMaxX + 80, y: centerPoint.y + 20 }, + { x: polygonMaxX + 80, y: centerPoint.y + 50 }, + { x: polygonMaxX + 110, y: centerPoint.y }, + { x: polygonMaxX + 80, y: centerPoint.y - 50 }, + { x: polygonMaxX + 80, y: centerPoint.y - 20 }, + { x: polygonMaxX + 50, y: centerPoint.y - 20 }, + ] + + stickeyPoint = { x: polygonMaxX + 110, y: centerPoint.y } + break + } + + arrow = new fabric.Polygon(points, { + selectable: false, + name: 'arrow', + fill: 'transparent', + stroke: 'black', + direction: direction, + parent: polygon, + stickeyPoint: stickeyPoint, + visible: isFlowDisplay, + }) + + polygon.arrow = arrow + polygon.canvas.add(arrow) + polygon.canvas.renderAll() + drawDirectionStringToArrow(polygon.canvas, 0) + } + + /** + * 방향을 나타낸 화살표에 각도에 따라 글씨 추가 + * @param canvas + * @param compass + */ + const drawDirectionStringToArrow = (canvas, compass = 0) => { + const arrows = canvas?.getObjects().filter((obj) => obj.name === 'arrow') + + if (arrows.length === 0) { + return + } + + const eastArrows = arrows.filter((arrow) => arrow.direction === 'east') + const westArrows = arrows.filter((arrow) => arrow.direction === 'west') + const northArrows = arrows.filter((arrow) => arrow.direction === 'north') + const southArrows = arrows.filter((arrow) => arrow.direction === 'south') + + let southText = '南' + let eastText = '東' + let westText = '西' + let northText = '北' + + if (compass === 0 || compass === 360) { + // 남,동,서 가능 + // 그대로 + } else if (compass < 45) { + //남(남남동),동(동북동),서(서남서) 가능 + //북(북북서) + southText = '南南東' + eastText = '東北東' + westText = '西南西' + northText = '北北西' + } else if (compass === 45) { + // 남, 서 가능 + // 남(남동) + // 서(남서) + // 북(북서) + // 동(북동) + southText = '南東' + westText = '南西' + northText = '北西' + eastText = '北東' + } else if (compass < 90) { + // 북(서북서) + // 동 (북북동) + // 남(동남동) + // 서(남남서) + northText = '北西北' + eastText = '北北東' + southText = '東南東' + westText = '南南西' + } else if (compass === 90) { + // 동(북) + // 서(남) + // 남(동) + // 북(서) + eastText = '北' + westText = '南' + southText = '東' + northText = '西' + } else if (compass < 135) { + // 남,서,북 가능 + // 동(북북서) + // 서(남남동) + // 남(동북동) + // 북(서남서) + eastText = '北北西' + westText = '南南東' + southText = '東北東' + northText = '西南西' + } else if (compass === 135) { + // 서,북 가능 + + // 서(남동) + // 북(남서) + // 남(북동) + // 동(북서) + + westText = '南東' + northText = '南西' + southText = '北東' + eastText = '北西' + } else if (compass < 180) { + // 북,동,서 가능 + // 북(남남서) + // 동(서북서) + // 남(북북동) + // 서(동남동) + + northText = '南南西' + eastText = '西北西' + southText = '北北東' + westText = '東南東' + } else if (compass === 180) { + // 북,동,서 가능 + // 북(남) + // 동(서) + // 남(북) + // 서(동) + northText = '南' + eastText = '西' + southText = '北' + westText = '東' + } else if (compass < 225) { + // 서,북,동 가능 + // 북(남남동) + // 동(서남서) + // 남(북북서) + // 서(동남동) + northText = '南南東' + eastText = '西南西' + southText = '北北西' + westText = '東南東' + } else if (compass === 225) { + // 북,동 가능 + // 북(남동) + // 동(남서) + // 남(북서) + // 서(북동) + northText = '南東' + eastText = '南西' + southText = '北西' + westText = '北東' + } else if (compass < 270) { + // 북동남 가능 + // 북(동남동) + // 동(남남서) + // 남(서북서) + // 서(북북동) + northText = '東南東' + eastText = '南南西' + southText = '西北西' + westText = '北北東' + } else if (compass === 270) { + // 북동남 가능 + // 북(동) + // 동(남) + // 남(서) + // 서(북) + northText = '東' + eastText = '南' + southText = '西' + westText = '北' + } else if (compass < 315) { + // 북,동,남 가능 + // 북(동북동) + // 동(남남동) + // 남(서남서) + // 서(북북서) + northText = '東北東' + eastText = '南南東' + southText = '西南西' + westText = '北北西' + } else if (compass === 315) { + // 동,남 가능 + // 북(북동) + // 동(남동) + // 남(남서) + // 서(북서) + northText = '北東' + eastText = '南東' + southText = '南西' + westText = '北西' + } else if (compass < 360) { + // 남,동,서 가능 + // 북(북북동) + // 동(동남동) + // 남(남남서) + // 서(서북서) + northText = '北北東' + eastText = '東南東' + southText = '南南西' + westText = '西北西' + } + + clearDirectionText(canvas) + + addTextByArrows(eastArrows, eastText, canvas) + addTextByArrows(westArrows, westText, canvas) + addTextByArrows(northArrows, northText, canvas) + addTextByArrows(southArrows, southText, canvas) + } + + const clearDirectionText = (canvas) => { + const texts = canvas.getObjects().filter((obj) => obj.name === 'directionText') + texts.forEach((text) => { + canvas.remove(text) + }) + } + + const addTextByArrows = (arrows, txt, canvas) => { + arrows.forEach((arrow, index) => { + const text = new fabric.Text(`${txt}${index + 1}`, { + fontSize: arrow.parent.fontSize, + fill: 'black', + originX: 'center', + originY: 'center', + name: 'directionText', + selectable: false, + left: arrow.stickeyPoint.x, + top: arrow.stickeyPoint.y, + parent: arrow, + visible: isFlowDisplay, + }) + canvas.add(text) + }) + } + return { addPolygon, addPolygonByLines, removePolygon, + drawDirectionArrow, } } diff --git a/src/hooks/usePopup.js b/src/hooks/usePopup.js new file mode 100644 index 00000000..f62fd6c5 --- /dev/null +++ b/src/hooks/usePopup.js @@ -0,0 +1,39 @@ +import { useRecoilState } from 'recoil' +import { popupState } from '@/store/popupAtom' +import { useEffect } from 'react' + +export function usePopup() { + const [popup, setPopup] = useRecoilState(popupState) + + useEffect(() => { + console.log(popup) + }, [popup]) + + const addPopup = (id, depth, component) => { + setPopup({ children: [...filterDepth(depth), { id: id, depth: depth, component: component }] }) + } + + const closePopup = (id) => { + setPopup({ children: [...popup.children.filter((child) => child.id !== id)] }) + } + + const closeAll = () => { + setPopup({ children: [] }) + } + + const closePrevPopup = () => { + setPopup({ children: [...popup.children.slice(popup.children.length - 1)] }) + } + + const filterDepth = (depth) => { + return [...popup.children.filter((child) => child.depth !== depth)] + } + + return { + popup, + setPopup, + addPopup, + closePopup, + closeAll, + } +} diff --git a/src/hooks/useToast.js b/src/hooks/useToast.js deleted file mode 100644 index d604c42d..00000000 --- a/src/hooks/useToast.js +++ /dev/null @@ -1,35 +0,0 @@ -import { toast } from 'react-toastify' - -const toastDefaultOptions = { - position: 'top-right', - autoClose: 3000, - draggable: false, - hideProgressBar: false, - rtl: false, - pauseOnFocusLoss: true, - pauseOnHover: true, - theme: 'light', - limit: 2, - closeOnClick: true, -} - -const toastUp = (props) => { - // type TypeOptions = 'info' | 'success' | 'warning' | 'error' | 'default' - const { message, type = 'info', options } = props - const customOptions = { ...toastDefaultOptions, ...options } - - switch (type) { - case 'info': - return toast.info(message, customOptions) - case 'success': - return toast.success(message, customOptions) - case 'warning': - return toast.warn(message, customOptions) - case 'error': - return toast.error(message, customOptions) - default: - return toast(message, customOptions) - } -} - -export { toastUp } diff --git a/src/lib/canvas.js b/src/lib/canvas.js index 5bd6b419..f8855e33 100644 --- a/src/lib/canvas.js +++ b/src/lib/canvas.js @@ -1,43 +1,43 @@ 'use server' -import { PrismaClient } from '@prisma/client' +// import { PrismaClient } from '@prisma/client' import fs from 'fs/promises' -const prisma = new PrismaClient() +// const prisma = new PrismaClient() const imagePath = 'public/canvasState' -export const getTests = () => { - return prisma.test.findMany() -} +// export const getTests = () => { +// return prisma.test.findMany() +// } -export const insertTest = async (param) => { - return prisma.test.create({ - data: { - content: param, - }, - }) -} +// export const insertTest = async (param) => { +// return prisma.test.create({ +// data: { +// content: param, +// }, +// }) +// } -export const getCanvasStateAll = () => { - return prisma.canvas.findMany() -} +// export const getCanvasStateAll = () => { +// return prisma.canvas.findMany() +// } -export const getCanvasState = () => { - return prisma.canvas.findFirst({ - where: { - loginId: 'test', - }, - orderBy: { - id: 'desc', - }, - }) -} +// export const getCanvasState = () => { +// return prisma.canvas.findFirst({ +// where: { +// loginId: 'test', +// }, +// orderBy: { +// id: 'desc', +// }, +// }) +// } -export const insertCanvasState = (param) => { - return prisma.canvas.create({ - data: param, - }) -} +// export const insertCanvasState = (param) => { +// return prisma.canvas.create({ +// data: param, +// }) +// } export const writeImage = async (title, data) => { // 해당 경로에 Directory 가 없다면 생성 diff --git a/src/lib/prisma.js b/src/lib/prisma.js deleted file mode 100644 index aa946098..00000000 --- a/src/lib/prisma.js +++ /dev/null @@ -1,14 +0,0 @@ -import { PrismaClient } from '@prisma/client' - -let prisma - -if (process.env.NODE_ENV === 'production') { - prisma = new PrismaClient() -} else { - if (!global.prisma) { - global.prisma = new PrismaClient() - } - prisma = global.prisma -} - -export default prisma diff --git a/src/locales/ja.json b/src/locales/ja.json index 3ccbdf40..20fea301 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -156,6 +156,7 @@ "plan.menu.simulation.pdf": "PDF", "plan.mode.vertical.horizontal": "垂直水平モード", "plan.mode.free": "프리 모드(JA)", + "modal.font.setting": "フォント設定", "modal.canvas.setting": "Canvas設定", "modal.canvas.setting.display": "ディスプレイ設定", "modal.canvas.setting.font.plan": " フォントと図面サイズの設定", @@ -198,6 +199,9 @@ "modal.canvas.setting.font.plan.absorption.medium": "中", "modal.canvas.setting.font.plan.absorption.large": "ティーン", "modal.canvas.setting.font.plan.absorption.dimension.line": "寸法線の設定", + "modal.canvas.setting.font.plan.absorption.dimension.line.font.size": "寸法線の線太さ", + "modal.canvas.setting.font.plan.absorption.dimension.line.color": "寸法線の線の色", + "modal.canvas.setting.font.plan.absorption.dimension.display": "見る", "modal.canvas.setting.font.plan.absorption.plan.size.setting": "図面サイズの設定", "modal.canvas.setting.first.option.info": "※図面に表示する項目をクリックすると適用されます。", "modal.canvas.setting.first.option.alloc": "할당표시", @@ -247,6 +251,8 @@ "modal.object.setting.direction.select": "方向の選択", "modal.placement.surface.setting.info": "ⓘ ①の長さ入力後に対角線の長さを入力すると、②の長さを自動計算します。", "modal.placement.surface.setting.diagonal.length": "斜めの長さ", + "modal.color.picker.title": "色の設定", + "modal.color.picker.default.color": "基本色", "plan.message.confirm.save": "PLAN을 저장하시겠습니까?", "plan.message.confirm.copy": "PLAN을 복사하시겠습니까?", "plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?", @@ -453,6 +459,7 @@ "stuff.addressPopup.btn1": "閉じる", "stuff.addressPopup.btn2": "住所適用", "stuff.planReqPopup.title": "設計依頼のインポート", + "stuff.temp.subTitle": "商品情報", "stuff.detail.required": "必須入力項目", "stuff.detail.planReqNo": "設計依頼No.", "stuff.detail.dispCompanyName": "担当者", diff --git a/src/locales/ko.json b/src/locales/ko.json index d87551a5..b853a3d0 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -160,6 +160,7 @@ "plan.menu.simulation.pdf": "PDF", "plan.mode.vertical.horizontal": "수직 수평 모드", "plan.mode.free": "프리 모드", + "modal.font.setting": "글꼴 설정", "modal.canvas.setting": "Canvas 설정", "modal.canvas.setting.display": "디스플레이 설정", "modal.canvas.setting.font.plan": "글꼴 및 도면 크기 설정", @@ -203,6 +204,9 @@ "modal.canvas.setting.font.plan.absorption.medium": "중", "modal.canvas.setting.font.plan.absorption.large": "대", "modal.canvas.setting.font.plan.absorption.dimension.line": "치수선 설정", + "modal.canvas.setting.font.plan.absorption.dimension.line.font.size": "치수선의 굵기", + "modal.canvas.setting.font.plan.absorption.dimension.line.color": "치수선의 색", + "modal.canvas.setting.font.plan.absorption.dimension.display": "보기", "modal.canvas.setting.font.plan.absorption.plan.size.setting": "도면크기 설정", "modal.canvas.setting.first.option.info": "※도면에 표시하는 항목을 클릭하면 적용됩니다.", "modal.canvas.setting.first.option.alloc": "할당표시", @@ -252,6 +256,8 @@ "modal.object.setting.direction.select": "방향 선택", "modal.placement.surface.setting.info": "ⓘ ①의 길이 입력 후 대각선 길이를 입력하면 ②의 길이를 자동 계산합니다.", "modal.placement.surface.setting.diagonal.length": "대각선 길이", + "modal.color.picker.title": "색 설정", + "modal.color.picker.default.color": "기본색상", "plan.message.confirm.save": "PLAN을 저장하시겠습니까?", "plan.message.confirm.copy": "PLAN을 복사하시겠습니까?", "plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?", @@ -458,6 +464,7 @@ "stuff.addressPopup.btn1": "닫기", "stuff.addressPopup.btn2": "주소적용", "stuff.planReqPopup.title": "설계의뢰 불러오기", + "stuff.temp.subTitle" : "물건정보", "stuff.detail.required": "필수 입력항목", "stuff.detail.planReqNo": "설계의뢰No.", "stuff.detail.dispCompanyName": "담당자", diff --git a/src/store/commonCodeAtom.js b/src/store/commonCodeAtom.js new file mode 100644 index 00000000..44f233f3 --- /dev/null +++ b/src/store/commonCodeAtom.js @@ -0,0 +1,6 @@ +import { atom } from 'recoil' + +export const commonCodeState = atom({ + key: 'commonCode', + default: {}, +}) diff --git a/src/store/planReqAtom.js b/src/store/planReqAtom.js deleted file mode 100644 index fddf1374..00000000 --- a/src/store/planReqAtom.js +++ /dev/null @@ -1,22 +0,0 @@ -import { atom } from 'recoil' -import dayjs from 'dayjs' -import { v1 } from 'uuid' -export const planReqSearchState = atom({ - key: `planReqSearchState/${v1()}`, - default: { - saleStoreId: '', //판매점ID 세션 - saleStoreLevel: '', //판매점레벨 세션 - schPlanReqNo: '', //설계의뢰 번호 - schTitle: '', //안건명 - schAddress: '', //도도부현 - schSaleStoreName: '', //판매대리점명 - schPlanReqName: '', //의뢰자명 - schPlanStatCd: '', //상태코드 - schDateGbn: 'S', //기간구분코드(S/R) - schStartDt: dayjs(new Date()).add(-3, 'month').format('YYYY-MM-DD'), //시작일 - schEndDt: dayjs(new Date()).format('YYYY-MM-DD'), //종료일 - startRow: 1, - endRow: 20, - }, - dangerouslyAllowMutability: true, -}) diff --git a/src/store/popupAtom.js b/src/store/popupAtom.js new file mode 100644 index 00000000..78de8660 --- /dev/null +++ b/src/store/popupAtom.js @@ -0,0 +1,13 @@ +import { atom } from 'recoil' + +/* + * id: uuid + * component: Popup Component + * */ +export const popupState = atom({ + key: 'popupState', + default: { + children: [], + }, + dangerouslyAllowMutability: true, +}) diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss index 9dc39b65..5a8167eb 100644 --- a/src/styles/_modal.scss +++ b/src/styles/_modal.scss @@ -1629,7 +1629,7 @@ $alert-color: #101010; min-height: 80px; background-color: #fff; } - + } // 치수선 설정 diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 07b46bc4..bfdf78a4 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -3038,314 +3038,3 @@ export const inPolygon = (polygonPoints, rectPoints) => { return allPointsInsidePolygon && noPolygonPointsInsideRect } - -/** - * poolygon의 방향에 따라 화살표를 추가한다. - * @param polygon - */ -export const drawDirectionArrow = (polygon) => { - const direction = polygon.direction - if (!direction) { - return - } - - polygon.canvas - .getObjects() - .filter((obj) => obj.name === 'directionText' && obj.parent === polygon.arrow) - .forEach((obj) => polygon.canvas.remove(obj)) - - let arrow = null - let points = [] - - if (polygon.arrow) { - polygon.canvas.remove(polygon.arrow) - } - - let centerPoint = { x: polygon.left, y: polygon.top } - let stickeyPoint - - const polygonMaxX = Math.max(...polygon.getCurrentPoints().map((point) => point.x)) - const polygonMinX = Math.min(...polygon.getCurrentPoints().map((point) => point.x)) - const polygonMaxY = Math.max(...polygon.getCurrentPoints().map((point) => point.y)) - const polygonMinY = Math.min(...polygon.getCurrentPoints().map((point) => point.y)) - - switch (direction) { - case 'north': - points = [ - { x: centerPoint.x, y: polygonMinY - 50 }, - { x: centerPoint.x + 20, y: polygonMinY - 50 }, - { x: centerPoint.x + 20, y: polygonMinY - 80 }, - { x: centerPoint.x + 50, y: polygonMinY - 80 }, - { x: centerPoint.x, y: polygonMinY - 110 }, - { x: centerPoint.x - 50, y: polygonMinY - 80 }, - { x: centerPoint.x - 20, y: polygonMinY - 80 }, - { x: centerPoint.x - 20, y: polygonMinY - 50 }, - ] - - stickeyPoint = { x: centerPoint.x, y: polygonMinY - 110 } - break - case 'south': - points = [ - { x: centerPoint.x, y: polygonMaxY + 50 }, - { x: centerPoint.x + 20, y: polygonMaxY + 50 }, - { x: centerPoint.x + 20, y: polygonMaxY + 80 }, - { x: centerPoint.x + 50, y: polygonMaxY + 80 }, - { x: centerPoint.x, y: polygonMaxY + 110 }, - { x: centerPoint.x - 50, y: polygonMaxY + 80 }, - { x: centerPoint.x - 20, y: polygonMaxY + 80 }, - { x: centerPoint.x - 20, y: polygonMaxY + 50 }, - ] - stickeyPoint = { x: centerPoint.x, y: polygonMaxY + 110 } - break - case 'west': - points = [ - { x: polygonMinX - 50, y: centerPoint.y }, - { x: polygonMinX - 50, y: centerPoint.y + 20 }, - { x: polygonMinX - 80, y: centerPoint.y + 20 }, - { x: polygonMinX - 80, y: centerPoint.y + 50 }, - { x: polygonMinX - 110, y: centerPoint.y }, - { x: polygonMinX - 80, y: centerPoint.y - 50 }, - { x: polygonMinX - 80, y: centerPoint.y - 20 }, - { x: polygonMinX - 50, y: centerPoint.y - 20 }, - ] - - stickeyPoint = { x: polygonMinX - 110, y: centerPoint.y } - break - case 'east': - points = [ - { x: polygonMaxX + 50, y: centerPoint.y }, - { x: polygonMaxX + 50, y: centerPoint.y + 20 }, - { x: polygonMaxX + 80, y: centerPoint.y + 20 }, - { x: polygonMaxX + 80, y: centerPoint.y + 50 }, - { x: polygonMaxX + 110, y: centerPoint.y }, - { x: polygonMaxX + 80, y: centerPoint.y - 50 }, - { x: polygonMaxX + 80, y: centerPoint.y - 20 }, - { x: polygonMaxX + 50, y: centerPoint.y - 20 }, - ] - - stickeyPoint = { x: polygonMaxX + 110, y: centerPoint.y } - break - } - - arrow = new fabric.Polygon(points, { - selectable: false, - name: 'arrow', - fill: 'transparent', - stroke: 'black', - direction: direction, - parent: polygon, - stickeyPoint: stickeyPoint, - }) - - polygon.arrow = arrow - polygon.canvas.add(arrow) - polygon.canvas.renderAll() - drawDirectionStringToArrow(polygon.canvas, 0) -} - -/** - * 방향을 나타낸 화살표에 각도에 따라 글씨 추가 - * @param canvas - * @param compass - */ -export const drawDirectionStringToArrow = (canvas, compass = 0) => { - const arrows = canvas?.getObjects().filter((obj) => obj.name === 'arrow') - - if (arrows.length === 0) { - return - } - - const eastArrows = arrows.filter((arrow) => arrow.direction === 'east') - const westArrows = arrows.filter((arrow) => arrow.direction === 'west') - const northArrows = arrows.filter((arrow) => arrow.direction === 'north') - const southArrows = arrows.filter((arrow) => arrow.direction === 'south') - - let southText = '南' - let eastText = '東' - let westText = '西' - let northText = '北' - - if (compass === 0 || compass === 360) { - // 남,동,서 가능 - // 그대로 - } else if (compass < 45) { - //남(남남동),동(동북동),서(서남서) 가능 - //북(북북서) - southText = '南南東' - eastText = '東北東' - westText = '西南西' - northText = '北北西' - } else if (compass === 45) { - // 남, 서 가능 - // 남(남동) - // 서(남서) - // 북(북서) - // 동(북동) - southText = '南東' - westText = '南西' - northText = '北西' - eastText = '北東' - } else if (compass < 90) { - // 북(서북서) - // 동 (북북동) - // 남(동남동) - // 서(남남서) - northText = '北西北' - eastText = '北北東' - southText = '東南東' - westText = '南南西' - } else if (compass === 90) { - // 동(북) - // 서(남) - // 남(동) - // 북(서) - eastText = '北' - westText = '南' - southText = '東' - northText = '西' - } else if (compass < 135) { - // 남,서,북 가능 - // 동(북북서) - // 서(남남동) - // 남(동북동) - // 북(서남서) - eastText = '北北西' - westText = '南南東' - southText = '東北東' - northText = '西南西' - } else if (compass === 135) { - // 서,북 가능 - - // 서(남동) - // 북(남서) - // 남(북동) - // 동(북서) - - westText = '南東' - northText = '南西' - southText = '北東' - eastText = '北西' - } else if (compass < 180) { - // 북,동,서 가능 - // 북(남남서) - // 동(서북서) - // 남(북북동) - // 서(동남동) - - northText = '南南西' - eastText = '西北西' - southText = '北北東' - westText = '東南東' - } else if (compass === 180) { - // 북,동,서 가능 - // 북(남) - // 동(서) - // 남(북) - // 서(동) - northText = '南' - eastText = '西' - southText = '北' - westText = '東' - } else if (compass < 225) { - // 서,북,동 가능 - // 북(남남동) - // 동(서남서) - // 남(북북서) - // 서(동남동) - northText = '南南東' - eastText = '西南西' - southText = '北北西' - westText = '東南東' - } else if (compass === 225) { - // 북,동 가능 - // 북(남동) - // 동(남서) - // 남(북서) - // 서(북동) - northText = '南東' - eastText = '南西' - southText = '北西' - westText = '北東' - } else if (compass < 270) { - // 북동남 가능 - // 북(동남동) - // 동(남남서) - // 남(서북서) - // 서(북북동) - northText = '東南東' - eastText = '南南西' - southText = '西北西' - westText = '北北東' - } else if (compass === 270) { - // 북동남 가능 - // 북(동) - // 동(남) - // 남(서) - // 서(북) - northText = '東' - eastText = '南' - southText = '西' - westText = '北' - } else if (compass < 315) { - // 북,동,남 가능 - // 북(동북동) - // 동(남남동) - // 남(서남서) - // 서(북북서) - northText = '東北東' - eastText = '南南東' - southText = '西南西' - westText = '北北西' - } else if (compass === 315) { - // 동,남 가능 - // 북(북동) - // 동(남동) - // 남(남서) - // 서(북서) - northText = '北東' - eastText = '南東' - southText = '南西' - westText = '北西' - } else if (compass < 360) { - // 남,동,서 가능 - // 북(북북동) - // 동(동남동) - // 남(남남서) - // 서(서북서) - northText = '北北東' - eastText = '東南東' - southText = '南南西' - westText = '西北西' - } - - clearDirectionText(canvas) - - addTextByArrows(eastArrows, eastText, canvas) - addTextByArrows(westArrows, westText, canvas) - addTextByArrows(northArrows, northText, canvas) - addTextByArrows(southArrows, southText, canvas) -} - -const clearDirectionText = (canvas) => { - const texts = canvas.getObjects().filter((obj) => obj.name === 'directionText') - texts.forEach((text) => { - canvas.remove(text) - }) -} - -const addTextByArrows = (arrows, txt, canvas) => { - arrows.forEach((arrow, index) => { - const text = new fabric.Text(`${txt}${index + 1}`, { - fontSize: arrow.parent.fontSize, - fill: 'black', - originX: 'center', - originY: 'center', - name: 'directionText', - selectable: false, - left: arrow.stickeyPoint.x, - top: arrow.stickeyPoint.y, - parent: arrow, - }) - canvas.add(text) - }) -} diff --git a/yarn.lock b/yarn.lock index c8c53b57..bf4e65b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1538,47 +1538,6 @@ resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@prisma/client@^5.18.0": - version "5.18.0" - resolved "https://registry.npmjs.org/@prisma/client/-/client-5.18.0.tgz" - integrity sha512-BWivkLh+af1kqC89zCJYkHsRcyWsM8/JHpsDMM76DjP3ZdEquJhXa4IeX+HkWPnwJ5FanxEJFZZDTWiDs/Kvyw== - -"@prisma/debug@5.18.0": - version "5.18.0" - resolved "https://registry.npmjs.org/@prisma/debug/-/debug-5.18.0.tgz" - integrity sha512-f+ZvpTLidSo3LMJxQPVgAxdAjzv5OpzAo/eF8qZqbwvgi2F5cTOI9XCpdRzJYA0iGfajjwjOKKrVq64vkxEfUw== - -"@prisma/engines-version@5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169": - version "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169" - resolved "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169.tgz" - integrity sha512-a/+LpJj8vYU3nmtkg+N3X51ddbt35yYrRe8wqHTJtYQt7l1f8kjIBcCs6sHJvodW/EK5XGvboOiwm47fmNrbgg== - -"@prisma/engines@5.18.0": - version "5.18.0" - resolved "https://registry.npmjs.org/@prisma/engines/-/engines-5.18.0.tgz" - integrity sha512-ofmpGLeJ2q2P0wa/XaEgTnX/IsLnvSp/gZts0zjgLNdBhfuj2lowOOPmDcfKljLQUXMvAek3lw5T01kHmCG8rg== - dependencies: - "@prisma/debug" "5.18.0" - "@prisma/engines-version" "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169" - "@prisma/fetch-engine" "5.18.0" - "@prisma/get-platform" "5.18.0" - -"@prisma/fetch-engine@5.18.0": - version "5.18.0" - resolved "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.18.0.tgz" - integrity sha512-I/3u0x2n31rGaAuBRx2YK4eB7R/1zCuayo2DGwSpGyrJWsZesrV7QVw7ND0/Suxeo/vLkJ5OwuBqHoCxvTHpOg== - dependencies: - "@prisma/debug" "5.18.0" - "@prisma/engines-version" "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169" - "@prisma/get-platform" "5.18.0" - -"@prisma/get-platform@5.18.0": - version "5.18.0" - resolved "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.18.0.tgz" - integrity sha512-Tk+m7+uhqcKDgnMnFN0lRiH7Ewea0OEsZZs9pqXa7i3+7svS3FSCqDBCaM9x5fmhhkufiG0BtunJVDka+46DlA== - dependencies: - "@prisma/debug" "5.18.0" - "@react-aria/breadcrumbs@3.5.13": version "3.5.13" resolved "https://registry.npmjs.org/@react-aria/breadcrumbs/-/breadcrumbs-3.5.13.tgz" @@ -5810,13 +5769,6 @@ prettier@^3.3.3: resolved "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz" integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== -prisma@^5.18.0: - version "5.18.0" - resolved "https://registry.npmjs.org/prisma/-/prisma-5.18.0.tgz" - integrity sha512-+TrSIxZsh64OPOmaSgVPH7ALL9dfU0jceYaMJXsNrTkFHO7/3RANi5K2ZiPB1De9+KDxCWn7jvRq8y8pvk+o9g== - dependencies: - "@prisma/engines" "5.18.0" - process@^0.11.10: version "0.11.10" resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" @@ -5998,13 +5950,6 @@ react-textarea-autosize@^8.5.3: use-composed-ref "^1.3.0" use-latest "^1.2.1" -react-toastify@^10.0.5: - version "10.0.5" - resolved "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.5.tgz" - integrity sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw== - dependencies: - clsx "^2.1.0" - react-transition-group@^4.3.0: version "4.4.5" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1"