Merge branch 'dev'
This commit is contained in:
commit
6850683eb4
@ -10,7 +10,8 @@
|
|||||||
복도치수(입력치수): inputSize
|
복도치수(입력치수): inputSize
|
||||||
실제치수: actualSize
|
실제치수: actualSize
|
||||||
테두리만: borderOnly
|
테두리만: borderOnly
|
||||||
라인해치: lineHatching
|
라인해치: lineHatch
|
||||||
|
Allpainted : allPainted
|
||||||
문자글꼴: textFont
|
문자글꼴: textFont
|
||||||
흐름방향글꼴 : flowDirectionFont
|
흐름방향글꼴 : flowDirectionFont
|
||||||
회로번호글꼴: circuitNumberFont
|
회로번호글꼴: circuitNumberFont
|
||||||
@ -23,4 +24,4 @@
|
|||||||
개구: openSpace
|
개구: openSpace
|
||||||
도머: dormer
|
도머: dormer
|
||||||
그림자: shadow
|
그림자: shadow
|
||||||
|
치수선: dimensionLine
|
||||||
@ -10,7 +10,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nextui-org/react": "^2.4.2",
|
"@nextui-org/react": "^2.4.2",
|
||||||
"@prisma/client": "^5.18.0",
|
|
||||||
"ag-grid-react": "^32.0.2",
|
"ag-grid-react": "^32.0.2",
|
||||||
"axios": "^1.7.3",
|
"axios": "^1.7.3",
|
||||||
"fabric": "^5.3.0",
|
"fabric": "^5.3.0",
|
||||||
@ -29,8 +28,8 @@
|
|||||||
"react-draggable": "^4.4.6",
|
"react-draggable": "^4.4.6",
|
||||||
"react-hook-form": "^7.53.0",
|
"react-hook-form": "^7.53.0",
|
||||||
"react-icons": "^5.3.0",
|
"react-icons": "^5.3.0",
|
||||||
|
"react-loading-skeleton": "^3.5.0",
|
||||||
"react-responsive-modal": "^6.4.2",
|
"react-responsive-modal": "^6.4.2",
|
||||||
"react-toastify": "^10.0.5",
|
|
||||||
"recoil": "^0.7.7",
|
"recoil": "^0.7.7",
|
||||||
"sweetalert2": "^11.14.1",
|
"sweetalert2": "^11.14.1",
|
||||||
"sweetalert2-react-content": "^5.0.7",
|
"sweetalert2-react-content": "^5.0.7",
|
||||||
@ -42,7 +41,6 @@
|
|||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"postcss": "^8",
|
"postcss": "^8",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"prisma": "^5.18.0",
|
|
||||||
"react-color-palette": "^7.2.2",
|
"react-color-palette": "^7.2.2",
|
||||||
"react-select": "^5.8.1",
|
"react-select": "^5.8.1",
|
||||||
"sass": "^1.77.8",
|
"sass": "^1.77.8",
|
||||||
|
|||||||
5
public/static/images/sub/product-del.svg
Normal file
5
public/static/images/sub/product-del.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<svg width="15" height="16" viewBox="0 0 15 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="0.5" y="1" width="14" height="14" rx="7" fill="white"/>
|
||||||
|
<rect x="0.5" y="1" width="14" height="14" rx="7" stroke="#94A0AD"/>
|
||||||
|
<path d="M9.741 11.059L7.509 8.827L5.277 11.059L4.512 10.294L6.744 8.062L4.512 5.83L5.277 5.065L7.509 7.297L9.741 5.065L10.506 5.83L8.274 8.062L10.506 10.294L9.741 11.059Z" fill="#94A0AD"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 427 B |
@ -1,27 +1,19 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useEffect } from 'react'
|
// import { useEffect } from 'react'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
|
||||||
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
|
|
||||||
import { ErrorBoundary } from 'next/dist/client/components/error-boundary'
|
import { ErrorBoundary } from 'next/dist/client/components/error-boundary'
|
||||||
|
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||||
import ServerError from './error'
|
import ServerError from './error'
|
||||||
|
|
||||||
import '@/styles/common.scss'
|
import '@/styles/common.scss'
|
||||||
|
|
||||||
import KO from '@/locales/ko.json'
|
|
||||||
import JA from '@/locales/ja.json'
|
|
||||||
|
|
||||||
export const QcastProvider = ({ children }) => {
|
export const QcastProvider = ({ children }) => {
|
||||||
const globalLocale = useRecoilValue(globalLocaleStore)
|
const { commonCode, findCommonCode } = useCommonCode()
|
||||||
const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
|
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
if (globalLocale === 'ko') {
|
// console.log('commonCode', commonCode)
|
||||||
setAppMessageState(KO)
|
// console.log(findCommonCode(113600))
|
||||||
} else {
|
// }, [commonCode, findCommonCode])
|
||||||
setAppMessageState(JA)
|
|
||||||
}
|
|
||||||
}, [globalLocale])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -1,11 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { I18nProviderClient } from '@/locales/client'
|
|
||||||
|
|
||||||
export function LocaleProvider({ locale, children }) {
|
|
||||||
return (
|
|
||||||
<I18nProviderClient locale={locale} fallback={''}>
|
|
||||||
{children}
|
|
||||||
</I18nProviderClient>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<Hero title="자료 다운로드" />
|
|
||||||
<div className="container flex flex-wrap items-center justify-between mx-auto p-4 m-4 border">
|
|
||||||
<Archive />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<Hero title="FAQ" />
|
|
||||||
<div className="container flex flex-wrap items-center justify-between mx-auto p-4 m-4 border">
|
|
||||||
<Faq />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<Hero title="공지사항" />
|
|
||||||
<div className="container flex flex-wrap items-center justify-between mx-auto p-4 m-4 border">
|
|
||||||
<Notice />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
export default function ServerError() {
|
|
||||||
return (
|
|
||||||
<section className="bg-white dark:bg-gray-900">
|
|
||||||
<div className="py-8 px-4 mx-auto max-w-screen-xl lg:py-16 lg:px-6">
|
|
||||||
<div className="mx-auto max-w-screen-sm text-center">
|
|
||||||
<h1 className="mb-4 text-7xl tracking-tight font-extrabold lg:text-9xl text-primary-600 dark:text-primary-500">500</h1>
|
|
||||||
<p className="mb-4 text-3xl tracking-tight font-bold text-gray-900 md:text-4xl dark:text-white">Internal Server Error.</p>
|
|
||||||
<p className="mb-4 text-lg font-light text-gray-500 dark:text-gray-400">We are already working to solve the problem. </p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
import FloorPlan from '@/components/floor-plan/FloorPlan'
|
|
||||||
|
|
||||||
export default function FloorPlanPage() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<FloorPlan />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<Hero title="Basic Settings" />
|
|
||||||
<div className="flex flex-col justify-center my-8">
|
|
||||||
<InitSettingsModal />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
import Intro from '@/components/Intro'
|
|
||||||
import { initCheck } from '@/util/session-util'
|
|
||||||
|
|
||||||
export default async function IntroPage() {
|
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="container mx-auto p-4 m-4 border">
|
|
||||||
<Intro />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
|
||||||
|
|
||||||
export default function CompletePage() {
|
|
||||||
const { getMessage } = useMessage()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
|
|
||||||
<h1 className="text-center text-4xl font-bold mb-10">{getMessage('join.complete.title')}</h1>
|
|
||||||
<div className="mt-10 mb-10 w-full text-center text-2xl">{getMessage('join.complete.contents')}</div>
|
|
||||||
<div className="mt-10 w-full text-center">
|
|
||||||
{getMessage('join.complete.email_comment')} : {getMessage('join.complete.email')}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
import Join from '@/components/auth/Join'
|
|
||||||
|
|
||||||
export default function JoinPage() {
|
|
||||||
return <>{<Join />}</>
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<ErrorBoundary fallback={<ServerError />}>
|
|
||||||
<LocaleProvider locale={locale} fallback={<ServerError />}>
|
|
||||||
{children}
|
|
||||||
</LocaleProvider>
|
|
||||||
</ErrorBoundary>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<Login {...loginPageProps} />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<Hero title="도면관리" />
|
|
||||||
<div className="container flex flex-wrap items-center justify-between mx-auto p-4 m-4 border">
|
|
||||||
<Plan />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<div className="pt-48 flex justify-left">
|
|
||||||
<h1 className="text-4xl archivo-black-regular">물건정보</h1>
|
|
||||||
<Link href="/management/plan">
|
|
||||||
<h1 className="text-4xl archivo-black-regular">도면작성</h1>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
<div className="m2">
|
|
||||||
<StuffDetail />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<Hero title="물건현황" />
|
|
||||||
<div>
|
|
||||||
<div className="m2">
|
|
||||||
<StuffSearchCondition />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col justify-center my-8 pt-20">
|
|
||||||
<Stuff />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import Hero from '@/components/Hero'
|
|
||||||
import StuffDetail from '@/components/management/StuffDetail'
|
|
||||||
export default function ManagementStuffDetailPage() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="pt-48 flex justify-left">
|
|
||||||
<h1 className="text-4xl archivo-black-regular">물건정보</h1>
|
|
||||||
</div>
|
|
||||||
<div className="m2">
|
|
||||||
<StuffDetail />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<Hero title="회사정보 조회" />
|
|
||||||
<div className="container flex flex-wrap items-center justify-between mx-auto p-4 m-4 border">
|
|
||||||
<Company />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<Hero title="가격 마스터 조회" />
|
|
||||||
<div className="container flex flex-wrap items-center justify-between mx-auto p-4 m-4 border">
|
|
||||||
<Price />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import Link from 'next/link'
|
|
||||||
|
|
||||||
export default function NotFound() {
|
|
||||||
return (
|
|
||||||
<section className="bg-white dark:bg-gray-900">
|
|
||||||
<div className="py-8 px-4 mx-auto max-w-screen-xl lg:py-16 lg:px-6">
|
|
||||||
<div className="mx-auto max-w-screen-sm text-center">
|
|
||||||
<h1 className="mb-4 text-7xl tracking-tight font-extrabold lg:text-9xl text-primary-600 dark:text-primary-500">404</h1>
|
|
||||||
<p className="mb-4 text-3xl tracking-tight font-bold text-gray-900 md:text-4xl dark:text-white">Something's missing.</p>
|
|
||||||
<p className="mb-4 text-lg font-light text-gray-500 dark:text-gray-400">
|
|
||||||
Sorry, we can't find that page. You'll find lots to explore on the home page.{' '}
|
|
||||||
</p>
|
|
||||||
<Link
|
|
||||||
href="/"
|
|
||||||
className="inline-flex text-white bg-primary-600 hover:bg-primary-800 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:focus:ring-primary-900 my-4"
|
|
||||||
>
|
|
||||||
Back to Homepage
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<div className="m-4">
|
|
||||||
<MainPage {...mainPageProps} />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<Playground />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<Hero title="Drawing on canvas 2D Roof" />
|
|
||||||
<div className="flex flex-col justify-center my-8">
|
|
||||||
<Roof />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
|
|
||||||
{roofMaterials.length > 0 && (
|
|
||||||
<Select label="지붕재" className="max-w-xs" onChange={handleRoofMaterialOnChange}>
|
|
||||||
{roofMaterials.map((roofMaterial) => (
|
|
||||||
<SelectItem key={roofMaterial.id}>{roofMaterial.name}</SelectItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
{manufacturers.length > 0 && (
|
|
||||||
<Select label="제조 회사" className="max-w-xs" onChange={handleManufacturersOnChange}>
|
|
||||||
{manufacturers.map((manufacturer) => (
|
|
||||||
<SelectItem key={manufacturer.id}>{manufacturer.name}</SelectItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
{trestles.length > 0 && (
|
|
||||||
<Select label="가대" className="max-w-xs" onChange={handleTrestlesOnChange}>
|
|
||||||
{trestles.map((trestle) => (
|
|
||||||
<SelectItem key={trestle.id}>{trestle.name}</SelectItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
{modules.length > 0 && (
|
|
||||||
<Select label="설치가능 모듈" className="max-w-xs">
|
|
||||||
{modules.map((module) => (
|
|
||||||
<SelectItem key={module.id}>{module.name}</SelectItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<div>
|
|
||||||
<div className="m-2">
|
|
||||||
<RoofSelect />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col justify-center my-8 pt-20">
|
|
||||||
<Roof2 {...roof2Props} />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 (
|
|
||||||
<>
|
|
||||||
<Hero title="Canvas Setting" />
|
|
||||||
<div className="flex flex-col justify-center my-8">
|
|
||||||
<Settings />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,10 +1,7 @@
|
|||||||
import Hero from '@/components/Hero'
|
import Hero from '@/components/Hero'
|
||||||
import Archive from '@/components/community/Archive'
|
import Archive from '@/components/community/Archive'
|
||||||
import { initCheck } from '@/util/session-util'
|
|
||||||
|
|
||||||
export default async function CommunityArchivePage() {
|
export default async function CommunityArchivePage() {
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Archive />
|
<Archive />
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
import Faq from '@/components/community/Faq'
|
import Faq from '@/components/community/Faq'
|
||||||
import { initCheck } from '@/util/session-util'
|
|
||||||
|
|
||||||
export default async function CommunityFaqPage() {
|
export default async function CommunityFaqPage() {
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Faq />
|
<Faq />
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
import Notice from '@/components/community/Notice'
|
import Notice from '@/components/community/Notice'
|
||||||
import { initCheck } from '@/util/session-util'
|
|
||||||
|
|
||||||
export default async function CommunityNoticePage() {
|
export default async function CommunityNoticePage() {
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Notice />
|
<Notice />
|
||||||
|
|||||||
9
src/app/floor-plan/estimate/[mid]/[pid]/page.jsx
Normal file
9
src/app/floor-plan/estimate/[mid]/[pid]/page.jsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import Estimate from '@/components/estimate/Estimate'
|
||||||
|
|
||||||
|
export default function EstimatePage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Estimate />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,11 +1,17 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
import FloorPlan from '@/components/floor-plan/FloorPlan'
|
||||||
import { FloorPlanProvider } from './FloorPlanProvider'
|
import { FloorPlanProvider } from './FloorPlanProvider'
|
||||||
|
import CanvasLayout from '@/components/floor-plan/CanvasLayout'
|
||||||
|
|
||||||
export default function FloorPlanLayout({ children }) {
|
export default function FloorPlanLayout({ children }) {
|
||||||
console.log('FloorPlanLayout')
|
console.log('FloorPlanLayout')
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FloorPlanProvider>{children}</FloorPlanProvider>
|
<FloorPlanProvider>
|
||||||
|
<FloorPlan>
|
||||||
|
<CanvasLayout>{children}</CanvasLayout>
|
||||||
|
</FloorPlan>
|
||||||
|
</FloorPlanProvider>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
|
import CanvasFrame from '@/components/floor-plan/CanvasFrame'
|
||||||
import FloorPlan from '@/components/floor-plan/FloorPlan'
|
import FloorPlan from '@/components/floor-plan/FloorPlan'
|
||||||
|
|
||||||
export default function FloorPlanPage() {
|
export default function FloorPlanPage() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FloorPlan />
|
<CanvasFrame />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
import Hero from '@/components/Hero'
|
import Hero from '@/components/Hero'
|
||||||
import InitSettingsModal from '@/components/InitSettingsModal'
|
import InitSettingsModal from '@/components/InitSettingsModal'
|
||||||
import { initCheck } from '@/util/session-util'
|
|
||||||
|
|
||||||
export default async function InitSettingsModalPage() {
|
export default async function InitSettingsModalPage() {
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Hero title="Basic Settings" />
|
<Hero title="Basic Settings" />
|
||||||
|
|||||||
@ -2,8 +2,6 @@ import Intro from '@/components/Intro'
|
|||||||
import { initCheck } from '@/util/session-util'
|
import { initCheck } from '@/util/session-util'
|
||||||
|
|
||||||
export default async function IntroPage() {
|
export default async function IntroPage() {
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="container mx-auto p-4 m-4 border">
|
<div className="container mx-auto p-4 m-4 border">
|
||||||
|
|||||||
@ -1,23 +1,19 @@
|
|||||||
// import { Inter } from 'next/font/google'
|
|
||||||
|
|
||||||
import { headers } from 'next/headers'
|
import { headers } from 'next/headers'
|
||||||
import { redirect } from 'next/navigation'
|
import { redirect } from 'next/navigation'
|
||||||
import { getSession } from '@/lib/authActions'
|
import { getSession } from '@/lib/authActions'
|
||||||
import RecoilRootWrapper from './RecoilWrapper'
|
import RecoilRootWrapper from './RecoilWrapper'
|
||||||
|
|
||||||
import { ToastContainer } from 'react-toastify'
|
|
||||||
|
|
||||||
import { QcastProvider } from './QcastProvider'
|
import { QcastProvider } from './QcastProvider'
|
||||||
import Header from '@/components/header/Header'
|
import Header from '@/components/header/Header'
|
||||||
import QModal from '@/components/common/modal/QModal'
|
import QModal from '@/components/common/modal/QModal'
|
||||||
|
import Dimmed from '@/components/ui/Dimmed'
|
||||||
|
import SessionProvider from './SessionProvider'
|
||||||
|
import PopupManager from '@/components/common/popupManager/PopupManager'
|
||||||
|
|
||||||
import './globals.css'
|
import './globals.css'
|
||||||
import '../styles/style.scss'
|
import '../styles/style.scss'
|
||||||
import '../styles/contents.scss'
|
import '../styles/contents.scss'
|
||||||
import Dimmed from '@/components/ui/Dimmed'
|
import Footer from '@/components/footer/Footer'
|
||||||
import SessionProvider from './SessionProvider'
|
|
||||||
|
|
||||||
// const inter = Inter({ subsets: ['latin'] })
|
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: 'Create Next App',
|
title: 'Create Next App',
|
||||||
@ -28,8 +24,6 @@ export default async function RootLayout({ children }) {
|
|||||||
const headersList = headers()
|
const headersList = headers()
|
||||||
const headerPathname = headersList.get('x-pathname') || ''
|
const headerPathname = headersList.get('x-pathname') || ''
|
||||||
|
|
||||||
// console.log('headerPathname:', headerPathname)
|
|
||||||
// const isLoggedIn = await checkSession()
|
|
||||||
const session = await getSession()
|
const session = await getSession()
|
||||||
console.log('session[layout]:', session)
|
console.log('session[layout]:', session)
|
||||||
|
|
||||||
@ -52,6 +46,7 @@ export default async function RootLayout({ children }) {
|
|||||||
storeLvl: session.storeLvl,
|
storeLvl: session.storeLvl,
|
||||||
groupId: session.groupId,
|
groupId: session.groupId,
|
||||||
pwdInitYn: session.pwdInitYn,
|
pwdInitYn: session.pwdInitYn,
|
||||||
|
custCd: session.custCd,
|
||||||
isLoggedIn: session.isLoggedIn,
|
isLoggedIn: session.isLoggedIn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,15 +70,11 @@ export default async function RootLayout({ children }) {
|
|||||||
<SessionProvider useSession={sessionProps}>{children}</SessionProvider>
|
<SessionProvider useSession={sessionProps}>{children}</SessionProvider>
|
||||||
</QcastProvider>
|
</QcastProvider>
|
||||||
</div>
|
</div>
|
||||||
<footer>
|
<Footer />
|
||||||
<div className="footer-inner">
|
|
||||||
<span>COPYRIGHT©2024 Hanwha Japan All Rights Reserved.</span>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<ToastContainer />
|
|
||||||
<QModal />
|
<QModal />
|
||||||
|
<PopupManager />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
</RecoilRootWrapper>
|
</RecoilRootWrapper>
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
import Hero from '@/components/Hero'
|
import Hero from '@/components/Hero'
|
||||||
import Plan from '@/components/management/Plan'
|
import Plan from '@/components/management/Plan'
|
||||||
import { initCheck } from '@/util/session-util'
|
|
||||||
|
|
||||||
export default async function ManagementPlanPage() {
|
export default async function ManagementPlanPage() {
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Hero title="도면관리" />
|
<Hero title="도면관리" />
|
||||||
|
|||||||
@ -1,36 +1,14 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Link from 'next/link'
|
|
||||||
import Image from 'next/image'
|
|
||||||
import '@/styles/contents.scss'
|
import '@/styles/contents.scss'
|
||||||
|
import StuffSubHeader from '@/components/management/StuffSubHeader'
|
||||||
import StuffHeader from '@/components/management/StuffHeader'
|
import StuffHeader from '@/components/management/StuffHeader'
|
||||||
import StuffDetail from '@/components/management/StuffDetail'
|
import StuffDetail from '@/components/management/StuffDetail'
|
||||||
|
import '@/styles/contents.scss'
|
||||||
|
import '@/styles/grid.scss'
|
||||||
export default function ManagementStuffDetailPage() {
|
export default function ManagementStuffDetailPage() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="sub-header">
|
<StuffSubHeader type={'detail'} />
|
||||||
<div className="sub-header-inner">
|
|
||||||
<ul className="sub-header-title-wrap">
|
|
||||||
<li className="title-item">
|
|
||||||
<Link className="sub-header-title" href={'#'}>
|
|
||||||
商品情報
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<ul className="sub-header-location">
|
|
||||||
<li className="location-item">
|
|
||||||
<span className="home">
|
|
||||||
<Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="location-item">
|
|
||||||
<span>物品及び図面管理</span>
|
|
||||||
</li>
|
|
||||||
<li className="location-item">
|
|
||||||
<span>商品情報</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="sub-content">
|
<div className="sub-content">
|
||||||
<div className="sub-content-inner">
|
<div className="sub-content-inner">
|
||||||
<div className="sub-content-box">
|
<div className="sub-content-box">
|
||||||
|
|||||||
@ -1,31 +1,11 @@
|
|||||||
import StuffSearchCondition from '@/components/management/StuffSearchCondition'
|
import StuffSearchCondition from '@/components/management/StuffSearchCondition'
|
||||||
import Stuff from '@/components/management/Stuff'
|
import Stuff from '@/components/management/Stuff'
|
||||||
import { initCheck } from '@/util/session-util'
|
import StuffSubHeader from '@/components/management/StuffSubHeader'
|
||||||
import Image from 'next/image'
|
import '@/styles/grid.scss'
|
||||||
import '@/styles/contents.scss'
|
|
||||||
export default async function ManagementStuffPage() {
|
export default async function ManagementStuffPage() {
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="sub-header">
|
<StuffSubHeader type={'list'} />
|
||||||
<div className="sub-header-inner">
|
|
||||||
<h1 className="sub-header-title">物品及び図面管理</h1>
|
|
||||||
<ul className="sub-header-location">
|
|
||||||
<li className="location-item">
|
|
||||||
<span className="home">
|
|
||||||
<Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="location-item">
|
|
||||||
<span>物品及び図面管理</span>
|
|
||||||
</li>
|
|
||||||
<li className="location-item">
|
|
||||||
<span>新規物件登録</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="sub-content">
|
<div className="sub-content">
|
||||||
<div className="sub-content-inner">
|
<div className="sub-content-inner">
|
||||||
<div className="sub-content-box">
|
<div className="sub-content-box">
|
||||||
|
|||||||
@ -1,35 +1,11 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Link from 'next/link'
|
import StuffSubHeader from '@/components/management/StuffSubHeader'
|
||||||
import Image from 'next/image'
|
|
||||||
import '@/styles/contents.scss'
|
import '@/styles/contents.scss'
|
||||||
import StuffDetail from '@/components/management/StuffDetail'
|
import StuffDetail from '@/components/management/StuffDetail'
|
||||||
export default function ManagementStuffDetailPage() {
|
export default function ManagementStuffDetailPage() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="sub-header">
|
<StuffSubHeader type={'temp'} />
|
||||||
<div className="sub-header-inner">
|
|
||||||
<ul className="sub-header-title-wrap">
|
|
||||||
<li className="title-item">
|
|
||||||
<Link className="sub-header-title" href={'#'}>
|
|
||||||
商品情報
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<ul className="sub-header-location">
|
|
||||||
<li className="location-item">
|
|
||||||
<span className="home">
|
|
||||||
<Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="location-item">
|
|
||||||
<span>物品及び図面管理</span>
|
|
||||||
</li>
|
|
||||||
<li className="location-item">
|
|
||||||
<span>商品情報</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="sub-content">
|
<div className="sub-content">
|
||||||
<div className="sub-content-inner">
|
<div className="sub-content-inner">
|
||||||
<div className="sub-content-box">
|
<div className="sub-content-box">
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
import Hero from '@/components/Hero'
|
import Hero from '@/components/Hero'
|
||||||
import Company from '@/components/master/Company'
|
import Company from '@/components/master/Company'
|
||||||
import { initCheck } from '@/util/session-util'
|
|
||||||
|
|
||||||
export default async function MasterCompanyPage() {
|
export default async function MasterCompanyPage() {
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Hero title="회사정보 조회" />
|
<Hero title="회사정보 조회" />
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
import Hero from '@/components/Hero'
|
import Hero from '@/components/Hero'
|
||||||
import Price from '@/components/master/Price'
|
import Price from '@/components/master/Price'
|
||||||
import { initCheck } from '@/util/session-util'
|
|
||||||
|
|
||||||
export default async function MasterPricePage() {
|
export default async function MasterPricePage() {
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Hero title="가격 마스터 조회" />
|
<Hero title="가격 마스터 조회" />
|
||||||
|
|||||||
@ -1,14 +1,6 @@
|
|||||||
import Playground from '@/components/Playground'
|
import Playground from '@/components/Playground'
|
||||||
import { initCheck } from '@/util/session-util'
|
|
||||||
|
|
||||||
export default async function PlaygroundPage() {
|
export default async function PlaygroundPage() {
|
||||||
// const { session } = await checkSession()
|
|
||||||
|
|
||||||
// if (!session.isLoggedIn) {
|
|
||||||
// redirect('/login')
|
|
||||||
// }
|
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Playground />
|
<Playground />
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
import Hero from '@/components/Hero'
|
import Hero from '@/components/Hero'
|
||||||
import Roof from '@/components/Roof'
|
import Roof from '@/components/Roof'
|
||||||
import { initCheck } from '@/util/session-util'
|
|
||||||
|
|
||||||
export default async function RoofPage() {
|
export default async function RoofPage() {
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Hero title="Drawing on canvas 2D Roof" />
|
<Hero title="Drawing on canvas 2D Roof" />
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import Roof2 from '@/components/Roof2'
|
import Roof2 from '@/components/Roof2'
|
||||||
import RoofSelect from '@/app/[locale]/roof2/RoofSelect'
|
|
||||||
import { initCheck } from '@/util/session-util'
|
import { initCheck } from '@/util/session-util'
|
||||||
|
import RoofSelect from '@/app/roof2/RoofSelect'
|
||||||
|
|
||||||
export default async function Roof2Page() {
|
export default async function Roof2Page() {
|
||||||
const session = await initCheck()
|
const session = await initCheck()
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
import Hero from '@/components/Hero'
|
import Hero from '@/components/Hero'
|
||||||
import Settings from '@/components/Settings'
|
import Settings from '@/components/Settings'
|
||||||
import { initCheck } from '@/util/session-util'
|
|
||||||
|
|
||||||
export default async function SettingsPage() {
|
export default async function SettingsPage() {
|
||||||
await initCheck()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Hero title="Canvas Setting" />
|
<Hero title="Canvas Setting" />
|
||||||
|
|||||||
23
src/components/LocaleSwitch.jsx
Normal file
23
src/components/LocaleSwitch.jsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
|
import { useRecoilState } from 'recoil'
|
||||||
|
|
||||||
|
export default function LocaleSwitch() {
|
||||||
|
const [globalLocale, setGlobalLocale] = useRecoilState(globalLocaleStore)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className="locale-switch"
|
||||||
|
onClick={() => {
|
||||||
|
if (globalLocale === 'ko') {
|
||||||
|
setGlobalLocale('ja')
|
||||||
|
} else {
|
||||||
|
setGlobalLocale('ko')
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{globalLocale.toUpperCase()}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -2,39 +2,32 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { modalContent, modalState, modalProps } from '@/store/modalAtom'
|
|
||||||
import { sessionStore } from '@/store/commonAtom'
|
import { sessionStore } from '@/store/commonAtom'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
import MainContents from './main/MainContents'
|
import MainContents from './main/MainContents'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { stuffSearchState } from '@/store/stuffAtom'
|
import { stuffSearchState } from '@/store/stuffAtom'
|
||||||
import { useForm } from 'react-hook-form'
|
|
||||||
import '@/styles/contents.scss'
|
import '@/styles/contents.scss'
|
||||||
import ChangePasswordPop from './main/ChangePasswordPop'
|
import ChangePasswordPop from './main/ChangePasswordPop'
|
||||||
import { searchState } from '@/store/boardAtom'
|
import { searchState } from '@/store/boardAtom'
|
||||||
export default function MainPage() {
|
export default function MainPage() {
|
||||||
const [sessionState, setSessionState] = useRecoilState(sessionStore)
|
const sessionState = useRecoilValue(sessionStore)
|
||||||
|
|
||||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||||
|
|
||||||
const { get } = useAxios(globalLocaleState)
|
const { promiseGet } = useAxios(globalLocaleState)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
const [searchTxt, setSearchTxt] = useState('')
|
const [searchTxt, setSearchTxt] = useState('')
|
||||||
|
|
||||||
const [searchRadioType, setSearchRadioType] = useState('object')
|
const [searchRadioType, setSearchRadioType] = useState('object')
|
||||||
//컨텐츠 관련
|
|
||||||
const [saleStoreId, setSaleStoreId] = useState('')
|
const [saleStoreId, setSaleStoreId] = useState('')
|
||||||
const [saleStoreName, setSaleStoreName] = useState('')
|
const [saleStoreName, setSaleStoreName] = useState('')
|
||||||
|
|
||||||
const [objectList, setObjectList] = useState([])
|
|
||||||
const [businessCharger, setBusinessCharger] = useState('')
|
|
||||||
const [businessChargerMail, setBusinessChargerMail] = useState('')
|
|
||||||
const [businessChargerTel, setBusinessChargerTel] = useState('')
|
|
||||||
|
|
||||||
const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState)
|
const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState)
|
||||||
|
|
||||||
const [searchForm, setSearchForm] = useRecoilState(searchState)
|
const [searchForm, setSearchForm] = useRecoilState(searchState)
|
||||||
@ -47,17 +40,15 @@ export default function MainPage() {
|
|||||||
|
|
||||||
const fetchObjectList = async () => {
|
const fetchObjectList = async () => {
|
||||||
try {
|
try {
|
||||||
// const apiUrl = `/api/main-page/object/X167/list`
|
|
||||||
const apiUrl = `/api/main-page/object/${sessionState?.storeId}/list`
|
const apiUrl = `/api/main-page/object/${sessionState?.storeId}/list`
|
||||||
const res = await get({ url: apiUrl })
|
await promiseGet({
|
||||||
if (res) {
|
url: apiUrl,
|
||||||
setSaleStoreId(res.saleStoreId)
|
}).then((res) => {
|
||||||
setSaleStoreName(res.saleStoreName)
|
if (res.status === 200) {
|
||||||
setObjectList(res.objectList)
|
setSaleStoreId(res.data.saleStoreId)
|
||||||
setBusinessCharger(res.businessCharger)
|
setSaleStoreName(res.data.saleStoreName)
|
||||||
setBusinessChargerMail(res.businessChargerMail)
|
|
||||||
setBusinessChargerTel(res.businessChargerTel)
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('MAIN API fetching error:', error)
|
console.error('MAIN API fetching error:', error)
|
||||||
}
|
}
|
||||||
@ -143,12 +134,7 @@ export default function MainPage() {
|
|||||||
<button className="search-icon" onClick={handleOnSubmit}></button>
|
<button className="search-icon" onClick={handleOnSubmit}></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MainContents
|
<MainContents />
|
||||||
objectList={objectList}
|
|
||||||
businessCharger={businessCharger}
|
|
||||||
businessChargerMail={businessChargerMail}
|
|
||||||
businessChargerTel={businessChargerTel}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)) || (
|
)) || (
|
||||||
|
|||||||
@ -138,7 +138,7 @@ export default function Playground() {
|
|||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
pagePerBlock: 10,
|
pagePerBlock: 10,
|
||||||
totalCount: 501,
|
totalCount: 26,
|
||||||
handleChangePage: (page) => {
|
handleChangePage: (page) => {
|
||||||
console.log('page', page)
|
console.log('page', page)
|
||||||
},
|
},
|
||||||
|
|||||||
@ -39,7 +39,7 @@ import QEmptyContextMenu from '@/components/common/context-menu/QEmptyContextMen
|
|||||||
import InitSettingsModal from './InitSettingsModal'
|
import InitSettingsModal from './InitSettingsModal'
|
||||||
import GridSettingsModal from './GridSettingsModal'
|
import GridSettingsModal from './GridSettingsModal'
|
||||||
import { SurfaceShapeModal } from '@/components/ui/SurfaceShape'
|
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 ThumbnailList from '@/components/ui/ThumbnailLIst'
|
||||||
import ObjectPlacement from '@/components/ui/ObjectPlacement'
|
import ObjectPlacement from '@/components/ui/ObjectPlacement'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
|
|||||||
21
src/components/auth/AutoLogin.jsx
Normal file
21
src/components/auth/AutoLogin.jsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
|
||||||
|
export default function AutoLoginPage() {
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="login-input-frame">
|
||||||
|
<div className="login-frame-tit ">
|
||||||
|
<span>{getMessage('site.name')}</span>
|
||||||
|
{getMessage('site.sub_name')}
|
||||||
|
</div>
|
||||||
|
<div className="login-input-wrap">
|
||||||
|
<div className="login-area id" style={{ fontWeight: 'bolder' }}>
|
||||||
|
{getMessage('login.auto.page.text')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,20 +1,138 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import { useRef } from 'react'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
|
|
||||||
|
import { isObjectNotEmpty, inputTelNumberCheck, inputNumberCheck } from '@/util/common-utils'
|
||||||
|
|
||||||
export default function Join() {
|
export default function Join() {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { promisePost } = useAxios()
|
const { promisePost } = useAxios()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
const storeQcastNmRef = useRef()
|
||||||
|
const storeQcastNmKanaRef = useRef()
|
||||||
|
const postCdRef = useRef()
|
||||||
|
const addrRef = useRef()
|
||||||
|
const telNoRef = useRef()
|
||||||
|
const faxRef = useRef()
|
||||||
|
const userNmRef = useRef()
|
||||||
|
const userIdRef = useRef()
|
||||||
|
const emailRef = useRef()
|
||||||
|
const userTelNoRef = useRef()
|
||||||
|
const userFaxRef = useRef()
|
||||||
|
|
||||||
|
// 가입 신청 유효성 검사
|
||||||
|
const joinValidation = (formData) => {
|
||||||
|
// 판매대리점 정보 - 판매대리점명
|
||||||
|
const storeQcastNm = formData.get('storeQcastNm')
|
||||||
|
if (!isObjectNotEmpty(storeQcastNm)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub1.storeQcastNm')]))
|
||||||
|
storeQcastNmRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 판매대리점 정보 - 판매대리점명 후리가나
|
||||||
|
const storeQcastNmKana = formData.get('storeQcastNmKana')
|
||||||
|
if (!isObjectNotEmpty(storeQcastNmKana)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub1.storeQcastNmKana')]))
|
||||||
|
storeQcastNmKanaRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 판매대리점 정보 - 우편번호
|
||||||
|
const postCd = formData.get('postCd')
|
||||||
|
if (!isObjectNotEmpty(postCd)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub1.postCd')]))
|
||||||
|
postCdRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 판매대리점 정보 - 주소
|
||||||
|
const addr = formData.get('addr')
|
||||||
|
if (!isObjectNotEmpty(addr)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub1.addr')]))
|
||||||
|
addrRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 판매대리점 정보 - 전화번호
|
||||||
|
const telNo = formData.get('telNo')
|
||||||
|
if (!isObjectNotEmpty(telNo)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub1.telNo')]))
|
||||||
|
telNoRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 판매대리점 정보 - FAX 번호
|
||||||
|
const fax = formData.get('fax')
|
||||||
|
if (!isObjectNotEmpty(fax)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub1.fax')]))
|
||||||
|
faxRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 담당자 정보 - 담당자명
|
||||||
|
const userNm = formData.get('userNm')
|
||||||
|
if (!isObjectNotEmpty(userNm)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub2.userNm')]))
|
||||||
|
userNmRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 담당자 정보 - 신청 ID
|
||||||
|
const userId = formData.get('userId')
|
||||||
|
if (!isObjectNotEmpty(userId)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub2.userId')]))
|
||||||
|
userIdRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 담당자 정보 - 이메일 주소
|
||||||
|
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
|
||||||
|
|
||||||
|
const email = formData.get('email')
|
||||||
|
if (!isObjectNotEmpty(email)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub2.email')]))
|
||||||
|
emailRef.current.focus()
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
// 이메일 정규식 검사
|
||||||
|
if (!emailRegex.test(email)) {
|
||||||
|
alert(getMessage('join.validation.check1', [getMessage('join.sub2.email')]))
|
||||||
|
emailRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 담당자 정보 - 전화번호
|
||||||
|
const userTelNo = formData.get('userTelNo')
|
||||||
|
if (!isObjectNotEmpty(userTelNo)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub2.telNo')]))
|
||||||
|
userTelNoRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 담당자 정보 - FAX 번호
|
||||||
|
const userFax = formData.get('userFax')
|
||||||
|
if (!isObjectNotEmpty(userFax)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub2.fax')]))
|
||||||
|
userFaxRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// 가입 신청
|
// 가입 신청
|
||||||
const joinProcess = async (e) => {
|
const joinProcess = async (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const formData = new FormData(e.target)
|
const formData = new FormData(e.target)
|
||||||
|
|
||||||
|
if (joinValidation(formData)) {
|
||||||
|
if (confirm(getMessage('join.complete.save.confirm'))) {
|
||||||
const param = {
|
const param = {
|
||||||
storeQcastNm: formData.get('storeQcastNm'),
|
storeQcastNm: formData.get('storeQcastNm'),
|
||||||
storeQcastNmKana: formData.get('storeQcastNmKana'),
|
storeQcastNmKana: formData.get('storeQcastNmKana'),
|
||||||
@ -49,6 +167,8 @@ export default function Join() {
|
|||||||
alert(error.response.data.message)
|
alert(error.response.data.message)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="center-page-wrap">
|
<div className="center-page-wrap">
|
||||||
@ -71,6 +191,7 @@ export default function Join() {
|
|||||||
<col />
|
<col />
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
{/* 판매대리점명 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub1.storeQcastNm')} <span className="important">*</span>
|
{getMessage('join.sub1.storeQcastNm')} <span className="important">*</span>
|
||||||
@ -81,14 +202,16 @@ export default function Join() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="storeQcastNm"
|
id="storeQcastNm"
|
||||||
name="storeQcastNm"
|
name="storeQcastNm"
|
||||||
required
|
|
||||||
alt={getMessage('join.sub1.storeQcastNm')}
|
alt={getMessage('join.sub1.storeQcastNm')}
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.storeQcastNm_placeholder')}
|
placeholder={getMessage('join.sub1.storeQcastNm_placeholder')}
|
||||||
|
maxLength={30}
|
||||||
|
ref={storeQcastNmRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 판매대리점명 후리가나 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub1.storeQcastNmKana')} <span className="important">*</span>
|
{getMessage('join.sub1.storeQcastNmKana')} <span className="important">*</span>
|
||||||
@ -99,13 +222,15 @@ export default function Join() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="storeQcastNmKana"
|
id="storeQcastNmKana"
|
||||||
name="storeQcastNmKana"
|
name="storeQcastNmKana"
|
||||||
required
|
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.storeQcastNmKana_placeholder')}
|
placeholder={getMessage('join.sub1.storeQcastNmKana_placeholder')}
|
||||||
|
maxLength={30}
|
||||||
|
ref={storeQcastNmKanaRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 우편번호/주소 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub1.postCd')}/{getMessage('join.sub1.addr')} <span className="important">*</span>
|
{getMessage('join.sub1.postCd')}/{getMessage('join.sub1.addr')} <span className="important">*</span>
|
||||||
@ -117,9 +242,11 @@ export default function Join() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="postCd"
|
id="postCd"
|
||||||
name="postCd"
|
name="postCd"
|
||||||
required
|
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.postCd_placeholder')}
|
placeholder={getMessage('join.sub1.postCd_placeholder')}
|
||||||
|
onChange={inputNumberCheck}
|
||||||
|
maxLength={7}
|
||||||
|
ref={postCdRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-wrap" style={{ width: '495px' }}>
|
<div className="input-wrap" style={{ width: '495px' }}>
|
||||||
@ -127,14 +254,16 @@ export default function Join() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="addr"
|
id="addr"
|
||||||
name="addr"
|
name="addr"
|
||||||
required
|
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.addr_placeholder')}
|
placeholder={getMessage('join.sub1.addr_placeholder')}
|
||||||
|
maxLength={50}
|
||||||
|
ref={addrRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 전화번호 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub1.telNo')} <span className="important">*</span>
|
{getMessage('join.sub1.telNo')} <span className="important">*</span>
|
||||||
@ -145,13 +274,16 @@ export default function Join() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="telNo"
|
id="telNo"
|
||||||
name="telNo"
|
name="telNo"
|
||||||
required
|
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.telNo_placeholder')}
|
placeholder={getMessage('join.sub1.telNo_placeholder')}
|
||||||
></input>
|
maxLength={15}
|
||||||
|
onChange={inputTelNumberCheck}
|
||||||
|
ref={telNoRef}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* FAX 번호 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub1.fax')} <span className="important">*</span>
|
{getMessage('join.sub1.fax')} <span className="important">*</span>
|
||||||
@ -162,18 +294,21 @@ export default function Join() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="fax"
|
id="fax"
|
||||||
name="fax"
|
name="fax"
|
||||||
required
|
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.fax_placeholder')}
|
placeholder={getMessage('join.sub1.fax_placeholder')}
|
||||||
></input>
|
maxLength={15}
|
||||||
|
onChange={inputTelNumberCheck}
|
||||||
|
ref={faxRef}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 법인번호 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{getMessage('join.sub1.bizNo')}</th>
|
<th>{getMessage('join.sub1.bizNo')}</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" id="bizNo" name="bizNo" className="input-light" />
|
<input type="text" id="bizNo" name="bizNo" className="input-light" maxLength={15} onChange={inputTelNumberCheck} />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -196,44 +331,49 @@ export default function Join() {
|
|||||||
<col />
|
<col />
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
{/* 담당자명 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub2.userNm')} <span className="important">*</span>
|
{getMessage('join.sub2.userNm')} <span className="important">*</span>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" id="userNm" name="userNm" className="input-light" required />
|
<input type="text" id="userNm" name="userNm" className="input-light" maxLength={20} ref={userNmRef} />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 담당자명 후리가나 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{getMessage('join.sub2.userNmKana')}</th>
|
<th>{getMessage('join.sub2.userNmKana')}</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" id="userNmKana" name="userNmKana" className="input-light" />
|
<input type="text" id="userNmKana" name="userNmKana" maxLength={20} className="input-light" />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 신청 ID */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub2.userId')} <span className="important">*</span>
|
{getMessage('join.sub2.userId')} <span className="important">*</span>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" id="userId" name="userId" className="input-light" required />
|
<input type="text" id="userId" name="userId" className="input-light" maxLength={20} ref={userIdRef} />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 이메일 주소 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub2.email')} <span className="important">*</span>
|
{getMessage('join.sub2.email')} <span className="important">*</span>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" id="email" name="email" className="input-light" required />
|
<input type="text" id="email" name="email" className="input-light" maxLength={30} ref={emailRef} />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 전화번호 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub2.telNo')} <span className="important">*</span>
|
{getMessage('join.sub2.telNo')} <span className="important">*</span>
|
||||||
@ -246,11 +386,14 @@ export default function Join() {
|
|||||||
name="userTelNo"
|
name="userTelNo"
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub2.telNo_placeholder')}
|
placeholder={getMessage('join.sub2.telNo_placeholder')}
|
||||||
required
|
maxLength={15}
|
||||||
|
onChange={inputTelNumberCheck}
|
||||||
|
ref={userTelNoRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* FAX 번호 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub2.fax')} <span className="important">*</span>
|
{getMessage('join.sub2.fax')} <span className="important">*</span>
|
||||||
@ -263,16 +406,19 @@ export default function Join() {
|
|||||||
name="userFax"
|
name="userFax"
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.fax_placeholder')}
|
placeholder={getMessage('join.sub1.fax_placeholder')}
|
||||||
required
|
maxLength={15}
|
||||||
|
onChange={inputTelNumberCheck}
|
||||||
|
ref={userFaxRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 부서명 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{getMessage('join.sub2.category')}</th>
|
<th>{getMessage('join.sub2.category')}</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" id="category" name="category" className="input-light" />
|
<input type="text" id="category" name="category" className="input-light" maxLength={20} />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -15,6 +15,8 @@ import Cookies from 'js-cookie'
|
|||||||
|
|
||||||
import { useSearchParams } from 'next/navigation'
|
import { useSearchParams } from 'next/navigation'
|
||||||
|
|
||||||
|
import AutoLogin from './AutoLogin'
|
||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
// 자동 로그인
|
// 자동 로그인
|
||||||
const initParams = useSearchParams()
|
const initParams = useSearchParams()
|
||||||
@ -69,6 +71,10 @@ export default function Login() {
|
|||||||
|
|
||||||
const { promisePost, promisePatch, post } = useAxios(globalLocaleState)
|
const { promisePost, promisePatch, post } = useAxios(globalLocaleState)
|
||||||
|
|
||||||
|
// focus state
|
||||||
|
const [idFocus, setIdFocus] = useState(false)
|
||||||
|
const [secFocus, setSecFocus] = useState(false)
|
||||||
|
|
||||||
// login process
|
// login process
|
||||||
const loginProcess = async (e) => {
|
const loginProcess = async (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@ -92,6 +98,7 @@ export default function Login() {
|
|||||||
pwdInitYn: 'Y',
|
pwdInitYn: 'Y',
|
||||||
storeLvl: '1',
|
storeLvl: '1',
|
||||||
groupId: '60000',
|
groupId: '60000',
|
||||||
|
custCd: '100000',
|
||||||
})
|
})
|
||||||
setSessionState({
|
setSessionState({
|
||||||
userId: 'NEW016610',
|
userId: 'NEW016610',
|
||||||
@ -109,6 +116,7 @@ export default function Login() {
|
|||||||
pwdInitYn: 'Y',
|
pwdInitYn: 'Y',
|
||||||
storeLvl: '1',
|
storeLvl: '1',
|
||||||
groupId: '60000',
|
groupId: '60000',
|
||||||
|
custCd: '100000',
|
||||||
})
|
})
|
||||||
if (chkLoginId) {
|
if (chkLoginId) {
|
||||||
Cookies.set('chkLoginId', formData.get('id'), { expires: 7 })
|
Cookies.set('chkLoginId', formData.get('id'), { expires: 7 })
|
||||||
@ -180,8 +188,7 @@ export default function Login() {
|
|||||||
<Link href={'/login'} className="login-logo">
|
<Link href={'/login'} className="login-logo">
|
||||||
<Image src="/static/images/main/login-logo.svg" alt="react" width={236} height={43} styles={{ width: '236px', height: '43px' }} priority />
|
<Image src="/static/images/main/login-logo.svg" alt="react" width={236} height={43} styles={{ width: '236px', height: '43px' }} priority />
|
||||||
</Link>
|
</Link>
|
||||||
|
{!autoLoginParam && passwordReset === 1 && (
|
||||||
{passwordReset === 1 && (
|
|
||||||
<>
|
<>
|
||||||
<div className="login-input-frame">
|
<div className="login-input-frame">
|
||||||
<form onSubmit={loginProcess} className="space-y-6">
|
<form onSubmit={loginProcess} className="space-y-6">
|
||||||
@ -190,7 +197,7 @@ export default function Login() {
|
|||||||
{getMessage('site.sub_name')}
|
{getMessage('site.sub_name')}
|
||||||
</div>
|
</div>
|
||||||
<div className="login-input-wrap">
|
<div className="login-input-wrap">
|
||||||
<div className="login-area id">
|
<div className={`login-area id ${idFocus ? 'focus' : ''}`}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="login-input"
|
className="login-input"
|
||||||
@ -202,6 +209,8 @@ export default function Login() {
|
|||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setUserId(e.target.value)
|
setUserId(e.target.value)
|
||||||
}}
|
}}
|
||||||
|
onFocus={() => setIdFocus(true)}
|
||||||
|
onBlur={() => setIdFocus(false)}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -211,7 +220,7 @@ export default function Login() {
|
|||||||
}}
|
}}
|
||||||
></button>
|
></button>
|
||||||
</div>
|
</div>
|
||||||
<div className="login-area password">
|
<div className={`login-area password ${secFocus ? 'focus' : ''}`}>
|
||||||
<input
|
<input
|
||||||
type={passwordVisible ? 'text' : 'password'}
|
type={passwordVisible ? 'text' : 'password'}
|
||||||
className="login-input"
|
className="login-input"
|
||||||
@ -223,8 +232,11 @@ export default function Login() {
|
|||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setPasswordVisible(passwordVisible)
|
setPasswordVisible(passwordVisible)
|
||||||
}}
|
}}
|
||||||
|
onFocus={() => setSecFocus(true)}
|
||||||
|
onBlur={() => setSecFocus(false)}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
className={`password-hidden ${passwordVisible ? 'visible' : ''}`}
|
className={`password-hidden ${passwordVisible ? 'visible' : ''}`}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@ -266,7 +278,7 @@ export default function Login() {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{passwordReset === 2 && (
|
{!autoLoginParam && passwordReset === 2 && (
|
||||||
<>
|
<>
|
||||||
<div className="login-input-frame">
|
<div className="login-input-frame">
|
||||||
<div className="login-frame-tit pw-reset">
|
<div className="login-frame-tit pw-reset">
|
||||||
@ -274,7 +286,7 @@ export default function Login() {
|
|||||||
{getMessage('login.init_password.sub_title')}
|
{getMessage('login.init_password.sub_title')}
|
||||||
</div>
|
</div>
|
||||||
<div className="login-input-wrap">
|
<div className="login-input-wrap">
|
||||||
<div className="login-area id">
|
<div className={`login-area id ${idFocus ? 'focus' : ''}`}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="checkId"
|
id="checkId"
|
||||||
@ -286,6 +298,8 @@ export default function Login() {
|
|||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setCheckId(e.target.value)
|
setCheckId(e.target.value)
|
||||||
}}
|
}}
|
||||||
|
onFocus={() => setIdFocus(true)}
|
||||||
|
onBlur={() => setIdFocus(false)}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -295,7 +309,7 @@ export default function Login() {
|
|||||||
}}
|
}}
|
||||||
></button>
|
></button>
|
||||||
</div>
|
</div>
|
||||||
<div className="login-area email">
|
<div className={`login-area email ${secFocus ? 'focus' : ''}`}>
|
||||||
<input
|
<input
|
||||||
id="checkEmail"
|
id="checkEmail"
|
||||||
name="checkEmail"
|
name="checkEmail"
|
||||||
@ -307,6 +321,8 @@ export default function Login() {
|
|||||||
setCheckEmail(e.target.value)
|
setCheckEmail(e.target.value)
|
||||||
}}
|
}}
|
||||||
placeholder={getMessage('login.init_password.email.placeholder')}
|
placeholder={getMessage('login.init_password.email.placeholder')}
|
||||||
|
onFocus={() => setSecFocus(true)}
|
||||||
|
onBlur={() => setSecFocus(false)}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -317,7 +333,15 @@ export default function Login() {
|
|||||||
></button>
|
></button>
|
||||||
</div>
|
</div>
|
||||||
<div className="pwreset-btn-box">
|
<div className="pwreset-btn-box">
|
||||||
<button type="button" className="login-btn light mr5" onClick={() => setPasswordReset(1)}>
|
<button
|
||||||
|
type="button"
|
||||||
|
className="login-btn light mr5"
|
||||||
|
onClick={() => {
|
||||||
|
setPasswordReset(1)
|
||||||
|
setCheckEmail('')
|
||||||
|
setCheckId('')
|
||||||
|
}}
|
||||||
|
>
|
||||||
{getMessage('login.init_password.btn.back')}
|
{getMessage('login.init_password.btn.back')}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" className="login-btn" onClick={initPasswordProcess}>
|
<button type="button" className="login-btn" onClick={initPasswordProcess}>
|
||||||
@ -328,6 +352,7 @@ export default function Login() {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{autoLoginParam && <AutoLogin />}
|
||||||
</div>
|
</div>
|
||||||
<div className="login-copyright">COPYRIGHT©2024 Hanwha Japan All Rights Reserved.</div>
|
<div className="login-copyright">COPYRIGHT©2024 Hanwha Japan All Rights Reserved.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,11 +1,30 @@
|
|||||||
import { HexColorPicker } from 'react-colorful'
|
import { HexColorPicker } from 'react-colorful'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
|
||||||
export default function ColorPicker(props) {
|
export default function ColorPicker(props) {
|
||||||
const { color, setColor } = props
|
const { color, setColor } = props
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const defaultColors = ['#EA575D', '#F29955', '#F2C957', '#32975D', '#3D7FED', '#828282', '#ffffff', '#000000']
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<div>
|
||||||
<HexColorPicker color={color} onChange={setColor} />
|
<HexColorPicker color={color} onChange={setColor} />
|
||||||
|
</div>
|
||||||
|
<div className="hex-color-box">
|
||||||
|
<div className="color-box-tit">HEX</div>
|
||||||
|
<div className="color-hex-input">
|
||||||
|
<input type="text" className="input-origin" value={color} onChange={(e) => setColor(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div className="color-box" style={{ backgroundColor: color }}></div>
|
||||||
|
</div>
|
||||||
|
<div className="default-color-wrap">
|
||||||
|
<div className="default-tit">{getMessage('modal.color.picker.default.color')}</div>
|
||||||
|
<div className="color-button-wrap">
|
||||||
|
{defaultColors.map((color, index) => (
|
||||||
|
<button key={index} className="default-color" style={{ backgroundColor: color }} onClick={() => setColor(color)}></button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
62
src/components/common/color-picker/ColorPickerModal.jsx
Normal file
62
src/components/common/color-picker/ColorPickerModal.jsx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
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'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
|
||||||
|
export default function ColorPickerModal(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState) // 현재 메뉴
|
||||||
|
const { isShow, setIsShow, pos = contextPopupPosition, color = '#ff0000', setColor, id } = props
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const [originColor, setOriginColor] = useState(color)
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setOriginColor(color)
|
||||||
|
}, [isShow])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos ?? ''}>
|
||||||
|
<div className={`modal-pop-wrap lr mount`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage('modal.color.picker.title')}</h1>
|
||||||
|
<button
|
||||||
|
className="modal-close"
|
||||||
|
onClick={() => {
|
||||||
|
if (setIsShow) {
|
||||||
|
setIsShow(false)
|
||||||
|
}
|
||||||
|
console.log(id)
|
||||||
|
closePopup(id)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="color-setting-wrap">
|
||||||
|
<div className="color-tit">COLOR PICKER</div>
|
||||||
|
<div className="color-picker">
|
||||||
|
<ColorPicker color={originColor} setColor={setOriginColor} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button
|
||||||
|
className="btn-frame modal act"
|
||||||
|
onClick={() => {
|
||||||
|
if (setColor) setColor(originColor)
|
||||||
|
if (setIsShow) setIsShow(false)
|
||||||
|
|
||||||
|
closePopup(id)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{getMessage('common.message.save')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,15 +1,13 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect } from 'react'
|
||||||
import '@/styles/contents.scss'
|
import '@/styles/contents.scss'
|
||||||
|
import { useRecoilState } from 'recoil'
|
||||||
|
import { contextMenuState } from '@/store/contextMenu'
|
||||||
|
|
||||||
export default function QContextMenu(props) {
|
export default function QContextMenu(props) {
|
||||||
const { contextRef, canvasProps } = props
|
const { contextRef, canvasProps, handleKeyup } = props
|
||||||
|
const [contextMenu, setContextMenu] = useRecoilState(contextMenuState)
|
||||||
// const children = useRecoilValue(modalContent)
|
|
||||||
const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0 })
|
|
||||||
|
|
||||||
const activeObject = canvasProps?.getActiveObject() //액티브된 객체를 가져옴
|
const activeObject = canvasProps?.getActiveObject() //액티브된 객체를 가져옴
|
||||||
|
|
||||||
let contextType = ''
|
let contextType = ''
|
||||||
|
|
||||||
if (activeObject) {
|
if (activeObject) {
|
||||||
@ -27,7 +25,7 @@ export default function QContextMenu(props) {
|
|||||||
const handleContextMenu = (e) => {
|
const handleContextMenu = (e) => {
|
||||||
// e.preventDefault() //기존 contextmenu 막고
|
// e.preventDefault() //기존 contextmenu 막고
|
||||||
setContextMenu({ visible: true, x: e.pageX, y: e.pageY })
|
setContextMenu({ visible: true, x: e.pageX, y: e.pageY })
|
||||||
// console.log(111, canvasProps)
|
document.addEventListener('keyup', (e) => handleKeyup(e))
|
||||||
canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제
|
canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
146
src/components/common/font/FontSetting.jsx
Normal file
146
src/components/common/font/FontSetting.jsx
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
|
import { fontSelector, globalFontAtom } from '@/store/fontAtom'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
|
||||||
|
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 contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, setIsShow, pos = contextPopupPosition, type } = props
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
const [globalFont, setGlobalFont] = useRecoilState(globalFontAtom)
|
||||||
|
const currentFont = useRecoilValue(fontSelector(type))
|
||||||
|
|
||||||
|
const [selectedFont, setSelectedFont] = useState(currentFont.fontFamily)
|
||||||
|
const [selectedFontWeight, setSelectedFontWeight] = useState(currentFont.fontWeight)
|
||||||
|
const [selectedFontSize, setSelectedFontSize] = useState(currentFont.fontSize)
|
||||||
|
const [selectedFontColor, setSelectedFontColor] = useState(currentFont.fontColor)
|
||||||
|
|
||||||
|
const handleSaveBtn = () => {
|
||||||
|
setGlobalFont((prev) => {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[type]: {
|
||||||
|
fontFamily: selectedFont,
|
||||||
|
fontSize: selectedFontSize,
|
||||||
|
fontColor: selectedFontColor,
|
||||||
|
fontWeight: selectedFontWeight,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (setIsShow) setIsShow(false)
|
||||||
|
closePopup(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap lrr mount`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage('modal.font')}</h1>
|
||||||
|
<button
|
||||||
|
className="modal-close"
|
||||||
|
onClick={() => {
|
||||||
|
if (setIsShow) setIsShow(false)
|
||||||
|
closePopup(id)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="slope-wrap">
|
||||||
|
<div className="font-option-warp">
|
||||||
|
<div className="font-option-item">
|
||||||
|
<div className="option-item-tit">{getMessage('modal.font')}(F)</div>
|
||||||
|
<div className="grid-select">
|
||||||
|
<QSelectBox options={fonts} value={selectedFont} onChange={(e) => setSelectedFont(e)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="font-option-item">
|
||||||
|
<div className="option-item-tit">{getMessage('modal.font.style')}(Y)</div>
|
||||||
|
<div className="grid-select">
|
||||||
|
<QSelectBox options={fontOptions} value={selectedFontWeight} onChange={(e) => setSelectedFontWeight(e)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="font-option-item">
|
||||||
|
<div className="option-item-tit">{getMessage('modal.font.size')}(S)</div>
|
||||||
|
<div className="grid-select">
|
||||||
|
<QSelectBox options={fontSizes} value={selectedFontSize} onChange={(e) => setSelectedFontSize(e)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="font-option-item">
|
||||||
|
<div className="option-item-tit">{getMessage('modal.font.color')}</div>
|
||||||
|
<div className="grid-select">
|
||||||
|
<QSelectBox title={''} options={fontColors} value={selectedFontColor} onChange={(e) => setSelectedFontColor(e)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="font-ex-wrap">
|
||||||
|
<div className="font-ex-tit">{getMessage('modal.font.setting.display')}</div>
|
||||||
|
<div className="font-ex-box">
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
fontFamily: selectedFont?.value ?? '',
|
||||||
|
fontSize: selectedFontSize?.value ?? '12px',
|
||||||
|
fontWeight: '400',
|
||||||
|
color: selectedFontColor?.value ?? 'black',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Aaあぁアァ
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="normal-font">{getMessage('modal.font.setting.info')}</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act" onClick={handleSaveBtn}>
|
||||||
|
{getMessage('modal.common.save')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -31,7 +31,7 @@ export default function QPagination(props) {
|
|||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (currentPage === totalPages) return
|
if (currentPage === totalPages) return
|
||||||
handlePage(Math.max(1, pageGroup * pagePerBlock + 1))
|
if (pageGroup * pagePerBlock + 1 <= totalPages) handlePage(Math.max(1, pageGroup * pagePerBlock + 1))
|
||||||
}}
|
}}
|
||||||
></button>
|
></button>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
9
src/components/common/popupManager/PopupManager.jsx
Normal file
9
src/components/common/popupManager/PopupManager.jsx
Normal file
@ -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) => <Fragment key={child.id}>{child.component}</Fragment>)
|
||||||
|
}
|
||||||
@ -20,7 +20,7 @@ export default function QSelectBox({ title = '', options, onChange, value }) {
|
|||||||
<ul className="select-item-wrap">
|
<ul className="select-item-wrap">
|
||||||
{options?.map((option) => (
|
{options?.map((option) => (
|
||||||
<li key={option.id} className="select-item" onClick={() => handleClickSelectOption(option)}>
|
<li key={option.id} className="select-item" onClick={() => handleClickSelectOption(option)}>
|
||||||
<button>{option.name}</button>
|
<button key={option.id + 'btn'}>{option.name}</button>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@ -81,11 +81,11 @@ export default function Table({ clsCode }) {
|
|||||||
{/* 번호 */}
|
{/* 번호 */}
|
||||||
{board.rowNumber}
|
{board.rowNumber}
|
||||||
</td>
|
</td>
|
||||||
<td style={{ textAlign: 'center' }}>
|
<td>
|
||||||
{/* 제목 */}
|
{/* 제목 */}
|
||||||
<div className="text-frame">
|
<div className="text-frame">
|
||||||
<div className="text-overflow">{board.title}</div>
|
<div className="text-overflow">{board.title}</div>
|
||||||
{board.attachYn && <span className="clip"></span>}
|
{board.attachYn === 'Y' && <span className="clip"></span>}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="al-c">
|
<td className="al-c">
|
||||||
|
|||||||
@ -3,8 +3,11 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { handleFileDown } from '@/util/board-utils'
|
import { handleFileDown } from '@/util/board-utils'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
|
||||||
export default function BoardDetailModal({ noticeNo, setOpen }) {
|
export default function BoardDetailModal({ noticeNo, setOpen }) {
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
// api 조회 관련
|
// api 조회 관련
|
||||||
const { get } = useAxios()
|
const { get } = useAxios()
|
||||||
const [boardDetail, setBoardDetail] = useState({})
|
const [boardDetail, setBoardDetail] = useState({})
|
||||||
@ -46,7 +49,7 @@ export default function BoardDetailModal({ noticeNo, setOpen }) {
|
|||||||
setOpen(false)
|
setOpen(false)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
닫기
|
{getMessage('board.sub.btn.close')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
@ -55,7 +58,7 @@ export default function BoardDetailModal({ noticeNo, setOpen }) {
|
|||||||
|
|
||||||
{boardDetail.listFile && (
|
{boardDetail.listFile && (
|
||||||
<dl className="community_detail-file-wrap">
|
<dl className="community_detail-file-wrap">
|
||||||
<dt>첨부파일 목록</dt>
|
<dt>{getMessage('board.sub.fileList')}</dt>
|
||||||
{boardDetail.listFile.map((boardFile) => (
|
{boardDetail.listFile.map((boardFile) => (
|
||||||
<dd key={boardFile.encodeFileNo}>
|
<dd key={boardFile.encodeFileNo}>
|
||||||
<button type="button" className="down" onClick={() => handleFileDown(boardFile)}>
|
<button type="button" className="down" onClick={() => handleFileDown(boardFile)}>
|
||||||
|
|||||||
307
src/components/estimate/Estimate.jsx
Normal file
307
src/components/estimate/Estimate.jsx
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
'use client'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import SingleDatePicker from '../common/datepicker/SingleDatePicker'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||||
|
|
||||||
|
export default function Estimate() {
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const objectRecoil = useRecoilValue(floorPlanObjectState)
|
||||||
|
console.log('견적서화면이군요', objectRecoil.floorPlanObjectNo)
|
||||||
|
return (
|
||||||
|
<div className="sub-content estimate">
|
||||||
|
<div className="sub-content-inner">
|
||||||
|
{/* 물건번호, 견적서번호, 등록일, 변경일시 시작 */}
|
||||||
|
<div className="sub-content-box">
|
||||||
|
<div className="sub-table-box">
|
||||||
|
<div className="estimate-list-wrap one">
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.objectNo')}</div>
|
||||||
|
<div className="estimate-name">RX524231020006 (Plan No: 1)</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.estimateNo')}</div>
|
||||||
|
<div className="estimate-name">5242310200065242</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.createDatetime')}</div>
|
||||||
|
<div className="estimate-name">9999.09.28</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.lastEditDatetime')}</div>
|
||||||
|
<div className="estimate-name">9999.09.28 06:36</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* 물건번호, 견적서번호, 등록일, 변경일시 끝 */}
|
||||||
|
{/* 기본정보 시작 */}
|
||||||
|
<div className="sub-content-box">
|
||||||
|
<div className="sub-table-box">
|
||||||
|
<div className="table-box-title-wrap">
|
||||||
|
<div className="title-wrap">
|
||||||
|
<h3>{getMessage('estimate.detail.header.title')}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="common-table bt-able">
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
{/* 1차 판매점명 */}
|
||||||
|
<th>{getMessage('estimate.detail.saleStoreId')}</th>
|
||||||
|
<td></td>
|
||||||
|
{/* 견적일 */}
|
||||||
|
<th>
|
||||||
|
{getMessage('estimate.detail.estimateDate')} <span className="important">*</span>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<div className="date-picker" style={{ width: '350px' }}>
|
||||||
|
<SingleDatePicker />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{/* 2차 판매점명 */}
|
||||||
|
<th>{getMessage('estimate.detail.otherSaleStoreId')}</th>
|
||||||
|
<td></td>
|
||||||
|
{/* 담당자 */}
|
||||||
|
<th>
|
||||||
|
{getMessage('estimate.detail.receiveUser')} <span className="important">*</span>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<div className="input-wrap" style={{ width: '350px' }}>
|
||||||
|
<input type="text" className="input-light" defaultValue={'물건정보에서 입력한 담당자명 표시'} />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{/* 안건명 */}
|
||||||
|
<th>
|
||||||
|
{getMessage('estimate.detail.title')} <span className="important">*</span>
|
||||||
|
</th>
|
||||||
|
<td colSpan={3}>
|
||||||
|
<div className="form-flex-wrap">
|
||||||
|
<div className="input-wrap mr5" style={{ width: '610px' }}>
|
||||||
|
<input type="text" className="input-light" defaultValue={'안건명:::'} />
|
||||||
|
</div>
|
||||||
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
|
<input type="text" className="input-light" defaultValue={'경칭?'} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{/* 메모 */}
|
||||||
|
<th>{getMessage('estimate.detail.remarks')}</th>
|
||||||
|
<td colSpan={3}>물건정보에서 입력한 메모 표시</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{/* 주문분류 */}
|
||||||
|
<th>
|
||||||
|
注文分類/주문분류 <span className="important">*</span>
|
||||||
|
</th>
|
||||||
|
<td colSpan={3}>
|
||||||
|
<div className="radio-wrap"></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{/* 지붕재・사양시공 최대4개*/}
|
||||||
|
<th>屋根材・仕様施工 / 지붕재・사양시공</th>
|
||||||
|
<td colSpan={3}>
|
||||||
|
<div className="form-flex-wrap mb5">
|
||||||
|
<div className="input-wrap mr5" style={{ width: '610px' }}>
|
||||||
|
<input type="text" className="input-light" defaultValue={'ハゼ式折板(角ハゼ)'} readOnly />
|
||||||
|
</div>
|
||||||
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
|
<input type="text" className="input-light" defaultValue={'標準施工'} readOnly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="form-flex-wrap mb5"></div>
|
||||||
|
<div className="form-flex-wrap mb5"></div>
|
||||||
|
{/* 마지막div엔 mb5 제외 */}
|
||||||
|
<div className="form-flex-wrap"></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{/* 비고 */}
|
||||||
|
<th>備考 /비고</th>
|
||||||
|
<td colSpan={3}>
|
||||||
|
<div className="input-wrap">
|
||||||
|
<input type="text" className="input-light" />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{/* 파일첨부 시작 */}
|
||||||
|
<div className="table-box-title-wrap">
|
||||||
|
<div className="title-wrap">
|
||||||
|
<h3>{getMessage('estimate.detail.header.fileList1')}</h3>
|
||||||
|
<div className="d-check-box light mr5">
|
||||||
|
<input type="checkbox" id="" />
|
||||||
|
<label htmlFor="" style={{ color: '#101010' }}>
|
||||||
|
後日資料提出 / 후일자료제출
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="common-table mb10">
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>{getMessage('estimate.detail.header.fileList1')}</th>
|
||||||
|
<td>
|
||||||
|
<div className="drag-file-box">
|
||||||
|
<div className="btn-area">
|
||||||
|
<button className="btn-origin grey">{getMessage('estimate.detail.fileList.btn')}</button>
|
||||||
|
</div>
|
||||||
|
<div className="drag-file-area">
|
||||||
|
<p>Drag file here</p>
|
||||||
|
<ul className="file-list"></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{/* 첨부파일 목록 시작 */}
|
||||||
|
<div className="common-table bt-able">
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>{getMessage('estimate.detail.header.fileList2')}</th>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{/* 첨부파일 목록 끝 */}
|
||||||
|
{/* 파일첨부 끝 */}
|
||||||
|
{/* 견적특이사항 시작 */}
|
||||||
|
<div className="table-box-title-wrap">
|
||||||
|
<div className="title-wrap">
|
||||||
|
<h3 className="product">{getMessage('estimate.detail.header.specialEstimate')}</h3>
|
||||||
|
<div className="product_tit">{getMessage('estimate.detail.header.specialEstimateProductInfo')}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* 공통코드영역시작 */}
|
||||||
|
<div className="special-note-check-wrap"></div>
|
||||||
|
{/* 공통코드영역끝 */}
|
||||||
|
{/* 견적특이사항 내용영역시작 */}
|
||||||
|
<div className="calculation-estimate"></div>
|
||||||
|
{/* 견적특이사항 내용영역끝 */}
|
||||||
|
{/* 견적특이사항 끝 */}
|
||||||
|
{/* 제품정보 시작 */}
|
||||||
|
<div className="table-box-title-wrap">
|
||||||
|
<div className="title-wrap">
|
||||||
|
<h3>{getMessage('estimate.detail.header.specialEstimateProductInfo')}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-wrap">
|
||||||
|
<div className="estimate-list-wrap one">
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">수량 (PCS)</div>
|
||||||
|
<div className="estimate-name blue">74</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">용량 (Kw)</div>
|
||||||
|
<div className="estimate-name blue">8300</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">공급가액</div>
|
||||||
|
<div className="estimate-name blue">6,798,900</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">부가세 (10%)</div>
|
||||||
|
<div className="estimate-name blue">679,890</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">총액</div>
|
||||||
|
<div className="estimate-name red">7,478,790</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* YJOD면 아래영역 숨김 */}
|
||||||
|
<div className="common-table bt-able">
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgUnitPrice')}
|
||||||
|
<span className="important">*</span>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<div className="input-wrap">
|
||||||
|
<input type="text" className="input-light" />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgWeight')}</th>
|
||||||
|
<td>(모듈수량 * 수량) / 100)</td>
|
||||||
|
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgPrice')}</th>
|
||||||
|
<td>PKG단가(W) * PKG용량(W)</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{/* 제품정보 끝 */}
|
||||||
|
{/* 가격표시영역시작 */}
|
||||||
|
<div className="estimate-product-option">
|
||||||
|
<div className="product-price-wrap">
|
||||||
|
<div className="product-price-tit">{getMessage('estimate.detail.header.showPrice')}</div>
|
||||||
|
<div className="select-wrap"></div>
|
||||||
|
<button className="btn-origin grey ml5">{getMessage('estimate.detail.showPrice.btn1')}</button>
|
||||||
|
</div>
|
||||||
|
<div className="product-edit-wrap">
|
||||||
|
<div className="product-edit-explane">
|
||||||
|
<div className="click-check">
|
||||||
|
<span className="ico"></span>
|
||||||
|
{getMessage('estimate.detail.showPrice.description')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="product-edit-btn">
|
||||||
|
<button className="btn-origin navy mr5">
|
||||||
|
<span className="plus"></span>
|
||||||
|
{getMessage('estimate.detail.showPrice.btn2')}
|
||||||
|
</button>
|
||||||
|
<button className="btn-origin grey">
|
||||||
|
<span className="minus"></span>
|
||||||
|
{getMessage('estimate.detail.showPrice.btn3')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* 가격표시영역끝 */}
|
||||||
|
{/* html테이블시작 */}
|
||||||
|
<div className="q-grid no-cols"></div>
|
||||||
|
{/* html테이블끝 */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* 기본정보끝 */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -12,7 +12,7 @@ export const QLine = fabric.util.createClass(fabric.Line, {
|
|||||||
idx: 0,
|
idx: 0,
|
||||||
area: 0,
|
area: 0,
|
||||||
children: [],
|
children: [],
|
||||||
initialize: function (points, options, canvas) {
|
initialize: function (points, options, length = 0) {
|
||||||
this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? true })
|
this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? true })
|
||||||
if (options.id) {
|
if (options.id) {
|
||||||
this.id = options.id
|
this.id = options.id
|
||||||
@ -21,15 +21,16 @@ export const QLine = fabric.util.createClass(fabric.Line, {
|
|||||||
}
|
}
|
||||||
this.line = this
|
this.line = this
|
||||||
// 소수점 전부 제거
|
// 소수점 전부 제거
|
||||||
points.forEach((point) => {
|
points = points.map((point) => Math.round(point))
|
||||||
point = Math.round(point)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.idx = options.idx ?? 0
|
this.idx = options.idx ?? 0
|
||||||
|
|
||||||
this.setLength()
|
|
||||||
|
|
||||||
this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 })
|
this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 })
|
||||||
|
if (length !== 0) {
|
||||||
|
this.length = length
|
||||||
|
} else {
|
||||||
|
this.setLength()
|
||||||
|
}
|
||||||
|
|
||||||
this.startPoint = { x: this.x1, y: this.y1 }
|
this.startPoint = { x: this.x1, y: this.y1 }
|
||||||
this.endPoint = { x: this.x2, y: this.y2 }
|
this.endPoint = { x: this.x2, y: this.y2 }
|
||||||
|
|
||||||
@ -58,11 +59,10 @@ export const QLine = fabric.util.createClass(fabric.Line, {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.on('removed', () => {
|
this.on('removed', () => {
|
||||||
const thisText = this.canvas.getObjects().find((obj) => obj.name === 'lengthText' && obj.parentId === this.id)
|
const children = this.canvas.getObjects().filter((obj) => obj.parentId === this.id)
|
||||||
if (thisText) {
|
children.forEach((child) => {
|
||||||
this.canvas.remove(thisText)
|
this.canvas.remove(child)
|
||||||
}
|
})
|
||||||
this.text = null
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ export const QLine = fabric.util.createClass(fabric.Line, {
|
|||||||
|
|
||||||
getLength() {
|
getLength() {
|
||||||
//10배 곱해진 값 return
|
//10배 곱해진 값 return
|
||||||
return Number(this.length.toFixed(0) * 10)
|
return Number(this.length.toFixed(1)) * 10
|
||||||
},
|
},
|
||||||
|
|
||||||
setViewLengthText(bool) {
|
setViewLengthText(bool) {
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { fabric } from 'fabric'
|
|||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util'
|
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'
|
import * as turf from '@turf/turf'
|
||||||
|
|
||||||
export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||||
@ -24,8 +24,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
initialize: function (points, options, canvas) {
|
initialize: function (points, options, canvas) {
|
||||||
// 소수점 전부 제거
|
// 소수점 전부 제거
|
||||||
points.forEach((point) => {
|
points.forEach((point) => {
|
||||||
point.x = Math.round(point.x)
|
point.x = Number(point.x.toFixed(1))
|
||||||
point.y = Math.round(point.y)
|
point.y = Number(point.y.toFixed(1))
|
||||||
})
|
})
|
||||||
options.selectable = options.selectable ?? true
|
options.selectable = options.selectable ?? true
|
||||||
options.sort = options.sort ?? true
|
options.sort = options.sort ?? true
|
||||||
@ -121,13 +121,9 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
|
|
||||||
this.on('modified', (e) => {
|
this.on('modified', (e) => {
|
||||||
this.addLengthText()
|
this.addLengthText()
|
||||||
// if (this.arrow) {
|
|
||||||
// drawDirectionArrow(this)
|
|
||||||
// }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
this.on('selected', () => {
|
this.on('selected', () => {
|
||||||
// drawDirectionArrow(this)
|
|
||||||
Object.keys(this.controls).forEach((controlKey) => {
|
Object.keys(this.controls).forEach((controlKey) => {
|
||||||
if (controlKey !== 'ml' && controlKey !== 'mr') {
|
if (controlKey !== 'ml' && controlKey !== 'mr') {
|
||||||
this.setControlVisible(controlKey, false)
|
this.setControlVisible(controlKey, false)
|
||||||
@ -136,22 +132,10 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.on('removed', () => {
|
this.on('removed', () => {
|
||||||
const thisText = this.canvas.getObjects().filter((obj) => obj.name === 'lengthText' && obj.parentId === this.id)
|
const children = this.canvas.getObjects().filter((obj) => obj.parentId === this.id)
|
||||||
thisText.forEach((text) => {
|
children.forEach((child) => {
|
||||||
this.canvas.remove(text)
|
this.canvas.remove(child)
|
||||||
})
|
})
|
||||||
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 })
|
// polygon.fillCell({ width: 50, height: 30, padding: 10 })
|
||||||
@ -188,7 +172,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
addLengthText() {
|
addLengthText() {
|
||||||
this.canvas
|
this.canvas
|
||||||
?.getObjects()
|
?.getObjects()
|
||||||
.filter((obj) => obj.name === 'lengthText' && obj.parent === this)
|
.filter((obj) => obj.name === 'lengthText' && obj.parentId === this.id)
|
||||||
.forEach((text) => {
|
.forEach((text) => {
|
||||||
this.canvas.remove(text)
|
this.canvas.remove(text)
|
||||||
})
|
})
|
||||||
@ -199,7 +183,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
const end = points[(i + 1) % points.length]
|
const end = points[(i + 1) % points.length]
|
||||||
const dx = end.x - start.x
|
const dx = end.x - start.x
|
||||||
const dy = end.y - start.y
|
const dy = end.y - start.y
|
||||||
const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0)) * 10
|
const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) * 10
|
||||||
|
|
||||||
let midPoint
|
let midPoint
|
||||||
|
|
||||||
|
|||||||
@ -2,50 +2,75 @@
|
|||||||
|
|
||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
|
|
||||||
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
|
|
||||||
import { useCanvas } from '@/hooks/useCanvas'
|
import { useCanvas } from '@/hooks/useCanvas'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import QContextMenu from '@/components/common/context-menu/QContextMenu'
|
import { usePlan } from '@/hooks/usePlan'
|
||||||
import { useContextMenu } from '@/hooks/useContextMenu'
|
import { useContextMenu } from '@/hooks/useContextMenu'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { currentMenuState, currentObjectState, modifiedPlanFlagState } from '@/store/canvasAtom'
|
||||||
import { currentObjectState } from '@/store/canvasAtom'
|
import { useCanvasEvent } from '@/hooks/useCanvasEvent'
|
||||||
|
import QContextMenu from '@/components/common/context-menu/QContextMenu'
|
||||||
|
import { useCanvasConfigInitialize } from '@/hooks/common/useCanvasConfigInitialize'
|
||||||
|
import { MENU } from '@/common/common'
|
||||||
|
import PanelBatchStatistics from '@/components/floor-plan/modal/panelBatch/PanelBatchStatistics'
|
||||||
|
|
||||||
export default function CanvasFrame({ plan }) {
|
export default function CanvasFrame() {
|
||||||
const canvasRef = useRef(null)
|
const canvasRef = useRef(null)
|
||||||
|
const [modifiedPlanFlag, setModifiedPlanFlag] = useRecoilState(modifiedPlanFlagState)
|
||||||
const { canvas } = useCanvas('canvas')
|
const { canvas } = useCanvas('canvas')
|
||||||
const { contextMenu, currentContextMenu, setCurrentContextMenu } = useContextMenu()
|
const { handleZoomClear } = useCanvasEvent()
|
||||||
|
const { canvasLoadInit, gridInit } = useCanvasConfigInitialize()
|
||||||
|
const currentObject = useRecoilValue(currentObjectState)
|
||||||
|
const currentMenu = useRecoilValue(currentMenuState)
|
||||||
|
const { contextMenu, handleClick, handleKeyup } = useContextMenu()
|
||||||
|
const { selectedPlan, checkCanvasObjectEvent, checkUnsavedCanvasPlan, resetModifiedPlans } = usePlan()
|
||||||
useEvent()
|
useEvent()
|
||||||
|
|
||||||
const loadCanvas = () => {
|
const loadCanvas = () => {
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
canvas?.clear() // 캔버스를 초기화합니다.
|
canvas?.clear() // 캔버스를 초기화합니다.
|
||||||
if (plan?.canvasStatus) {
|
if (selectedPlan?.canvasStatus) {
|
||||||
canvas?.loadFromJSON(JSON.parse(plan.canvasStatus), function () {
|
canvas?.loadFromJSON(JSON.parse(selectedPlan.canvasStatus), function () {
|
||||||
|
canvasLoadInit() //config된 상태로 캔버스 객체를 그린다
|
||||||
canvas?.renderAll() // 캔버스를 다시 그립니다.
|
canvas?.renderAll() // 캔버스를 다시 그립니다.
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
gridInit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadCanvas()
|
if (modifiedPlanFlag && selectedPlan?.id) {
|
||||||
}, [plan, canvas])
|
checkCanvasObjectEvent(selectedPlan.id)
|
||||||
|
}
|
||||||
|
}, [modifiedPlanFlag])
|
||||||
|
|
||||||
const onClickContextMenu = (index) => {}
|
useEffect(() => {
|
||||||
|
loadCanvas()
|
||||||
|
resetModifiedPlans()
|
||||||
|
}, [selectedPlan, canvas])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="canvas-frame flex justify-center">
|
<div className="canvas-frame">
|
||||||
<canvas ref={canvasRef} id={'canvas'}></canvas>
|
<canvas ref={canvasRef} id="canvas" style={{ position: 'relative' }}></canvas>
|
||||||
<QContextMenu contextRef={canvasRef} canvasProps={canvas}>
|
|
||||||
|
<QContextMenu contextRef={canvasRef} canvasProps={canvas} handleKeyup={handleKeyup}>
|
||||||
{contextMenu.map((menus, index) => (
|
{contextMenu.map((menus, index) => (
|
||||||
<ul key={index}>
|
<ul key={index}>
|
||||||
{menus.map((menu) => (
|
{menus.map((menu) => (
|
||||||
<li onClick={(e) => setCurrentContextMenu(menu)}>{menu.name}</li>
|
<li key={menu.id} onClick={(e) => handleClick(e, menu)}>
|
||||||
|
{menu.name}
|
||||||
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
))}
|
))}
|
||||||
</QContextMenu>
|
</QContextMenu>
|
||||||
{currentContextMenu?.component}
|
{[
|
||||||
|
MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING,
|
||||||
|
MENU.MODULE_CIRCUIT_SETTING.CIRCUIT_TRESTLE_SETTING,
|
||||||
|
MENU.MODULE_CIRCUIT_SETTING.PLAN_ORIENTATION,
|
||||||
|
].includes(currentMenu) && <PanelBatchStatistics />}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,22 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useContext, useEffect, useState } from 'react'
|
import { useContext, useEffect, useState } from 'react'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import CanvasFrame from './CanvasFrame'
|
import CanvasFrame from './CanvasFrame'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import { usePlan } from '@/hooks/usePlan'
|
import { usePlan } from '@/hooks/usePlan'
|
||||||
|
import { modifiedPlansState } from '@/store/canvasAtom'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
import { sessionStore } from '@/store/commonAtom'
|
|
||||||
import { SessionContext } from '@/app/SessionProvider'
|
import { SessionContext } from '@/app/SessionProvider'
|
||||||
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
|
|
||||||
export default function CanvasLayout() {
|
export default function CanvasLayout({ children }) {
|
||||||
|
// const { menuNumber } = props
|
||||||
|
const { menuNumber } = useCanvasMenu()
|
||||||
const { session } = useContext(SessionContext)
|
const { session } = useContext(SessionContext)
|
||||||
console.log('session >>> ', session)
|
|
||||||
const [objectNo, setObjectNo] = useState('test123240822001') // 이후 삭제 필요
|
const [objectNo, setObjectNo] = useState('test123240822001') // 이후 삭제 필요
|
||||||
const sessionState = useRecoilValue(sessionStore)
|
const [modifiedPlans, setModifiedPlans] = useRecoilState(modifiedPlansState) // 변경된 canvas plan
|
||||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||||
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
@ -22,21 +24,23 @@ export default function CanvasLayout() {
|
|||||||
const { plans, loadCanvasPlanData, handleCurrentPlan, handleAddPlan, handleDeletePlan } = usePlan()
|
const { plans, loadCanvasPlanData, handleCurrentPlan, handleAddPlan, handleDeletePlan } = usePlan()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('loadCanvasPlanData 실행, sessionState.userId >>> ', sessionState.userId)
|
loadCanvasPlanData(session.userId, objectNo)
|
||||||
loadCanvasPlanData(sessionState.userId, objectNo)
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="canvas-layout">
|
<div className="canvas-layout">
|
||||||
<div className="canvas-page-list">
|
<div className={`canvas-page-list ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
||||||
<div className="canvas-plane-wrap">
|
<div className="canvas-plane-wrap">
|
||||||
{plans.map((plan) => (
|
{plans.map((plan) => (
|
||||||
<button
|
<button
|
||||||
key={`plan-${plan.id}`}
|
key={`plan-${plan.id}`}
|
||||||
className={`canvas-page-box ${plan.isCurrent === true ? 'on' : ''}`}
|
className={`canvas-page-box ${plan.isCurrent === true ? 'on' : ''}`}
|
||||||
onClick={() => handleCurrentPlan(sessionState.userId, plan.id)}
|
onClick={() => handleCurrentPlan(session.userId, plan.id)}
|
||||||
>
|
>
|
||||||
<span>{plan.name}</span>
|
<span>
|
||||||
|
{plan.name}
|
||||||
|
{modifiedPlans.some((modifiedPlan) => modifiedPlan === plan.id) && ' [ M ]'}
|
||||||
|
</span>
|
||||||
<i
|
<i
|
||||||
className="close"
|
className="close"
|
||||||
onClick={(e) =>
|
onClick={(e) =>
|
||||||
@ -53,12 +57,12 @@ export default function CanvasLayout() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
{plans.length < 10 && (
|
{plans.length < 10 && (
|
||||||
<button className="plane-add" onClick={() => handleAddPlan(sessionState.userId, objectNo)}>
|
<button className="plane-add" onClick={() => handleAddPlan(session.userId, objectNo)}>
|
||||||
<span></span>
|
<span></span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<CanvasFrame plan={plans.find((plan) => plan.isCurrent === true)} />
|
{children}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,75 +4,77 @@ import { useEffect, useState } from 'react'
|
|||||||
|
|
||||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
||||||
|
|
||||||
|
import { usePathname, useRouter } from 'next/navigation'
|
||||||
import MenuDepth01 from './MenuDepth01'
|
import MenuDepth01 from './MenuDepth01'
|
||||||
import QSelectBox from '@/components/common/select/QSelectBox'
|
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { usePlan } from '@/hooks/usePlan'
|
import { usePlan } from '@/hooks/usePlan'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import { canvasState, canvasZoomState, currentCanvasPlanState, currentMenuState, verticalHorizontalModeState } from '@/store/canvasAtom'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
|
import {
|
||||||
|
canvasSettingState,
|
||||||
|
canvasState,
|
||||||
|
canvasZoomState,
|
||||||
|
currentCanvasPlanState,
|
||||||
|
currentMenuState,
|
||||||
|
verticalHorizontalModeState,
|
||||||
|
} from '@/store/canvasAtom'
|
||||||
import { sessionStore } from '@/store/commonAtom'
|
import { sessionStore } from '@/store/commonAtom'
|
||||||
import { outerLinePointsState } from '@/store/outerLineAtom'
|
import { outerLinePointsState } from '@/store/outerLineAtom'
|
||||||
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
|
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
|
||||||
import { MENU } from '@/common/common'
|
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
||||||
|
|
||||||
import KO from '@/locales/ko.json'
|
import KO from '@/locales/ko.json'
|
||||||
import JA from '@/locales/ja.json'
|
import JA from '@/locales/ja.json'
|
||||||
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
import { useCanvasEvent } from '@/hooks/useCanvasEvent'
|
||||||
|
import SettingModal01 from '@/components/floor-plan/modal/setting01/SettingModal01'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom'
|
import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom'
|
||||||
|
import PlacementShapeSetting from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
|
||||||
const canvasMenus = [
|
import { useCommonUtils } from '@/hooks/common/useCommonUtils'
|
||||||
{ index: 0, name: 'plan.menu.plan.drawing', icon: 'con00', title: MENU.PLAN_DRAWING },
|
import { menusState, menuTypeState } from '@/store/menuAtom'
|
||||||
{ index: 1, name: 'plan.menu.placement.surface.initial.setting', icon: 'con01', title: MENU.INITIAL_CANVAS_SETTING },
|
import useMenu from '@/hooks/common/useMenu'
|
||||||
{ index: 2, name: 'plan.menu.roof.cover', icon: 'con02', title: MENU.ROOF_COVERING.DEFAULT },
|
import { MENU } from '@/common/common'
|
||||||
{ index: 3, name: 'plan.menu.placement.surface', icon: 'con03', title: MENU.BATCH_CANVAS.DEFAULT },
|
|
||||||
{ index: 4, name: 'plan.menu.module.circuit.setting', icon: 'con04', title: MENU.MODULE_CIRCUIT_SETTING.DEFAULT },
|
|
||||||
{ index: 5, name: 'plan.menu.estimate', icon: 'con06', title: MENU.ESTIMATE.DEFAULT },
|
|
||||||
{ index: 6, name: 'plan.menu.simulation', icon: 'con05', title: MENU.POWER_GENERATION_SIMULATION.DEFAULT },
|
|
||||||
]
|
|
||||||
|
|
||||||
export default function CanvasMenu(props) {
|
export default function CanvasMenu(props) {
|
||||||
const {
|
const { menuNumber, setMenuNumber } = props
|
||||||
setShowCanvasSettingModal,
|
const pathname = usePathname()
|
||||||
showOutlineModal,
|
const router = useRouter()
|
||||||
setShowOutlineModal,
|
const { addPopup } = usePopup()
|
||||||
setShowPlaceShapeModal,
|
const canvasMenus = useRecoilValue(menusState)
|
||||||
setShowSlopeSettingModal,
|
const [type, setType] = useRecoilState(menuTypeState)
|
||||||
setShowPlacementSurfaceSettingModal,
|
|
||||||
setShowPlaceShapeDrawingModal,
|
|
||||||
setShowRoofShapeSettingModal,
|
|
||||||
setShowObjectSettingModal,
|
|
||||||
setShowRoofShapePassivitySettingModal,
|
|
||||||
setShowAuxiliaryModal,
|
|
||||||
setShowEavesGableEditModal,
|
|
||||||
setShowMovementModal,
|
|
||||||
setShowWallLineOffsetSettingModal,
|
|
||||||
setShowRoofAllocationSettingModal,
|
|
||||||
setShowBasicSettingModal,
|
|
||||||
setShowCircuitTrestleSettingModal,
|
|
||||||
setShowPropertiesSettingModal,
|
|
||||||
} = props
|
|
||||||
|
|
||||||
const [menuNumber, setMenuNumber] = useState(null)
|
|
||||||
const [type, setType] = useState('')
|
|
||||||
|
|
||||||
const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
|
const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
|
||||||
const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
|
const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
|
||||||
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
||||||
const setOuterLinePoints = useSetRecoilState(outerLinePointsState)
|
const setOuterLinePoints = useSetRecoilState(outerLinePointsState)
|
||||||
const setPlacementPoints = useSetRecoilState(placementShapeDrawingPointsState)
|
const setPlacementPoints = useSetRecoilState(placementShapeDrawingPointsState)
|
||||||
|
const canvasSetting = useRecoilValue(canvasSettingState)
|
||||||
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
|
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
|
||||||
const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
|
const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
|
||||||
|
const sessionState = useRecoilValue(sessionStore)
|
||||||
const globalLocale = useRecoilValue(globalLocaleStore)
|
const globalLocale = useRecoilValue(globalLocaleStore)
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const sessionState = useRecoilValue(sessionStore)
|
const { handleZoomClear } = useCanvasEvent()
|
||||||
|
const { handleMenu } = useMenu()
|
||||||
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { saveCanvas } = usePlan()
|
const { saveCanvas } = usePlan()
|
||||||
const { swalFire } = useSwal()
|
const { swalFire } = useSwal()
|
||||||
|
const { initEvent, addCanvasMouseEventListener, addDocumentEventListener } = useEvent()
|
||||||
|
|
||||||
|
const [commonFunctionState, setCommonFunctionState] = useState({
|
||||||
|
text: false,
|
||||||
|
dimension: false,
|
||||||
|
distance: false,
|
||||||
|
})
|
||||||
|
const { commonFunctions } = useCommonUtils({
|
||||||
|
commonFunctionState,
|
||||||
|
setCommonFunctionState,
|
||||||
|
})
|
||||||
|
|
||||||
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
|
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
|
||||||
|
|
||||||
const onClickNav = (menu) => {
|
const onClickNav = (menu) => {
|
||||||
setMenuNumber(menu.index)
|
setMenuNumber(menu.index)
|
||||||
setCurrentMenu(menu.title)
|
setCurrentMenu(menu.title)
|
||||||
@ -92,25 +94,8 @@ export default function CanvasMenu(props) {
|
|||||||
setType('module')
|
setType('module')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
|
||||||
const menuProps = {
|
if (pathname !== '/floor-plan') router.push('/floor-plan')
|
||||||
setShowOutlineModal,
|
|
||||||
setShowPlaceShapeModal,
|
|
||||||
setShowRoofShapeSettingModal,
|
|
||||||
setShowRoofShapePassivitySettingModal,
|
|
||||||
setShowAuxiliaryModal,
|
|
||||||
setShowEavesGableEditModal,
|
|
||||||
setShowMovementModal,
|
|
||||||
setShowSlopeSettingModal,
|
|
||||||
setShowPlacementSurfaceSettingModal,
|
|
||||||
setShowPlaceShapeDrawingModal,
|
|
||||||
setShowWallLineOffsetSettingModal,
|
|
||||||
setShowRoofAllocationSettingModal,
|
|
||||||
setShowObjectSettingModal,
|
|
||||||
setShowBasicSettingModal,
|
|
||||||
setShowCircuitTrestleSettingModal,
|
|
||||||
setShowPropertiesSettingModal,
|
|
||||||
type,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const settingsModalOptions = useRecoilState(settingModalFirstOptionsState)
|
const settingsModalOptions = useRecoilState(settingModalFirstOptionsState)
|
||||||
@ -119,7 +104,6 @@ export default function CanvasMenu(props) {
|
|||||||
if (menuNumber === 1) {
|
if (menuNumber === 1) {
|
||||||
onClickPlacementInitialMenu()
|
onClickPlacementInitialMenu()
|
||||||
}
|
}
|
||||||
if (menuNumber !== 2 && showOutlineModal) setShowOutlineModal(false)
|
|
||||||
}, [menuNumber, type])
|
}, [menuNumber, type])
|
||||||
|
|
||||||
// 저장버튼(btn08) 클릭 시 호출되는 함수
|
// 저장버튼(btn08) 클릭 시 호출되는 함수
|
||||||
@ -133,12 +117,16 @@ export default function CanvasMenu(props) {
|
|||||||
// })
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [placementInitialId, setPlacementInitialId] = useState(uuidv4())
|
||||||
|
const placementInitialProps = {
|
||||||
|
id: placementInitialId,
|
||||||
|
pos: {
|
||||||
|
x: 50,
|
||||||
|
y: 180,
|
||||||
|
},
|
||||||
|
}
|
||||||
const onClickPlacementInitialMenu = () => {
|
const onClickPlacementInitialMenu = () => {
|
||||||
setShowOutlineModal(false)
|
addPopup(placementInitialId, 1, <PlacementShapeSetting {...placementInitialProps} />)
|
||||||
setShowCanvasSettingModal(false)
|
|
||||||
setShowEavesGableEditModal(false)
|
|
||||||
setShowMovementModal(false)
|
|
||||||
setShowPlaceShapeModal(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
@ -146,12 +134,17 @@ export default function CanvasMenu(props) {
|
|||||||
setPlacementPoints([])
|
setPlacementPoints([])
|
||||||
canvas?.clear()
|
canvas?.clear()
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// const handleZoomClear = () => {
|
||||||
|
// setCanvasZoom(100)
|
||||||
|
// canvas.set({ zoom: 1 })
|
||||||
|
// canvas.viewportTransform = [1, 0, 0, 1, 0, 0]
|
||||||
|
// canvas.renderAll()
|
||||||
|
// }
|
||||||
|
|
||||||
const handleZoomClear = () => {
|
const handlePopup = () => {
|
||||||
setCanvasZoom(100)
|
const id = uuidv4()
|
||||||
canvas.set({ zoom: 1 })
|
addPopup(id, 0, <SettingModal01 id={id} />)
|
||||||
canvas.viewportTransform = [1, 0, 0, 1, 0, 0]
|
|
||||||
canvas.renderAll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -160,7 +153,19 @@ export default function CanvasMenu(props) {
|
|||||||
} else {
|
} else {
|
||||||
setAppMessageState(JA)
|
setAppMessageState(JA)
|
||||||
}
|
}
|
||||||
}, [menuNumber, type, globalLocale])
|
}, [type, globalLocale])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (['2', '3'].includes(canvasSetting?.roofSizeSet?.toString())) {
|
||||||
|
setMenuNumber(3)
|
||||||
|
setType('surface')
|
||||||
|
setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
|
||||||
|
} else {
|
||||||
|
setMenuNumber(2)
|
||||||
|
setType('outline')
|
||||||
|
setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
||||||
|
}
|
||||||
|
}, [canvasSetting])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`canvas-menu-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
<div className={`canvas-menu-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
||||||
@ -171,9 +176,12 @@ export default function CanvasMenu(props) {
|
|||||||
<li
|
<li
|
||||||
key={`canvas-menu-${menu.index}`}
|
key={`canvas-menu-${menu.index}`}
|
||||||
className={`canvas-menu-item ${menuNumber === menu.index ? 'active' : ''}`}
|
className={`canvas-menu-item ${menuNumber === menu.index ? 'active' : ''}`}
|
||||||
onClick={() => onClickNav(menu)}
|
onClick={() => {
|
||||||
|
if (['2', '3'].includes(canvasSetting?.roofSizeSet?.toString()) && menu.index === 2) return
|
||||||
|
onClickNav(menu)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<button>
|
<button className={['2', '3'].includes(canvasSetting?.roofSizeSet?.toString()) && menu.index === 2 ? 'no-click' : ''}>
|
||||||
<span className={`menu-icon ${menu.icon}`}></span>
|
<span className={`menu-icon ${menu.icon}`}></span>
|
||||||
{getMessage(menu.name)}
|
{getMessage(menu.name)}
|
||||||
</button>
|
</button>
|
||||||
@ -191,15 +199,16 @@ export default function CanvasMenu(props) {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div className="btn-from">
|
<div className="btn-from">
|
||||||
<button className="btn01" onClick={() => {}}></button>
|
<button className={`btn01 ${commonFunctionState.text ? 'active' : ''}`} onClick={() => commonFunctions('text')}></button>
|
||||||
<button className="btn02 active"></button>
|
<button className={`btn02 ${commonFunctionState.dimension ? 'active' : ''} `} onClick={() => commonFunctions('dimension')}></button>
|
||||||
<button className="btn03 "></button>
|
<button className={`btn03 ${commonFunctionState.distance ? 'active' : ''} `} onClick={() => commonFunctions('distance')}></button>
|
||||||
</div>
|
</div>
|
||||||
<div className="select-box">
|
<div className="select-box">
|
||||||
<QSelectBox title={'瓦53A'} option={SelectOption} />
|
<QSelectBox title={'瓦53A'} option={SelectOption} />
|
||||||
</div>
|
</div>
|
||||||
<div className="btn-from">
|
<div className="btn-from">
|
||||||
<button className="btn04" onClick={() => setShowCanvasSettingModal(true)}></button>
|
{/*<button className="btn04" onClick={() => setShowCanvasSettingModal(true)}></button>*/}
|
||||||
|
<button className="btn04" onClick={handlePopup}></button>
|
||||||
<button className="btn05"></button>
|
<button className="btn05"></button>
|
||||||
<button className="btn06"></button>
|
<button className="btn06"></button>
|
||||||
</div>
|
</div>
|
||||||
@ -260,7 +269,7 @@ export default function CanvasMenu(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={`canvas-depth2-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
<div className={`canvas-depth2-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
||||||
{(menuNumber === 2 || menuNumber === 3 || menuNumber === 4) && <MenuDepth01 {...menuProps} />}
|
{(menuNumber === 2 || menuNumber === 3 || menuNumber === 4) && <MenuDepth01 />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -2,168 +2,39 @@
|
|||||||
|
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
|
||||||
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
|
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
|
||||||
import '@/styles/contents.scss'
|
|
||||||
import CanvasMenu from '@/components/floor-plan/CanvasMenu'
|
import CanvasMenu from '@/components/floor-plan/CanvasMenu'
|
||||||
import SettingModal01 from '@/components/floor-plan/modal/setting01/SettingModal01'
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
import CanvasLayout from '@/components/floor-plan/CanvasLayout'
|
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
|
||||||
import DotLineGrid from '@/components/floor-plan/modal/grid/DotLineGrid'
|
import '@/styles/contents.scss'
|
||||||
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'
|
|
||||||
|
|
||||||
import AuxiliaryDrawing from '@/components/floor-plan/modal/auxiliary/AuxiliaryDrawing'
|
|
||||||
import EavesGableEdit from '@/components/floor-plan/modal/eavesGable/EavesGableEdit'
|
|
||||||
import WallLineOffsetSetting from '@/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting'
|
|
||||||
import ObjectSetting from '@/components/floor-plan/modal/object/ObjectSetting'
|
|
||||||
import PlacementSurfaceSetting from '@/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting'
|
|
||||||
import RoofShapePassivitySetting from '@/components/floor-plan/modal/roofShape/RoofShapePassivitySetting'
|
|
||||||
import MovementSetting from '@/components/floor-plan/modal/movement/MovementSetting'
|
|
||||||
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'
|
|
||||||
|
|
||||||
export default function FloorPlan() {
|
|
||||||
const [showCanvasSettingModal, setShowCanvasSettingModal] = useState(false)
|
|
||||||
const [showOutlineModal, setShowOutlineModal] = useState(false)
|
|
||||||
const [showPlaceShapeModal, setShowPlaceShapeModal] = useState(false)
|
|
||||||
const [showPropertiesSettingModal, setShowPropertiesSettingModal] = useState(false)
|
|
||||||
const [showRoofShapeSettingModal, setShowRoofShapeSettingModal] = useState(false)
|
|
||||||
const [showRoofShapePassivitySettingModal, setShowRoofShapePassivitySettingModal] = useState(false)
|
|
||||||
const [showAuxiliaryModal, setShowAuxiliaryModal] = useState(false)
|
|
||||||
const [showSlopeSettingModal, setShowSlopeSettingModal] = useState(false)
|
|
||||||
const [showPlacementSurfaceSettingModal, setShowPlacementSurfaceSettingModal] = useState(false)
|
|
||||||
const [showPlaceShapeDrawingModal, setShowPlaceShapeDrawingModal] = useState(false)
|
|
||||||
const [showObjectSettingModal, setShowObjectSettingModal] = useState(false)
|
|
||||||
const [showEavesGableEditModal, setShowEavesGableEditModal] = useState(false)
|
|
||||||
const [showMovementModal, setShowMovementModal] = useState(false)
|
|
||||||
const [showWallLineOffsetSettingModal, setShowWallLineOffsetSettingModal] = useState(false)
|
|
||||||
const [showRoofAllocationSettingModal, setShowRoofAllocationSettingModal] = useState(false)
|
|
||||||
const [showBasicSettingModal, setShowBasicSettingModal] = useState(false)
|
|
||||||
const [showCircuitTrestleSettingModal, setShowCircuitTrestleSettingModal] = useState(false)
|
|
||||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
|
||||||
const { get } = useAxios(globalLocaleState)
|
|
||||||
|
|
||||||
|
export default function FloorPlan({ children }) {
|
||||||
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
|
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
|
||||||
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
|
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
|
||||||
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||||
|
|
||||||
const [showDotLineGridModal, setShowDotLineGridModal] = useState(false)
|
const { menuNumber, setMenuNumber } = useCanvasMenu()
|
||||||
const [showGridCopyModal, setShowGridCopyModal] = useState(false)
|
|
||||||
const [showGridMoveModal, setShowGridMoveModal] = useState(false)
|
|
||||||
const [showColorPickerModal, setShowColorPickerModal] = useState(false)
|
|
||||||
const canvasSettingProps = {
|
|
||||||
setShowCanvasSettingModal,
|
|
||||||
setShowDotLineGridModal,
|
|
||||||
setShowColorPickerModal,
|
|
||||||
}
|
|
||||||
|
|
||||||
const outlineProps = {
|
const { fetchSettings } = useCanvasSetting()
|
||||||
setShowOutlineModal,
|
|
||||||
setShowPropertiesSettingModal,
|
|
||||||
}
|
|
||||||
|
|
||||||
const modalProps = {
|
const modalProps = {
|
||||||
setShowCanvasSettingModal,
|
menuNumber,
|
||||||
showOutlineModal,
|
setMenuNumber,
|
||||||
setShowOutlineModal,
|
|
||||||
setShowPlaceShapeModal,
|
|
||||||
setShowSlopeSettingModal,
|
|
||||||
setShowPlacementSurfaceSettingModal,
|
|
||||||
setShowPlaceShapeDrawingModal,
|
|
||||||
setShowRoofShapeSettingModal,
|
|
||||||
setShowObjectSettingModal,
|
|
||||||
setShowRoofShapePassivitySettingModal,
|
|
||||||
setShowAuxiliaryModal,
|
|
||||||
setShowEavesGableEditModal,
|
|
||||||
setShowMovementModal,
|
|
||||||
setShowWallLineOffsetSettingModal,
|
|
||||||
setShowRoofAllocationSettingModal,
|
|
||||||
setShowBasicSettingModal,
|
|
||||||
setShowCircuitTrestleSettingModal,
|
|
||||||
setShowPropertiesSettingModal,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('FloorPlan useEffect 실행')
|
|
||||||
fetchSettings()
|
fetchSettings()
|
||||||
}, [showOutlineModal, objectNo])
|
}, [objectNo])
|
||||||
|
|
||||||
// Canvas Setting 조회
|
useEffect(() => {
|
||||||
const fetchSettings = async () => {
|
setMenuNumber(1)
|
||||||
try {
|
}, [])
|
||||||
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 optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
|
|
||||||
const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
|
|
||||||
const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({
|
|
||||||
...item,
|
|
||||||
}))
|
|
||||||
// 데이터 설정
|
|
||||||
setSettingModalFirstOptions({
|
|
||||||
option1: optionData1,
|
|
||||||
option2: optionData2,
|
|
||||||
dimensionDisplay: optionData5,
|
|
||||||
})
|
|
||||||
setSettingModalSecondOptions({
|
|
||||||
option3: optionData3,
|
|
||||||
option4: optionData4,
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Data fetching error:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const dotLineProps = {
|
|
||||||
showDotLineGridModal,
|
|
||||||
setShowDotLineGridModal,
|
|
||||||
}
|
|
||||||
|
|
||||||
const gridColorProps = {
|
|
||||||
setShowColorPickerModal,
|
|
||||||
}
|
|
||||||
|
|
||||||
const propertiesSettingProps = {
|
|
||||||
setShowPropertiesSettingModal,
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {}, [showOutlineModal])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="canvas-wrap">
|
<div className="canvas-wrap">
|
||||||
<CanvasMenu {...modalProps} />
|
<CanvasMenu {...modalProps} />
|
||||||
<div className="canvas-content">
|
<div className={`canvas-content ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>{children}</div>
|
||||||
<CanvasLayout />
|
|
||||||
{showCanvasSettingModal && <SettingModal01 {...canvasSettingProps} />}
|
|
||||||
{showOutlineModal && <WallLineSetting {...outlineProps} />}
|
|
||||||
{showDotLineGridModal && <DotLineGrid {...dotLineProps} />}
|
|
||||||
{showColorPickerModal && <GridColorSetting {...gridColorProps} />}
|
|
||||||
{showPropertiesSettingModal && <PropertiesSetting {...propertiesSettingProps} />}
|
|
||||||
|
|
||||||
{showPlaceShapeModal && <PlacementShapeSetting setShowPlaceShapeModal={setShowPlaceShapeModal} />}
|
|
||||||
{showRoofShapeSettingModal && <RoofShapeSetting setShowRoofShapeSettingModal={setShowRoofShapeSettingModal} />}
|
|
||||||
{showRoofShapePassivitySettingModal && (
|
|
||||||
<RoofShapePassivitySetting setShowRoofShapePassivitySettingModal={setShowRoofShapePassivitySettingModal} />
|
|
||||||
)}
|
|
||||||
{showAuxiliaryModal && <AuxiliaryDrawing setShowAuxiliaryModal={setShowAuxiliaryModal} />}
|
|
||||||
{showSlopeSettingModal && <Slope setShowSlopeSettingModal={setShowSlopeSettingModal} />}
|
|
||||||
{showPlaceShapeDrawingModal && <PlacementShapeDrawing setShowPlaceShapeDrawingModal={setShowPlaceShapeDrawingModal} />}
|
|
||||||
{showEavesGableEditModal && <EavesGableEdit setShowEavesGableEditModal={setShowEavesGableEditModal} />}
|
|
||||||
{showMovementModal && <MovementSetting setShowMovementModal={setShowMovementModal} />}
|
|
||||||
{showRoofAllocationSettingModal && <RoofAllocationSetting setShowRoofAllocationSettingModal={setShowRoofAllocationSettingModal} />}
|
|
||||||
{showWallLineOffsetSettingModal && <WallLineOffsetSetting setShowWallLineOffsetSettingModal={setShowWallLineOffsetSettingModal} />}
|
|
||||||
{showObjectSettingModal && <ObjectSetting setShowObjectSettingModal={setShowObjectSettingModal} />}
|
|
||||||
{showPlacementSurfaceSettingModal && <PlacementSurfaceSetting setShowPlacementSurfaceSettingModal={setShowPlacementSurfaceSettingModal} />}
|
|
||||||
{showBasicSettingModal && <BasicSetting setShowBasicSettingModal={setShowBasicSettingModal} />}
|
|
||||||
{showCircuitTrestleSettingModal && <CircuitTrestleSetting setShowCircuitTrestleSettingModal={setShowCircuitTrestleSettingModal} />}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,143 +1,32 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useEffect, useState } from 'react'
|
|
||||||
import { MENU } from '@/common/common'
|
|
||||||
import { currentMenuState } from '@/store/canvasAtom'
|
import { currentMenuState } from '@/store/canvasAtom'
|
||||||
import { useSetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
import { menuTypeState, subMenusState } from '@/store/menuAtom'
|
||||||
export default function MenuDepth01(props) {
|
import useMenu from '@/hooks/common/useMenu'
|
||||||
const {
|
import { useEffect } from 'react'
|
||||||
setShowOutlineModal,
|
|
||||||
type,
|
export default function MenuDepth01() {
|
||||||
setShowPlaceShapeModal,
|
const type = useRecoilValue(menuTypeState)
|
||||||
setShowRoofShapeSettingModal,
|
|
||||||
setShowRoofShapePassivitySettingModal,
|
|
||||||
setShowAuxiliaryModal,
|
|
||||||
setShowEavesGableEditModal,
|
|
||||||
setShowMovementModal,
|
|
||||||
setShowSlopeSettingModal,
|
|
||||||
setShowPlacementSurfaceSettingModal,
|
|
||||||
setShowPlaceShapeDrawingModal,
|
|
||||||
setShowWallLineOffsetSettingModal,
|
|
||||||
setShowRoofAllocationSettingModal,
|
|
||||||
setShowObjectSettingModal,
|
|
||||||
setShowBasicSettingModal,
|
|
||||||
setShowCircuitTrestleSettingModal,
|
|
||||||
setShowPropertiesSettingModal,
|
|
||||||
} = props
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [activeMenu, setActiveMenu] = useState()
|
const { handleMenu } = useMenu()
|
||||||
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
const [currentMenu, setCurrentMenu] = useRecoilState(currentMenuState)
|
||||||
|
const subMenus = useRecoilValue(subMenusState)
|
||||||
|
|
||||||
const { deleteAllSurfacesAndObjects } = useSurfaceShapeBatch()
|
const onClickMenu = ({ id, menu }) => {
|
||||||
|
|
||||||
const onClickMenu = ({ id, menu, name }) => {
|
|
||||||
setActiveMenu(menu)
|
|
||||||
setShowOutlineModal(menu === MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
|
||||||
setCurrentMenu(menu)
|
setCurrentMenu(menu)
|
||||||
setShowPlaceShapeModal(false)
|
|
||||||
if (type === 'outline') {
|
|
||||||
setShowOutlineModal(id === 0)
|
|
||||||
setShowRoofShapeSettingModal(id === 1)
|
|
||||||
setShowRoofShapePassivitySettingModal(id === 2)
|
|
||||||
setShowAuxiliaryModal(id === 3)
|
|
||||||
setShowEavesGableEditModal(id === 4)
|
|
||||||
setShowMovementModal(id === 5)
|
|
||||||
setShowWallLineOffsetSettingModal(id === 6)
|
|
||||||
setShowRoofAllocationSettingModal(id === 7)
|
|
||||||
setShowPlaceShapeDrawingModal(false)
|
|
||||||
setShowPropertiesSettingModal(false)
|
|
||||||
setShowCircuitTrestleSettingModal(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'surface') {
|
|
||||||
setShowOutlineModal(false)
|
|
||||||
setShowRoofShapeSettingModal(false)
|
|
||||||
setShowRoofShapePassivitySettingModal(false)
|
|
||||||
setShowAuxiliaryModal(false)
|
|
||||||
setShowEavesGableEditModal(false)
|
|
||||||
setShowMovementModal(false)
|
|
||||||
setShowWallLineOffsetSettingModal(false)
|
|
||||||
setShowRoofAllocationSettingModal(false)
|
|
||||||
setShowPropertiesSettingModal(false)
|
|
||||||
setShowCircuitTrestleSettingModal(false)
|
|
||||||
setShowSlopeSettingModal(id === 0)
|
|
||||||
setShowPlaceShapeDrawingModal(id === 1)
|
|
||||||
setShowPlacementSurfaceSettingModal(id === 2)
|
|
||||||
setShowObjectSettingModal(id === 3)
|
|
||||||
|
|
||||||
//배치면 전체 삭제
|
|
||||||
if (id === 4) {
|
|
||||||
deleteAllSurfacesAndObjects()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'module') {
|
|
||||||
setShowOutlineModal(false)
|
|
||||||
setShowRoofShapeSettingModal(false)
|
|
||||||
setShowRoofShapePassivitySettingModal(false)
|
|
||||||
setShowAuxiliaryModal(false)
|
|
||||||
setShowEavesGableEditModal(false)
|
|
||||||
setShowMovementModal(false)
|
|
||||||
setShowWallLineOffsetSettingModal(false)
|
|
||||||
setShowRoofAllocationSettingModal(false)
|
|
||||||
setShowPropertiesSettingModal(false)
|
|
||||||
setShowBasicSettingModal(id === 0)
|
|
||||||
setShowCircuitTrestleSettingModal(id === 1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setActiveMenu(null)
|
handleMenu(type)
|
||||||
}, [type])
|
}, [currentMenu])
|
||||||
|
|
||||||
const menuInfo = {
|
|
||||||
outline: [
|
|
||||||
// 지붕덮개
|
|
||||||
{ id: 0, name: 'plan.menu.roof.cover.outline.drawing', menu: MENU.ROOF_COVERING.EXTERIOR_WALL_LINE },
|
|
||||||
{ id: 1, name: 'plan.menu.roof.cover.roof.shape.setting', menu: MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS },
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'plan.menu.roof.cover.roof.shape.passivity.setting',
|
|
||||||
menu: MENU.ROOF_COVERING.ROOF_SHAPE_PASSIVITY_SETTINGS,
|
|
||||||
},
|
|
||||||
{ id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing', menu: MENU.ROOF_COVERING.HELP_LINE_DRAWING },
|
|
||||||
{ id: 4, name: 'plan.menu.roof.cover.eaves.kerava.edit', menu: MENU.ROOF_COVERING.EAVES_KERAVA_EDIT },
|
|
||||||
{ id: 5, name: 'plan.menu.roof.cover.movement.shape.updown', menu: MENU.ROOF_COVERING.MOVEMENT_SHAPE_UPDOWN },
|
|
||||||
{ id: 6, name: 'plan.menu.roof.cover.outline.edit.offset', menu: MENU.ROOF_COVERING.OUTLINE_EDIT_OFFSET },
|
|
||||||
{ id: 7, name: 'plan.menu.roof.cover.roof.surface.alloc', menu: MENU.ROOF_COVERING.ROOF_SHAPE_ALLOC },
|
|
||||||
],
|
|
||||||
surface: [
|
|
||||||
// 배치면
|
|
||||||
{ id: 0, name: 'plan.menu.placement.surface.slope.setting', menu: MENU.BATCH_CANVAS.SLOPE_SETTING },
|
|
||||||
{ id: 1, name: 'plan.menu.placement.surface.drawing', menu: MENU.BATCH_CANVAS.BATCH_DRAWING },
|
|
||||||
{ id: 2, name: 'plan.menu.placement.surface.arrangement', menu: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH },
|
|
||||||
{ id: 3, name: 'plan.menu.placement.surface.object', menu: MENU.BATCH_CANVAS.OBJECT_BATCH },
|
|
||||||
{ id: 4, name: 'plan.menu.placement.surface.all.remove', menu: MENU.BATCH_CANVAS.ALL_REMOVE },
|
|
||||||
],
|
|
||||||
module: [
|
|
||||||
// 모듈, 회로 구성
|
|
||||||
|
|
||||||
{ id: 0, name: 'plan.menu.module.circuit.setting.default', menu: MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING },
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'plan.menu.module.circuit.setting.circuit.trestle.setting',
|
|
||||||
menu: MENU.MODULE_CIRCUIT_SETTING.CIRCUIT_TRESTLE_SETTING,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'plan.menu.module.circuit.setting.plan.orientation',
|
|
||||||
menu: MENU.MODULE_CIRCUIT_SETTING.PLAN_ORIENTATION,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<div className="canvas-depth2-inner">
|
<div className="canvas-depth2-inner">
|
||||||
<ul className="canvas-depth2-list">
|
<ul className="canvas-depth2-list">
|
||||||
{menuInfo[type].map((menu) => {
|
{subMenus[type]?.map((menu) => {
|
||||||
return (
|
return (
|
||||||
<li key={menu.id} className={`canvas-depth2-item ${menu.menu === activeMenu ? 'active' : ''}`}>
|
<li key={menu.id} className={`canvas-depth2-item ${menu.menu === currentMenu ? 'active' : ''}`}>
|
||||||
<button onClick={() => onClickMenu(menu)}>{getMessage(menu.name)}</button>
|
<button onClick={() => onClickMenu(menu)}>{getMessage(menu.name)}</button>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,19 +1,23 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import { globalPitchState } from '@/store/canvasAtom'
|
import { globalPitchState, pitchSelector, pitchTextSelector } from '@/store/canvasAtom'
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState } from 'recoil'
|
||||||
import { useRef } from 'react'
|
import { useRef } from 'react'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
export default function Slope({ setShowSlopeSettingModal }) {
|
export default function Slope({ id, pos = { x: 50, y: 230 } }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [globalPitch, setGlobalPitch] = useRecoilState(globalPitchState)
|
const { closePopup } = usePopup()
|
||||||
|
const [globalPitch, setGlobalPitch] = useRecoilState(pitchSelector)
|
||||||
|
const pitchText = useRecoilState(pitchTextSelector)
|
||||||
const inputRef = useRef()
|
const inputRef = useRef()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xxxm`}>
|
<div className={`modal-pop-wrap xxxm`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('plan.menu.placement.surface.slope.setting')} </h1>
|
<h1 className="title">{getMessage('plan.menu.placement.surface.slope.setting')} </h1>
|
||||||
<button className="modal-close" onClick={() => setShowSlopeSettingModal(false)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -26,7 +30,7 @@ export default function Slope({ setShowSlopeSettingModal }) {
|
|||||||
<div className="input-grid mr5">
|
<div className="input-grid mr5">
|
||||||
<input type="text" className="input-origin block" defaultValue={globalPitch} ref={inputRef} />
|
<input type="text" className="input-origin block" defaultValue={globalPitch} ref={inputRef} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">{getMessage('size.angle')}</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
@ -34,7 +38,7 @@ export default function Slope({ setShowSlopeSettingModal }) {
|
|||||||
className="btn-frame modal act"
|
className="btn-frame modal act"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setGlobalPitch(inputRef.current.value)
|
setGlobalPitch(inputRef.current.value)
|
||||||
setShowSlopeSettingModal(false)
|
closePopup(id)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{getMessage('modal.common.save')}
|
{getMessage('modal.common.save')}
|
||||||
|
|||||||
55
src/components/floor-plan/modal/auxiliary/AuxiliaryCopy.jsx
Normal file
55
src/components/floor-plan/modal/auxiliary/AuxiliaryCopy.jsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
|
||||||
|
export default function AuxiliaryCopy(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition } = props
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap xm`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">補助線のコピー </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="grid-option-tit">コピーする方向を入力してください</div>
|
||||||
|
<div className="grid-option-wrap">
|
||||||
|
<div className="grid-option-box">
|
||||||
|
<div className="move-form">
|
||||||
|
<p className="mb5">長さ</p>
|
||||||
|
<div className="input-move-wrap mb5">
|
||||||
|
<div className="input-move">
|
||||||
|
<input type="text" className="input-origin" defaultValue={910} />
|
||||||
|
</div>
|
||||||
|
<span>mm</span>
|
||||||
|
</div>
|
||||||
|
<div className="input-move-wrap">
|
||||||
|
<div className="input-move">
|
||||||
|
<input type="text" className="input-origin" defaultValue={910} />
|
||||||
|
</div>
|
||||||
|
<span>mm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="direction-move-wrap">
|
||||||
|
<button className="direction up"></button>
|
||||||
|
<button className="direction down act"></button>
|
||||||
|
<button className="direction left"></button>
|
||||||
|
<button className="direction right"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act">保存</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,4 +1,3 @@
|
|||||||
import { useState } from 'react'
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import RightAngle from '@/components/floor-plan/modal/lineTypes/RightAngle'
|
import RightAngle from '@/components/floor-plan/modal/lineTypes/RightAngle'
|
||||||
@ -6,12 +5,13 @@ import DoublePitch from '@/components/floor-plan/modal/lineTypes/DoublePitch'
|
|||||||
import Angle from '@/components/floor-plan/modal/lineTypes/Angle'
|
import Angle from '@/components/floor-plan/modal/lineTypes/Angle'
|
||||||
import Diagonal from '@/components/floor-plan/modal/lineTypes/Diagonal'
|
import Diagonal from '@/components/floor-plan/modal/lineTypes/Diagonal'
|
||||||
import { OUTER_LINE_TYPE } from '@/store/outerLineAtom'
|
import { OUTER_LINE_TYPE } from '@/store/outerLineAtom'
|
||||||
import { useOuterLineWall } from '@/hooks/roofcover/useOuterLineWall'
|
|
||||||
import OuterLineWall from '@/components/floor-plan/modal/lineTypes/OuterLineWall'
|
import OuterLineWall from '@/components/floor-plan/modal/lineTypes/OuterLineWall'
|
||||||
import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing'
|
import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) {
|
export default function AuxiliaryDrawing({ id, pos = { x: 50, y: 230 } }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
const types = [
|
const types = [
|
||||||
{ id: 1, name: getMessage('straight.line'), type: OUTER_LINE_TYPE.OUTER_LINE },
|
{ id: 1, name: getMessage('straight.line'), type: OUTER_LINE_TYPE.OUTER_LINE },
|
||||||
@ -49,7 +49,7 @@ export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) {
|
|||||||
handleFix,
|
handleFix,
|
||||||
buttonAct,
|
buttonAct,
|
||||||
setButtonAct,
|
setButtonAct,
|
||||||
} = useAuxiliaryDrawing(setShowAuxiliaryModal)
|
} = useAuxiliaryDrawing(id)
|
||||||
|
|
||||||
const outerLineProps = {
|
const outerLineProps = {
|
||||||
length1,
|
length1,
|
||||||
@ -123,11 +123,11 @@ export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) {
|
|||||||
setType(button.type)
|
setType(button.type)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap r`}>
|
<div className={`modal-pop-wrap r`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('modal.auxiliary.drawing')}</h1>
|
<h1 className="title">{getMessage('modal.auxiliary.drawing')}</h1>
|
||||||
<button className="modal-close" onClick={() => setShowAuxiliaryModal(false)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -151,8 +151,8 @@ export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) {
|
|||||||
<button className="btn-frame modal mr5" onClick={handleRollback}>
|
<button className="btn-frame modal mr5" onClick={handleRollback}>
|
||||||
{getMessage('modal.cover.outline.rollback')}
|
{getMessage('modal.cover.outline.rollback')}
|
||||||
</button>
|
</button>
|
||||||
<button className="btn-frame modal act" onClick={() => handleFix(setShowAuxiliaryModal)}>
|
<button className="btn-frame modal act" onClick={() => handleFix(id)}>
|
||||||
{getMessage('modal.cover.outline.fix')}
|
{getMessage('apply')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,14 +1,22 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
export default function AuxiliaryMove({ setCurrentContextMenu }) {
|
export default function AuxiliaryMove(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 0, y: 150 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xm`}>
|
<div className={`modal-pop-wrap xm`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">補助線の移動 </h1>
|
<h1 className="title">補助線の移動 </h1>
|
||||||
<button className="modal-close" onClick={() => setCurrentContextMenu(null)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,14 +1,20 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
|
||||||
export default function AuxiliarySize({ setCurrentContextMenu }) {
|
export default function AuxiliarySize(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 0, y: 150 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xm`}>
|
<div className={`modal-pop-wrap xm`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">補助線サイズ変更 </h1>
|
<h1 className="title">補助線サイズ変更 </h1>
|
||||||
<button className="modal-close" onClick={() => setCurrentContextMenu(null)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -8,17 +8,19 @@ import PitchPlacement from '@/components/floor-plan/modal/basic/step/pitch/Pitch
|
|||||||
import Placement from '@/components/floor-plan/modal/basic/step/Placement'
|
import Placement from '@/components/floor-plan/modal/basic/step/Placement'
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState } from 'recoil'
|
||||||
import { canvasSettingState } from '@/store/canvasAtom'
|
import { canvasSettingState } from '@/store/canvasAtom'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
export default function BasicSetting({ setShowBasicSettingModal }) {
|
export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
const [tabNum, setTabNum] = useState(1)
|
const [tabNum, setTabNum] = useState(1)
|
||||||
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
|
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap lx-2`}>
|
<div className={`modal-pop-wrap lx-2`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('plan.menu.module.circuit.setting.default')}</h1>
|
<h1 className="title">{getMessage('plan.menu.module.circuit.setting.default')}</h1>
|
||||||
<button className="modal-close" onClick={() => setShowBasicSettingModal(false)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -6,6 +6,19 @@ export default function Orientation({ setTabNum }) {
|
|||||||
const [compasDeg, setCompasDeg] = useState(0)
|
const [compasDeg, setCompasDeg] = useState(0)
|
||||||
const [hasAnglePassivity, setHasAnglePassivity] = useState(false)
|
const [hasAnglePassivity, setHasAnglePassivity] = useState(false)
|
||||||
|
|
||||||
|
const getDegree = (degree) => {
|
||||||
|
if (degree % 15 === 0) return degree
|
||||||
|
|
||||||
|
let value = Math.floor(degree / 15)
|
||||||
|
const remain = ((degree / 15) % 1).toFixed(5)
|
||||||
|
|
||||||
|
if (remain > 0.4) {
|
||||||
|
value++
|
||||||
|
}
|
||||||
|
|
||||||
|
return value * 15
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="properties-setting-wrap">
|
<div className="properties-setting-wrap">
|
||||||
@ -18,7 +31,7 @@ export default function Orientation({ setTabNum }) {
|
|||||||
{Array.from({ length: 180 / 15 }).map((dot, index) => (
|
{Array.from({ length: 180 / 15 }).map((dot, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className={`circle ${compasDeg === 15 * (12 + index) ? 'act' : ''}`}
|
className={`circle ${getDegree(compasDeg) === 15 * (12 + index) ? 'act' : ''}`}
|
||||||
onClick={() => setCompasDeg(15 * (12 + index))}
|
onClick={() => setCompasDeg(15 * (12 + index))}
|
||||||
>
|
>
|
||||||
{index === 0 && <i>180°</i>}
|
{index === 0 && <i>180°</i>}
|
||||||
@ -26,13 +39,13 @@ export default function Orientation({ setTabNum }) {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{Array.from({ length: 180 / 15 }).map((dot, index) => (
|
{Array.from({ length: 180 / 15 }).map((dot, index) => (
|
||||||
<div key={index} className={`circle ${compasDeg === 15 * index ? 'act' : ''}`} onClick={() => setCompasDeg(15 * index)}>
|
<div key={index} className={`circle ${getDegree(compasDeg) === 15 * index ? 'act' : ''}`} onClick={() => setCompasDeg(15 * index)}>
|
||||||
{index === 0 && <i>0°</i>}
|
{index === 0 && <i>0°</i>}
|
||||||
{index === 6 && <i>90°</i>}
|
{index === 6 && <i>90°</i>}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<div className="compas">
|
<div className="compas">
|
||||||
<div className="compas-arr" style={{ transform: `rotate(${compasDeg}deg)` }}></div>
|
<div className="compas-arr" style={{ transform: `rotate(${getDegree(compasDeg)}deg)` }}></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,9 +4,11 @@ import PowerConditionalSelect from '@/components/floor-plan/modal/circuitTrestle
|
|||||||
import CircuitAllocation from '@/components/floor-plan/modal/circuitTrestle/step/CircuitAllocation'
|
import CircuitAllocation from '@/components/floor-plan/modal/circuitTrestle/step/CircuitAllocation'
|
||||||
import StepUp from '@/components/floor-plan/modal/circuitTrestle/step/StepUp'
|
import StepUp from '@/components/floor-plan/modal/circuitTrestle/step/StepUp'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
export default function CircuitTrestleSetting({ setShowCircuitTrestleSettingModal }) {
|
export default function CircuitTrestleSetting({ id }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
const [tabNum, setTabNum] = useState(1)
|
const [tabNum, setTabNum] = useState(1)
|
||||||
const [circuitAllocationType, setCircuitAllocationType] = useState(1)
|
const [circuitAllocationType, setCircuitAllocationType] = useState(1)
|
||||||
const circuitProps = {
|
const circuitProps = {
|
||||||
@ -14,11 +16,11 @@ export default function CircuitTrestleSetting({ setShowCircuitTrestleSettingModa
|
|||||||
setCircuitAllocationType,
|
setCircuitAllocationType,
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>
|
<WithDraggable isShow={true} pos={{ x: 50, y: 230 }}>
|
||||||
<div className={`modal-pop-wrap lx-2`}>
|
<div className={`modal-pop-wrap lx-2`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('modal.circuit.trestle.setting')} </h1>
|
<h1 className="title">{getMessage('modal.circuit.trestle.setting')} </h1>
|
||||||
<button className="modal-close" onClick={() => setShowCircuitTrestleSettingModal(false)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -0,0 +1,76 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||||
|
import { pitchTextSelector } from '@/store/canvasAtom'
|
||||||
|
|
||||||
|
export default function DimensionLineSetting(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, setIsShow, pos = contextPopupPosition } = props
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
const pitchText = useRecoilState(pitchTextSelector)
|
||||||
|
const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }]
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap xm`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">表示の変更 </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="guide">寸法線に表示する数値を入力してください</div>
|
||||||
|
<div className="mb-box">
|
||||||
|
<div className="slope-wrap">
|
||||||
|
<div className="outline-form mb15">
|
||||||
|
<span className="mr10">既存の長さ</span>
|
||||||
|
<div className="input-grid mr5">
|
||||||
|
<input type="text" className="input-origin block" defaultValue={5933} readOnly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-box">
|
||||||
|
<div className="outline-form">
|
||||||
|
<span className="mr10">変更の長さ</span>
|
||||||
|
<div className="input-grid mr5">
|
||||||
|
<input type="text" className="input-origin block" defaultValue={0} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="d-check-box pop">
|
||||||
|
<input type="checkbox" id="ch99" />
|
||||||
|
<label htmlFor="ch99">コーナー・ゴールの場合</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="slope-wrap">
|
||||||
|
<div className="warning">傾斜を着せてください。</div>
|
||||||
|
<div className="display-change-wrap">
|
||||||
|
<div className="outline-form mb15">
|
||||||
|
<span className="mr10">傾斜</span>
|
||||||
|
<div className="grid-select mr10">
|
||||||
|
<QSelectBox title={'0'} option={SelectOption01} />
|
||||||
|
</div>
|
||||||
|
<span className="thin">{pitchText}</span>
|
||||||
|
</div>
|
||||||
|
<div className="outline-form">
|
||||||
|
<span className="mr10">傾斜</span>
|
||||||
|
<div className="grid-select mr10">
|
||||||
|
<QSelectBox title={'0'} option={SelectOption01} />
|
||||||
|
</div>
|
||||||
|
<span className="thin">{pitchText}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="warning">傾き設定されている場合、入力した数値に傾き計算をした数値が表示されます。</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act">保存</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
67
src/components/floor-plan/modal/distance/Distance.jsx
Normal file
67
src/components/floor-plan/modal/distance/Distance.jsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/withDraggable'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
|
||||||
|
export default function Distance(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition, distance } = props
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap xxxm`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">距離測定 </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="slope-wrap">
|
||||||
|
<div className="eaves-keraba-table">
|
||||||
|
<div className="eaves-keraba-item">
|
||||||
|
<div className="eaves-keraba-th">2点間距離</div>
|
||||||
|
<div className="eaves-keraba-td">
|
||||||
|
<div className="outline-form">
|
||||||
|
<div className="input-grid mr5" style={{ width: '98px' }}>
|
||||||
|
<input type="text" className="input-origin block" defaultValue={0} value={distance.diagonal} readOnly />
|
||||||
|
</div>
|
||||||
|
<span className="thin">mm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="eaves-keraba-item">
|
||||||
|
<div className="eaves-keraba-th">水平距離</div>
|
||||||
|
<div className="eaves-keraba-td">
|
||||||
|
<div className="outline-form">
|
||||||
|
<div className="input-grid mr5" style={{ width: '98px' }}>
|
||||||
|
<input type="text" className="input-origin block" defaultValue={0} value={distance.horizon} readOnly />
|
||||||
|
</div>
|
||||||
|
<span className="thin">mm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="eaves-keraba-item">
|
||||||
|
<div className="eaves-keraba-th">垂直距離</div>
|
||||||
|
<div className="eaves-keraba-td">
|
||||||
|
<div className="outline-form">
|
||||||
|
<div className="input-grid mr5" style={{ width: '98px' }}>
|
||||||
|
<input type="text" className="input-origin block" defaultValue={0} value={distance.vertical} readOnly />
|
||||||
|
</div>
|
||||||
|
<span className="thin">mm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act">確認</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,21 +1,23 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import { useState } from 'react'
|
|
||||||
import Eaves from '@/components/floor-plan/modal/eavesGable/type/Eaves'
|
import Eaves from '@/components/floor-plan/modal/eavesGable/type/Eaves'
|
||||||
import Gable from '@/components/floor-plan/modal/eavesGable/type/Gable'
|
import Gable from '@/components/floor-plan/modal/eavesGable/type/Gable'
|
||||||
import WallMerge from '@/components/floor-plan/modal/eavesGable/type/WallMerge'
|
import WallMerge from '@/components/floor-plan/modal/eavesGable/type/WallMerge'
|
||||||
import Shed from '@/components/floor-plan/modal/eavesGable/type/Shed'
|
import Shed from '@/components/floor-plan/modal/eavesGable/type/Shed'
|
||||||
import { useEavesGableEdit } from '@/hooks/roofcover/useEavesGableEdit'
|
import { useEavesGableEdit } from '@/hooks/roofcover/useEavesGableEdit'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
export default function EavesGableEdit({ setShowEavesGableEditModal }) {
|
export default function EavesGableEdit({ id, pos = { x: 50, y: 230 } }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
const { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef } = useEavesGableEdit(setShowEavesGableEditModal)
|
const { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef, pitchText } = useEavesGableEdit(id)
|
||||||
const eavesProps = {
|
const eavesProps = {
|
||||||
pitchRef,
|
pitchRef,
|
||||||
offsetRef,
|
offsetRef,
|
||||||
widthRef,
|
widthRef,
|
||||||
radioTypeRef,
|
radioTypeRef,
|
||||||
|
pitchText,
|
||||||
}
|
}
|
||||||
|
|
||||||
const gableProps = {
|
const gableProps = {
|
||||||
@ -23,6 +25,7 @@ export default function EavesGableEdit({ setShowEavesGableEditModal }) {
|
|||||||
offsetRef,
|
offsetRef,
|
||||||
widthRef,
|
widthRef,
|
||||||
radioTypeRef,
|
radioTypeRef,
|
||||||
|
pitchText,
|
||||||
}
|
}
|
||||||
|
|
||||||
const wallMergeProps = {
|
const wallMergeProps = {
|
||||||
@ -35,11 +38,11 @@ export default function EavesGableEdit({ setShowEavesGableEditModal }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap r`}>
|
<div className={`modal-pop-wrap r`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('modal.eaves.gable.edit')}</h1>
|
<h1 className="title">{getMessage('modal.eaves.gable.edit')}</h1>
|
||||||
<button className="modal-close" onClick={() => setShowEavesGableEditModal(false)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom'
|
||||||
|
|
||||||
export default function Eaves({ pitchRef, offsetRef, widthRef, radioTypeRef }) {
|
export default function Eaves({ pitchRef, offsetRef, widthRef, radioTypeRef, pitchText }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [type, setType] = useState('1')
|
const [type, setType] = useState('1')
|
||||||
const onChange = (e) => {
|
const onChange = (e) => {
|
||||||
setType(e.target.value)
|
setType(e.target.value)
|
||||||
radioTypeRef.current = e.target.value
|
radioTypeRef.current = e.target.value
|
||||||
}
|
}
|
||||||
|
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="outline-wrap">
|
<div className="outline-wrap">
|
||||||
@ -17,9 +20,9 @@ export default function Eaves({ pitchRef, offsetRef, widthRef, radioTypeRef }) {
|
|||||||
{getMessage('slope')}
|
{getMessage('slope')}
|
||||||
</span>
|
</span>
|
||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="number" className="input-origin block" defaultValue={4} ref={pitchRef} />
|
<input type="number" className="input-origin block" defaultValue={currentAngleType === ANGLE_TYPE.SLOPE ? 4 : 21.8} ref={pitchRef} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">寸</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<span className="mr10" style={{ width: '24px' }}>
|
<span className="mr10" style={{ width: '24px' }}>
|
||||||
|
|||||||
@ -1,14 +1,18 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom'
|
||||||
|
|
||||||
export default function Gable({ pitchRef, offsetRef, widthRef, radioTypeRef }) {
|
export default function Gable({ pitchRef, offsetRef, widthRef, radioTypeRef, pitchText }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [type, setType] = useState('1')
|
const [type, setType] = useState('1')
|
||||||
const onChange = (e) => {
|
const onChange = (e) => {
|
||||||
setType(e.target.value)
|
setType(e.target.value)
|
||||||
radioTypeRef.current = e.target.value
|
radioTypeRef.current = e.target.value
|
||||||
}
|
}
|
||||||
|
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="outline-wrap">
|
<div className="outline-wrap">
|
||||||
@ -57,9 +61,15 @@ export default function Gable({ pitchRef, offsetRef, widthRef, radioTypeRef }) {
|
|||||||
{getMessage('slope')}
|
{getMessage('slope')}
|
||||||
</span>
|
</span>
|
||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="text" className="input-origin block" defaultValue={4.5} ref={pitchRef} readOnly={type === '1'} />
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
defaultValue={currentAngleType === ANGLE_TYPE.SLOPE ? 4.5 : 20}
|
||||||
|
ref={pitchRef}
|
||||||
|
readOnly={type === '1'}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">寸</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
|
|||||||
@ -0,0 +1,140 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/withDraggable'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
|
export default function FlowDirectionSetting(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition, target } = props
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
const [compasDeg, setCompasDeg] = useState(360)
|
||||||
|
const orientations = [
|
||||||
|
{ name: `${getMessage('commons.south')}`, value: 360 },
|
||||||
|
{ name: `${getMessage('commons.south')}${getMessage('commons.east')}`, value: 315 },
|
||||||
|
{ name: `${getMessage('commons.south')}${getMessage('commons.west')}`, value: 45 },
|
||||||
|
{ name: `${getMessage('commons.east')}`, value: 270 },
|
||||||
|
{ name: `${getMessage('commons.west')}`, value: 90 },
|
||||||
|
{ name: `${getMessage('commons.north')}${getMessage('commons.east')}`, value: 225 },
|
||||||
|
{ name: `${getMessage('commons.north')}${getMessage('commons.west')}`, value: 135 },
|
||||||
|
{ name: `${getMessage('commons.north')}`, value: 180 },
|
||||||
|
]
|
||||||
|
const [selectedOrientation, setSelectedOrientation] = useState(orientations[0])
|
||||||
|
const [type, setType] = useState('0')
|
||||||
|
useEffect(() => {
|
||||||
|
if (target?.angle === 0) {
|
||||||
|
setCompasDeg(360)
|
||||||
|
} else {
|
||||||
|
setCompasDeg(target?.angle ?? 360)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
useEffect(() => {
|
||||||
|
if (type === '0') {
|
||||||
|
setCompasDeg(selectedOrientation.value)
|
||||||
|
}
|
||||||
|
}, [selectedOrientation])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (type === '1') {
|
||||||
|
if ([15, 345, 360].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[0])
|
||||||
|
} else if ([30, 45, 60].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[2])
|
||||||
|
} else if ([75, 90, 105].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[4])
|
||||||
|
} else if ([120, 135, 150].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[6])
|
||||||
|
} else if ([165, 180, 195].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[7])
|
||||||
|
} else if ([210, 225, 240].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[5])
|
||||||
|
} else if ([255, 270, 285].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[3])
|
||||||
|
} else if ([300, 315, 330].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [compasDeg])
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap lx`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage('modal.shape.flow.direction.setting')} </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="drawing-flow-wrap">
|
||||||
|
<div className="discrimination-box">
|
||||||
|
<div className="discrimination-tit mb15">{getMessage('modal.flow.direction.setting')}</div>
|
||||||
|
<div className="guide">{getMessage('modal.flow.direction.setting.info')}</div>
|
||||||
|
<div className="object-direction-wrap">
|
||||||
|
<div className="plane-direction">
|
||||||
|
<span className="top">{getMessage('commons.north')}</span>
|
||||||
|
<button className="plane-btn up"></button>
|
||||||
|
<span className="right">{getMessage('commons.east')}</span>
|
||||||
|
<button className="plane-btn right"></button>
|
||||||
|
<span className="bottom">{getMessage('commons.south')}</span>
|
||||||
|
<button className="plane-btn down act"></button>
|
||||||
|
<span className="left">{getMessage('commons.west')}</span>
|
||||||
|
<button className="plane-btn left"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="discrimination-box">
|
||||||
|
<div className="discrimination-tit mb15">{getMessage('modal.module.basic.setting.orientation.setting')}</div>
|
||||||
|
<div className="guide">{getMessage('modal.shape.flow.direction.setting.orientation.setting.info')}</div>
|
||||||
|
<div className="mb-box">
|
||||||
|
<div className="d-check-radio pop mb15">
|
||||||
|
<input type="radio" name="radio01" id="ra01" value={0} checked={type === '0'} onChange={(e) => setType(e.target.value)} />
|
||||||
|
<label htmlFor="ra01">{getMessage('modal.shape.flow.direction.setting.orientation.8')}</label>
|
||||||
|
</div>
|
||||||
|
<div className="grid-select ">
|
||||||
|
<QSelectBox title={''} options={orientations} value={selectedOrientation} onChange={(e) => setSelectedOrientation(e)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-box">
|
||||||
|
<div className="d-check-radio pop">
|
||||||
|
<input type="radio" name="radio01" id="ra02" value={1} checked={type === '1'} onChange={(e) => setType(e.target.value)} />
|
||||||
|
<label htmlFor="ra02">{getMessage('modal.shape.flow.direction.setting.orientation.24')}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="compas-box">
|
||||||
|
<div className="compas-box-inner">
|
||||||
|
{Array.from({ length: 180 / 15 + 1 }).map((dot, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className={`circle ${compasDeg === 15 * (12 + index) ? 'act' : ''}`}
|
||||||
|
onClick={() => setCompasDeg(15 * (12 + index))}
|
||||||
|
>
|
||||||
|
<i>{13 - index}</i>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{Array.from({ length: 180 / 15 - 1 }).map((dot, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className={`circle ${compasDeg === 15 * (index + 1) ? 'act' : ''}`}
|
||||||
|
onClick={() => setCompasDeg(15 * (index + 1))}
|
||||||
|
>
|
||||||
|
<i>{24 - index}</i>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<div className="compas">
|
||||||
|
<div className="compas-arr" style={{ transform: `rotate(${compasDeg}deg)` }}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -7,31 +7,48 @@ import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState
|
|||||||
import { onlyNumberInputChange } from '@/util/input-utils'
|
import { onlyNumberInputChange } from '@/util/input-utils'
|
||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import { gridColorState } from '@/store/gridAtom'
|
import { gridColorState } from '@/store/gridAtom'
|
||||||
import { settingModalGridOptionsState } from '@/store/settingAtom'
|
import { gridDisplaySelector, settingModalGridOptionsState } from '@/store/settingAtom'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
const TYPE = {
|
const TYPE = {
|
||||||
DOT: 'DOT',
|
DOT: 'DOT',
|
||||||
LINE: 'LINE',
|
LINE: 'LINE',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultDotLineGridSetting = {
|
||||||
|
INTERVAL: {
|
||||||
|
type: 2, // 1: 가로,세로 간격 수동, 2: 비율 간격
|
||||||
|
ratioInterval: 910,
|
||||||
|
verticalInterval: 910,
|
||||||
|
horizontalInterval: 910,
|
||||||
|
dimension: 1, // 치수
|
||||||
|
},
|
||||||
|
DOT: false,
|
||||||
|
LINE: false,
|
||||||
|
}
|
||||||
|
|
||||||
export default function DotLineGrid(props) {
|
export default function DotLineGrid(props) {
|
||||||
// const [modalOption, setModalOption] = useRecoilState(modalState); //modal 열림닫힘 state
|
// const [modalOption, setModalOption] = useRecoilState(modalState); //modal 열림닫힘 state
|
||||||
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||||
const [close, setClose] = useState(false)
|
const [close, setClose] = useState(false)
|
||||||
const { setShowDotLineGridModal } = props
|
const { id, setIsShow, pos = { x: 840, y: -815 } } = props
|
||||||
const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState)
|
const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState)
|
||||||
const gridColor = useRecoilValue(gridColorState)
|
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
|
|
||||||
const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState)
|
const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState)
|
||||||
|
const [currentSetting, setCurrentSetting] = useState(
|
||||||
|
JSON.stringify(dotLineGridSetting) === JSON.stringify(defaultDotLineGridSetting) ? { ...defaultDotLineGridSetting } : { ...dotLineGridSetting },
|
||||||
|
)
|
||||||
const resetDotLineGridSetting = useResetRecoilState(dotLineGridSettingState)
|
const resetDotLineGridSetting = useResetRecoilState(dotLineGridSettingState)
|
||||||
const interval = useRecoilValue(dotLineIntervalSelector)
|
const interval = useRecoilValue(dotLineIntervalSelector)
|
||||||
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { get, post } = useAxios()
|
const { get, post } = useAxios()
|
||||||
const { swalFire } = useSwal()
|
const { swalFire } = useSwal()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
@ -54,7 +71,7 @@ export default function DotLineGrid(props) {
|
|||||||
// 데이터를 최초 한 번만 조회
|
// 데이터를 최초 한 번만 조회
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('DotLineGrid useEffect 실행')
|
console.log('DotLineGrid useEffect 실행')
|
||||||
fetchGridSettings()
|
// fetchGridSettings()
|
||||||
}, [objectNo])
|
}, [objectNo])
|
||||||
|
|
||||||
const HandleClickClose = () => {
|
const HandleClickClose = () => {
|
||||||
@ -67,7 +84,7 @@ export default function DotLineGrid(props) {
|
|||||||
|
|
||||||
const handleCheckBoxChange = (e) => {
|
const handleCheckBoxChange = (e) => {
|
||||||
const { value, checked } = e.target
|
const { value, checked } = e.target
|
||||||
setDotLineGridSettingState((prev) => {
|
setCurrentSetting((prev) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
[value]: checked,
|
[value]: checked,
|
||||||
@ -98,150 +115,34 @@ export default function DotLineGrid(props) {
|
|||||||
setSelectOption(matchedOption)
|
setSelectOption(matchedOption)
|
||||||
|
|
||||||
// 서버에서 받은 데이터로 상태 업데이트
|
// 서버에서 받은 데이터로 상태 업데이트
|
||||||
setDotLineGridSettingState(patternData)
|
setCurrentSetting(patternData)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Data fetching error:', error)
|
console.error('Data fetching error:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
|
if (!currentSetting.DOT && !currentSetting.LINE) {
|
||||||
|
swalFire({ text: '배치할 그리드를 설정해주세요.' })
|
||||||
|
return
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const patternData = {
|
const patternData = {
|
||||||
objectNo,
|
objectNo,
|
||||||
dotGridDisplay: dotLineGridSetting.DOT,
|
dotGridDisplay: currentSetting.DOT,
|
||||||
lineGridDisplay: dotLineGridSetting.LINE,
|
lineGridDisplay: currentSetting.LINE,
|
||||||
gridType: dotLineGridSetting.INTERVAL.type,
|
gridType: currentSetting.INTERVAL.type,
|
||||||
gridHorizon: dotLineGridSetting.INTERVAL.horizontalInterval,
|
gridHorizon: currentSetting.INTERVAL.horizontalInterval / 10,
|
||||||
gridVertical: dotLineGridSetting.INTERVAL.verticalInterval,
|
gridVertical: currentSetting.INTERVAL.verticalInterval / 10,
|
||||||
gridRatio: dotLineGridSetting.INTERVAL.ratioInterval,
|
gridRatio: currentSetting.INTERVAL.ratioInterval / 10,
|
||||||
gridDimen: dotLineGridSetting.INTERVAL.dimension,
|
gridDimen: currentSetting.INTERVAL.dimension,
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTP POST 요청 보내기
|
// HTTP POST 요청 보내기
|
||||||
await post({ url: `/api/canvas-management/canvas-grid-settings`, data: patternData }).then((res) => {
|
await post({ url: `/api/canvas-management/canvas-grid-settings`, data: patternData }).then((res) => {
|
||||||
swalFire({ text: getMessage(res.returnMessage) })
|
swalFire({ text: getMessage(res.returnMessage) })
|
||||||
|
setDotLineGridSettingState({ ...currentSetting })
|
||||||
// 1. 점.선 그리드 설정으로 만들어진 기존 오브젝트 제거
|
closePopup(id)
|
||||||
canvas
|
|
||||||
?.getObjects()
|
|
||||||
.filter((obj) => obj.name === 'lineGrid')
|
|
||||||
.forEach((obj) => canvas?.remove(obj))
|
|
||||||
canvas
|
|
||||||
?.getObjects()
|
|
||||||
.filter((obj) => obj.name === 'dotGrid')
|
|
||||||
.forEach((obj) => canvas?.remove(obj))
|
|
||||||
|
|
||||||
//const horizontalInterval = interval.horizontalInterval
|
|
||||||
//const verticalInterval = interval.verticalInterval
|
|
||||||
|
|
||||||
if (patternData.dotGridDisplay) {
|
|
||||||
const circle = new fabric.Circle({
|
|
||||||
radius: 2,
|
|
||||||
fill: 'red',
|
|
||||||
strokeWidth: 0.7,
|
|
||||||
originX: 'center',
|
|
||||||
originY: 'center',
|
|
||||||
selectable: false,
|
|
||||||
lockMovementX: true,
|
|
||||||
lockMovementY: true,
|
|
||||||
lockRotation: true,
|
|
||||||
lockScalingX: true,
|
|
||||||
lockScalingY: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
const patternSourceCanvas = new fabric.StaticCanvas(null, {
|
|
||||||
width: patternData.gridHorizon,
|
|
||||||
height: patternData.gridVertical,
|
|
||||||
})
|
|
||||||
|
|
||||||
patternSourceCanvas.add(circle)
|
|
||||||
|
|
||||||
circle.set({
|
|
||||||
left: patternSourceCanvas.width / 2,
|
|
||||||
top: patternSourceCanvas.height / 2,
|
|
||||||
})
|
|
||||||
|
|
||||||
patternSourceCanvas.renderAll()
|
|
||||||
|
|
||||||
const pattern = new fabric.Pattern({
|
|
||||||
source: patternSourceCanvas.getElement(),
|
|
||||||
repeat: 'repeat',
|
|
||||||
})
|
|
||||||
|
|
||||||
const backgroundPolygon = new fabric.Polygon(
|
|
||||||
[
|
|
||||||
{ x: 0, y: 0 },
|
|
||||||
{ x: canvas.width, y: 0 },
|
|
||||||
{ x: canvas.width, y: canvas.height },
|
|
||||||
{ x: 0, y: canvas.height },
|
|
||||||
],
|
|
||||||
{
|
|
||||||
fill: pattern,
|
|
||||||
selectable: false,
|
|
||||||
name: 'dotGrid',
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
canvas.add(backgroundPolygon)
|
|
||||||
backgroundPolygon.sendToBack()
|
|
||||||
canvas.renderAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (patternData.lineGridDisplay) {
|
|
||||||
for (let i = 0; i < canvas.height / patternData.gridVertical + 1; i++) {
|
|
||||||
const horizontalLine = new fabric.Line(
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
i * patternData.gridVertical - patternData.gridVertical / 2,
|
|
||||||
canvas.width,
|
|
||||||
i * patternData.gridVertical - patternData.gridVertical / 2,
|
|
||||||
],
|
|
||||||
{
|
|
||||||
stroke: gridColor,
|
|
||||||
strokeWidth: 1,
|
|
||||||
selectable: true,
|
|
||||||
lockMovementX: true,
|
|
||||||
lockMovementY: true,
|
|
||||||
lockRotation: true,
|
|
||||||
lockScalingX: true,
|
|
||||||
lockScalingY: true,
|
|
||||||
name: 'lineGrid',
|
|
||||||
strokeDashArray: [5, 2],
|
|
||||||
opacity: 0.3,
|
|
||||||
direction: 'horizontal',
|
|
||||||
},
|
|
||||||
)
|
|
||||||
canvas.add(horizontalLine)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < canvas.width / patternData.gridHorizon + 1; i++) {
|
|
||||||
const verticalLine = new fabric.Line(
|
|
||||||
[
|
|
||||||
i * patternData.gridHorizon - patternData.gridHorizon / 2,
|
|
||||||
0,
|
|
||||||
i * patternData.gridHorizon - patternData.gridHorizon / 2,
|
|
||||||
canvas.height,
|
|
||||||
],
|
|
||||||
{
|
|
||||||
stroke: gridColor,
|
|
||||||
strokeWidth: 1,
|
|
||||||
selectable: true,
|
|
||||||
lockMovementX: true,
|
|
||||||
lockMovementY: true,
|
|
||||||
lockRotation: true,
|
|
||||||
lockScalingX: true,
|
|
||||||
lockScalingY: true,
|
|
||||||
name: 'lineGrid',
|
|
||||||
strokeDashArray: [5, 2],
|
|
||||||
opacity: 0.3,
|
|
||||||
direction: 'vertical',
|
|
||||||
},
|
|
||||||
)
|
|
||||||
canvas.add(verticalLine)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.renderAll()
|
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
|
swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
|
||||||
@ -251,7 +152,7 @@ export default function DotLineGrid(props) {
|
|||||||
const handleRadioChange = (e) => {
|
const handleRadioChange = (e) => {
|
||||||
const { value, name, checked, selected } = e.target
|
const { value, name, checked, selected } = e.target
|
||||||
|
|
||||||
setDotLineGridSettingState((prev) => {
|
setCurrentSetting((prev) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
INTERVAL: {
|
INTERVAL: {
|
||||||
@ -264,7 +165,7 @@ export default function DotLineGrid(props) {
|
|||||||
|
|
||||||
const changeInput = (value, e) => {
|
const changeInput = (value, e) => {
|
||||||
const { name } = e.target
|
const { name } = e.target
|
||||||
setDotLineGridSettingState((prev) => {
|
setCurrentSetting((prev) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
INTERVAL: {
|
INTERVAL: {
|
||||||
@ -277,7 +178,7 @@ export default function DotLineGrid(props) {
|
|||||||
|
|
||||||
const changeDimension = (result) => {
|
const changeDimension = (result) => {
|
||||||
const { value } = result
|
const { value } = result
|
||||||
setDotLineGridSettingState((prev) => {
|
setCurrentSetting((prev) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
INTERVAL: {
|
INTERVAL: {
|
||||||
@ -298,27 +199,34 @@ export default function DotLineGrid(props) {
|
|||||||
?.getObjects()
|
?.getObjects()
|
||||||
.filter((obj) => obj.name === 'dotGrid')
|
.filter((obj) => obj.name === 'dotGrid')
|
||||||
.forEach((obj) => canvas?.remove(obj))
|
.forEach((obj) => canvas?.remove(obj))
|
||||||
|
|
||||||
resetDotLineGridSetting()
|
resetDotLineGridSetting()
|
||||||
setSelectOption(SelectOption[0])
|
setSelectOption(SelectOption[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 1300, y: -660 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap ssm mount`}>
|
<div className={`modal-pop-wrap ssm mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('modal.canvas.setting.grid.dot.line.setting')}</h1>
|
<h1 className="title">{getMessage('modal.canvas.setting.grid.dot.line.setting')}</h1>
|
||||||
<button className="modal-close" onClick={() => setShowDotLineGridModal(false)}>
|
<button
|
||||||
|
className="modal-close"
|
||||||
|
onClick={() => {
|
||||||
|
setIsShow(false)
|
||||||
|
closePopup(id)
|
||||||
|
}}
|
||||||
|
>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<div className="grid-check-form">
|
<div className="grid-check-form">
|
||||||
<div className="d-check-box pop">
|
<div className="d-check-box pop">
|
||||||
<input type="checkbox" id="ch01" value={TYPE.DOT} onChange={handleCheckBoxChange} checked={dotLineGridSetting.DOT} />
|
<input type="checkbox" id="ch01" value={TYPE.DOT} onChange={handleCheckBoxChange} checked={currentSetting.DOT} />
|
||||||
<label htmlFor="ch01">{getMessage('modal.canvas.setting.grid.dot.line.setting.dot.display')}</label>
|
<label htmlFor="ch01">{getMessage('modal.canvas.setting.grid.dot.line.setting.dot.display')}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="d-check-box pop">
|
<div className="d-check-box pop">
|
||||||
<input type="checkbox" id="ch02" value={TYPE.LINE} onChange={handleCheckBoxChange} checked={dotLineGridSetting.LINE} />
|
<input type="checkbox" id="ch02" value={TYPE.LINE} onChange={handleCheckBoxChange} checked={currentSetting.LINE} />
|
||||||
<label htmlFor="ch02">{getMessage('modal.canvas.setting.grid.dot.line.setting.line.display')}</label>
|
<label htmlFor="ch02">{getMessage('modal.canvas.setting.grid.dot.line.setting.line.display')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -331,7 +239,8 @@ export default function DotLineGrid(props) {
|
|||||||
id="ra01"
|
id="ra01"
|
||||||
value={1}
|
value={1}
|
||||||
onChange={handleRadioChange}
|
onChange={handleRadioChange}
|
||||||
checked={dotLineGridSetting.INTERVAL.type === 1}
|
checked={(currentSetting.DOT || currentSetting.LINE) && currentSetting.INTERVAL.type === 1}
|
||||||
|
readOnly={!currentSetting.DOT && !currentSetting.LINE}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="ra01"></label>
|
<label htmlFor="ra01"></label>
|
||||||
</div>
|
</div>
|
||||||
@ -342,7 +251,7 @@ export default function DotLineGrid(props) {
|
|||||||
type="text"
|
type="text"
|
||||||
className="input-origin"
|
className="input-origin"
|
||||||
name={`horizontalInterval`}
|
name={`horizontalInterval`}
|
||||||
value={dotLineGridSetting.INTERVAL.horizontalInterval}
|
value={currentSetting.INTERVAL.horizontalInterval}
|
||||||
onChange={(e) => onlyNumberInputChange(e, changeInput)}
|
onChange={(e) => onlyNumberInputChange(e, changeInput)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -355,7 +264,7 @@ export default function DotLineGrid(props) {
|
|||||||
type="text"
|
type="text"
|
||||||
className="input-origin"
|
className="input-origin"
|
||||||
name={`verticalInterval`}
|
name={`verticalInterval`}
|
||||||
value={dotLineGridSetting.INTERVAL.verticalInterval}
|
value={currentSetting.INTERVAL.verticalInterval}
|
||||||
onChange={(e) => onlyNumberInputChange(e, changeInput)}
|
onChange={(e) => onlyNumberInputChange(e, changeInput)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -370,7 +279,8 @@ export default function DotLineGrid(props) {
|
|||||||
id="ra02"
|
id="ra02"
|
||||||
value={2}
|
value={2}
|
||||||
onChange={handleRadioChange}
|
onChange={handleRadioChange}
|
||||||
checked={dotLineGridSetting.INTERVAL.type === 2}
|
checked={(currentSetting.DOT || currentSetting.LINE) && currentSetting.INTERVAL.type === 2}
|
||||||
|
readOnly={!currentSetting.DOT && !currentSetting.LINE}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="ra02"></label>
|
<label htmlFor="ra02"></label>
|
||||||
</div>
|
</div>
|
||||||
@ -381,7 +291,7 @@ export default function DotLineGrid(props) {
|
|||||||
type="text"
|
type="text"
|
||||||
className="input-origin"
|
className="input-origin"
|
||||||
name={`ratioInterval`}
|
name={`ratioInterval`}
|
||||||
value={dotLineGridSetting.INTERVAL.ratioInterval}
|
value={currentSetting.INTERVAL.ratioInterval}
|
||||||
onChange={(e) => onlyNumberInputChange(e, changeInput)}
|
onChange={(e) => onlyNumberInputChange(e, changeInput)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -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 (
|
|
||||||
<WithDraggable isShow={true} pos={{ x: 1300, y: -660 }}>
|
|
||||||
<div className={`modal-pop-wrap ssm mount`}>
|
|
||||||
<div className="modal-head">
|
|
||||||
<h1 className="title">{getMessage('modal.canvas.setting.grid.color.setting')}</h1>
|
|
||||||
<button className="modal-close" onClick={() => setShowColorPickerModal(false)}>
|
|
||||||
닫기
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="modal-body">
|
|
||||||
<ColorPicker color={color} setColor={setColor} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</WithDraggable>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,16 +1,21 @@
|
|||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
|
||||||
export default function GridCopy(props) {
|
export default function GridCopy(props) {
|
||||||
const { setShowGridMoveModal, setShowGridCopyModal } = props
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: 380 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xm mount`}>
|
<div className={`modal-pop-wrap xm mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('modal.grid.copy')} </h1>
|
<h1 className="title">{getMessage('modal.grid.copy')} </h1>
|
||||||
<button className="modal-close" onClick={() => setShowGridCopyModal(false)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,16 +1,21 @@
|
|||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
|
||||||
export default function GridMove(props) {
|
export default function GridMove(props) {
|
||||||
const { setShowGridMoveModal, setShowGridCopyModal } = props
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: 30 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xm mount`}>
|
<div className={`modal-pop-wrap xm mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('modal.grid.move')} </h1>
|
<h1 className="title">{getMessage('modal.grid.move')} </h1>
|
||||||
<button className="modal-close" onClick={() => setShowGridMoveModal(false)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
42
src/components/floor-plan/modal/image/ImageSizeSetting.jsx
Normal file
42
src/components/floor-plan/modal/image/ImageSizeSetting.jsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
|
||||||
|
export default function ImageSizeSetting(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition, size, setSize } = props
|
||||||
|
const [sizeValue, setSizeValue] = useState(100)
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap xxxm`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage('modal.image.size.setting')} </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="range-wrap">
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
id="size"
|
||||||
|
name="volume"
|
||||||
|
min="20"
|
||||||
|
max="200"
|
||||||
|
step={10}
|
||||||
|
value={sizeValue}
|
||||||
|
onChange={(e) => setSizeValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
<label htmlFor="size">{sizeValue}%</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/withDraggable'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
export default function LinePropertySetting(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition } = props
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
const properties = [
|
||||||
|
{ name: getMessage('eaves.line'), value: 'eaves' },
|
||||||
|
{ name: getMessage('ridge'), value: 'ridge' },
|
||||||
|
{ name: getMessage('oneside.flow.ridge'), value: 'onesideFlowRidge' },
|
||||||
|
{ name: getMessage('gable'), value: 'gable' },
|
||||||
|
{ name: getMessage('gable.left'), value: 'gableLeft' },
|
||||||
|
{ name: getMessage('gable.right'), value: 'gableRight' },
|
||||||
|
{ name: getMessage('yosemune'), value: 'yosemune' },
|
||||||
|
{ name: getMessage('valley'), value: 'valley' },
|
||||||
|
{ name: getMessage('l.abandon.valley'), value: 'lAbandonValley' },
|
||||||
|
{ name: getMessage('mansard'), value: 'mansard' },
|
||||||
|
{ name: getMessage('wall.merge'), value: 'wallCollection' },
|
||||||
|
{ name: getMessage('wall.merge.type'), value: 'wallCollectionType' },
|
||||||
|
{ name: getMessage('wall.merge.flow'), value: 'wallCollectionFlow' },
|
||||||
|
{ name: getMessage('wall.merge.flow.left'), value: 'wallCollectionFlowLeft' },
|
||||||
|
{ name: getMessage('wall.merge.flow.right'), value: 'wallCollectionFlowRight' },
|
||||||
|
{ name: getMessage('no.setting'), value: 'noSetting' },
|
||||||
|
]
|
||||||
|
const [selectedProperty, setSelectedProperty] = useState(null)
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap r mount`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage('contextmenu.line.property.edit')} </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="guide">
|
||||||
|
<span className="mb10">{getMessage('modal.line.property.edit.info')}</span>
|
||||||
|
<span>
|
||||||
|
{getMessage('modal.line.property.edit.selected')} [ {selectedProperty?.name} ]
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="properties-setting-wrap outer">
|
||||||
|
<div className="setting-tit">{getMessage('setting')}</div>
|
||||||
|
<div className="outline-wrap">
|
||||||
|
<div className="radio-grid-wrap">
|
||||||
|
{properties.map((property, index) => {
|
||||||
|
return (
|
||||||
|
<div className="d-check-radio pop" key={index}>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="radio01"
|
||||||
|
id={'ra' + (index + 1 >= 10 ? index + 1 : `0${index + 1}`)}
|
||||||
|
onChange={(e) => setSelectedProperty(property)}
|
||||||
|
/>
|
||||||
|
<label htmlFor={'ra' + (index + 1 > 10 ? index + 1 : `0${index + 1}`)}>{property.name}</label>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -3,9 +3,11 @@ import WithDraggable from '@/components/common/draggable/WithDraggable'
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import FlowLine from '@/components/floor-plan/modal/movement/type/FlowLine'
|
import FlowLine from '@/components/floor-plan/modal/movement/type/FlowLine'
|
||||||
import Updown from '@/components/floor-plan/modal/movement/type/Updown'
|
import Updown from '@/components/floor-plan/modal/movement/type/Updown'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
export default function MovementSetting({ setShowMovementModal }) {
|
export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
const [buttonAct, setButtonAct] = useState(1)
|
const [buttonAct, setButtonAct] = useState(1)
|
||||||
const buttonMenu = [
|
const buttonMenu = [
|
||||||
{ id: 1, name: getMessage('modal.movement.flow.line.move') },
|
{ id: 1, name: getMessage('modal.movement.flow.line.move') },
|
||||||
@ -13,11 +15,11 @@ export default function MovementSetting({ setShowMovementModal }) {
|
|||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap r`}>
|
<div className={`modal-pop-wrap r`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('plan.menu.roof.cover.movement.shape.updown')}</h1>
|
<h1 className="title">{getMessage('plan.menu.roof.cover.movement.shape.updown')}</h1>
|
||||||
<button className="modal-close" onClick={() => setShowMovementModal(false)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
55
src/components/floor-plan/modal/object/DormerOffset.jsx
Normal file
55
src/components/floor-plan/modal/object/DormerOffset.jsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
|
export default function DormerOffset(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition } = props
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap xm`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage('contextmenu.dormer.offset')}</h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="grid-option-tit">{getMessage('modal.dormer.offset.info')}</div>
|
||||||
|
<div className="grid-option-wrap">
|
||||||
|
<div className="grid-option-box">
|
||||||
|
<div className="move-form">
|
||||||
|
<p className="mb5">{getMessage('length')}</p>
|
||||||
|
<div className="input-move-wrap mb5">
|
||||||
|
<div className="input-move">
|
||||||
|
<input type="text" className="input-origin" defaultValue={0} />
|
||||||
|
</div>
|
||||||
|
<span>mm</span>
|
||||||
|
</div>
|
||||||
|
<div className="input-move-wrap">
|
||||||
|
<div className="input-move">
|
||||||
|
<input type="text" className="input-origin" defaultValue={0} />
|
||||||
|
</div>
|
||||||
|
<span>mm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="direction-move-wrap">
|
||||||
|
<button className="direction up"></button>
|
||||||
|
<button className="direction down act"></button>
|
||||||
|
<button className="direction left"></button>
|
||||||
|
<button className="direction right"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,9 +1,8 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useState, useRef, useEffect } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import { useObjectBatch } from '@/hooks/object/useObjectBatch'
|
import { useObjectBatch } from '@/hooks/object/useObjectBatch'
|
||||||
@ -13,13 +12,15 @@ import OpenSpace from '@/components/floor-plan/modal/object/type/OpenSpace'
|
|||||||
import Shadow from '@/components/floor-plan/modal/object/type/Shadow'
|
import Shadow from '@/components/floor-plan/modal/object/type/Shadow'
|
||||||
import TriangleDormer from '@/components/floor-plan/modal/object/type/TriangleDormer'
|
import TriangleDormer from '@/components/floor-plan/modal/object/type/TriangleDormer'
|
||||||
import PentagonDormer from '@/components/floor-plan/modal/object/type/PentagonDormer'
|
import PentagonDormer from '@/components/floor-plan/modal/object/type/PentagonDormer'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
export default function ObjectSetting({ setShowObjectSettingModal }) {
|
export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const [buttonAct, setButtonAct] = useState(1)
|
const [buttonAct, setButtonAct] = useState(1)
|
||||||
const { swalFire } = useSwal()
|
const { swalFire } = useSwal()
|
||||||
const { applyOpeningAndShadow, applyDormers } = useObjectBatch()
|
const { applyOpeningAndShadow, applyDormers } = useObjectBatch()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
|
|
||||||
@ -51,15 +52,12 @@ export default function ObjectSetting({ setShowObjectSettingModal }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const applyObject = () => {
|
const applyObject = () => {
|
||||||
// if (surfaceShapePolygons.length === 0) {
|
if (surfaceShapePolygons.length === 0) {
|
||||||
// swalFire({ text: '지붕이 없어요 지붕부터 그리세요', icon: 'error' })
|
swalFire({ text: '지붕이 없어요 지붕부터 그리세요', icon: 'error' })
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
|
|
||||||
//개구배치, 그림자배치
|
//개구배치, 그림자배치
|
||||||
|
|
||||||
console.log(surfaceShapePolygons)
|
|
||||||
|
|
||||||
if (buttonAct === 1 || buttonAct === 2) {
|
if (buttonAct === 1 || buttonAct === 2) {
|
||||||
applyOpeningAndShadow(objectPlacement, buttonAct, surfaceShapePolygons)
|
applyOpeningAndShadow(objectPlacement, buttonAct, surfaceShapePolygons)
|
||||||
} else {
|
} else {
|
||||||
@ -74,11 +72,11 @@ export default function ObjectSetting({ setShowObjectSettingModal }) {
|
|||||||
{ id: 4, name: getMessage('modal.object.setting.type.pentagon.dormer') },
|
{ id: 4, name: getMessage('modal.object.setting.type.pentagon.dormer') },
|
||||||
]
|
]
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap lrr`}>
|
<div className={`modal-pop-wrap lrr`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('plan.menu.placement.surface.object')} </h1>
|
<h1 className="title">{getMessage('plan.menu.placement.surface.object')} </h1>
|
||||||
<button className="modal-close" onClick={() => setShowObjectSettingModal(false)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -0,0 +1,45 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||||
|
|
||||||
|
export default function RoofMaterialSetting(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition } = props
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
const roofMaterials = [
|
||||||
|
{ name: '기와1', value: 'material1' },
|
||||||
|
{ name: '기와2', value: 'material2' },
|
||||||
|
{ name: '기와3', value: 'material3' },
|
||||||
|
{ name: '기와4', value: 'material4' },
|
||||||
|
{ name: '기와5', value: 'material5' },
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap xxxm`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">変更 </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="slope-wrap">
|
||||||
|
<div className="grid-select">
|
||||||
|
<QSelectBox title={'지붕재 선택'} options={roofMaterials} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act">ストレージ</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
69
src/components/floor-plan/modal/object/SizeSetting.jsx
Normal file
69
src/components/floor-plan/modal/object/SizeSetting.jsx
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
export default function SizeSetting(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const [settingTarget, setSettingTarget] = useState(1)
|
||||||
|
const { id, pos = contextPopupPosition, target } = props
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap ssm`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage('modal.size.setting')} </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="slope-wrap">
|
||||||
|
<div className="size-option-top">
|
||||||
|
<div className="size-option-wrap">
|
||||||
|
<div className="size-option mb5">
|
||||||
|
<input type="text" className="input-origin mr5" defaultValue={1000} readOnly value={target?.width * 10 * 2} />
|
||||||
|
<span className="normal-font">mm</span>
|
||||||
|
</div>
|
||||||
|
<div className="size-option">
|
||||||
|
<input type="text" className="input-origin mr5" defaultValue={1000} value={target?.width * 10 * 2} />
|
||||||
|
<span className="normal-font">mm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="size-inner-warp">
|
||||||
|
<div className="size-option-side">
|
||||||
|
<div className="size-option-wrap">
|
||||||
|
<div className="size-option mb5">
|
||||||
|
<input type="text" className="input-origin mr5" defaultValue={1000} readOnly value={target?.height * 10} />
|
||||||
|
<span className="normal-font">mm</span>
|
||||||
|
</div>
|
||||||
|
<div className="size-option">
|
||||||
|
<input type="text" className="input-origin mr5" defaultValue={1000} value={target?.height * 10} />
|
||||||
|
<span className="normal-font">mm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="size-check-wrap">
|
||||||
|
<button className={`size-btn ${settingTarget === 1 ? 'act' : ''}`} onClick={() => setSettingTarget(1)}></button>
|
||||||
|
<button className={`size-btn ${settingTarget === 2 ? 'act' : ''}`} onClick={() => setSettingTarget(2)}></button>
|
||||||
|
<button className={`size-btn ${settingTarget === 3 ? 'act' : ''}`} onClick={() => setSettingTarget(3)}></button>
|
||||||
|
<button className={`size-btn ${settingTarget === 4 ? 'act' : ''}`} onClick={() => setSettingTarget(4)}></button>
|
||||||
|
<div className="size-box"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act">{getMessage('write')}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -4,21 +4,15 @@ import { usePropertiesSetting } from '@/hooks/roofcover/usePropertiesSetting'
|
|||||||
|
|
||||||
export default function PropertiesSetting(props) {
|
export default function PropertiesSetting(props) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { setShowPropertiesSettingModal } = props
|
const { id, pos = { x: 50, y: 230 } } = props
|
||||||
|
const { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } = usePropertiesSetting(id)
|
||||||
const { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } = usePropertiesSetting(setShowPropertiesSettingModal)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap ssm`}>
|
<div className={`modal-pop-wrap ssm`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('modal.canvas.setting.wallline.properties.setting')}</h1>
|
<h1 className="title">{getMessage('modal.canvas.setting.wallline.properties.setting')}</h1>
|
||||||
<button
|
<button className="modal-close" onClick={() => closeModal(id)}>
|
||||||
className="modal-close"
|
|
||||||
onClick={() => {
|
|
||||||
closeModal(setShowPropertiesSettingModal)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -39,13 +33,7 @@ export default function PropertiesSetting(props) {
|
|||||||
<button className="btn-frame modal mr5" onClick={handleRollback}>
|
<button className="btn-frame modal mr5" onClick={handleRollback}>
|
||||||
{getMessage('modal.cover.outline.rollback')}
|
{getMessage('modal.cover.outline.rollback')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button className="btn-frame modal act" onClick={() => handleFix()}>
|
||||||
className="btn-frame modal act"
|
|
||||||
onClick={() => {
|
|
||||||
handleFix()
|
|
||||||
setShowPropertiesSettingModal(false)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{getMessage('modal.cover.outline.finish')}
|
{getMessage('modal.cover.outline.finish')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,10 +9,15 @@ import RightAngle from '@/components/floor-plan/modal/lineTypes/RightAngle'
|
|||||||
import Angle from '@/components/floor-plan/modal/lineTypes/Angle'
|
import Angle from '@/components/floor-plan/modal/lineTypes/Angle'
|
||||||
import DoublePitch from '@/components/floor-plan/modal/lineTypes/DoublePitch'
|
import DoublePitch from '@/components/floor-plan/modal/lineTypes/DoublePitch'
|
||||||
import Diagonal from '@/components/floor-plan/modal/lineTypes/Diagonal'
|
import Diagonal from '@/components/floor-plan/modal/lineTypes/Diagonal'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
export default function WallLineSetting(props) {
|
export default function WallLineSetting(props) {
|
||||||
const { setShowOutlineModal, setShowPropertiesSettingModal } = props
|
const { id } = props
|
||||||
|
const { addPopup, closePopup } = usePopup()
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const [propertiesId, setPropertiesId] = useState(uuidv4())
|
||||||
const {
|
const {
|
||||||
length1,
|
length1,
|
||||||
setLength1,
|
setLength1,
|
||||||
@ -39,7 +44,7 @@ export default function WallLineSetting(props) {
|
|||||||
outerLineDiagonalLengthRef,
|
outerLineDiagonalLengthRef,
|
||||||
handleRollback,
|
handleRollback,
|
||||||
handleFix,
|
handleFix,
|
||||||
} = useOuterLineWall(setShowOutlineModal)
|
} = useOuterLineWall(id, propertiesId)
|
||||||
|
|
||||||
const outerLineProps = {
|
const outerLineProps = {
|
||||||
length1,
|
length1,
|
||||||
@ -109,13 +114,11 @@ export default function WallLineSetting(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>
|
<WithDraggable isShow={true} pos={{ x: 50, y: 230 }}>
|
||||||
<div className={`modal-pop-wrap r mount`}>
|
<div className={`modal-pop-wrap r mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('modal.cover.outline.drawing')}</h1>
|
<h1 className="title">{getMessage('modal.cover.outline.drawing')}</h1>
|
||||||
<button className="modal-close" onClick={() => setShowOutlineModal(false)}>
|
<button className="modal-close" onClick={() => closePopup(id)}></button>
|
||||||
닫기
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<div className="modal-btn-wrap">
|
<div className="modal-btn-wrap">
|
||||||
@ -172,7 +175,9 @@ export default function WallLineSetting(props) {
|
|||||||
className="btn-frame modal act"
|
className="btn-frame modal act"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleFix()
|
handleFix()
|
||||||
setShowPropertiesSettingModal(true)
|
// closePopup(id)
|
||||||
|
|
||||||
|
// setShowPropertiesSettingModal(true)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{getMessage('modal.cover.outline.fix')}
|
{getMessage('modal.cover.outline.fix')}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user