diff --git a/next.config.mjs b/next.config.mjs index 1e7afb62..d4759fb3 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,6 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - reactStrictMode: true, + reactStrictMode: false, swcMinify: true, webpack: (config) => { config.resolve.fallback = { fs: false } diff --git a/package.json b/package.json index a91884a8..78fd71b3 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,9 @@ "react-colorful": "^5.6.1", "react-datepicker": "^7.3.0", "react-dom": "^18", + "react-hook-form": "^7.53.0", + "react-draggable": "^4.4.6", + "react-icons": "^5.3.0", "react-responsive-modal": "^6.4.2", "react-toastify": "^10.0.5", "recoil": "^0.7.7", diff --git a/public/assets/img/doc.svg b/public/assets/img/doc.svg new file mode 100644 index 00000000..73d7f003 --- /dev/null +++ b/public/assets/img/doc.svg @@ -0,0 +1,12 @@ + + + + doc-document + + + + + + + + \ No newline at end of file diff --git a/public/assets/img/excel.svg b/public/assets/img/excel.svg new file mode 100644 index 00000000..2bb190e1 --- /dev/null +++ b/public/assets/img/excel.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/public/assets/img/file.svg b/public/assets/img/file.svg new file mode 100644 index 00000000..3df8b4d8 --- /dev/null +++ b/public/assets/img/file.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/public/assets/img/image.svg b/public/assets/img/image.svg new file mode 100644 index 00000000..2e856737 --- /dev/null +++ b/public/assets/img/image.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/public/assets/img/ppt.svg b/public/assets/img/ppt.svg new file mode 100644 index 00000000..d9b7382a --- /dev/null +++ b/public/assets/img/ppt.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/public/fonts/NotoSansJP-Black.woff b/public/fonts/NotoSansJP-Black.woff new file mode 100644 index 00000000..6d1eb871 Binary files /dev/null and b/public/fonts/NotoSansJP-Black.woff differ diff --git a/public/fonts/NotoSansJP-Black.woff2 b/public/fonts/NotoSansJP-Black.woff2 new file mode 100644 index 00000000..57b73cea Binary files /dev/null and b/public/fonts/NotoSansJP-Black.woff2 differ diff --git a/public/fonts/NotoSansJP-Bold.woff b/public/fonts/NotoSansJP-Bold.woff new file mode 100644 index 00000000..528d5dc0 Binary files /dev/null and b/public/fonts/NotoSansJP-Bold.woff differ diff --git a/public/fonts/NotoSansJP-Bold.woff2 b/public/fonts/NotoSansJP-Bold.woff2 new file mode 100644 index 00000000..7385f01a Binary files /dev/null and b/public/fonts/NotoSansJP-Bold.woff2 differ diff --git a/public/fonts/NotoSansJP-ExtraBold.woff b/public/fonts/NotoSansJP-ExtraBold.woff new file mode 100644 index 00000000..3d5b4030 Binary files /dev/null and b/public/fonts/NotoSansJP-ExtraBold.woff differ diff --git a/public/fonts/NotoSansJP-ExtraBold.woff2 b/public/fonts/NotoSansJP-ExtraBold.woff2 new file mode 100644 index 00000000..e23b5938 Binary files /dev/null and b/public/fonts/NotoSansJP-ExtraBold.woff2 differ diff --git a/public/fonts/NotoSansJP-ExtraLight.woff b/public/fonts/NotoSansJP-ExtraLight.woff new file mode 100644 index 00000000..8d606939 Binary files /dev/null and b/public/fonts/NotoSansJP-ExtraLight.woff differ diff --git a/public/fonts/NotoSansJP-ExtraLight.woff2 b/public/fonts/NotoSansJP-ExtraLight.woff2 new file mode 100644 index 00000000..c43674fb Binary files /dev/null and b/public/fonts/NotoSansJP-ExtraLight.woff2 differ diff --git a/public/fonts/NotoSansJP-Light.woff b/public/fonts/NotoSansJP-Light.woff new file mode 100644 index 00000000..dbe70e43 Binary files /dev/null and b/public/fonts/NotoSansJP-Light.woff differ diff --git a/public/fonts/NotoSansJP-Light.woff2 b/public/fonts/NotoSansJP-Light.woff2 new file mode 100644 index 00000000..d0ead44d Binary files /dev/null and b/public/fonts/NotoSansJP-Light.woff2 differ diff --git a/public/fonts/NotoSansJP-Medium.woff b/public/fonts/NotoSansJP-Medium.woff new file mode 100644 index 00000000..fdfffa10 Binary files /dev/null and b/public/fonts/NotoSansJP-Medium.woff differ diff --git a/public/fonts/NotoSansJP-Medium.woff2 b/public/fonts/NotoSansJP-Medium.woff2 new file mode 100644 index 00000000..5d3da28f Binary files /dev/null and b/public/fonts/NotoSansJP-Medium.woff2 differ diff --git a/public/fonts/NotoSansJP-Regular.woff b/public/fonts/NotoSansJP-Regular.woff new file mode 100644 index 00000000..cad22106 Binary files /dev/null and b/public/fonts/NotoSansJP-Regular.woff differ diff --git a/public/fonts/NotoSansJP-Regular.woff2 b/public/fonts/NotoSansJP-Regular.woff2 new file mode 100644 index 00000000..d31b3285 Binary files /dev/null and b/public/fonts/NotoSansJP-Regular.woff2 differ diff --git a/public/fonts/NotoSansJP-SemiBold.woff b/public/fonts/NotoSansJP-SemiBold.woff new file mode 100644 index 00000000..2922f150 Binary files /dev/null and b/public/fonts/NotoSansJP-SemiBold.woff differ diff --git a/public/fonts/NotoSansJP-SemiBold.woff2 b/public/fonts/NotoSansJP-SemiBold.woff2 new file mode 100644 index 00000000..4ec2170e Binary files /dev/null and b/public/fonts/NotoSansJP-SemiBold.woff2 differ diff --git a/public/fonts/NotoSansJP-Thin.woff b/public/fonts/NotoSansJP-Thin.woff new file mode 100644 index 00000000..517b984f Binary files /dev/null and b/public/fonts/NotoSansJP-Thin.woff differ diff --git a/public/fonts/NotoSansJP-Thin.woff2 b/public/fonts/NotoSansJP-Thin.woff2 new file mode 100644 index 00000000..85a6b500 Binary files /dev/null and b/public/fonts/NotoSansJP-Thin.woff2 differ diff --git a/public/fonts/Pretendard-Black.woff b/public/fonts/Pretendard-Black.woff new file mode 100644 index 00000000..20b0641b Binary files /dev/null and b/public/fonts/Pretendard-Black.woff differ diff --git a/public/fonts/Pretendard-Black.woff2 b/public/fonts/Pretendard-Black.woff2 new file mode 100644 index 00000000..306697cc Binary files /dev/null and b/public/fonts/Pretendard-Black.woff2 differ diff --git a/public/fonts/Pretendard-Bold.woff b/public/fonts/Pretendard-Bold.woff new file mode 100644 index 00000000..bfc573c4 Binary files /dev/null and b/public/fonts/Pretendard-Bold.woff differ diff --git a/public/fonts/Pretendard-Bold.woff2 b/public/fonts/Pretendard-Bold.woff2 new file mode 100644 index 00000000..d99618c2 Binary files /dev/null and b/public/fonts/Pretendard-Bold.woff2 differ diff --git a/public/fonts/Pretendard-ExtraBold.woff b/public/fonts/Pretendard-ExtraBold.woff new file mode 100644 index 00000000..14a61abd Binary files /dev/null and b/public/fonts/Pretendard-ExtraBold.woff differ diff --git a/public/fonts/Pretendard-ExtraBold.woff2 b/public/fonts/Pretendard-ExtraBold.woff2 new file mode 100644 index 00000000..d7a908e3 Binary files /dev/null and b/public/fonts/Pretendard-ExtraBold.woff2 differ diff --git a/public/fonts/Pretendard-ExtraLight.woff b/public/fonts/Pretendard-ExtraLight.woff new file mode 100644 index 00000000..a7af8a24 Binary files /dev/null and b/public/fonts/Pretendard-ExtraLight.woff differ diff --git a/public/fonts/Pretendard-ExtraLight.woff2 b/public/fonts/Pretendard-ExtraLight.woff2 new file mode 100644 index 00000000..0c41886d Binary files /dev/null and b/public/fonts/Pretendard-ExtraLight.woff2 differ diff --git a/public/fonts/Pretendard-Light.woff b/public/fonts/Pretendard-Light.woff new file mode 100644 index 00000000..6e00ad2d Binary files /dev/null and b/public/fonts/Pretendard-Light.woff differ diff --git a/public/fonts/Pretendard-Light.woff2 b/public/fonts/Pretendard-Light.woff2 new file mode 100644 index 00000000..805d10c0 Binary files /dev/null and b/public/fonts/Pretendard-Light.woff2 differ diff --git a/public/fonts/Pretendard-Medium.woff b/public/fonts/Pretendard-Medium.woff new file mode 100644 index 00000000..71b13eb5 Binary files /dev/null and b/public/fonts/Pretendard-Medium.woff differ diff --git a/public/fonts/Pretendard-Medium.woff2 b/public/fonts/Pretendard-Medium.woff2 new file mode 100644 index 00000000..a96e69b8 Binary files /dev/null and b/public/fonts/Pretendard-Medium.woff2 differ diff --git a/public/fonts/Pretendard-Regular.woff b/public/fonts/Pretendard-Regular.woff new file mode 100644 index 00000000..741be57b Binary files /dev/null and b/public/fonts/Pretendard-Regular.woff differ diff --git a/public/fonts/Pretendard-Regular.woff2 b/public/fonts/Pretendard-Regular.woff2 new file mode 100644 index 00000000..a5d5aea8 Binary files /dev/null and b/public/fonts/Pretendard-Regular.woff2 differ diff --git a/public/fonts/Pretendard-SemiBold.woff b/public/fonts/Pretendard-SemiBold.woff new file mode 100644 index 00000000..7bf28607 Binary files /dev/null and b/public/fonts/Pretendard-SemiBold.woff differ diff --git a/public/fonts/Pretendard-SemiBold.woff2 b/public/fonts/Pretendard-SemiBold.woff2 new file mode 100644 index 00000000..d5a77179 Binary files /dev/null and b/public/fonts/Pretendard-SemiBold.woff2 differ diff --git a/public/fonts/Pretendard-Thin.woff b/public/fonts/Pretendard-Thin.woff new file mode 100644 index 00000000..665fe440 Binary files /dev/null and b/public/fonts/Pretendard-Thin.woff differ diff --git a/public/fonts/Pretendard-Thin.woff2 b/public/fonts/Pretendard-Thin.woff2 new file mode 100644 index 00000000..8ce8ee27 Binary files /dev/null and b/public/fonts/Pretendard-Thin.woff2 differ diff --git a/public/static/images/canvas/arr_btn_ico.svg b/public/static/images/canvas/arr_btn_ico.svg new file mode 100644 index 00000000..65ac8bfe --- /dev/null +++ b/public/static/images/canvas/arr_btn_ico.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/arr_btn_ico_black.svg b/public/static/images/canvas/arr_btn_ico_black.svg new file mode 100644 index 00000000..cbffea32 --- /dev/null +++ b/public/static/images/canvas/arr_btn_ico_black.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/check-black.svg b/public/static/images/canvas/check-black.svg new file mode 100644 index 00000000..75184dea --- /dev/null +++ b/public/static/images/canvas/check-black.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/check-grey.svg b/public/static/images/canvas/check-grey.svg new file mode 100644 index 00000000..617acc83 --- /dev/null +++ b/public/static/images/canvas/check-grey.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/depth2-arr.svg b/public/static/images/canvas/depth2-arr.svg new file mode 100644 index 00000000..31e04787 --- /dev/null +++ b/public/static/images/canvas/depth2-arr.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/menu_icon00.svg b/public/static/images/canvas/menu_icon00.svg new file mode 100644 index 00000000..f0adffd5 --- /dev/null +++ b/public/static/images/canvas/menu_icon00.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/static/images/canvas/menu_icon01.svg b/public/static/images/canvas/menu_icon01.svg new file mode 100644 index 00000000..ce77c2dd --- /dev/null +++ b/public/static/images/canvas/menu_icon01.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/public/static/images/canvas/menu_icon02.svg b/public/static/images/canvas/menu_icon02.svg new file mode 100644 index 00000000..363e483d --- /dev/null +++ b/public/static/images/canvas/menu_icon02.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/menu_icon03.svg b/public/static/images/canvas/menu_icon03.svg new file mode 100644 index 00000000..56896c63 --- /dev/null +++ b/public/static/images/canvas/menu_icon03.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/menu_icon04.svg b/public/static/images/canvas/menu_icon04.svg new file mode 100644 index 00000000..3df7b7da --- /dev/null +++ b/public/static/images/canvas/menu_icon04.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/static/images/canvas/menu_icon05.svg b/public/static/images/canvas/menu_icon05.svg new file mode 100644 index 00000000..b5ea63d0 --- /dev/null +++ b/public/static/images/canvas/menu_icon05.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/static/images/canvas/menu_icon06.svg b/public/static/images/canvas/menu_icon06.svg new file mode 100644 index 00000000..6c9705f3 --- /dev/null +++ b/public/static/images/canvas/menu_icon06.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/static/images/canvas/minus.svg b/public/static/images/canvas/minus.svg new file mode 100644 index 00000000..6949c3e8 --- /dev/null +++ b/public/static/images/canvas/minus.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/modal_close.svg b/public/static/images/canvas/modal_close.svg new file mode 100644 index 00000000..081c0ccc --- /dev/null +++ b/public/static/images/canvas/modal_close.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/static/images/canvas/plan_close_black.svg b/public/static/images/canvas/plan_close_black.svg new file mode 100644 index 00000000..47445748 --- /dev/null +++ b/public/static/images/canvas/plan_close_black.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/plan_close_gray.svg b/public/static/images/canvas/plan_close_gray.svg new file mode 100644 index 00000000..bba119ea --- /dev/null +++ b/public/static/images/canvas/plan_close_gray.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/plane_add.svg b/public/static/images/canvas/plane_add.svg new file mode 100644 index 00000000..9b6e3e06 --- /dev/null +++ b/public/static/images/canvas/plane_add.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/plus.svg b/public/static/images/canvas/plus.svg new file mode 100644 index 00000000..6b5fc7f2 --- /dev/null +++ b/public/static/images/canvas/plus.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/static/images/canvas/side_icon01.svg b/public/static/images/canvas/side_icon01.svg new file mode 100644 index 00000000..6de890e2 --- /dev/null +++ b/public/static/images/canvas/side_icon01.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/side_icon02.svg b/public/static/images/canvas/side_icon02.svg new file mode 100644 index 00000000..e320aefc --- /dev/null +++ b/public/static/images/canvas/side_icon02.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/side_icon03.svg b/public/static/images/canvas/side_icon03.svg new file mode 100644 index 00000000..3f952192 --- /dev/null +++ b/public/static/images/canvas/side_icon03.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/static/images/canvas/side_icon04.svg b/public/static/images/canvas/side_icon04.svg new file mode 100644 index 00000000..cc196515 --- /dev/null +++ b/public/static/images/canvas/side_icon04.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/side_icon05.svg b/public/static/images/canvas/side_icon05.svg new file mode 100644 index 00000000..569c5b64 --- /dev/null +++ b/public/static/images/canvas/side_icon05.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/side_icon06.svg b/public/static/images/canvas/side_icon06.svg new file mode 100644 index 00000000..7ee72ac1 --- /dev/null +++ b/public/static/images/canvas/side_icon06.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/side_icon07.svg b/public/static/images/canvas/side_icon07.svg new file mode 100644 index 00000000..ec65154f --- /dev/null +++ b/public/static/images/canvas/side_icon07.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/side_icon08.svg b/public/static/images/canvas/side_icon08.svg new file mode 100644 index 00000000..afbb1e64 --- /dev/null +++ b/public/static/images/canvas/side_icon08.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/side_icon09.svg b/public/static/images/canvas/side_icon09.svg new file mode 100644 index 00000000..aac0b489 --- /dev/null +++ b/public/static/images/canvas/side_icon09.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/common/Logo.svg b/public/static/images/common/Logo.svg new file mode 100644 index 00000000..a72d0b4e --- /dev/null +++ b/public/static/images/common/Logo.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/public/static/images/common/nav-arr.svg b/public/static/images/common/nav-arr.svg new file mode 100644 index 00000000..a9ddbf4a --- /dev/null +++ b/public/static/images/common/nav-arr.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/common/profile_icon.svg b/public/static/images/common/profile_icon.svg new file mode 100644 index 00000000..837e4f5a --- /dev/null +++ b/public/static/images/common/profile_icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/static/images/common/select-arr.svg b/public/static/images/common/select-arr.svg new file mode 100644 index 00000000..aa74665c --- /dev/null +++ b/public/static/images/common/select-arr.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/common/signout_icon.svg b/public/static/images/common/signout_icon.svg new file mode 100644 index 00000000..a20ccdb1 --- /dev/null +++ b/public/static/images/common/signout_icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/static/images/thomas-tastet-hSODeSbvzE0-unsplash.jpg b/public/static/images/thomas-tastet-hSODeSbvzE0-unsplash.jpg new file mode 100644 index 00000000..fc8774a2 Binary files /dev/null and b/public/static/images/thomas-tastet-hSODeSbvzE0-unsplash.jpg differ diff --git a/src/app/[locale]/floor-plan/page.jsx b/src/app/[locale]/floor-plan/page.jsx new file mode 100644 index 00000000..f503099e --- /dev/null +++ b/src/app/[locale]/floor-plan/page.jsx @@ -0,0 +1,9 @@ +import FloorPlan from '@/components/floor-plan/FloorPlan' + +export default function FloorPlanPage() { + return ( + <> + + + ) +} diff --git a/src/app/[locale]/initSettingsModal/page.jsx b/src/app/[locale]/initSettingsModal/page.jsx new file mode 100644 index 00000000..a081ef47 --- /dev/null +++ b/src/app/[locale]/initSettingsModal/page.jsx @@ -0,0 +1,16 @@ +import Hero from '@/components/Hero' +import InitSettingsModal from '@/components/InitSettingsModal' +import { initCheck } from '@/util/session-util' + +export default async function InitSettingsModalPage() { + await initCheck() + + return ( + <> + +
+ +
+ + ) +} diff --git a/src/app/[locale]/join/complete/page.jsx b/src/app/[locale]/join/complete/page.jsx new file mode 100644 index 00000000..3f9fc462 --- /dev/null +++ b/src/app/[locale]/join/complete/page.jsx @@ -0,0 +1,19 @@ +'use client' + +import { useMessage } from '@/hooks/useMessage' + +export default function CompletePage() { + const { getMessage } = useMessage() + + return ( + <> +
+

{getMessage('join.complete.title')}

+
{getMessage('join.complete.contents')}
+
+ {getMessage('join.complete.email_comment')} : {getMessage('join.complete.email')} +
+
+ + ) +} diff --git a/src/app/[locale]/join/page.jsx b/src/app/[locale]/join/page.jsx new file mode 100644 index 00000000..118a25b4 --- /dev/null +++ b/src/app/[locale]/join/page.jsx @@ -0,0 +1,5 @@ +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 index 71410d17..334cfbb3 100644 --- a/src/app/[locale]/layout.js +++ b/src/app/[locale]/layout.js @@ -4,6 +4,7 @@ import { useCurrentLocale } from '@/locales/client' import { LocaleProvider } from './LocaleProvider' import ServerError from './error' import { ErrorBoundary } from 'next/dist/client/components/error-boundary' +import '@/styles/common.scss' export default function LocaleLayout({ children }) { const locale = useCurrentLocale() diff --git a/src/app/[locale]/login/page.jsx b/src/app/[locale]/login/page.jsx index 0686da2e..47a23986 100644 --- a/src/app/[locale]/login/page.jsx +++ b/src/app/[locale]/login/page.jsx @@ -1,9 +1,16 @@ 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/stuff/detail/page.jsx b/src/app/[locale]/management/stuff/detail/page.jsx new file mode 100644 index 00000000..8b84287a --- /dev/null +++ b/src/app/[locale]/management/stuff/detail/page.jsx @@ -0,0 +1,15 @@ +import React from 'react' +import Hero from '@/components/Hero' +import StuffDetail from '@/components/management/StuffDetail' +export default function ManagementStuffDetailPage() { + return ( + <> +
+

๋ฌผ๊ฑด์ •๋ณด

+
+
+ +
+ + ) +} diff --git a/src/app/[locale]/management/stuff/page.jsx b/src/app/[locale]/management/stuff/page.jsx index e2d3c1cd..7590a7cf 100644 --- a/src/app/[locale]/management/stuff/page.jsx +++ b/src/app/[locale]/management/stuff/page.jsx @@ -1,14 +1,19 @@ -import Hero from '@/components/Hero' +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/api/html2canvas/route.js b/src/app/api/html2canvas/route.js new file mode 100644 index 00000000..54af611d --- /dev/null +++ b/src/app/api/html2canvas/route.js @@ -0,0 +1,29 @@ +'use server' + +import fs from 'fs/promises' + +import { NextResponse } from 'next/server' + +export async function GET(req) { + const path = 'public/mapImages' + const q = req.nextUrl.searchParams.get('q') + const fileNm = req.nextUrl.searchParams.get('fileNm') + const zoom = req.nextUrl.searchParams.get('zoom') + const targetUrl = `https://maps.googleapis.com/maps/api/staticmap?center=${q}&zoom=${zoom}&maptype=satellite&size=640x640&scale=1&key=AIzaSyDO7nVR1N_D2tKy60hgGFavpLaXkHpiHpc` + const decodeUrl = decodeURIComponent(targetUrl) + + const response = await fetch(decodeUrl) + + const data = await response.arrayBuffer() + const buffer = Buffer.from(data) + + try { + await fs.readdir(path) + } catch { + await fs.mkdir(path) + } finally { + await fs.writeFile(`${path}/${fileNm}.png`, buffer) + } + + return NextResponse.json({ fileNm: `${fileNm}.png` }) +} diff --git a/src/app/layout.js b/src/app/layout.js index 72ac7bf3..90a46e6e 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -2,14 +2,13 @@ import { Inter } from 'next/font/google' import RecoilRootWrapper from './RecoilWrapper' import UIProvider from './UIProvider' -import { headers } from 'next/headers' -import Headers from '@/components/Headers' import { ToastContainer } from 'react-toastify' import QModal from '@/components/common/modal/QModal' import './globals.css' import '../styles/style.scss' +import Header from '@/components/header/Header' const inter = Inter({ subsets: ['latin'] }) @@ -19,18 +18,19 @@ export const metadata = { } export default function RootLayout({ children }) { - const headersList = headers() - const headerPathname = headersList.get('x-pathname') || '' - // console.log('headerPathname', headerPathname) - return ( - {headerPathname !== '/login' && } + {/*{headerPathname !== '/login' && }*/} - {children} - +
+
+
+ {children} +
+
+
diff --git a/src/common/common.js b/src/common/common.js index 91a9583a..d4c22570 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -12,10 +12,37 @@ export const Mode = { CELL_POWERCON: 'cellPowercon', //ํŒŒ์›Œ์ฝ˜ DRAW_HELP_LINE: 'drawHelpLine', // ๋ณด์กฐ์„  ๊ทธ๋ฆฌ๊ธฐ ๋ชจ๋“œ ์ง€๋ถ• ์กด์žฌํ•ด์•ผํ•จ ADSORPTION_POINT: 'adsorptionPoint', //ํก์ฐฉ์  ๋ชจ๋“œ + OPENING: 'opening', //๊ฐœ๊ตฌ ๋ชจ๋“œ + SHADOW: 'shadow', //๊ทธ๋ฆผ์ž ์ƒ์„ฑ ๋ชจ๋“œ DEFAULT: 'default', } export const LineType = { EAVES: 'eaves', // ์ฒ˜๋งˆ RIDGE: 'ridge', // ์šฉ๋งˆ๋ฃจ.... + YOSEMUNE: 'yosemune', //์š”์„ธ๋ฌด๋„ค + ONESIDE_FLOW_RIDGE: 'onesideFlowRidge', //ํ•œ์ชฝํ๋ฆ„ ์šฉ๋งˆ๋ฃจ + WALL_COLLECTION: 'wallCollection', //๋ฒฝ์ทจํ•ฉ + WALL_COLLECTION_TYPE: 'wallCollectionType', //๋ฒฝ์ทจํ•ฉ(ํ˜•) + WALL_COLLECTION_FLOW: 'wallCollectionFlow', //๋ฒฝ์ทจํ•ฉ(ํ๋ฆ„) + WALL_COLLECTION_FLOW_LEFT: 'wallCollectionFlowLeft', //๋ฒฝ์ทจํ•ฉ(ํ๋ฆ„ ์™ผ์ชฝ) + WALL_COLLECTION_FLOW_RIGHT: 'wallCollectionFlowRight', //๋ฒฝ์ทจํ•ฉ(ํ๋ฆ„ ์˜ค๋ฅธ์ชฝ) + KERABA: 'keraba', //์ผ€๋ผ๋ฐ” + KERABA_LEFT: 'kerabaLeft', //์ผ€๋ผ๋ฐ” ์™ผ์ชฝ + KERABA_RIGHT: 'kerabaRight', //์ผ€๋ผ๋ฐ” ์˜ค๋ฅธ์ชฝ + VALLEY: 'valley', //๊ณจ์งœ๊ธฐ + L_ABANDON_VALLEY: 'lAbandonValley', //l์˜๋ฒ„๋ฆผ๊ณ„๊ณก + MANSARD: 'mansard', //๋งจ์‚ฌ๋“œ + NO_SETTING: 'noSetting', //์„ค์ •์—†์Œ +} + +// ์˜ค๋ธŒ์ ํŠธ ๋ฐฐ์น˜ > ๊ฐœ๊ตฌ๋ฐฐ์น˜, ๊ทธ๋ฆผ์ž๋ฐฐ์น˜ +export const BATCH_TYPE = { + OPENING: 'opening', + SHADOW: 'shadow', +} +// ์˜ค๋ธŒ์ ํŠธ ๋ฐฐ์น˜ > ํ”„๋ฆฌ์ž…๋ ฅ, ์น˜์ˆ˜์ž…๋ ฅ +export const INPUT_TYPE = { + FREE: 'free', + DIMENSION: 'dimension', } diff --git a/src/components/Headers.jsx b/src/components/Headers.jsx index 331e899c..02859c96 100644 --- a/src/components/Headers.jsx +++ b/src/components/Headers.jsx @@ -10,6 +10,7 @@ export default function Headers() {
Intro Playground + Basic Settings Canvas Settings Roof Roof2 diff --git a/src/components/InitSettingsModal.jsx b/src/components/InitSettingsModal.jsx index a79c7a9e..5a6aad64 100644 --- a/src/components/InitSettingsModal.jsx +++ b/src/components/InitSettingsModal.jsx @@ -1,22 +1,32 @@ +'use client' + import { useEffect, useState, memo, useCallback } from 'react' import { Button, Checkbox, CheckboxGroup, RadioGroup, Radio, Input, Select, SelectItem } from '@nextui-org/react' import { useRecoilState, useRecoilValue } from 'recoil' import { modalContent, modalState } from '@/store/modalAtom' import { canvasSettingState } from '@/store/canvasAtom' import { useAxios } from '@/hooks/useAxios' +import { get, post } from '@/lib/Axios' export default function InitSettingsModal(props) { + const [objectNo, setObjectNo] = useState('test123240909002') // ํ›„์— ์‚ญ์ œ ํ•„์š” + const [lastRoofSeq, setLastRoofSeq] = useState(0) // ๋งˆ์ง€๋ง‰ roofSeq๋ฅผ ์ถ”์  const [open, setOpen] = useRecoilState(modalState) const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const [roofMaterials, setRoofMaterials] = useState([]) const [basicSetting, setBasicSettings] = useState({ - type: '1', - inputType: '1', - angleType: 'slope', + roofDrawingSet: '1', + roofSizeSet: '1', + roofAngleSet: 'slope', roofs: [], }) - const { get, post } = useAxios() + const modelProps = { + open, + setOpen, + } + + //const { get, post } = useAxios() useEffect(() => { get({ url: '/api/roof-material/roof-material-infos' }).then((res) => { @@ -26,6 +36,49 @@ export default function InitSettingsModal(props) { setRoofMaterials(res) }) + get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${objectNo}` }).then((res) => { + if (res.length == 0) return + + // 'roofs' ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•˜์—ฌ ๊ฐ ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ + const roofsRow = res.map((item) => { + return { + roofDrawingSet: String(item.roofDrawingSet), + roofSizeSet: String(item.roofSizeSet), + roofAngleSet: item.roofAngleSet, + } + }) + + const roofsArray = res.some((item) => !item.roofSeq) + ? null //์ง€๋ถ•์žฌ ์ถ”๊ฐ€ ์ •๋ณด๊ฐ€ ์—†๋‹ค๋ฉด roofsArray๋ฅผ null ์ฒ˜๋ฆฌํ•˜์—ฌ ์ง€๋ถ•์žฌ ์ถ”๊ฐ€ ์ •๋ณด๊ฐ€ ๋ณด์ด์ง€ ์•Š๊ฒŒ ํ•œ๋‹ค. + : res.map((item) => ({ + roofSeq: String(item.roofSeq), + roofType: String(item.roofType), + roofWidth: String(item.roofWidth), + roofHeight: String(item.roofHeight), + roofGap: String(item.roofGap), + roofLayout: item.roofLayout, + })) + + // ๋‚˜๋จธ์ง€ ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ 'roofs' ๋ฐฐ์—ด์„ patternData์— ๋„ฃ์Œ + const patternData = { + roofDrawingSet: roofsRow[0].roofDrawingSet, // ์ฒซ ๋ฒˆ์งธ ํ•ญ๋ชฉ์˜ ๊ฐ’์„ ์‚ฌ์šฉ + roofSizeSet: roofsRow[0].roofSizeSet, // ์ฒซ ๋ฒˆ์งธ ํ•ญ๋ชฉ์˜ ๊ฐ’์„ ์‚ฌ์šฉ + roofAngleSet: roofsRow[0].roofAngleSet, // ์ฒซ ๋ฒˆ์งธ ํ•ญ๋ชฉ์˜ ๊ฐ’์„ ์‚ฌ์šฉ + roofs: roofsArray, // ๋งŒ๋“ค์–ด์ง„ roofs ๋ฐฐ์—ด + } + + // ๋ฐ์ดํ„ฐ ์„ค์ • + setBasicSettings({ ...patternData }) + + // ์ดˆ๊ธฐ roofSeq ๊ฐ’์„ ์—…๋ฐ์ดํŠธ + if (roofsArray == null) { + //roofs(์ง€๋ถ•์žฌ์ถ”๊ฐ€) ๊ฐ’์ด ์—†์œผ๋ฉด lastRoofSeq๋Š” 1 ์„ค์ • + setLastRoofSeq(1) + } else { + setLastRoofSeq(roofsArray.length + 1) + } + }) + if (!(Object.keys(canvasSetting).length === 0 && canvasSetting.constructor === Object)) { setBasicSettings({ ...canvasSetting }) } @@ -39,42 +92,99 @@ export default function InitSettingsModal(props) { //๋ฐฐ์—ด ์ถ”๊ฐ€ ํ•จ์ˆ˜ const addRoofSetting = () => { - if (basicSetting.roofs.length === 4) { + if (basicSetting.roofs != null && basicSetting.roofs.length === 4) { alert('์ง€๋ถ•์žฌ๋Š” ์ตœ๋Œ€ 4์ข…๊นŒ์ง€ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.') return } + //roofs๊ฐ€ null์ธ ๊ฒฝ์šฐ ๋ฐฐ์—ด ์ƒ์„ฑ + if (basicSetting.roofs == null) { + basicSetting.roofs = [] + } + //๊ธฐ๋ณธ๊ฐ’ const newRoofSettings = { - id: basicSetting.roofs.length + 1, - roofId: '3', - width: '200', - height: '200', - gap: '0', - layout: 'parallel', + //roofSeq: basicSetting.roofs.length + 1, + roofSeq: lastRoofSeq, // ๋งˆ์ง€๋ง‰ roofSeq๋ฅผ 1 ์ฆ๊ฐ€ + roofType: '3', + roofWidth: '200', + roofHeight: '200', + roofGap: '0', + roofLayout: 'parallel', } setBasicSettings((prevState) => ({ ...prevState, roofs: [...prevState.roofs, newRoofSettings], })) + + setLastRoofSeq(newRoofSettings.roofSeq + 1) // roofSeq ๊ฐ’์„ ์—…๋ฐ์ดํŠธ } //๋ฐฐ์—ด ๊ฐ’ ๋ณ€๊ฒฝ ํ•จ์ˆ˜ const handleRoofSettings = (id, event) => { - const roof = basicSetting.roofs.map((roof, i) => (id === roof.id ? { ...roof, [event.target.name]: event.target.value } : roof)) - setBasicSettings((prevState) => ({ - ...prevState, - roofs: [...roof], - })) + console.log(id) + + // ๊ธฐ๋ณธ ์„ธํŒ…์—์„œ roofs ๋ฐฐ์—ด์„ ๋ณต์‚ฌ + const updatedRoofs = [...basicSetting.roofs] + + // roofSeq๊ฐ€ id์™€ ์ผ์น˜ํ•˜๋Š” ํ•ญ๋ชฉ์˜ ์ธ๋ฑ์Šค ์ฐพ๊ธฐ + const index = updatedRoofs.findIndex((roof) => roof.roofSeq === id) + + if (index !== -1) { + // ํ•ด๋‹น ์ธ๋ฑ์Šค์˜ ํ•ญ๋ชฉ์„ ์ˆ˜์ • + updatedRoofs[index] = { + ...updatedRoofs[index], + [event.target.name]: event.target.value, + } + + // ์ˆ˜์ •๋œ ๋ฐฐ์—ด์„ ์ƒํƒœ์— ๋ฐ˜์˜ + setBasicSettings((prevState) => ({ + ...prevState, + roofs: updatedRoofs, + })) + } + + // const roof = basicSetting.roofs.map((roof, i) => (id === roof.roofSeq ? { ...roof, [event.target.name]: event.target.value } : roof)) + + // setBasicSettings((prevState) => ({ + // ...prevState, + // roofs: [...roof], + // })) } - const submitCanvasConfig = () => { - post({ url: '/api/canvas-config', data: basicSetting }).then((res) => { - if (!res) { - setCanvasSetting({ ...basicSetting }) - } - }) + //์ €์žฅ + const submitCanvasConfig = async () => { + if (!objectNo) { + alert('object_no๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.') + return + } + + const patternData = { + objectNo, + roofDrawingSet: basicSetting.roofDrawingSet, + roofSizeSet: basicSetting.roofSizeSet, + roofAngleSet: basicSetting.roofAngleSet, + roofMaterialsAddList: basicSetting.roofs, + } + await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }) + + //Recoil ์„ค์ • + setCanvasSetting({ ...basicSetting }) + + // ์ €์žฅ ํ›„ ์žฌ์กฐํšŒ + //await handleSelect() + } + + // ์‚ญ์ œ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ํ•ด๋‹น ์š”์†Œ id๋ฅผ targetId๋กœ ์ „๋‹ฌ๋ฐ›์Œ + const onRemove = async (targetId) => { + console.log(targetId) + + setBasicSettings((prevState) => ({ + ...prevState, + roofs: prevState.roofs.filter((roof) => roof.roofSeq !== targetId), + })) + // setBasicSettings({ ...newRoofSettings }) // ์‚ญ์ œํ•œ ๋ฐ์ดํ„ฐ ๋ฐฐ์—ด์„ setData()์— ์ƒํƒœ๋ฅผ ๋ณ€ํ™”์‹œํ‚ด } return ( @@ -84,7 +194,13 @@ export default function InitSettingsModal(props) {
- + ์น˜์ˆ˜ ์ž…๋ ฅ์— ์˜ํ•œ ๋ฌผ๊ฑด์ž‘์„ฑ
@@ -92,7 +208,13 @@ export default function InitSettingsModal(props) {
- + ๋ณต์‚ฌ๋„ ์ž…๋ ฅ ์‹ค์ธก๊ฐ’ ์ž…๋ ฅ ์œก์ง€๋ถ• @@ -102,13 +224,20 @@ export default function InitSettingsModal(props) {
- + ๊ฒฝ์‚ฌ ๊ฐ๋„
+
์ง€๋ถ•์žฌ ์ถ”๊ฐ€(๋‹จ์œ„ : mm)
+ {/* Roofs Array Rendering */} {basicSetting.roofs && basicSetting.roofs.map((roof, index) => { - return + return ( +
+ ํƒ€์ž… : + + ๋„ˆ๋น„ : + handleRoofSettings(roof.roofSeq, e)} + /> + mm + ๋†’์ด : + handleRoofSettings(roof.roofSeq, e)} + /> + mm + ์„œ๊นŒ๋ž˜ ๊ฐ„๊ฒฉ : + handleRoofSettings(roof.roofSeq, e)} + /> + mm +
+ handleRoofSettings(roof.roofSeq, e)} + > + ๋ณ‘๋ ฌ์‹ + ๊ณ„๋‹จ์‹ + +
+
+ +
+
+ ) })}
@@ -128,62 +330,9 @@ export default function InitSettingsModal(props) { + setObjectNo(e.target.value)} />
) } - -const RoofSelectBox = (props) => { - return ( -
- - props.onChange(props.roof.id, e)} - /> - props.onChange(props.roof.id, e)} - /> - mm - props.onChange(props.roof.id, e)} /> - mm -
- props.onChange(props.roof.id, e)} - > - ๋ณ‘๋ ฌ์‹ - ๊ณ„๋‹จ์‹ - -
-
- ) -} diff --git a/src/components/Main.jsx b/src/components/Main.jsx index 554c7e8b..224ce1ea 100644 --- a/src/components/Main.jsx +++ b/src/components/Main.jsx @@ -3,6 +3,7 @@ import { logout } from '@/lib/authActions' import { useChangeLocale, useI18n } from '@/locales/client' import { Button, Chip } from '@nextui-org/react' +import Link from 'next/link' export default function MainPage(props) { const { currentLocale, isLoggedIn } = props @@ -34,7 +35,28 @@ export default function MainPage(props) {
)} + {!isLoggedIn && ( +
+ + + +
+ )}
font-test
+ {/*

{t('locale', { locale: {currentLocale} })}

*/} + {/*
{t('hello')}
*/} + {/*
{t('welcome', { name: 'ํšจ์ค€' })}
*/} + {/*
*/} + {/* */} + {/*
*/} + {/*{isLoggedIn && (*/} + {/*
*/} + {/* */} + {/*
*/} + {/*)}*/} + {/*
font-test
*/} ) } diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx index 624113de..da470ab3 100644 --- a/src/components/Playground.jsx +++ b/src/components/Playground.jsx @@ -1,25 +1,32 @@ 'use client' import { useRef, useState } from 'react' -import { Button } from '@nextui-org/react' -import ColorPicker from './common/color-picker/ColorPicker' +import { useRecoilState } from 'recoil' +import { v4 as uuidv4 } from 'uuid' +import { FaAnglesUp } from 'react-icons/fa6' +import { FaAnglesDown } from 'react-icons/fa6' import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' import { convertDwgToPng } from '@/lib/cadAction' -// import { get } from '@/lib/Axios' +import { cadFileNameState, googleMapFileNameState, useCadFileState, useGoogleMapFileState } from '@/store/canvasAtom' import QSelect from '@/components/ui/QSelect' +import { Button } from '@nextui-org/react' +import ColorPicker from './common/color-picker/ColorPicker' +import { toastUp } from '@/hooks/useToast' import styles from './playground.module.css' -import { useRecoilState } from 'recoil' -import { cadFileNameState, useCadFileState } from '@/store/canvasAtom' -import { toastUp } from '@/hooks/useToast' +import Image from 'next/image' export default function Playground() { const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState) const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState) + const [useGoogleMapFile, setUseGoogleMapFile] = useRecoilState(useGoogleMapFileState) + const [googleMapFileName, setGoogleMapFileName] = useRecoilState(googleMapFileNameState) const fileRef = useRef(null) + const queryRef = useRef(null) + const [zoom, setZoom] = useState(20) const { get, promisePost } = useAxios() const testVar = process.env.NEXT_PUBLIC_TEST const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL @@ -56,6 +63,26 @@ export default function Playground() { }) } + const handleDownImage = async (fileName = '') => { + const fileNm = fileName === '' ? uuidv4() : fileName + const queryString = queryRef.current.value === '' ? '์„œ์šธ์‹œ ์„œ๋Œ€๋ฌธ๊ตฌ ์—ฐ์„ธ๋กœ5๋‹ค๊ธธ 22-3 ๋ฐœ๋ฆฌ๋นŒ๋ผ 3์ธต' : queryRef.current.value + const res = await get({ url: `http://localhost:3000/api/html2canvas?q=${queryString}&fileNm=${fileNm}&zoom=${zoom}` }) + console.log('res', res) + setGoogleMapFileName(res.fileNm) + toastUp({ message: '์ด๋ฏธ์ง€ ์ €์žฅ ์™„๋ฃŒ', type: 'success' }) + setUseGoogleMapFile(true) + } + + const handleZoom = async (type) => { + if (type === 'up') { + setZoom((prevState) => prevState + 1) + } else { + setZoom((prevState) => prevState - 1) + } + + await handleDownImage() + } + const data = [ { id: 1, @@ -99,11 +126,31 @@ export default function Playground() {
{color}
+

์บ๋“œ ํŒŒ์ผ ์ด๋ฏธ์ง€ ์‚ฌ์šฉ

+
+

๊ตฌ๊ธ€ ๋งต ์ด๋ฏธ์ง€ ์‚ฌ์šฉ

+ +
+ +
+ {useGoogleMapFile && ( + <> +
+

Zoom Controller : {zoom}

+ + +
+
+ +
+ + )} +
) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 5fa121f2..3d410c10 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -16,11 +16,13 @@ import { currentObjectState, fontSizeState, globalCompassState, + googleMapFileNameState, roofMaterialState, roofState, sortedPolygonArray, templateTypeState, useCadFileState, + useGoogleMapFileState, wallState, } from '@/store/canvasAtom' import { QLine } from '@/components/fabric/QLine' @@ -39,6 +41,7 @@ import GridSettingsModal from './GridSettingsModal' import { SurfaceShapeModal } from '@/components/ui/SurfaceShape' import { changeAllGableRoof, drawDirectionStringToArrow } from '@/util/qpolygon-utils' import ThumbnailList from '@/components/ui/ThumbnailLIst' +import ObjectPlacement from '@/components/ui/ObjectPlacement' export default function Roof2(props) { const { name, userId, email, isLoggedIn } = props @@ -49,7 +52,7 @@ export default function Roof2(props) { setCanvasBackgroundWithDots, saveImage, addCanvas, - handleCadImageLoad, + handleBackImageLoadToCanvas, handleCadImageInit, backImg, setBackImg, @@ -99,13 +102,18 @@ export default function Roof2(props) { canvas, } + let imgPath // cad ํŒŒ์ผ ์—…๋กœ๋“œ const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState) const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState) const [cadFileComplete, setCadFileComplete] = useRecoilState(cadFileCompleteState) - let imgPath useCadFile && (imgPath = `/cadImages/${cadFileName}`) + // ๊ตฌ๊ธ€๋งต ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ + const [useGoogleMapFile, setUseGoogleMapFile] = useRecoilState(useGoogleMapFileState) + const [googleMapFileName, setGoogleMapFileName] = useRecoilState(googleMapFileNameState) + useGoogleMapFile && (imgPath = `/mapImages/${googleMapFileName}`) + const [globalCampass, setGlobalCampass] = useRecoilState(globalCompassState) const { @@ -157,7 +165,11 @@ export default function Roof2(props) { if (!cadFileComplete && useCadFile) { // cad ํŒŒ์ผ ๋กœ๋“œ - useCadFile && handleCadImageLoad(imgPath, canvas) + useCadFile && handleBackImageLoadToCanvas(imgPath, canvas) + } + + if (useGoogleMapFile) { + handleBackImageLoadToCanvas(imgPath, canvas) } }, [canvas, mode]) @@ -768,6 +780,15 @@ export default function Roof2(props) { > ๋ฉดํ˜•์ƒ + {/**/} @@ -827,6 +848,7 @@ export default function Roof2(props) { backImg .set({ selectable: false, + opacity: 0.7, }) .sendToBack() canvas.clear() @@ -836,7 +858,7 @@ export default function Roof2(props) { } }} > - cad ํŒŒ์ผ ์กฐ์ • ์™„๋ฃŒ + ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€ ์กฐ์ • ์™„๋ฃŒ

+ +

+ + ) + + const customStyles = { + overlay: { + backgroundColor: 'rgba(0,0,0,0.5)', + }, + content: { + width: '300px', + height: '400px', + margin: 'auto', + borderRadius: '4px', + boxShadow: '0 2px 4px rgba(0,0,0,0.2)', + padding: '20px', + }, + } + // ์ƒํƒœ๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ๊ด€๋ฆฌ const [settings, setSettings] = useState({ display1: Array(11).fill(false), // ํ™”๋ฉด ํ‘œ์‹œ1 @@ -48,6 +93,21 @@ export default function Settings() { // ํด๋ฆญ ์‹œ ์ƒํƒœ ๋ณ€๊ฒฝ ํ•จ์ˆ˜ const handleToggle = (type, index) => { + // '์‹ค์„  ๊ทธ๋ฆฌ๋“œ' ํด๋ฆญ ์‹œ ํŒ์—… ์—ด๊ธฐ + if (type === 'gridSettings' && gridItems.gridSettings[index] === '์‹ค์„  ๊ทธ๋ฆฌ๋“œ') { + //openGridPopup() + } + + // '๊ทธ๋ฆฌ๋“œ ์ƒ‰ ์„ค์ •' ํด๋ฆญ ์‹œ ํŒ์—… ์—ด๊ธฐ + if (type === 'gridSettings' && gridItems.gridSettings[index] === '๊ทธ๋ฆฌ๋“œ ์ƒ‰ ์„ค์ •') { + //setSelectedGridSetting(gridItems.gridSettings[index]) + //setIsPopupOpen(true) + //return prevSettings // ์„ค์ •์€ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์Œ + + setOpen(true) + setContent({ ...colorSetting }) + } + setSettings((prevSettings) => { // prevSettings[type]์ด ๋ฐฐ์—ด์ธ์ง€ ํ™•์ธํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋นˆ ๋ฐฐ์—ด๋กœ ์ดˆ๊ธฐํ™” let updated = Array.isArray(prevSettings[type]) ? [...prevSettings[type]] : [] @@ -61,6 +121,24 @@ export default function Settings() { }) } + // '์‹ค์„  ๊ทธ๋ฆฌ๋“œ' ํด๋ฆญ ์‹œ ํŒ์—…์„ ์—ด๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜ + const openGridPopup = () => { + const popupWidth = 500 + const popupHeight = 300 + + // ํŒ์—… ์ฐฝ ์œ„์น˜๋ฅผ ํ™”๋ฉด ์ค‘์•™์œผ๋กœ ์กฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด ๊ณ„์‚ฐ + const left = window.innerWidth / 2 - popupWidth / 2 + const top = window.innerHeight / 2 - popupHeight / 2 + + // ์ƒˆ ์ฐฝ ์—ด๊ธฐ + window + .open + //'./components/intro', // ํŒ์—…์œผ๋กœ ๋„์šธ ํŽ˜์ด์ง€์˜ URL + //'_blank', // ์ƒˆ ์ฐฝ์œผ๋กœ ์—ด๊ธฐ + //`width=${popupWidth},height=${popupHeight},top=${top},left=${left}`, // ํฌ๊ธฐ์™€ ์œ„์น˜ ์ง€์ • + () + } + // Canvas Setting ์กฐํšŒ ๋ฐ ์ดˆ๊ธฐํ™” const handleSelect = async () => { try { @@ -221,6 +299,10 @@ export default function Settings() {
ํก์ฐฉ์  ON

[๊ทธ๋ฆฌ๋“œ ์„ค์ •]

+
+ +
{color}
+
{gridItems.gridSettings.map((item, index) => (
{ + const param = { + langCd: 'JA', + lastEditUser: formData.get('userId'), + storeQcastNm: formData.get('storeQcastNm'), + storeQcastNmKana: formData.get('storeQcastNmKana'), + postCd: formData.get('postCd'), + addr: formData.get('addr'), + telNo: formData.get('telNo'), + fax: formData.get('fax'), + payTermsCd: 'JB02', + kamId: 'E1101011', + qtCompNm: formData.get('qtCompNm'), + qtPostCd: formData.get('qtPostCd'), + qtAddr: formData.get('qtAddr'), + qtTelNo: formData.get('qtTelNo'), + qtFax: formData.get('qtFax'), + userInfo: { + userId: formData.get('userId'), + userNm: formData.get('userNm'), + userNmKana: formData.get('userNmKana'), + telNo: formData.get('userTelNo'), + fax: formData.get('userFax'), + email: formData.get('email'), + category: formData.get('category'), + }, + } + + await post({ url: '/api/login/v1.0/user/join', data: param }).then((res) => { + if (res) { + if (res.result.resultCode == 'S') { + redirect('/join/complete') + } else { + alert(res.result.resultMsg) + } + } + }) + } + + return ( +
+

{getMessage('join.title')}

+
+
+
+ โ— {getMessage('join.sub1.title')} (*{getMessage('common.require')}) {getMessage('join.sub1.comment')} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
{getMessage('join.sub1.storeQcastNm')} * + +
{getMessage('join.sub1.storeQcastNmKana')} * + +
+ {getMessage('join.sub1.postCd')}/{getMessage('join.sub1.addr')} * + + + +
{getMessage('join.sub1.telNo')} * + +
{getMessage('join.sub1.fax')} * + +
+ +
+ โ— {getMessage('join.sub2.title')} (*{getMessage('common.require')}) +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{getMessage('join.sub2.userNm')} * + +
{getMessage('join.sub2.userNmKana')} * + +
{getMessage('join.sub2.userId')} * + +
{getMessage('join.sub2.email')} * + +
{getMessage('join.sub2.telNo')} * + +
{getMessage('join.sub2.fax')} * + +
{getMessage('join.sub2.category')} + +
+ +
+ โ— {getMessage('join.sub3.title')} (*{getMessage('common.require')}) +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
{getMessage('join.sub3.qtCompNm')} + +
+ {getMessage('join.sub3.qtPostCd')}/{getMessage('join.sub3.qtAddr')} + + + +
{getMessage('join.sub3.qtEmail')} + +
{getMessage('join.sub3.qtTelNo')} + +
{getMessage('join.sub3.qtFax')} + +
+
+
+ +
+
+
+ ) +} diff --git a/src/components/auth/Login.jsx b/src/components/auth/Login.jsx index 72363367..5772ab79 100644 --- a/src/components/auth/Login.jsx +++ b/src/components/auth/Login.jsx @@ -1,21 +1,127 @@ 'use client' -import { login } from '@/lib/authActions' +import { post, patch } from '@/lib/Axios' +import { setSession } from '@/lib/authActions' +import { redirect } from 'next/navigation' +import { useMessage } from '@/hooks/useMessage' -export default function Login() { - return ( -
-
-
- Your Company -

Sign in to your account

+import { Button } from '@nextui-org/react' +import { useRecoilState } from 'recoil' +import { modalContent, modalState } from '@/store/modalAtom' + +export default function Login(props) { + const { currentLocale } = props + const { getMessage } = useMessage() + + // login process + const loginProcess = async (formData) => { + const param = { + langCd: currentLocale, + lastEditUser: formData.get('id'), + loginId: formData.get('id'), + pwd: formData.get('password'), + } + + await post({ url: '/api/login/v1.0/login', data: param }).then((res) => { + if (res) { + if (res.result.resultCode == 'S') { + // console.log('res.data', res.data) + // ๋น„๋ฐ€๋ฒˆํ˜ธ ์ดˆ๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ + // if (res.data.pwdInitYn != 'Y') { + // alert('๋น„๋ฐ€๋ฒˆํ˜ธ ์ดˆ๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ') + // } else { + setSession(res.data) + redirect('/') + // } + } else { + alert(res.result.resultMsg) + } + } + }) + } + + // ๋น„๋ฐ€๋ฒˆํ˜ธ ์ดˆ๊ธฐํ™” ๊ด€๋ จ + const [open, setOpen] = useRecoilState(modalState) + const [contents, setContent] = useRecoilState(modalContent) + + const initPasswordProcess = async (formData) => { + const param = { + langCd: currentLocale, + lastEditUser: formData.get('checkId'), + loginId: formData.get('checkId'), + email: formData.get('checkEmail'), + } + + await patch({ url: '/api/login/v1.0/user/init-password', data: param }).then((res) => { + if (res) { + if (res.result.resultCode == 'S') { + alert(getMessage('login.init_password.complete_message')) + redirect('/login') + } else { + alert(res.result.resultMsg) + } + } + }) + } + + const initPasswordContent = ( +
+
+

{getMessage('login.init_password.title')}

+

{getMessage('login.init_password.sub_title')}

+
+ +
+ +
+
+
+ +
+
+ +
+
+

+ +

+
+
+ ) + + return ( +
+
-
+

{getMessage('site.name')}

+

{getMessage('site.sub_name')}

+
+ +
+
Password -
-

- Not a member?{' '} - - Start a 14 day free trial - +

+

diff --git a/src/components/common/context-menu/QContextMenu.jsx b/src/components/common/context-menu/QContextMenu.jsx index 9a805ba1..4658ef6f 100644 --- a/src/components/common/context-menu/QContextMenu.jsx +++ b/src/components/common/context-menu/QContextMenu.jsx @@ -12,9 +12,11 @@ export default function QContextMenu(props) { let contextType = '' if (activeObject) { - //์ด๊ฑด ๋ฐ”๋€” ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Œ - if (activeObject.initOptions.name.indexOf('guide') > -1) { - contextType = 'surface' //๋ฉดํ˜•์ƒ + if (activeObject.initOptions) { + //์ด๊ฑด ๋ฐ”๋€” ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Œ + if (activeObject.initOptions.name.indexOf('guide') > -1) { + contextType = 'surface' //๋ฉดํ˜•์ƒ + } } } diff --git a/src/components/common/datepicker/RangeDatePicker.jsx b/src/components/common/datepicker/RangeDatePicker.jsx index ad802f49..de80221f 100644 --- a/src/components/common/datepicker/RangeDatePicker.jsx +++ b/src/components/common/datepicker/RangeDatePicker.jsx @@ -14,6 +14,7 @@ export default function RangeDatePicker(props) { setDateRange(update) }} isClearable={true} + // showMonthYearPicker={true} /> ) } diff --git a/src/components/common/draggable/withDraggable.jsx b/src/components/common/draggable/withDraggable.jsx new file mode 100644 index 00000000..9f322583 --- /dev/null +++ b/src/components/common/draggable/withDraggable.jsx @@ -0,0 +1,22 @@ +'use client' + +import { useState } from 'react' +import Draggable from 'react-draggable' + +export default function WithDraggable({ isShow, children }) { + const [position, setPosition] = useState({ x: 0, y: 0 }) + + const handleOnDrag = (data) => { + setPosition({ x: data.x, y: data.y }) + } + + return ( + <> + {isShow && ( + handleOnDrag(data)}> + {children} + + )} + + ) +} diff --git a/src/components/common/select/QSelectBox.jsx b/src/components/common/select/QSelectBox.jsx new file mode 100644 index 00000000..6e77a539 --- /dev/null +++ b/src/components/common/select/QSelectBox.jsx @@ -0,0 +1,19 @@ +'use client' +import { useState } from 'react' + +export default function QSelectBox({ title, option }) { + const [selectAct, setSelectAct] = useState(false) + + return ( +
setSelectAct(!selectAct)}> +

{title}

+
    + {option.map((el, idx) => ( +
  • + +
  • + ))} +
+
+ ) +} diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 0991fd84..84e57974 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -119,6 +119,9 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { this.on('modified', (e) => { this.addLengthText() + if (this.arrow) { + drawDirectionArrow(this) + } }) this.on('selected', () => { @@ -136,6 +139,17 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { this.canvas.remove(text) }) this.texts = null + + if (this.arrow) { + this.canvas.remove(this.arrow) + this.canvas + .getObjects() + .filter((obj) => obj.name === 'directionText' && obj.parent === this.arrow) + .forEach((text) => { + this.canvas.remove(text) + }) + this.arrow = null + } }) // polygon.fillCell({ width: 50, height: 30, padding: 10 }) diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx new file mode 100644 index 00000000..5923888f --- /dev/null +++ b/src/components/floor-plan/CanvasFrame.jsx @@ -0,0 +1,7 @@ +export default function CanvasFrame () { + return( +
+ +
+ ) +} \ No newline at end of file diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx new file mode 100644 index 00000000..5be6a114 --- /dev/null +++ b/src/components/floor-plan/CanvasLayout.jsx @@ -0,0 +1,45 @@ +'use client' + +import { useState } from "react" +import CanvasFrame from "./CanvasFrame"; + +export default function CanvasLayout () { + const [plans, setPlans] = useState([{ id: 0, name: 'Plan 1' }, { id: 1, name: 'Plan 2' }, { id: 2, name: 'Plan 3' }]); + const [idxNum, setIdxNum] = useState(null); + + const onClickPlane = (num) => { + setIdxNum(num); + } + + const handleDeletePlan = (e, id) => { + e.stopPropagation(); // ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง ๋ฐฉ์ง€ + setPlans(plans.filter(plan => plan.id !== id)); // ์‚ญ์ œํ•  ์•„์ด๋””์™€ ๋‹ค๋ฅธ ์•„์ดํ…œ๋งŒ ๋‚จ๊น€ + } + + const addNewPlan = () => { + setPlans([...plans, { id: plans.length, name: `Plan ${plans.length + 1}` }]); + } + + return( +
+
+
+ {plans.map((plan, idx) => ( + + ))} +
+ +
+ +
+ ) +} \ No newline at end of file diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx new file mode 100644 index 00000000..4533747a --- /dev/null +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -0,0 +1,97 @@ +'use client' +import { useState } from 'react' +import MenuDepth01 from './MenuDepth01' +import QSelectBox from '@/components/common/select/QSelectBox' + +export default function CanvasMenu({ setModalOpen }) { + const [menuNumber, setMenuNumber] = useState(null) + const [vertical, setVertical] = useState(true) + const SelectOption = [{ name: '็“ฆ53A' }, { name: '็“ฆ53A' }] + const onClickNav = (number) => { + setMenuNumber(number) + if (menuNumber === number) { + setMenuNumber(null) + } + } + return ( +
+
+
    +
  • onClickNav(0)}> + +
  • +
  • onClickNav(1)}> + +
  • +
  • onClickNav(2)}> + +
  • +
  • onClickNav(3)}> + +
  • +
  • onClickNav(4)}> + +
  • +
  • onClickNav(5)}> + +
  • +
  • onClickNav(6)}> + +
  • +
+
+
+ + + +
+
+ ๅž‚็›ดๆฐดๅนณใƒขใƒผใƒ‰ + +
+
+ +
+
+ + + +
+
+ + 100% + +
+
+ + + +
+
+
+
+ {menuNumber === 0 && } + {menuNumber === 1 && } + {menuNumber === 2 && } + {menuNumber === 3 && } + {menuNumber === 4 && } + {menuNumber === 5 && } + {menuNumber === 6 && } +
+
+ ) +} diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx new file mode 100644 index 00000000..fecffea7 --- /dev/null +++ b/src/components/floor-plan/FloorPlan.jsx @@ -0,0 +1,21 @@ +'use client' + +import CanvasMenu from '@/components/floor-plan/CanvasMenu' +import CanvasLayout from '@/components/floor-plan/CanvasLayout' +import SettingModal01 from '@/components/floor-plan/modal/settoing01/SettingModal01' +import { useState } from 'react' + +export default function FloorPlan() { + const [modalOpen, setModalOpen] = useState('option') + return ( + <> +
+ +
+ + {modalOpen === 'option' && } +
+
+ + ) +} diff --git a/src/components/floor-plan/MenuDepth01.jsx b/src/components/floor-plan/MenuDepth01.jsx new file mode 100644 index 00000000..90ba4e60 --- /dev/null +++ b/src/components/floor-plan/MenuDepth01.jsx @@ -0,0 +1,44 @@ +'use client' + +import { ToggleonMouse } from '@/components/header/Header' + +export default function MenuDepth01() { + return ( +
+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
    +
  • ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}> + +
  • +
  • ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}> + +
  • +
  • ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}> + +
  • +
+
+ ) +} diff --git a/src/components/floor-plan/modal/settoing01/FirstOption.jsx b/src/components/floor-plan/modal/settoing01/FirstOption.jsx new file mode 100644 index 00000000..e91f81ab --- /dev/null +++ b/src/components/floor-plan/modal/settoing01/FirstOption.jsx @@ -0,0 +1,39 @@ +import { useRecoilState } from 'recoil' +import { settingModalFirstOptionsState } from '@/store/settingAtom' + +export default function FirstOption() { + const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalFirstOptionsState) + const { option1, option2 } = settingsModalOptions + const onClickOption = (option) => { + option.selected = !option.selected + + setSettingModalOptions({ option1, option2 }) + } + + return ( + <> +
+

โ€ปๅ›ณ้ขใซ่กจ็คบใ™ใ‚‹้ …็›ฎใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ™ใ‚‹ใจ้ฉ็”จใ•ใ‚Œใพใ™ใ€‚

+
+ {settingsModalOptions?.option1?.map((item) => ( + + ))} +
+
+
+

็”ป้ข่กจ็คบ

+
+ {settingsModalOptions?.option2?.map((item) => ( + + ))} +
+
+ + ) +} diff --git a/src/components/floor-plan/modal/settoing01/SecondOption.jsx b/src/components/floor-plan/modal/settoing01/SecondOption.jsx new file mode 100644 index 00000000..5b417f2b --- /dev/null +++ b/src/components/floor-plan/modal/settoing01/SecondOption.jsx @@ -0,0 +1,45 @@ +import { useRecoilState } from 'recoil' +import { settingModalSecondOptionsState } from '@/store/settingAtom' + +export default function SecondOption() { + const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalSecondOptionsState) + const { option1, option2 } = settingsModalOptions + const onClickOption = (option) => { + option.selected = !option.selected + + setSettingModalOptions({ option1: option1, option2: option2 }) + } + return ( + <> +
+

ใƒ•ใ‚ฉใƒณใƒˆใจใ‚ตใ‚คใ‚บใฎๅค‰ๆ›ด

+
+ {settingsModalOptions.option1.map((item) => ( + + ))} +
+
+
+

ๅธ็€็ฏ„ๅ›ฒใฎ่จญๅฎš

+
+ {settingsModalOptions.option2.map((item) => ( + + ))} +
+
+ + +
+
+ + ) +} diff --git a/src/components/floor-plan/modal/settoing01/SettingModal01.jsx b/src/components/floor-plan/modal/settoing01/SettingModal01.jsx new file mode 100644 index 00000000..5a79c795 --- /dev/null +++ b/src/components/floor-plan/modal/settoing01/SettingModal01.jsx @@ -0,0 +1,44 @@ +'use client' + +import { useState } from 'react' +import FirstOption from './FirstOption' +import WithDraggable from '@/components/common/draggable/withDraggable' +import SecondOption from '@/components/floor-plan/modal/settoing01/SecondOption' + +export default function SettingModal01({ modalOpen, setModalOpen }) { + const [buttonAct, setButtonAct] = useState(1) + const [close, setClose] = useState(false) + const HandleClickClose = () => { + setClose(true) + setTimeout(() => { + setModalOpen('') + setClose(false) + }, 180) + } + + return ( + +
+
+

Canvas่จญๅฎš

+ +
+
+
+ + + +
+ {buttonAct === 1 && } + {buttonAct === 2 && } +
+
+
+ ) +} diff --git a/src/components/header/Header.jsx b/src/components/header/Header.jsx new file mode 100644 index 00000000..028ef6ed --- /dev/null +++ b/src/components/header/Header.jsx @@ -0,0 +1,117 @@ +'use client' +import Link from 'next/link' +import QSelectBox from '@/components/common/select/QSelectBox' +import { usePathname } from 'next/navigation' + +export const ToggleonMouse = (e, act, target) => { + const listWrap = e.target.closest(target) + const ListItem = Array.from(listWrap.childNodes) + ListItem.forEach((el) => { + if (act === 'add') { + el.classList.add('mouse') + } else { + el.classList.remove('mouse') + } + }) + if (act === 'add') { + e.target.parentElement.classList.remove('mouse') + } +} + +export default function Header() { + const pathName = usePathname() + if (pathName.includes('login') || pathName.includes('join')) { + return null + } + const SelectOption = [{ name: 'ใ‚ชใƒณใƒฉใ‚คใƒณไฟ่จผใ‚ท' }, { name: 'ใ‚นใƒ†ใƒ ' }] + + return ( +
+
+
+

+ +

+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ ) +} diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index da7b834d..f8467027 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -1,7 +1,361 @@ +'use client' + +import React, { useEffect, useState, useRef } from 'react' +import { useRouter, usePathname } from 'next/navigation' +import { Button } from '@nextui-org/react' +import { useAxios } from '@/hooks/useAxios' +import { useMessage } from '@/hooks/useMessage' +import StuffQGrid from './StuffQGrid' +import { useRecoilValue } from 'recoil' +import { stuffSearchState } from '@/store/stuffAtom' +import { queryStringFormatter } from '@/util/common-utils' +import dayjs from 'dayjs' +import isLeapYear from 'dayjs/plugin/isLeapYear' // ์œค๋…„ ํŒ๋‹จ ํ”Œ๋Ÿฌ๊ทธ์ธ +dayjs.extend(isLeapYear) + export default function Stuff() { + const stuffSearchParams = useRecoilValue(stuffSearchState) + const { getMessage } = useMessage() + const [curPage, setCurPage] = useState(1) //ํ˜„์žฌ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ + const [size, setSize] = useState(100) //ํŽ˜์ด์ง€ ๋‹น ๊ฒŒ์‹œ๋ฌผ ์ˆ˜ + const { get, del } = useAxios() + const gridRef = useRef() + + const [gridCount, setGridCount] = useState(0) + const [selectedRowData, setSelectedRowData] = useState([]) + const [selectedRowDataCount, setSelectedRowDataCount] = useState(0) + + const router = useRouter() + const pathname = usePathname() + + //๊ทธ๋ฆฌ๋“œ ๋‚ด๋ถ€ ๋ณต์‚ฌ๋ฒ„ํŠผ + const copyNo = async (value) => { + try { + await navigator.clipboard.writeText(value) + alert('๋ฌผ๊ฑด๋ฒˆํ˜ธ๊ฐ€ ๋ณต์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.') + } catch (error) { + alert('๋ฌผ๊ฑด๋ฒˆํ˜ธ ๋ณต์‚ฌ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.') + } + } + + const [gridProps, setGridProps] = useState({ + gridData: [], + isPageable: false, + // sets 10 rows per page (default is 100) + paginationPageSize: 100, + // allows the user to select the page size from a predefined list of page sizes + paginationPageSizeSelector: [100, 200, 300, 400], + gridColumns: [ + { + field: 'lastEditDatetime', + headerName: getMessage('stuff.gridHeader.lastEditDatetime'), + headerCheckboxSelection: true, + headerCheckboxSelectionCurrentPageOnly: true, //ํŽ˜์ด์ง•์‹œ ํ˜„์žฌ ํŽ˜์ด์ง€๋งŒ ์ฒดํฌ๋˜๋„๋ก + checkboxSelection: true, + showDisabledCheckboxes: true, + // headerClass: 'centered', //_test.scss์— ์ถ”๊ฐ€ ํ…Œ์ŠคํŠธ + // .centered { + // .ag-header-cell-label { + // justify-content: center !important; + // } + // } + cellStyle: { textAlign: 'center' }, + //suppressMovable: true, //ํ—ค๋” ๋ชป์›€์ง์ด๊ฒŒ + // width : 100 + // minWidth : 100 + // maxWidth : 100 + valueFormatter: function (params) { + if (params.value) { + return dayjs(params?.value).format('YYYY.MM.DD HH:mm:ss') + } else { + return null + } + }, + }, + { + field: 'objectNo', + headerName: getMessage('stuff.gridHeader.objectNo'), + // headerClass: 'centered', //_test.scss์— ์ถ”๊ฐ€ ํ…Œ์ŠคํŠธ + cellRenderer: function (params) { + if (params.data.objectNo) { + return ( +
+ + {params.value} +
+ ) + } + }, + cellRendererParams: { + onPress: copyNo, + }, + }, + { + field: 'planTotCnt', + headerName: getMessage('stuff.gridHeader.planTotCnt'), + cellStyle: { textAlign: 'right' }, + }, + { field: 'objectName', headerName: getMessage('stuff.gridHeader.objectName'), cellStyle: { textAlign: 'left' } }, + { + field: 'saleStoreId', + headerName: getMessage('stuff.gridHeader.saleStoreId'), + cellStyle: { textAlign: 'left' }, + }, + { field: 'saleStoreName', headerName: getMessage('stuff.gridHeader.saleStoreName'), cellStyle: { textAlign: 'left' } }, + { field: 'address', headerName: getMessage('stuff.gridHeader.address'), cellStyle: { textAlign: 'left' } }, + { field: 'dispCompanyName', headerName: getMessage('stuff.gridHeader.dispCompanyName'), cellStyle: { textAlign: 'left' } }, + { field: 'receiveUser', headerName: getMessage('stuff.gridHeader.receiveUser'), cellStyle: { textAlign: 'left' } }, + { + field: 'specDate', + headerName: getMessage('stuff.gridHeader.specDate'), + valueFormatter: function (params) { + if (params.value) { + return dayjs(params?.value).format('YYYY.MM.DD') + } else { + return null + } + }, + cellStyle: { textAlign: 'center' }, + }, + { + field: 'createDatetime', + headerName: getMessage('stuff.gridHeader.createDatetime'), + valueFormatter: function (params) { + if (params.value) { + return dayjs(params?.value).format('YYYY.MM.DD') + } else { + return null + } + }, + cellStyle: { textAlign: 'center' }, + }, + ], + gridCount: 0, + }) + + //๊ทธ๋ฆฌ๋“œ ๋”๋ธ”ํด๋ฆญ + const getCellDoubleClicked = (event) => { + if (event.column.colId === 'objectNo') { + return + } else { + console.log(' ์ƒ์„ธ์ด๋™::::::::', event.data) + if (event.data.objectNo) { + router.push(`${pathname}/detail?objectNo=${event.data.objectNo.toString()}`) + } + } + } + + //๊ทธ๋ฆฌ๋“œ ์ฒดํฌ๋ฐ•์Šค ์„ ํƒ์‹œ + const getSelectedRowdata = (data) => { + setSelectedRowData(data) + setSelectedRowDataCount(data.length) + } + + //๋ฌผ๊ฑด์‚ญ์ œ + const fnDeleteRowData = (data) => { + console.log('๋ฌผ๊ฑด์‚ญ์ œ:::::::::::') + if (data.length === 0) { + return alert('์‚ญ์ œํ•  ๋ฐ์ดํ„ฐ๋ฅผ ์„ ํƒํ•˜์„ธ์š”') + } + let errCount = 0 + data.forEach((cell) => { + if (!cell.objectNo) { + if (errCount === 0) { + alert('๋ฌผ๊ฑด์ •๋ณด๊ฐ€ ์žˆ๋Š” ํ–‰๋งŒ ์‚ญ์ œ ๋ฉ๋‹ˆ๋‹ค') + } + errCount++ + } + }) + + async function fetchDelete(data) { + console.log('๋ฌผ๊ฑด์‚ญ์ œAPIํ˜ธ์ถœ!!!!!!!!!', data) + //ํ–‰์ถ”๊ฐ€๋ง๊ณ  api๋ฐ์ดํ„ฐ๋งŒ ๋ณด๋ƒ„ + // let newData = data.filter((item) => item.company != null) + // console.log('์‚ญ์ œ์— ์ „์†ก๋˜๋Š” ๋ฐ์ดํƒ€::', newData) + // await del({ url: '', data:newData }) + await get({ url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' }) + // try { + // const res = await del({url:'', data:newData}) + + // if(!res || res.length === 0) { + + // } else { + fetchData() + // } + // } catch (error) { + // console.error('Data Delete error:', error); + // } + } + + // ์‚ญ์ œAPI ์™„๋ฃŒ ํ›„ fetchData Apiํ˜ธ์ถœ + async function fetchData() { + console.log('๋ฌผ๊ฑด์‚ญ์ œํ›„ ์กฐํšŒAPIํ˜ธ์ถœ!!!!!!!!!!!!!', stuffSearchParams) + const data = await get({ url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' }) + setGridProps({ ...gridProps, gridData: data, count: data.length }) + setGridCount(data.length) + //data.length = 10 + //setGridProps({ ...gridProps, gridData: data, count: data.length-1}) + //setGridCount(data.length - 1 ) + } + + if (errCount === 0) { + // console.log('errCount::::::::', errCount) + fetchDelete(data) + // fetchData() + } else { + alert('๋ฌผ๊ฑด์ •๋ณด๊ฐ€ ์žˆ๋Š” ํ–‰๋งŒ ์„ ํƒํ•ด์ฃผ์„ธ์š”') + } + } + + //ํ–‰์ถ”๊ฐ€ + let newCount = 0 + const addRowItems = () => { + // console.log('girdRef::::::', gridRef.current.api) + const newItems = [ + { + mission: newCount + 1, + successful: true, + }, + ] + gridRef.current.api.applyTransaction({ + add: newItems, + addIndex: newCount, + }) + newCount++ + } + + //ํ–‰์‚ญ์ œ + const removeRowItems = () => { + // console.log('selectedRowData::', selectedRowData) + let errCount = 0 + selectedRowData.forEach((cell) => { + if (!cell.company) { + let newSelectedRowData = selectedRowData.filter((item) => item.company == null) + gridRef.current.api.applyTransaction({ remove: newSelectedRowData }) + } else { + if (errCount === 0) { + alert('ํ–‰์ถ”๊ฐ€๋กœ ์ถ”๊ฐ€ ํ•œ ํ–‰๋งŒ ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค.') + } + errCount++ + } + }) + } + + // ์ง„์ž…์‹œ ๊ทธ๋ฆฌ๋“œ ๋ฐ์ดํ„ฐ ์กฐํšŒ + useEffect(() => { + if (stuffSearchParams?.code === 'S') { + const params = { + schObjectNo: '', + schSaleStoreId: '', + schAddress: '', + schObjectName: '', + schSaleStoreName: '', + schSpecDateYn: '', + schReceiveUser: '', + schDispCompanyName: '', + schDateType: 'U', + schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), + schToDt: dayjs(new Date()).format('YYYY-MM-DD'), + startRow: (curPage - 1) * size + 1, + endRow: curPage * size, + } + + async function fetchData() { + console.log('ํ™”๋ฉด์ง„์ž…:::::::::::::', params) + console.log('ํ˜„์žฌํŽ˜์ด์ง€::::::', curPage) + console.log('ํŽ˜์ด์ง€๋‹น ๊ฒŒ์‹œ๋ฌผ์ˆ˜::::::', size) + + //api์— ๋„˜๊ธธ๊ฐ’ startRow, endRow + // let startRow + // let endRow + // startRow = (curPage - 1) * size + 1 + // endRow = curPage * size + // console.log('startrow::', startRow) + // console.log('endRow::', endRow) + + // let curPage + // let totalpage + // let totalCount + // let size + // let pageCount + + const apiUrl = `/api/object/v1.0/object?saleStoreId=201TES01&${queryStringFormatter(params)}` + + await get({ + url: apiUrl, + }).then((res) => { + if (res.length > 0) { + console.log('API๊ฒฐ๊ณผ:::::::', res) + setGridProps({ ...gridProps, gridData: res, count: res.length }) + setGridCount(res.length) + } + }) + } + fetchData() + } + }, []) + + useEffect(() => { + if (stuffSearchParams?.code === 'E') { + console.log('์กฐํšŒ ๋ˆŒ๋Ÿฟ์„๋•Œ ::::::::::::::', stuffSearchParams) + async function fetchData() { + const apiUrl = `/api/object/v1.0/object?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` + await get({ url: apiUrl }).then((res) => { + console.log('API๊ฒฐ๊ณผ:::::::', res) + setGridProps({ ...gridProps, gridData: res, count: res.length }) + setGridCount(res.length) + }) + } + fetchData() + } + }, [stuffSearchParams]) + return ( <> -

Management Stuff

+
+ ๋ฌผ๊ฑด๋ชฉ๋ก + + ์ „์ฒด : {gridCount} // ์„ ํƒ : {selectedRowDataCount} + +
+ {/* */} + {/* + */} +
+
+ +
+
) } diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx new file mode 100644 index 00000000..ed15d729 --- /dev/null +++ b/src/components/management/StuffDetail.jsx @@ -0,0 +1,475 @@ +'use client' + +import React, { useState, useEffect } from 'react' +import { useRouter, useSearchParams } from 'next/navigation' +import { Input, RadioGroup, Radio, Button, Autocomplete, AutocompleteItem, Select, SelectItem, Checkbox, Textarea, button } from '@nextui-org/react' +import Link from 'next/link' +import { get } from '@/lib/Axios' +import { queryStringFormatter } from '@/util/common-utils' +import dayjs from 'dayjs' +import { useForm } from 'react-hook-form' +export default function StuffDetail() { + const router = useRouter() + const searchParams = useSearchParams() + + //form + const formInitValue = { + // ๋ฌผ๊ฑด๋ฒˆํ˜ธ T...(์ž„์‹œ) R...(์ง„์งœ) + dispCompanyName: '', //๋‹ด๋‹น์ž + objectStatusId: '0', //๋ฌผ๊ฑด๊ตฌ๋ถ„(์‹ ์ถ•:0 ๊ธฐ์ถ• : 1) + objectName: '', //๋ฌผ๊ฑด๋ช… + objectNameOmit: '', //๊ฒฝ์นญ์„ ํƒ + objectNameKana: '', //๋ฌผ๊ฑด๋ช… ํ›„๋ฆฌ๊ฐ€๋‚˜ + saleStoreId: '', //ํŒ๋งค์ ID + saleStoreName: '', //ํŒ๋งค์ ๋ช… + zipNo: '', //์šฐํŽธ๋ฒˆํ˜ธ + prefId: '', //๋„๋„๋ถ€ํ˜„ + address: '', //์ฃผ์†Œ + powerSimArea: '', //๋ฐœ์ „๋Ÿ‰์‹œ๋ฎฌ๋ ˆ์ด์…˜์ง€์—ญ + windSpeed: '', //๊ธฐ์ค€ํ’์† + snowCover: '', //์ˆ˜์ง์ ์„ค๋Ÿ‰ + coldAreaChk: false, //ํ•œ๋žญ์ง€๋Œ€์ฑ…์‹œํ–‰ + surfaceType: '', //๋ฉด์กฐ๋„๊ตฌ๋ถ„(โ…ขใƒปโ…ฃ / โ…ก) + saltAreaChk: false, //์—ผํ•ด์ง€์—ญ์šฉ์•„์ดํ…œ์‚ฌ์šฉ + installHeight: '', //์„ค์น˜๋†’์ด + powerConTerms: '', //๊ณ„์•ฝ์กฐ๊ฑด + remark: '', //๋ฉ”๋ชจ + tempFlag: 'T', //์ž„์‹œ์ €์žฅ(1) ์ €์žฅ(0) + } + const { register, setValue, getValues, handleSubmit, resetField, control, watch } = useForm({ + defaultValues: formInitValue, + }) + + const form = { register, setValue, getValues, handleSubmit, resetField, control, watch } + + const [receiveUser, setReceiveUser] = useState('') //๋‹ด๋‹น์ž + const [name2, setName2] = useState('') //๋ฌผ๊ฑด๋ช… + const [name3, setName3] = useState('') //๋ฌผ๊ฑด๋ช…ํ›„๋ฆฌ๊ฐ€๋‚˜ + const [zipCode, setZipCode] = useState('') //์šฐํŽธ๋ฒˆํ˜ธ + const [name5, setName5] = useState('') //์ˆ˜์ง์ ์„ค๋Ÿ‰ + const [gubun, setGubun] = useState('NEW') //์‹ ์ถ• ๊ธฐ์ถ• + const [sel, setSel] = useState('') //๊ฒฝ์นญ์„ ํƒ + const [sel2, setSel2] = useState('') //๋ฐœ์ „๋Ÿ‰์‹œ๋ฎฌ๋ ˆ์ด์…˜์ง€์—ญ + const [sel3, setSel3] = useState('') //๊ธฐ์ค€ํ’์† + const [sel4, setSel4] = useState('') //์„ค์น˜๋†’์ด + + const [errors, setErrors] = useState({}) + const [isFormValid, setIsFormValid] = useState(false) //์ž„์‹œ์ €์žฅ, ์ง„์งœ์ €์žฅ ๋ฒ„ํŠผ ์ปจํŠธ๋กค + const [testSelOption, setTestSelOption] = useState([]) // ํ…Œ์ŠคํŠธ์šฉ + const [autoSelectValue, setAutoSelectValue] = useState('') //ํŒ๋งค์ ๋ช… ์ž๋™์™„์„ฑ + const [buttonValid, setButtonValid] = useState(false) //์ฃผ์†Œ๊ฒ€์ƒ‰ ํ™œ์„ฑํ™” ์ปจํŠธ๋กค + const [isSelected, setIsSelected] = useState(false) //ํ•œ๋žญ์ง€๋Œ€์ฒต ์ฒดํฌ๋ฐ•์Šค + const [isSelected2, setIsSelected2] = useState(false) //์—ผํ•ด์ง€์—ญ์šฉ์•„์ดํ…œ์‚ฌ์šฉ ์ฒดํฌ๋ฐ•์Šค + const [gubun2, setGubun2] = useState('1') //๋ฉด์กฐ๋„๊ตฌ๋ถ„ ๋ผ๋””์˜ค + const [gubun3, setGubun3] = useState('A') //๊ณ„์•ฝ์กฐ๊ฑด ๋ผ๋””์˜ค + const [memo, setMemo] = useState('') //๋ฉ”๋ชจ + const objectNo = searchParams.get('objectNo') //url์—์„œ ๋ฌผ๊ฑด๋ฒˆํ˜ธ ๊บผ๋‚ด์„œ ๋ฐ”๋กœ set + + // const [address1, setAddress1] = useState('') //์šฐํŽธAPI๋ฆฌํ„ด ๋„๋„๋ถ€ํ˜„๋ช… + // const [address2, setAddress2] = useState('') //์šฐํŽธAPI๋ฆฌํ„ด ์‹œ๊ตฌ์ •์ดŒ๋ช… + // const [address3, setAddress3] = useState('') //์šฐํŽธAPI๋ฆฌํ„ด ๋งˆ์„ ์ง€์—ญ๋ช… + // const [prefCode, setPrefCode] = useState(1) //์šฐํŽธAPI prefcode + + const [editMode, setEditMode] = useState('NEW') + const [detailData, setDetailData] = useState({}) + + useEffect(() => { + // console.log('์ƒ์„ธํ™”๋ฉด์ง„์ž…:::::::::', searchParams.get('objectNo')) + console.log('๋ฌผ๊ฑด๋ฒˆํ˜ธ::::', objectNo) + + if (objectNo) { + // console.log('์ƒ์„ธ::', objectNo) + setEditMode('EDIT') + if (objectNo.substring(0, 1) === 'R') { + setIsFormValid(true) + } + //์ผ๋‹จ ํ”Œ๋žœ๋ฒˆํ˜ธ ๋ฌด์กฐ๊ฑด 1๋กœ + //API ํ˜ธ์ถœ + get({ url: `/api/object/v1.0/object/${objectNo}/1` }).then((res) => { + if (res != null) { + // console.log('res:::::::', res) + setDetailData(res) + } + }) + } + }, [objectNo]) + + useEffect(() => { + // validateForm() + }, [receiveUser, name2, name3, gubun, sel, autoSelectValue, zipCode, sel2, sel3, name5, sel4]) + + // ์šฐํŽธ๋ฒˆํ˜ธ ์ˆซ์ž๋งŒ ์ฒดํฌ + const _zipNo = watch('zipNo') + useEffect(() => { + console.log('์‹ค์‹œ๊ฐ„์ด๋‹ˆ:::::', _zipNo) + if (_zipNo !== '' && _zipNo.length === 7 && !_zipNo.match(/\D/g)) { + console.log('๋ฒจ๋ฆฌํ†ต๊ณผํ–ˆ๊ตฐ') + setButtonValid(true) + } else { + setButtonValid(false) + } + }, [_zipNo]) + + // ์ˆ˜์ง์ ์„ค๋Ÿ‰ ์ˆซ์ž๋งŒ + const textTypeHandler2 = (e) => { + if (!e.target.value.match(/[^0-9]/g)) { + setName5(e.target.value) + } + } + const validateForm = () => { + let errors = {} + + if (!receiveUser || receiveUser.trim().length === 0) { + errors.receiveUser = '๋‹ด๋‹น์ž is required.' + } + + if (!name2 || name2.trim().length === 0) { + errors.name2 = '๋ฌผ๊ฑด๋ช… is required.' + } + + if (!name3 || name3.trim().length === 0) { + errors.name3 = '๋ฌผ๊ฑด๋ช…ํ›„๋ฆฌ๊ฐ€๋‚˜ is required.' + } + + if (!sel) { + errors.sel = '๊ฒฝ์นญ์„ ํƒ is required' + } + + if (!sel2) { + errors.sel2 = '๋ฐœ์ „๋Ÿ‰์‹œ๋ฎฌ๋ ˆ์ด์…˜์ง€์—ญ is required' + } + + if (!sel3) { + errors.sel3 = '๊ธฐ์ค€ํ’์† is required' + } + + if (!sel4) { + errors.sel4 = '์„ค์น˜๋†’์ด is required' + } + + if (!autoSelectValue) { + errors.autoSelectValue = 'ํŒ๋งค์ ID์ž๋™์™„์„ฑ is required' + } + + if (!zipCode || zipCode.length != 7) { + errors.zipCode = '์šฐํŽธ๋ฒˆํ˜ธ is required.' + setButtonValid(true) + } else { + setButtonValid(false) + } + + if (!name5) { + errors.name5 = '์ˆ˜์ง์ ์„ค๋Ÿ‰ is required.' + } + + console.log('errors::', errors) + setErrors(errors) + setIsFormValid(Object.keys(errors).length === 0) + } + + // ์šฐํŽธ๋ฒˆํ˜ธ API + const onSearchPostNumber = () => { + const params = { + zipcode: _zipNo, + } + get({ url: `https://zipcloud.ibsnet.co.jp/api/search?${queryStringFormatter(params)}` }).then((res) => { + console.log('์šฐํŽธAPI RES::::::::', res) + //7830060 + if (res.status === 200) { + if (res.results?.length > 0) { + // setAddress1(res.results[0].address1) + // setAddress2(res.results[0].address2) + // setAddress3(res.results[0].address3) + // setPrefCode(res.results[0].prefcode) + // prefId: '', //๋„๋„๋ถ€ํ˜„ + // address: '', //์ฃผ์†Œ + form.setValue('prefId', res.results[0].prefcode) + form.setValue('address', res.results[0].address2 + res.results[0].address3) + } else { + alert('๋“ฑ๋ก๋œ ์šฐํŽธ๋ฒˆํ˜ธ์—์„œ ์ฃผ์†Œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.') + } + } else { + alert(res.message) + } + }) + } + + const onTempSave = () => { + console.log('์ž„์‹œ์ €์žฅ::', isFormValid) + } + + const onSave = () => { + console.log('์ง„์งœ์ €์žฅisFormValid:::', isFormValid) + } + + const moveList = () => { + router.push('/management/stuff') + } + + const changeAddress2 = (e) => { + console.log('e:::::::', e.target.value) + } + + //ํ•„์ˆ˜๊ฐ’ ๋‹ค ์ž…๋ ฅํ–ˆ์„๋•Œ + const onValid = (data) => { + console.log('data::::::', data) + const formData = form.getValues() + //console.log('formData::::', formData) + const _dispCompanyName = watch('dispCompanyName') + const _objectStatusId = watch('objectStatusId') + const _objectNameOmit = watch('objectNameOmit') + const _zipno = watch('zipno') + console.log(_dispCompanyName) + console.log(_objectStatusId) + console.log(_objectNameOmit) + console.log(_zipno) + } + + //ํ•„์ˆ˜๊ฐ’ ์•ˆ๋„ฃ์—ˆ์„๋•Œ + const onInvalid = (errors) => { + console.log('์‹คํŒจ', errors) + } + + return ( + <> + {(editMode === 'NEW' && ( +
+
+
(*ํ•„์ˆ˜ ์ž…๋ ฅํ•ญ๋ชฉ)
+
+ + +
+
+ + + + + + +
+ +
+
+
+ + +
+
+ +
+
+ +
+
+ + + + *์šฐํŽธ๋ฒˆํ˜ธ 7์ž๋ฆฌ๋ฅผ ์ž…๋ ฅํ•œ ํ›„, ์ฃผ์†Œ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ด ์ฃผ์‹ญ์‹œ์˜ค +
+
+ + + +
+
+ +
+ )) ||
์ƒ์„ธ:::::::::::
} + + {/*
+
+ ๋ฌผ๊ฑด๋ฒˆํ˜ธ + {objectNo} +
+
+ ์‚ฌ์–‘ํ™•์ •์ผ + {detailData?.specDate ? dayjs(detailData.specDate).format('YYYY.MM.DD') : null} +
+
+ ๊ฐฑ์‹ ์ผ์‹œ + + {detailData?.lastEditDatetime + ? dayjs(detailData.lastEditDatetime).format('YYYY.MM.DD HH:mm:ss') + : detailData?.createDatetime + ? dayjs(detailData.createDatetime).format('YYYY.MM.DD HH:mm:ss') + : null} + +
+
+ ๋“ฑ๋ก์ผ + +
+
*/} + {/*
(*ํ•„์ˆ˜ ์ž…๋ ฅํ•ญ๋ชฉ)
+ +
+ setName2(e.target.value)} /> +
+
+ +
+
+ ๋ฌผ๊ฑด๋ช… ํ›„๋ฆฌ๊ฐ€๋‚˜ + setName3(e.target.value)} /> +
+
*/} + {/*
+ ํŒ๋งค์ ๋ช… /ID * +
+ + {(option) => {option.name}} + +
+
*/} + {/*
+ ์šฐํŽธ๋ฒˆํ˜ธ* + + + *์šฐํŽธ๋ฒˆํ˜ธ 7์ž๋ฆฌ๋ฅผ ์ž…๋ ฅํ•œ ํ›„, ์ฃผ์†Œ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ด ์ฃผ์‹ญ์‹œ์˜ค +
*/} + {/*
+ ๋„๋„๋ถ€ํ˜„ / ์ฃผ์†Œ* + +
*/} + {/*
+ ๋ฐœ์ „๋Ÿ‰์‹œ๋ฎฌ๋ ˆ์ด์…˜์ง€์—ญ* + +
+
+ ๊ธฐ์ค€ํ’์†* + + m/s์ดํ•˜ +
+
+ ์ˆ˜์ง์ ์„ค๋Ÿ‰* + cm + + ํ•œ๋žญ์ง€๋Œ€์ฑ…์‹œํ–‰ + +
*/} + {/*
+ ๋ฉด์กฐ๋„๊ตฌ๋ถ„* + { + setGubun2(e.target.value) + }} + /> + + { + setGubun2(e.target.value) + }} + /> + + + ์—ผํ•ด์ง€์—ญ์šฉ์•„์ดํ…œ์‚ฌ์šฉ + +
+
+ ์„ค์น˜๋†’์ด* + + m +
+
+ ๊ณ„์•ฝ์กฐ๊ฑด + { + setGubun3(e.target.value) + }} + /> + + { + setGubun3(e.target.value) + }} + /> + +
+
+ ๋ฉ”๋ชจ +