diff --git a/.env b/.env index 50ab0d74..e69de29b 100644 --- a/.env +++ b/.env @@ -1,12 +0,0 @@ -# Environment variables declared in this file are automatically made available to Prisma. -# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema - -# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. -# See the documentation for all the connection string options: https://pris.ly/d/connection-strings - -# DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" -# DATABASE_URL="mongodb://yoo32767:GuCtswjLGqUaNL0G@cluster0.vsdtcnb.mongodb.net/sample_mflix?retryWrites=true&w=majority" -#DATABASE_URL = "mongodb%2Bsrv%3A%2F%2Fyoo32767%3AGuCtswjLGqUaNL0G%40cluster0.vsdtcnb.mongodb.net%2F%3FretryWrites%3Dtrue%26w%3Dmajority%26appName%3DCluster0" -# DATABASE_URL = "mongodb+srv://yoo32767:GuCtswjLGqUaNL0G@cluster0.vsdtcnb.mongodb.net/Cluster0?retryWrites=true&w=majority" -# DATABASE_URL="mongodb://yoo32767:GuCtswjLGqUaNL0G@cluster0.vsdtcnb.mongodb.net/sample_mflix?retryWrites=true&w=majority" -DATABASE_URL="mongodb+srv://yoo32767:GuCtswjLGqUaNL0G@cluster0.vsdtcnb.mongodb.net/mytest" \ No newline at end of file diff --git a/.env.development b/.env.development index 933db5d3..f843c86b 100644 --- a/.env.development +++ b/.env.development @@ -1,14 +1,8 @@ -NEXT_PUBLIC_TEST="테스트변수입니다. development" - NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080" -# NEXT_PUBLIC_API_SERVER_PATH="http://localhost:8080" -# NEXT_PUBLIC_API_SERVER_PATH="http://172.30.1.60:8080" - -DATABASE_URL="sqlserver://mssql.devgrr.kr:1433;database=qcast;user=qcast;password=Qwertqaz12345;trustServerCertificate=true" SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3" -NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-local.q-cells.jp:8120/eos/login/autoLogin" -NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-local.q-cells.jp:8120/qm/login/autoLogin" \ No newline at end of file +NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-qa.q-cells.jp:8120/eos/login/autoLogin" +NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-qa.q-cells.jp:8120/qm/login/autoLogin" \ No newline at end of file diff --git a/.env.production b/.env.production index 9bad1719..c4c7918d 100644 --- a/.env.production +++ b/.env.production @@ -1,12 +1,8 @@ -NEXT_PUBLIC_TEST="테스트변수입니다. production" - NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080" -DATABASE_URL="" - SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3" -NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-local.q-cells.jp:8120/eos/login/autoLogin" -NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-local.q-cells.jp:8120/qm/login/autoLogin" \ No newline at end of file +NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="https://q-order.q-cells.jp/eos/login/autoLogin" +NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="https://q-musubi.q-cells.jp/qm/login/autoLogin" \ No newline at end of file diff --git a/package.json b/package.json index d7214b51..4dfef6dd 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "prettier": "^3.3.3", "prisma": "^5.18.0", "react-color-palette": "^7.2.2", - "react-dropdown-select": "^4.11.3", "react-select": "^5.8.1", "sass": "^1.77.8", "tailwindcss": "^3.4.1" diff --git a/src/app/QcastProvider.js b/src/app/QcastProvider.js index 3ae0993d..84a5638e 100644 --- a/src/app/QcastProvider.js +++ b/src/app/QcastProvider.js @@ -1,27 +1,24 @@ 'use client' -import { useEffect } from 'react' -import { useRecoilState, useRecoilValue } from 'recoil' -import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' import { ErrorBoundary } from 'next/dist/client/components/error-boundary' import ServerError from './error' import '@/styles/common.scss' -import KO from '@/locales/ko.json' -import JA from '@/locales/ja.json' +// import KO from '@/locales/ko.json' +// import JA from '@/locales/ja.json' export const QcastProvider = ({ children }) => { - const globalLocale = useRecoilValue(globalLocaleStore) - const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore) + // const globalLocale = useRecoilValue(globalLocaleStore) + // const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore) - useEffect(() => { - if (globalLocale === 'ko') { - setAppMessageState(KO) - } else { - setAppMessageState(JA) - } - }, [globalLocale]) + // useEffect(() => { + // if (globalLocale === 'ko') { + // setAppMessageState(KO) + // } else { + // setAppMessageState(JA) + // } + // }, [globalLocale]) return ( <> diff --git a/src/app/SessionProvider.js b/src/app/SessionProvider.js new file mode 100644 index 00000000..d8f3caa9 --- /dev/null +++ b/src/app/SessionProvider.js @@ -0,0 +1,12 @@ +'use client' + +import { createContext, useState } from 'react' + +export const SessionContext = createContext({ + session: {}, +}) + +export default function SessionProvider({ useSession, children }) { + const [session, setSession] = useState(useSession) + return {children} +} diff --git a/src/app/layout.js b/src/app/layout.js index d27522fe..64b374e8 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -15,6 +15,8 @@ import './globals.css' import '../styles/style.scss' import '../styles/contents.scss' import Dimmed from '@/components/ui/Dimmed' +import SessionProvider from './SessionProvider' +import LocaleSwitch from '@/components/LocaleSwitch' // const inter = Inter({ subsets: ['latin'] }) @@ -70,11 +72,14 @@ export default async function RootLayout({ children }) {
- {children} + + {children} +
diff --git a/src/common/common.js b/src/common/common.js index ebb394d3..cf9788be 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -66,8 +66,13 @@ export const LINE_TYPE = { }, SUBLINE: { /** - * + * 추녀 / 마루 / 박공 / 지붕골 / 박공단 */ + HIP: 'hip', + RIDGE: 'ridge', + GABLE: 'gable', + VALLEY: 'valley', + VERGE: 'verge', }, } diff --git a/src/components/LocaleSwitch.jsx b/src/components/LocaleSwitch.jsx new file mode 100644 index 00000000..291f2043 --- /dev/null +++ b/src/components/LocaleSwitch.jsx @@ -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 ( + { + if (globalLocale === 'ko') { + setGlobalLocale('ja') + } else { + setGlobalLocale('ko') + } + }} + > + {globalLocale.toUpperCase()} + + ) +} diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx index 6393158d..3bdb7ccb 100644 --- a/src/components/Playground.jsx +++ b/src/components/Playground.jsx @@ -30,7 +30,7 @@ export default function Playground() { const fileRef = useRef(null) const queryRef = useRef(null) const [zoom, setZoom] = useState(20) - const { get, promisePost } = useAxios() + const { get, promiseGet, promisePost } = useAxios() const testVar = process.env.NEXT_PUBLIC_TEST const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL const { getMessage } = useMessage() @@ -43,6 +43,8 @@ export default function Playground() { const [checkboxInput, setCheckboxInput] = useState([]) const [selectedValue, setSelectedValue] = useState('') + const [users, setUsers] = useState([]) + useEffect(() => { console.log('textInput:', textInput) }, [textInput]) @@ -142,6 +144,10 @@ export default function Playground() { }, } + useEffect(() => { + console.log('users:', users) + }, [users]) + return ( <>
@@ -305,6 +311,32 @@ export default function Playground() {
+
+ +
+
+ +
) diff --git a/src/components/Settings.jsx b/src/components/Settings.jsx index 43288dbe..51680711 100644 --- a/src/components/Settings.jsx +++ b/src/components/Settings.jsx @@ -3,7 +3,8 @@ import React, { useEffect, useState } from 'react' import { Button } from '@nextui-org/react' -import { get, post } from '@/lib/Axios' +import { useAxios } from '@/hooks/useAxios' + import { useRecoilState } from 'recoil' import { customSettingsState } from '@/store/canvasAtom' import { modalContent, modalState } from '@/store/modalAtom' @@ -20,6 +21,8 @@ export default function Settings() { const [open, setOpen] = useRecoilState(modalState) const [contents, setContent] = useRecoilState(modalContent) + const { get, post } = useAxios() + const handleSavePopup = () => { console.log('color ', color) } diff --git a/src/components/auth/AutoLogin.jsx b/src/components/auth/AutoLogin.jsx new file mode 100644 index 00000000..0d539cbb --- /dev/null +++ b/src/components/auth/AutoLogin.jsx @@ -0,0 +1,21 @@ +'use client' + +import { useMessage } from '@/hooks/useMessage' + +export default function AutoLoginPage() { + const { getMessage } = useMessage() + + return ( +
+
+ {getMessage('site.name')} + {getMessage('site.sub_name')} +
+
+
+ {getMessage('login.auto.page.text')} +
+
+
+ ) +} diff --git a/src/components/auth/Login.jsx b/src/components/auth/Login.jsx index 28416284..d75d9b6e 100644 --- a/src/components/auth/Login.jsx +++ b/src/components/auth/Login.jsx @@ -15,6 +15,8 @@ import Cookies from 'js-cookie' import { useSearchParams } from 'next/navigation' +import AutoLogin from './AutoLogin' + export default function Login() { // 자동 로그인 const initParams = useSearchParams() @@ -180,8 +182,7 @@ export default function Login() { react - - {passwordReset === 1 && ( + {!autoLoginParam && passwordReset === 1 && ( <>
@@ -266,7 +267,7 @@ export default function Login() {
)} - {passwordReset === 2 && ( + {!autoLoginParam && passwordReset === 2 && ( <>
@@ -328,6 +329,7 @@ export default function Login() {
)} + {autoLoginParam && }
COPYRIGHT©2024 Hanwha Japan All Rights Reserved.
diff --git a/src/components/common/context-menu/QContextMenu.jsx b/src/components/common/context-menu/QContextMenu.jsx index a86e40af..8e3e2314 100644 --- a/src/components/common/context-menu/QContextMenu.jsx +++ b/src/components/common/context-menu/QContextMenu.jsx @@ -27,7 +27,7 @@ export default function QContextMenu(props) { const handleContextMenu = (e) => { // e.preventDefault() //기존 contextmenu 막고 setContextMenu({ visible: true, x: e.pageX, y: e.pageY }) - console.log(111, canvasProps) + // console.log(111, canvasProps) canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제 } diff --git a/src/components/community/Archive.jsx b/src/components/community/Archive.jsx index 768bc500..55de76f1 100644 --- a/src/components/community/Archive.jsx +++ b/src/components/community/Archive.jsx @@ -61,7 +61,7 @@ export default function Archive() {
- +
diff --git a/src/components/community/ArchiveTable.jsx b/src/components/community/ArchiveTable.jsx index ef6b303b..371ae454 100644 --- a/src/components/community/ArchiveTable.jsx +++ b/src/components/community/ArchiveTable.jsx @@ -45,7 +45,7 @@ export default function ArchiveTable({ clsCode }) { } fetchData() - }, [search.searchValue]) + }, [search.searchValue, search.searchFlag]) // 상세 파일 목록 조회 const handleDetailFileListDown = async (noticeNo) => { @@ -74,30 +74,34 @@ export default function ArchiveTable({ clsCode }) { return ( <> -
- {boardList?.map((board) => ( -
-
-
- {/* 번호 */} - {board.rowNumber} + {boardList.length > 0 ? ( +
+ {boardList?.map((board) => ( +
+
+
+ {/* 번호 */} + {board.rowNumber} +
+
+ {/* 제목 */} + {board.title} +
+
+ {/* 등록일 */} + {getMessage('board.sub.updDt')} : {board.uptDt ? board.uptDt : board.regDt} +
-
- {/* 제목 */} - {board.title} -
-
- {/* 등록일 */} - {getMessage('board.sub.updDt')} : {board.uptDt ? board.uptDt : board.regDt} +
+ {/* 첨부파일 */} +
-
- {/* 첨부파일 */} - -
-
- ))} -
+ ))} +
+ ) : ( +
{getMessage('common.message.no.data')}
+ )} ) } diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index ae3c6c62..616143fe 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -75,7 +75,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { const y2 = this.top + this.height * scaleY const dx = x2 - x1 const dy = y2 - y1 - this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0)) + this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) }, addLengthText() { @@ -150,7 +150,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { getLength() { //10배 곱해진 값 return - return Number(this.length.toFixed(1) * 10) + return Number(this.length.toFixed(0) * 10) }, setViewLengthText(bool) { diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 0ac7a519..ad08e884 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -199,32 +199,16 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { const end = points[(i + 1) % points.length] const dx = end.x - start.x const dy = end.y - start.y - const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) * 10 + const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0)) * 10 let midPoint - switch (this.direction) { - case 'north': - midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2 - 30) - break - case 'west': - midPoint = new fabric.Point((start.x + end.x) / 2 - 30, (start.y + end.y) / 2) - break - case 'south': - midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2 + 30) - break - case 'east': - midPoint = new fabric.Point((start.x + end.x) / 2 + 30, (start.y + end.y) / 2) - break - default: - midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2) - break - } + midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2) const degree = (Math.atan2(dy, dx) * 180) / Math.PI // Create new text object if it doesn't exist - const text = new fabric.Text(length.toFixed(0), { + const text = new fabric.Text(length.toString(), { left: midPoint.x, top: midPoint.y, fontSize: this.fontSize, diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx index f34d1cb6..d6a4e179 100644 --- a/src/components/floor-plan/CanvasFrame.jsx +++ b/src/components/floor-plan/CanvasFrame.jsx @@ -13,11 +13,7 @@ export default function CanvasFrame({ plan }) { const canvasRef = useRef(null) const { canvas } = useCanvas('canvas') const { contextMenu, currentContextMenu, setCurrentContextMenu } = useContextMenu() - const currentObject = useRecoilValue(currentObjectState) - useEffect(() => { - console.log(currentObject) - }, [currentObject]) useEvent() const loadCanvas = () => { diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx index 7138907c..405d5106 100644 --- a/src/components/floor-plan/CanvasLayout.jsx +++ b/src/components/floor-plan/CanvasLayout.jsx @@ -1,122 +1,25 @@ 'use client' -import { useEffect, useState } from 'react' -import { useRecoilState, useRecoilValue } from 'recoil' +import { useContext, useEffect, useState } from 'react' +import { useRecoilValue } from 'recoil' import CanvasFrame from './CanvasFrame' import { useMessage } from '@/hooks/useMessage' import { useSwal } from '@/hooks/useSwal' import { usePlan } from '@/hooks/usePlan' import { globalLocaleStore } from '@/store/localeAtom' -import { currentCanvasPlanState, initCanvasPlansState, plansState } from '@/store/canvasAtom' -import { sessionStore } from '@/store/commonAtom' +import { SessionContext } from '@/app/SessionProvider' export default function CanvasLayout() { + const { session } = useContext(SessionContext) const [objectNo, setObjectNo] = useState('test123240822001') // 이후 삭제 필요 - const [planNum, setPlanNum] = useState(0) - const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) - const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) - const [plans, setPlans] = useRecoilState(plansState) const globalLocaleState = useRecoilValue(globalLocaleStore) - const sessionState = useRecoilValue(sessionStore) const { getMessage } = useMessage() const { swalFire } = useSwal() - const { getCanvasByObjectNo, delCanvasById, checkModifiedCanvasPlan, saveCanvas, currentCanvasData } = usePlan() - - const handleCurrentPlan = (newCurrentId) => { - // console.log('currentPlan newCurrentId: ', newCurrentId) - if (!currentCanvasPlan || currentCanvasPlan.id !== newCurrentId) { - if (currentCanvasPlan?.id && checkModifiedCanvasPlan()) { - swalFire({ - html: getMessage('common.message.confirm.save') + `
${currentCanvasPlan.name}`, - type: 'confirm', - confirmFn: async () => { - await saveCanvas(sessionState.userId) - updateCurrentPlan(newCurrentId) - }, - denyFn: () => { - updateCurrentPlan(newCurrentId) - }, - }) - } else { - updateCurrentPlan(newCurrentId) - } - } - } - const updateCurrentPlan = (newCurrentId) => { - setPlans((plans) => - plans.map((plan) => { - return { ...plan, isCurrent: plan.id === newCurrentId } - }), - ) - } - useEffect(() => { - setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null) - }, [plans]) - - const handleDeletePlan = (e, id) => { - e.stopPropagation() // 이벤트 버블링 방지 - - if (initCanvasPlans.some((plan) => plan.id === id)) { - delCanvasById(id) - .then((res) => { - swalFire({ text: getMessage('common.message.delete') }) - // console.log('[DELETE] canvas-statuses res :::::::: %o', res) - setInitCanvasPlans((initCanvasPlans) => initCanvasPlans.filter((plan) => plan.id !== id)) - setPlans((plans) => plans.filter((plan) => plan.id !== id)) - }) - .catch((error) => { - swalFire({ text: error.message, icon: 'error' }) - // console.error('[DELETE] canvas-statuses res error :::::::: %o', error) - }) - } else { - setPlans((plans) => plans.filter((plan) => plan.id !== id)) - swalFire({ text: getMessage('common.message.delete') }) - } - - // 삭제 후 last 데이터에 포커싱 - const lastPlan = plans.filter((plan) => plan.id !== id).at(-1) - if (!lastPlan) { - setPlanNum(0) - setCurrentCanvasPlan(null) - } else if (id !== lastPlan.id) { - handleCurrentPlan(lastPlan.id) - } - } - - const addEmptyPlan = () => { - setPlans([...plans, { id: planNum, name: `Plan ${planNum + 1}`, objectNo: `${objectNo}` }]) - handleCurrentPlan(planNum) - setPlanNum(planNum + 1) - } - - const addCopyPlan = () => { - const copyPlan = { - id: planNum, - name: `Plan ${planNum + 1}`, - objectNo: `${objectNo}`, - userId: sessionState.userId, - canvasStatus: currentCanvasData(), - } - setPlans((plans) => [...plans, copyPlan]) - handleCurrentPlan(planNum) - setPlanNum(planNum + 1) - } + const { plans, loadCanvasPlanData, handleCurrentPlan, handleAddPlan, handleDeletePlan } = usePlan() useEffect(() => { - if (!currentCanvasPlan) { - getCanvasByObjectNo(sessionState.userId, objectNo).then((res) => { - // console.log('canvas 목록 ', res) - if (res.length > 0) { - setInitCanvasPlans(res) - setPlans(res) - handleCurrentPlan(res.at(-1).id) // last 데이터에 포커싱 - setPlanNum(res.length) - } else { - addEmptyPlan() - } - }) - } + loadCanvasPlanData(session.userId, objectNo) }, []) return ( @@ -127,14 +30,14 @@ export default function CanvasLayout() {
{plans.length < 10 && ( - )} diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index ae8cc79d..c0cd09e5 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -19,6 +19,7 @@ import { MENU } from '@/common/common' import KO from '@/locales/ko.json' import JA from '@/locales/ja.json' import { settingModalFirstOptionsState } from '@/store/settingAtom' +import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom' const canvasMenus = [ { index: 0, name: 'plan.menu.plan.drawing', icon: 'con00', title: MENU.PLAN_DRAWING }, @@ -58,7 +59,8 @@ export default function CanvasMenu(props) { const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState) const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore) const setCurrentMenu = useSetRecoilState(currentMenuState) - const setPoints = useSetRecoilState(outerLinePointsState) + const setOuterLinePoints = useSetRecoilState(outerLinePointsState) + const setPlacementPoints = useSetRecoilState(placementShapeDrawingPointsState) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) @@ -121,14 +123,14 @@ export default function CanvasMenu(props) { }, [menuNumber, type]) // 저장버튼(btn08) 클릭 시 호출되는 함수 - const handleSaveCanvas = () => { - swalFire({ - html: getMessage('common.message.confirm.save') + `
${currentCanvasPlan.name}`, - type: 'confirm', - confirmFn: () => { - saveCanvas(sessionState.userId) - }, - }) + const handleSaveCanvas = async () => { + // swalFire({ + // text: `${currentCanvasPlan.name} ` + getMessage('plan.message.confirm.save'), + // type: 'confirm', + // confirmFn: async () => { + await saveCanvas(sessionState.userId) + // }, + // }) } const onClickPlacementInitialMenu = () => { @@ -140,7 +142,8 @@ export default function CanvasMenu(props) { } const handleClear = () => { - setPoints([]) + setOuterLinePoints([]) + setPlacementPoints([]) canvas?.clear() } diff --git a/src/components/floor-plan/modal/Slope.jsx b/src/components/floor-plan/modal/Slope.jsx index 0ae32ab6..ba9ede2a 100644 --- a/src/components/floor-plan/modal/Slope.jsx +++ b/src/components/floor-plan/modal/Slope.jsx @@ -1,8 +1,13 @@ import { useMessage } from '@/hooks/useMessage' import WithDraggable from '@/components/common/draggable/WithDraggable' +import { globalPitchState } from '@/store/canvasAtom' +import { useRecoilState } from 'recoil' +import { useRef } from 'react' export default function Slope({ setShowSlopeSettingModal }) { const { getMessage } = useMessage() + const [globalPitch, setGlobalPitch] = useRecoilState(globalPitchState) + const inputRef = useRef() return (
@@ -19,13 +24,21 @@ export default function Slope({ setShowSlopeSettingModal }) { {getMessage('slope')}
- +
{getMessage('size.angle')}
- +
diff --git a/src/components/floor-plan/modal/grid/DotLineGrid.jsx b/src/components/floor-plan/modal/grid/DotLineGrid.jsx index eb5a834e..d9919351 100644 --- a/src/components/floor-plan/modal/grid/DotLineGrid.jsx +++ b/src/components/floor-plan/modal/grid/DotLineGrid.jsx @@ -7,7 +7,7 @@ import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState import { onlyNumberInputChange } from '@/util/input-utils' import { fabric } from 'fabric' import { gridColorState } from '@/store/gridAtom' -import { settingModalGridOptionsState } from '@/store/settingAtom' +import { gridDisplaySelector, settingModalGridOptionsState } from '@/store/settingAtom' import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' @@ -24,6 +24,7 @@ export default function DotLineGrid(props) { const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState) const gridColor = useRecoilValue(gridColorState) const canvas = useRecoilValue(canvasState) + const isGridDisplay = useRecoilValue(gridDisplaySelector) const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState) const resetDotLineGridSetting = useResetRecoilState(dotLineGridSettingState) @@ -179,6 +180,7 @@ export default function DotLineGrid(props) { fill: pattern, selectable: false, name: 'dotGrid', + visible: isGridDisplay, }, ) @@ -209,6 +211,7 @@ export default function DotLineGrid(props) { strokeDashArray: [5, 2], opacity: 0.3, direction: 'horizontal', + visible: isGridDisplay, }, ) canvas.add(horizontalLine) @@ -235,6 +238,7 @@ export default function DotLineGrid(props) { strokeDashArray: [5, 2], opacity: 0.3, direction: 'vertical', + visible: isGridDisplay, }, ) canvas.add(verticalLine) diff --git a/src/components/floor-plan/modal/object/ObjectSetting.jsx b/src/components/floor-plan/modal/object/ObjectSetting.jsx index d5fe934e..764535e3 100644 --- a/src/components/floor-plan/modal/object/ObjectSetting.jsx +++ b/src/components/floor-plan/modal/object/ObjectSetting.jsx @@ -46,6 +46,7 @@ export default function ObjectSetting({ setShowObjectSettingModal }) { heightRef: useRef(null), pitchRef: useRef(null), offsetRef: useRef(null), + offsetWidthRef: useRef(null), directionRef: useRef(null), } diff --git a/src/components/floor-plan/modal/object/type/PentagonDormer.jsx b/src/components/floor-plan/modal/object/type/PentagonDormer.jsx index e2aeea15..73f9c5d8 100644 --- a/src/components/floor-plan/modal/object/type/PentagonDormer.jsx +++ b/src/components/floor-plan/modal/object/type/PentagonDormer.jsx @@ -1,8 +1,17 @@ import Image from 'next/image' import { useMessage } from '@/hooks/useMessage' +import { forwardRef, useState } from 'react' -export default function PentagonDormer() { +const PentagonDormer = forwardRef((props, refs) => { const { getMessage } = useMessage() + const [direction, setDirection] = useState('down') + refs.directionRef.current = direction + + const getDirection = (e) => { + setDirection(e.target.value) + refs.directionRef.current = e.target.value + } + return ( <>
@@ -18,7 +27,7 @@ export default function PentagonDormer() {
- +
mm
@@ -29,7 +38,7 @@ export default function PentagonDormer() {
- +
mm
@@ -40,18 +49,18 @@ export default function PentagonDormer() {
- +
mm
-
{getMessage('modal.object.setting.offset.depth')}
+
{getMessage('modal.object.setting.offset.width')}
- +
mm
@@ -62,7 +71,7 @@ export default function PentagonDormer() {
- +
@@ -80,13 +89,15 @@ export default function PentagonDormer() { {getMessage('commons.east')} {getMessage('commons.south')} {getMessage('commons.west')} - - - - + + + +
) -} +}) + +export default PentagonDormer diff --git a/src/components/floor-plan/modal/object/type/TriangleDormer.jsx b/src/components/floor-plan/modal/object/type/TriangleDormer.jsx index 9ab7712d..f2a8a1f0 100644 --- a/src/components/floor-plan/modal/object/type/TriangleDormer.jsx +++ b/src/components/floor-plan/modal/object/type/TriangleDormer.jsx @@ -5,7 +5,6 @@ import { forwardRef, useState } from 'react' const TriangleDormer = forwardRef((props, refs) => { const { getMessage } = useMessage() const [direction, setDirection] = useState('down') - refs.directionRef.current = direction const getDirection = (e) => { diff --git a/src/components/floor-plan/modal/setting01/FirstOption.jsx b/src/components/floor-plan/modal/setting01/FirstOption.jsx index c4e75ea4..848596ba 100644 --- a/src/components/floor-plan/modal/setting01/FirstOption.jsx +++ b/src/components/floor-plan/modal/setting01/FirstOption.jsx @@ -1,14 +1,14 @@ import { useRecoilState } from 'recoil' -import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom' +import { settingModalSecondOptionsState } from '@/store/settingAtom' import { useMessage } from '@/hooks/useMessage' import React, { useEffect, useState } from 'react' import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' -import { adsorptionPointAddModeState } from '@/store/canvasAtom' +import { useFirstOption } from '@/hooks/option/useFirstOption' export default function FirstOption() { const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요 - const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) + const { settingModalFirstOptions, setSettingModalFirstOptions } = useFirstOption() const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState) const { option1, option2, dimensionDisplay } = settingModalFirstOptions const { option3, option4 } = settingModalSecondOptions diff --git a/src/components/main/MainContents.jsx b/src/components/main/MainContents.jsx index ba9a8d77..6dcca943 100644 --- a/src/components/main/MainContents.jsx +++ b/src/components/main/MainContents.jsx @@ -34,7 +34,6 @@ export default function MainContents({ objectList, businessCharger, businessChar startRow: 1, endRow: 1, } - // const noticeApiUrl = `api/board/list?schNoticeTpCd=QC&schNoticeClsCd=NOTICE&schTitle=&startRow=1&endRow=1` const noticeApiUrl = `api/board/list?${queryStringFormatter(param)}` const res = await get({ url: noticeApiUrl }) //console.log('공지res::', res) @@ -57,7 +56,6 @@ export default function MainContents({ objectList, businessCharger, businessChar startRow: 1, endRow: 3, } - // const faqApiUrl = `api/board/list?schNoticeTpCd=QC&schNoticeClsCd=FAQ&schTitle=&startRow=1&endRow=1` const faqApiUrl = `api/board/list?${queryStringFormatter(param)}` const res = await get({ url: faqApiUrl }) //console.log('FAQres::', res) diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index 9a0a73c5..58cd7bff 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -15,6 +15,7 @@ import { convertNumberToPriceDecimal } from '@/util/common-utils' import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' import KO from '@/locales/ko.json' import JA from '@/locales/ja.json' +import QPagination from '../common/pagination/QPagination' import '@/styles/grid.scss' import { sessionStore } from '@/store/commonAtom' @@ -24,9 +25,9 @@ export default function Stuff() { const stuffSearchParams = useRecoilValue(stuffSearchState) const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState) const { getMessage } = useMessage() - const [curPage, setCurPage] = useState(1) //현재 페이지 번호 - const [defaultSize, setDefaultSize] = useState(100) //페이지 당 게시물 수 - const [gridCount, setGridCount] = useState(0) //총 갯수 + const [pageNo, setPageNo] = useState(1) //현재 페이지 번호 + const [pageSize, setPageSize] = useState(100) //페이지 당 게시물 수 + const [totalCount, setTotalCount] = useState(0) //총 갯수 const [defaultSortType, setDefaultSortType] = useState('R') const globalLocaleState = useRecoilValue(globalLocaleStore) @@ -62,13 +63,10 @@ export default function Stuff() { const [gridProps, setGridProps] = useState({ gridData: [], isPageable: false, - // sets 10 rows per page (default is 100) - // paginationPageSize: 100, - // allows the user to select the page size from a predefined list of page sizes - // paginationPageSizeSelector: [100, 200, 300, 400], gridColumns: [ { field: 'lastEditDatetime', + minWidth: 200, headerName: getMessage('stuff.gridHeader.lastEditDatetime'), headerCheckboxSelection: true, headerCheckboxSelectionCurrentPageOnly: true, //페이징시 현재 페이지만 체크되도록 @@ -228,56 +226,40 @@ export default function Stuff() { // 진입시 그리드 데이터 조회 useEffect(() => { if (isObjectNotEmpty(sessionState)) { + //물건 메뉴 눌러서 최초 진입 sessionState if (stuffSearchParams?.code === 'S') { const params = { - schObjectNo: '', - schAddress: '', - schObjectName: '', - schSaleStoreName: '', - schReceiveUser: '', - schDispCompanyName: '', - schDateType: 'U', + schObjectNo: stuffSearchParams?.schObjectNo, + schAddress: stuffSearchParams?.schAddress, + schObjectName: stuffSearchParams?.schObjectName, + schSaleStoreName: stuffSearchParams?.schSaleStoreName, + schReceiveUser: stuffSearchParams?.schReceiveUser, + schDispCompanyName: stuffSearchParams?.schDispCompanyName, + schDateType: stuffSearchParams.schDateType, schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), schToDt: dayjs(new Date()).format('YYYY-MM-DD'), - startRow: (curPage - 1) * defaultSize + 1, - endRow: curPage * defaultSize, + startRow: (pageNo - 1) * pageSize + 1, + endRow: pageNo * pageSize, schSelSaleStoreId: '', - schSortType: 'R', + schSortType: stuffSearchParams.schSortType, } async function fetchData() { - //api에 넘길값 startRow, endRow - // let startRow - // let endRow - // startRow = (curPage - 1) * size + 1 - // endRow = curPage * size - // console.log('startrow::', startRow) - // console.log('endRow::', endRow) - - // let curPage - // let totalpage - // let totalCount - // let size - // let pageCount - - // console.log('화면진입 세션정보::::::::::', sessionState) - // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(params)}` - // const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(params)}` const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(params)}` - await get({ url: apiUrl, }).then((res) => { if (!isEmptyArray(res)) { setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) - setGridCount(res[0].totCnt) + setTotalCount(res[0].totCnt) } }) } fetchData() } else { + //메인화면에서 진입 const params = { - schObjectNo: '', + schObjectNo: stuffSearchParams.schObjectNo, schAddress: '', schObjectName: '', schSaleStoreName: '', @@ -286,30 +268,13 @@ export default function Stuff() { schDateType: 'U', schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), schToDt: dayjs(new Date()).format('YYYY-MM-DD'), - startRow: (curPage - 1) * defaultSize + 1, - endRow: curPage * defaultSize, + startRow: (pageNo - 1) * pageSize + 1, + endRow: pageNo * pageSize, schSelSaleStoreId: '', schSortType: 'R', } async function fetchData() { - //api에 넘길값 startRow, endRow - // let startRow - // let endRow - // startRow = (curPage - 1) * size + 1 - // endRow = curPage * size - // console.log('startrow::', startRow) - // console.log('endRow::', endRow) - - // let curPage - // let totalpage - // let totalCount - // let size - // let pageCount - - // console.log('화면진입 세션정보::::::::::', sessionState) - // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(params)}` - // const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(params)}` const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(params)}` await get({ @@ -317,34 +282,33 @@ export default function Stuff() { }).then((res) => { if (!isEmptyArray(res)) { setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) - setGridCount(res[0].totCnt) + setTotalCount(res[0].totCnt) } }) } fetchData() } } - }, [sessionState]) + }, [pageNo, sessionState]) useEffect(() => { if (stuffSearchParams?.code === 'E') { - //console.log('조회누름::::::::', stuffSearchParams) - stuffSearchParams.startRow = (curPage - 1) * defaultSize + 1 - stuffSearchParams.endRow = curPage * defaultSize + stuffSearchParams.startRow = 1 + stuffSearchParams.endRow = 1 * pageSize stuffSearchParams.schSortType = defaultSortType + + setPageNo(1) + async function fetchData() { - // console.log('조회누름 세션정보:::::::::::::', sessionState) - // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` - // const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` + // const apiUrl = `/api/object/list?saleStoreId=T01&${queryStringFormatter(stuffSearchParams)}` const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}` await get({ url: apiUrl }).then((res) => { - // console.log('검색조건 변경 조회 API결과:::::::', res) if (!isEmptyArray(res)) { setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) - setGridCount(res[0].totCnt) + setTotalCount(res[0].totCnt) } else { setGridProps({ ...gridProps, gridData: [], count: 0 }) - setGridCount(0) + setTotalCount(0) } }) } @@ -354,53 +318,58 @@ export default function Stuff() { //페이지 갯수 변경 이벤트 const onChangePerPage = (e) => { - let startRow = (curPage - 1) * e.target.value + 1 + let startRow = (1 - 1) * e.target.value + 1 stuffSearchParams.startRow = startRow - stuffSearchParams.endRow = curPage * e.target.value - setDefaultSize(e.target.value) + stuffSearchParams.endRow = 1 * e.target.value + setPageSize(e.target.value) setStuffSearch({ ...stuffSearch, code: 'S', startRow: startRow, - endRow: curPage * e.target.value, + endRow: 1 * e.target.value, }) - // console.log('페이지 갯수 변경 때 셋팅된 검색조건:::', stuffSearchParams) - // console.log('페이지 갯수 변경 때 sessionState:::', sessionState) - // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` - // const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` + + setPageNo(1) + // const apiUrl = `/api/object/list?saleStoreId=T01&${queryStringFormatter(stuffSearchParams)}` const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}` get({ url: apiUrl }).then((res) => { if (!isEmptyArray(res)) { setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) - setGridCount(res[0].totCnt) + setTotalCount(res[0].totCnt) } else { setGridProps({ ...gridProps, gridData: [], count: 0 }) - setGridCount(0) + setTotalCount(0) } }) } //최근 등록일 수정일 정렬 이벤트 const onChangeSortType = (e) => { + let startRow = (1 - 1) * pageSize + 1 + stuffSearchParams.startRow = startRow + stuffSearchParams.endRow = 1 * pageSize + stuffSearchParams.schSortType = e.target.value - // console.log('셋팅된 검색조건:::', stuffSearchParams) setDefaultSortType(e.target.value) setStuffSearch({ ...stuffSearch, code: 'S', + startRow: startRow, + endRow: 1 * pageSize, schSortType: e.target.value, }) - // console.log('정렬 변경시 세션정보::::::::::::', sessionState) - // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` - // const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` + + setPageNo(1) + + // const apiUrl = `/api/object/list?saleStoreId=T01&${queryStringFormatter(stuffSearchParams)}` const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}` get({ url: apiUrl }).then((res) => { if (!isEmptyArray(res)) { setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) - setGridCount(res[0].totCnt) + setTotalCount(res[0].totCnt) } else { setGridProps({ ...gridProps, gridData: [], count: 0 }) - setGridCount(0) + setTotalCount(0) } }) } @@ -413,20 +382,34 @@ export default function Stuff() { } }, [globalLocaleState]) + // 페이징 현재페이지 변경 + const handleChangePage = (page) => { + stuffSearchParams.code = 'S' + + setStuffSearch({ + ...stuffSearch, + code: 'S', + startRow: (page - 1) * pageSize + 1, + endRow: page * pageSize, + }) + + setPageNo(page) + } + return ( <> {/* 퍼블시작 */}
-

물건목록

+

{getMessage('stuff.search.grid.title')}

  • - 전체 - {convertNumberToPriceDecimal(gridCount)} + {getMessage('stuff.search.grid.all')} + {convertNumberToPriceDecimal(totalCount)}
  • - 선택 + {getMessage('stuff.search.grid.selected')} {convertNumberToPriceDecimal(selectedRowDataCount)}
@@ -434,8 +417,8 @@ export default function Stuff() {
@@ -450,7 +433,9 @@ export default function Stuff() {
-
페이징 컴포넌트예정
+
+ +
diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index 7167fc63..6800a5e8 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -16,6 +16,8 @@ import FindAddressPop from './popup/FindAddressPop' import PlanRequestPop from './popup/PlanRequestPop' import WindSelectPop from './popup/WindSelectPop' export default function StuffDetail() { + const [selOptions, setSelOptions] = useState('') + const sessionState = useRecoilValue(sessionStore) const router = useRouter() @@ -79,7 +81,7 @@ export default function StuffDetail() { const [detailData, setDetailData] = useState({}) useEffect(() => { - console.log('objectNo::', objectNo) + // console.log('objectNo::', objectNo) if (objectNo) { console.log('수정화면') @@ -100,33 +102,34 @@ export default function StuffDetail() { // 도도부현API get({ url: '/api/object/prefecture/list' }).then((res) => { if (!isEmptyArray(res)) { - // console.log('신규화면 도도부현API 결과:::', res) setPrefCodeList(res) } }) // 임시 1차점 판매점코드 saleStoreId=201TES01 // T01 - //1차점 : X167 - get({ url: `/api/object/saleStore/T01/list` }).then((res) => { - // get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => { + //1차점 : X167 T01 + // get({ url: `/api/object/saleStore/TEMP02/list` }).then((res) => { + get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => { if (!isEmptyArray(res)) { const firstList = res.filter((row) => row.saleStoreLevel === '1') const otherList = res.filter((row) => row.saleStoreLevel !== '1') //1차점 셀렉트박스 setSaleStoreList(firstList) + setSelOptions(sessionState?.storeId) + form.setValue('saleStoreId', sessionState?.storeId) + form.setValue('saleStoreLevel', sessionState?.storeLvl) + //1차점 아닌 판매점 셀렉트박스 setOriginOtherSaleStoreList(otherList) setOtherSaleStoreList(otherList) } }) } - }, [objectNo]) + }, [objectNo, sessionState]) useEffect(() => { if (isObjectNotEmpty(detailData)) { - console.log('상세데이타:::::::', detailData) - // 도도부현API get({ url: '/api/object/prefecture/list' }).then((res) => { if (!isEmptyArray(res)) { @@ -151,6 +154,8 @@ export default function StuffDetail() { setOtherSaleStoreList(otherList) } }) + + console.log('상세데이타::세팅:::::', detailData) } }, [detailData]) @@ -161,12 +166,14 @@ export default function StuffDetail() { form.setValue('saleStoreId', key.saleStoreId) form.setValue('saleStoreName', key.saleStoreName) form.setValue('saleStoreLevel', key.saleStoreLevel) + setSelOptions(key.saleStoreId) //선택한 1차점 정보로 2차점 list 추리기 //長府工産株式会社 大阪支社 let newOtherSaleStoreList = originOtherSaleStoreList.filter((row) => row.firstAgentId === key.saleStoreId) setOtherSaleStoreList(newOtherSaleStoreList) } else { //X누름 + setSelOptions('') form.setValue('saleStoreId', '') form.setValue('saleStoreName', '') form.setValue('saleStoreLevel', '') @@ -209,8 +216,17 @@ export default function StuffDetail() { form.setValue('zipNo', info.zipNo) } - //팝업에서 넘어온 설계의뢰 정보 - const setPlanReqInfo = (info) => {} + //팝업에서 넘어온 설계의뢰 정보로 바꾸기 + const setPlanReqInfo = (info) => { + console.log('팝업에서 넘어온 설계의뢰 정보::: ', info) + //building : 신축 기축 + //planReqName : 물건명 + //zipNo : 우편번호 + //도도부현 :address1 주소 : address2 미세팅 + //기준풍속 팝업열려면 setPrefValue(info.prefId) 필요 + //기준풍속 : + // form.setValue('dispCompanyName', info.planReqName) + } //팝업에서 넘어온 바람정보 const setWindSppedInfo = (info) => { @@ -286,7 +302,7 @@ export default function StuffDetail() { } // console.log('임시저장용::', errors) - setIsFormValid(Object.keys(errors).length === 0) + setIsFormValid(Object.keys(errors).length === 0 ? true : false) } else { console.log('상세일때 폼체크') } @@ -331,9 +347,8 @@ export default function StuffDetail() { // 발전량시뮬레이션 지역 목록 get({ url: `/api/object/prefecture/${prefValue}/list` }).then((res) => { if (!isEmptyArray(res)) { - // console.log('발전량 시뮬레이션::::::::', res) - form.setValue('areaId', res[0].areaId) - form.setValue('areaName', res[0].prefName) + // form.setValue('areaId', res[0].areaId) + // form.setValue('areaName', res[0].prefName) setAreaIdList(res) } }) @@ -342,28 +357,18 @@ export default function StuffDetail() { // 발전량 시뮬레이션 변경 const handleAreaIdOnChange = (e) => { - form.setValue('areaId', e.target.value) + form.setValue('areaId', e.areaId) + form.setValue('areaName', e.prefName) } - // useEffect(() => { - // if (!isEmptyArray(areaIdList)) { - // let _prefName = form.watch('prefName') - // // console.log('기준풍속 가져오는 API', _prefName) - // get({ url: `/api/object/windSpeed/${_prefName}/list` }).then((res) => { - // // console.log('res::', res) - // if (!isEmptyArray(res)) { - // setWindSpeedList(res) - // } - // }) - // } - // }, [areaIdList]) - //필수값 다 입력했을때 - const onValid = (data) => { + const onValid = (data, e) => { + const formData = form.getValues() + console.log('필수값 통과:::', data, formData) + // console.log('필수값 formData:::', formData) // 수정모드일때는 PUT // console.log('필수값 다 있고 저장') // console.log('data::::::', data) - const formData = form.getValues() // console.log('formData::::', formData) // const _dispCompanyName = watch('dispCompanyName') // const _objectStatusId = watch('objectStatusId') @@ -391,6 +396,8 @@ export default function StuffDetail() { // 임시저장 const onTempSave = async () => { + console.log('임시저장:::::') + return const formData = form.getValues() // console.log('formData::', formData) const params = { @@ -441,7 +448,7 @@ export default function StuffDetail() { let testobj = '10' del({ url: `/api/object/${testobj}` }).then((res) => { - // console.log('삭제 결과:::', res) + console.log('삭제 결과:::', res) router.push('/management/stuff') }) } @@ -470,9 +477,9 @@ export default function StuffDetail() {
- +
@@ -536,13 +543,21 @@ export default function StuffDetail() {
-
+
{prefCodeList?.length > 0 && ( - + // + 0 ? false : true} @@ -643,8 +678,25 @@ export default function StuffDetail() { {row.prefName} ) + })} + + */} + + isDisabled={areaIdList.length > 0 ? false : true} + />
@@ -669,9 +721,9 @@ export default function StuffDetail() {
*/} {getMessage('stuff.detail.windSpeedSpan')} - +
@@ -764,13 +816,13 @@ export default function StuffDetail() {
{!isFormValid ? ( - + ) : ( - + )} +
@@ -813,7 +865,7 @@ export default function StuffDetail() {
- {/* */} +
@@ -865,7 +917,7 @@ export default function StuffDetail() {
-
+
{/* { - setObjectNo(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schObjectNo: e.target.value }) + setObjectNo(objectNoRef.current.value) }} + onKeyUp={handleByOnKeyUp} />
@@ -204,12 +237,11 @@ export default function StuffSearchCondition() {
{ - setSaleStoreName(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schSaleStoreName: e.target.value }) + setSaleStoreName(saleStoreNameRef.current.value) }} />
@@ -219,12 +251,11 @@ export default function StuffSearchCondition() {
{ - setAddress(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schAddress: e.target.value }) + setAddress(addressRef.current.value) }} />
@@ -236,12 +267,11 @@ export default function StuffSearchCondition() {
{ - setobjectName(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schObjectName: e.target.value }) + setobjectName(objectNameRef.current.value) }} />
@@ -251,30 +281,50 @@ export default function StuffSearchCondition() {
{ - setDispCompanyName(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schDispCompanyName: e.target.value }) + setDispCompanyName(dispCompanyNameRef.current.value) }} />
{getMessage('stuff.search.schSelSaleStoreId')} - {schSelSaleStoreList?.length > 0 && ( - x.saleStoreName} + getOptionValue={(x) => x.saleStoreId} + value={schSelSaleStoreList.filter(function (option) { + if (stuffSearch?.code === 'S' && schSelSaleStoreId === '') { + return false + } else if (stuffSearch?.code === 'S' && schSelSaleStoreId !== '') { + return option.saleStoreId === schSelSaleStoreId + } else if (stuffSearch?.code === 'E' && schSelSaleStoreId !== '') { + return option.saleStoreId === schSelSaleStoreId + } else { + if (stuffSearch?.schSelSaleStoreId !== '') { + return option.saleStoreId === stuffSearch.schSelSaleStoreId + } else { + return false + } + } + })} + isDisabled={sessionState?.storeLvl === '1' ? false : true} + isClearable={true} + /> + )} +
@@ -284,11 +334,10 @@ export default function StuffSearchCondition() { { - setReceiveUser(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schReceiveUser: e.target.value }) + setReceiveUser(receiveUserRef.current.value) }} />
@@ -323,7 +372,7 @@ export default function StuffSearchCondition() { setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value }) }} /> - +
diff --git a/src/components/management/popup/FindAddressPop.jsx b/src/components/management/popup/FindAddressPop.jsx index b3702ded..0c480a52 100644 --- a/src/components/management/popup/FindAddressPop.jsx +++ b/src/components/management/popup/FindAddressPop.jsx @@ -79,7 +79,6 @@ export default function FindAddressPop(props) { } // 주소적용 클릭 const applyAddress = () => { - // console.log('주소적용 클릭:::::::::', prefId, address1, address2, address3, zipNo) if (prefId == null) { alert(getMessage('stuff.addressPopup.error.message2')) } else { diff --git a/src/components/management/popup/PlanRequestPop.jsx b/src/components/management/popup/PlanRequestPop.jsx index 224519d0..ab2a836c 100644 --- a/src/components/management/popup/PlanRequestPop.jsx +++ b/src/components/management/popup/PlanRequestPop.jsx @@ -1,6 +1,5 @@ import React, { useState, useRef, useEffect } from 'react' import { useForm } from 'react-hook-form' -import { queryStringFormatter } from '@/util/common-utils' import { useAxios } from '@/hooks/useAxios' import { globalLocaleStore } from '@/store/localeAtom' import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' @@ -12,14 +11,24 @@ import dayjs from 'dayjs' import PlanRequestPopQGrid from './PlanRequestPopQGrid' import { sessionStore } from '@/store/commonAtom' import { planReqSearchState } from '@/store/planReqAtom' +import { isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils' + +import Select from 'react-select' +import QPagination from '@/components/common/pagination/QPagination' export default function PlanRequestPop(props) { - const sessionState = useRecoilValue(sessionStore) + const [pageNo, setPageNo] = useState(1) //현재 페이지 번호 + const [pageSize, setPageSize] = useState(20) //페이지 당 게시물 개수 + const [totalCount, setTotalCount] = useState(0) //총 갯수 const globalLocaleState = useRecoilValue(globalLocaleStore) - const { get } = useAxios(globalLocaleState) + const [planReqObject, setPlanReqObject] = useState({}) + + const { get, promiseGet } = useAxios(globalLocaleState) const { getMessage } = useMessage() + //Select ref + const ref = useRef() // 검색조건 달력 셋팅 const [startDate, setStartDate] = useState(dayjs(new Date()).add(-3, 'month').format('YYYY-MM-DD')) const [endDate, setEndDate] = useState(dayjs(new Date()).format('YYYY-MM-DD')) @@ -34,7 +43,6 @@ export default function PlanRequestPop(props) { setStartDate: setEndDate, } - const ref = useRef() const resetPlanReqRecoil = useResetRecoilState(planReqSearchState) const [planReqSearch, setPlanReqSearch] = useRecoilState(planReqSearchState) @@ -47,14 +55,41 @@ export default function PlanRequestPop(props) { const [schDateGbn, setSchDateGbn] = useState('S') //기간구분코드(S/R) //초기화 - const resetRecoil = () => {} + const resetRecoil = () => { + setSchPlanReqNo('') + setSchTitle('') + setSchAddress('') + setSchSaleStoreName('') + setSchPlanReqName('') + setSchDateGbn('S') + setStartDate(dayjs(new Date()).add(-3, 'month').format('YYYY-MM-DD')) + setEndDate(dayjs(new Date()).format('YYYY-MM-DD')) + setSchPlanStatCd('') + handleClear() //셀렉트 자동완성 초기화 + resetPlanReqRecoil() + } - //초기화 눌렀을 때 자동완성도.. + //셀렉트 자동완성 초기화 const handleClear = () => { - if (ref.current.state.dropDown) { - ref.current.methods.dropDown() + if (ref.current) { + ref.current.clearValue() + } + } + + // 상태 검색조건 변경 + const onSelectionChange = (key) => { + //임시작업 + // console.log('E::::::::', key) + if (isObjectNotEmpty(key)) { + setSchPlanStatCd(key.value) + setPlanReqSearch({ + ...planReqSearch, + schPlanStatCd: key.value, + }) } else { - ref.current.state.values = [] + //X누름 + setSchPlanStatCd('') + setPlanReqSearch({ ...planReqSearch, schPlanStatCd: '' }) } } @@ -63,6 +98,60 @@ export default function PlanRequestPop(props) { setEndDate(planReqSearch?.schEndDt ? planReqSearch.schEndDt : dayjs(new Date()).format('YYYY-MM-DD')) }, [planReqSearch]) + // 조회 + const onSubmit = (page, type) => { + const params = { + // saleStoreId: 'T100', + // saleStoreLevel: '1', + saleStoreId: props?.otherSaleStoreId ? props.otherSaleStoreId : props.saleStoreId, + saleStoreLevel: props?.otherSaleStoreLevel ? props.otherSaleStoreLevel : props.saleStoreLevel, + schPlanReqNo: planReqSearch?.schPlanReqNo ? planReqSearch.schPlanReqNo : schPlanReqNo, + schTitle: planReqSearch?.schTitle ? planReqSearch.schTitle : schTitle, + schAddress: planReqSearch?.schAddress ? planReqSearch.schAddress : schAddress, + schSaleStoreName: planReqSearch?.schSaleStoreName ? planReqSearch.schSaleStoreName : schSaleStoreName, + schPlanReqName: planReqSearch?.schPlanReqName ? planReqSearch.schPlanReqName : schPlanReqName, + schPlanStatCd: planReqSearch?.schPlanStatCd ? planReqSearch.schPlanStatCd : schPlanStatCd, + schDateGbn: planReqSearch?.schDateGbn ? planReqSearch.schDateGbn : schDateGbn, + schStartDt: dayjs(startDate).format('YYYY-MM-DD'), + schEndDt: dayjs(endDate).format('YYYY-MM-DD'), + startRow: type === 'S' ? (1 - 1) * pageSize + 1 : (page - 1) * pageSize + 1, + endRow: type === 'S' ? 1 * pageSize : page * pageSize, + } + if (type === 'S') { + setPageNo(1) + } else { + setPageNo(page) + } + // console.log(params) + + const apiUrl = `/api/object/planReq/list?${queryStringFormatter(params)}` + promiseGet({ url: apiUrl }).then((res) => { + if (res.status === 200) { + if (isNotEmptyArray(res.data.data)) { + setGridProps({ ...gridProps, gridData: res.data.data, gridCount: res.data.data[0].totCnt }) + setTotalCount(res.data.data[0].totCnt) + } else { + setGridProps({ ...gridProps, gridData: [], gridCount: 0 }) + setTotalCount(0) + } + } else { + setGridProps({ ...gridProps, gridData: [], gridCount: 0 }) + setTotalCount(0) + } + }) + } + // 페이징 현재페이지 변경 + const handleChangePage = (page) => { + setPlanReqSearch({ + ...planReqSearch, + startRow: (page - 1) * pageSize + 1, + endRow: page * pageSize, + }) + setPageNo(page) + + onSubmit(page, 'P') + } + const [gridProps, setGridProps] = useState({ gridData: [], isPageable: false, @@ -117,6 +206,45 @@ export default function PlanRequestPop(props) { ], }) + //설계의뢰 그리드에서 선택한 설계의로 정보 + const getSelectedRowdata = (data) => { + if (isNotEmptyArray(data)) { + setPlanReqObject(data[0]) + } else { + setPlanReqObject({}) + } + } + + // 설계의뢰 적용 클릭 + const applyPlanReq = () => { + if (isObjectNotEmpty(planReqObject)) { + props.planReqInfo(planReqObject) + // 팝업닫기 + props.setShowDesignRequestButtonValid(false) + } else { + alert(getMessage('stuff.planReqPopup.error.message1')) + } + } + + const tempList = [ + { + label: '완료', + value: 'C', + }, + { + label: '저장', + value: 'I', + }, + { + label: '접수', + value: 'R', + }, + { + label: '제출', + value: 'S', + }, + ] + return (
@@ -132,8 +260,17 @@ export default function PlanRequestPop(props) {

{getMessage('stuff.planReqPopup.popTitle')}

- - + +
@@ -224,12 +361,18 @@ export default function PlanRequestPop(props) { {getMessage('stuff.planReqPopup.search.planStatName')}
- + +
@@ -158,7 +158,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal {getMessage('myinfo.info.nameKana')}
- +
@@ -166,7 +166,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal {getMessage('myinfo.info.name')}
- +
@@ -235,7 +235,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal {getMessage('myinfo.info.category')}
- +
@@ -243,7 +243,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal {getMessage('myinfo.info.tel')}
- +
@@ -251,7 +251,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal {getMessage('myinfo.info.fax')}
- +
@@ -259,7 +259,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal {getMessage('myinfo.info.mail')}
- +
diff --git a/src/hooks/object/useObjectBatch.js b/src/hooks/object/useObjectBatch.js index 7229f470..9ad8af5d 100644 --- a/src/hooks/object/useObjectBatch.js +++ b/src/hooks/object/useObjectBatch.js @@ -4,14 +4,7 @@ import { useRecoilState, useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' import { INPUT_TYPE, BATCH_TYPE } from '@/common/common' import { useEvent } from '@/hooks/useEvent' -import { - polygonToTurfPolygon, - rectToPolygon, - triangleToPolygon, - pointsToTurfPolygon, - splitDormerTriangle, - setSurfaceShapePattern, -} from '@/util/canvas-util' +import { polygonToTurfPolygon, rectToPolygon, triangleToPolygon, pointsToTurfPolygon, setSurfaceShapePattern } from '@/util/canvas-util' import { useSwal } from '@/hooks/useSwal' import * as turf from '@turf/turf' import { QPolygon } from '@/components/fabric/QPolygon' @@ -211,11 +204,13 @@ export function useObjectBatch() { const dormerName = buttonAct === 3 ? BATCH_TYPE.TRIANGLE_DORMER : BATCH_TYPE.PENTAGON_DORMER const dormerTempName = buttonAct === 3 ? BATCH_TYPE.TRIANGLE_DORMER_TEMP : BATCH_TYPE.PENTAGON_DORMER_TEMP const height = dormerPlacement.heightRef.current.value / 10 + const width = dormerPlacement.widthRef.current.value / 10 const pitch = dormerPlacement.pitchRef.current.value - const directionRef = dormerPlacement.directionRef.current const offsetRef = dormerPlacement.offsetRef.current.value === '' ? 0 : parseInt(dormerPlacement.offsetRef.current.value) / 10 + const offsetWidthRef = dormerPlacement.offsetWidthRef.current.value === '' ? 0 : parseInt(dormerPlacement.offsetWidthRef.current.value) / 10 + const directionRef = dormerPlacement.directionRef.current - let dormer, dormerOffset, isDown, selectedSurface + let dormer, dormerOffset, isDown, selectedSurface, pentagonPoints, pentagonOffsetPoints console.log('dormerPlacement', dormerPlacement) @@ -229,8 +224,6 @@ export function useObjectBatch() { const bottomLength = height / (pitch * 0.25) const bottomOffsetLength = (height + offsetRef) / (pitch * 0.25) - console.log(bottomOffsetLength) - addCanvasMouseEventListener('mouse:move', (e) => { isDown = true if (!isDown) return @@ -305,16 +298,16 @@ export function useObjectBatch() { addCanvasMouseEventListener('mouse:up', (e) => { if (dormer) { - // const trianglePolygon = pointsToTurfPolygon(triangleToPolygon(dormer)) - // const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface) + const trianglePolygon = pointsToTurfPolygon(triangleToPolygon(dormer)) + const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface) - // //지붕 밖으로 그렸을때 - // if (!turf.booleanWithin(trianglePolygon, selectedSurfacePolygon)) { - // swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' }) - // //일단 지워 - // deleteTempObjects() - // return - // } + //지붕 밖으로 그렸을때 + if (!turf.booleanWithin(trianglePolygon, selectedSurfacePolygon)) { + swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' }) + //일단 지워 + deleteTempObjects() + return + } //각도 추가 let originAngle = 0 //기본 남쪽 @@ -387,6 +380,183 @@ export function useObjectBatch() { drawDirectionArrow(leftTriangle) drawDirectionArrow(rightTriangle) + isDown = false + initEvent() + } + }) + } else if (buttonAct === 4) { + const heightLength = height - (width / 2) * (pitch * 0.25) + //(동의길이 깊이)+출폭(깊이)-[(입력한 폭값)/2+출폭(폭)]*(0.25*입력한 寸) + const heightOffsetLength = height + offsetRef - (width / 2 + offsetWidthRef) * (pitch * 0.25) + + addCanvasMouseEventListener('mouse:move', (e) => { + isDown = true + if (!isDown) return + + canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === dormerTempName)) //움직일때 일단 지워가면서 움직임 + const pointer = canvas.getPointer(e.e) + + surfaceShapePolygons.forEach((surface) => { + if (surface.inPolygon({ x: pointer.x, y: pointer.y })) { + selectedSurface = surface + } + }) + + let angle = 0 + if (directionRef === 'left') { + //서 + angle = 90 + } else if (directionRef === 'right') { + //동 + angle = 270 + } else if (directionRef === 'up') { + //북 + angle = 180 + } + + pentagonPoints = [ + { x: pointer.x, y: pointer.y }, + { x: pointer.x - width / 2, y: pointer.y + (height - heightLength) }, + { x: pointer.x - width / 2, y: pointer.y + height }, + { x: pointer.x + width / 2, y: pointer.y + height }, + { x: pointer.x + width / 2, y: pointer.y + (height - heightLength) }, + ] + + pentagonOffsetPoints = [ + { x: pointer.x, y: pointer.y }, + { x: pointer.x - width / 2 - offsetWidthRef, y: pointer.y + height + offsetRef - heightOffsetLength }, + { x: pointer.x - width / 2 - offsetWidthRef, y: pointer.y + height + offsetRef }, + { x: pointer.x + width / 2 + offsetWidthRef, y: pointer.y + height + offsetRef }, + { x: pointer.x + width / 2 + offsetWidthRef, y: pointer.y + height + offsetRef - heightOffsetLength }, + ] + + dormer = new QPolygon(pentagonPoints, { + fill: 'white', + stroke: 'red', + strokeDashArray: [5, 5], + strokeWidth: 1, + selectable: true, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + name: dormerTempName, + originX: 'center', + originY: 'top', + angle: angle, + }) + canvas?.add(dormer) + + if (offsetRef > 0 || offsetWidthRef > 0) { + dormerOffset = new QPolygon(pentagonOffsetPoints, { + fill: 'gray', + stroke: 'red', + strokeDashArray: [5, 5], + strokeWidth: 1, + selectable: true, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + name: dormerTempName, + originX: 'center', + originY: 'top', + angle: angle, + }) + canvas?.add(dormerOffset) + } + }) + + addCanvasMouseEventListener('mouse:up', (e) => { + if (dormer) { + // const trianglePolygon = pointsToTurfPolygon(triangleToPolygon(dormer)) + // const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface) + + // //지붕 밖으로 그렸을때 + // if (!turf.booleanWithin(trianglePolygon, selectedSurfacePolygon)) { + // swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' }) + // //일단 지워 + // deleteTempObjects() + // return + // } + + //각도 추가 + let originAngle = 0 //기본 남쪽 + let direction = 'south' + + if (directionRef === 'left') { + //서 + originAngle = 90 + direction = 'west' + } else if (directionRef === 'right') { + //동 + originAngle = 270 + direction = 'east' + } else if (directionRef === 'up') { + //북 + originAngle = 180 + direction = 'north' + } + + const offsetMode = offsetRef > 0 || offsetWidthRef > 0 ? 'offset' : 'normal' + let splitedPentagon = + offsetRef > 0 || offsetWidthRef > 0 + ? splitDormerPentagon(dormerOffset, directionRef, offsetMode) + : splitDormerPentagon(dormer, directionRef, offsetMode) + canvas?.remove(offsetRef > 0 || offsetWidthRef > 0 ? dormerOffset : dormer) + + if (offsetRef > 0) + dormer.set({ + name: dormerName, + stroke: 'black', + strokeWidth: 1, + strokeDashArray: [0], + }) //오프셋이 있을땐 같이 도머로 만든다 + + const leftPentagon = new QPolygon(splitedPentagon[0], { + fill: 'transparent', + stroke: 'red', + strokeWidth: 1, + selectable: true, + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + viewLengthText: true, + fontSize: 14, + direction: direction, + originX: 'center', + originY: 'center', + name: dormerName, + }) + + const rightPentagon = new QPolygon(splitedPentagon[1], { + fill: 'transparent', + stroke: 'red', + strokeWidth: 1, + selectable: true, + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + viewLengthText: true, + fontSize: 14, + direction: direction, + originX: 'center', + originY: 'center', + name: dormerName, + }) + + canvas?.add(leftPentagon) + canvas?.add(rightPentagon) + + //패턴 + setSurfaceShapePattern(leftPentagon) + setSurfaceShapePattern(rightPentagon) + //방향 + drawDirectionArrow(leftPentagon) + drawDirectionArrow(rightPentagon) + isDown = false initEvent() } @@ -408,8 +578,140 @@ export function useObjectBatch() { initEvent() //이벤트 초기화 } + const splitDormerTriangle = (triangle, direction) => { + const halfWidth = triangle.width / 2 + + let leftPoints = [] + let rightPoints = [] + + if (direction === 'down') { + leftPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left - halfWidth, y: triangle.top + triangle.height }, + { x: triangle.left, y: triangle.top + triangle.height }, + ] + + rightPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left, y: triangle.top + triangle.height }, + { x: triangle.left + halfWidth, y: triangle.top + triangle.height }, + ] + } else if (direction === 'up') { + leftPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left - halfWidth, y: triangle.top - triangle.height }, + { x: triangle.left, y: triangle.top - triangle.height }, + ] + + rightPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left, y: triangle.top - triangle.height }, + { x: triangle.left + halfWidth, y: triangle.top - triangle.height }, + ] + } else if (direction === 'left') { + leftPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left - triangle.height, y: triangle.top - halfWidth }, + { x: triangle.left - triangle.height, y: triangle.top }, + ] + + rightPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left - triangle.height, y: triangle.top }, + { x: triangle.left - triangle.height, y: triangle.top + halfWidth }, + ] + } else if (direction === 'right') { + leftPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left + triangle.height, y: triangle.top }, + { x: triangle.left + triangle.height, y: triangle.top + triangle.height }, + ] + + rightPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left + triangle.height, y: triangle.top }, + { x: triangle.left + triangle.height, y: triangle.top - triangle.height }, + ] + } + + return [leftPoints, rightPoints] + } + + const splitDormerPentagon = (pentagon, direction, offsetMode) => { + const points = pentagon.points + + console.log(pentagon.points) + + let leftPoints = [] + let rightPoints = [] + + if (direction === 'down') { + leftPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[1].x, y: points[1].y }, + { x: points[2].x, y: points[2].y }, + { x: points[0].x, y: points[3].y }, + ] + + rightPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[0].x, y: points[2].y }, + { x: points[3].x, y: points[3].y }, + { x: points[4].x, y: points[4].y }, + ] + } else if (direction === 'up') { + leftPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[1].x, y: points[0].y - (points[1].y - points[0].y) }, + { x: points[2].x, y: points[0].y - (points[2].y - points[0].y) }, + { x: points[0].x, y: points[0].y - (points[2].y - points[0].y) }, + ] + + rightPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[3].x, y: points[0].y - (points[1].y - points[0].y) }, + { x: points[3].x, y: points[0].y - (points[2].y - points[0].y) }, + { x: points[0].x, y: points[0].y - (points[2].y - points[0].y) }, + ] + } else if (direction === 'left') { + leftPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[0].x - (points[1].y - points[0].y), y: points[0].y - (points[0].x - points[1].x) }, + { x: points[0].x - (points[1].y - points[0].y) - (points[2].y - points[1].y), y: points[0].y - (points[0].x - points[1].x) }, + { x: points[0].x - (points[1].y - points[0].y) - (points[2].y - points[1].y), y: points[0].y }, + ] + + rightPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[0].x - (points[1].y - points[0].y), y: points[0].y + (points[0].x - points[1].x) }, + { x: points[0].x - (points[1].y - points[0].y) - (points[2].y - points[1].y), y: points[0].y + (points[0].x - points[1].x) }, + { x: points[0].x - (points[1].y - points[0].y) - (points[2].y - points[1].y), y: points[0].y }, + ] + } else if (direction === 'right') { + leftPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[0].x + (points[1].y - points[0].y), y: points[0].y + (points[0].x - points[1].x) }, + { x: points[0].x + (points[1].y - points[0].y) + (points[2].y - points[1].y), y: points[0].y + (points[0].x - points[1].x) }, + { x: points[0].x + (points[1].y - points[0].y) + (points[2].y - points[1].y), y: points[0].y }, + ] + + rightPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[0].x + (points[1].y - points[0].y), y: points[0].y - (points[0].x - points[1].x) }, + { x: points[0].x + (points[1].y - points[0].y) + (points[2].y - points[1].y), y: points[0].y - (points[0].x - points[1].x) }, + { x: points[0].x + (points[1].y - points[0].y) + (points[2].y - points[1].y), y: points[0].y }, + ] + } + + console.log(leftPoints, rightPoints) + + return [leftPoints, rightPoints] + } + return { applyOpeningAndShadow, applyDormers, + splitDormerTriangle, + splitDormerPentagon, } } diff --git a/src/hooks/option/useFirstOption.js b/src/hooks/option/useFirstOption.js new file mode 100644 index 00000000..4010b69e --- /dev/null +++ b/src/hooks/option/useFirstOption.js @@ -0,0 +1,23 @@ +import { useRecoilState, useRecoilValue } from 'recoil' +import { canvasState } from '@/store/canvasAtom' +import { useEffect } from 'react' +import { settingModalFirstOptionsState } from '@/store/settingAtom' + +export function useFirstOption() { + const canvas = useRecoilValue(canvasState) + + const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) + + useEffect(() => { + const option1 = settingModalFirstOptions.option1 + + canvas + .getObjects() + .filter((obj) => obj.name === '') + .forEach((obj) => { + obj.set({ visible: !obj.visible }) + }) + }, [settingModalFirstOptions]) + + return { settingModalFirstOptions, setSettingModalFirstOptions } +} diff --git a/src/hooks/roofcover/useAuxiliaryDrawing.js b/src/hooks/roofcover/useAuxiliaryDrawing.js index cb33f407..e5e79740 100644 --- a/src/hooks/roofcover/useAuxiliaryDrawing.js +++ b/src/hooks/roofcover/useAuxiliaryDrawing.js @@ -23,10 +23,11 @@ import { outerLineLength2State, outerLineTypeState, } from '@/store/outerLineAtom' -import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util' +import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint, polygonToTurfPolygon } from '@/util/canvas-util' import { fabric } from 'fabric' import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint' import { useSwal } from '@/hooks/useSwal' +import { booleanPointInPolygon } from '@turf/turf' // 보조선 작성 export function useAuxiliaryDrawing(setShowAuxiliaryModal) { @@ -76,6 +77,8 @@ export function useAuxiliaryDrawing(setShowAuxiliaryModal) { useEffect(() => { typeRef.current = type + clear() + addDocumentEventListener('keydown', document, keydown[type]) }, [type]) useEffect(() => { @@ -103,12 +106,8 @@ export function useAuxiliaryDrawing(setShowAuxiliaryModal) { } }, []) - useEffect(() => { - clear() - addDocumentEventListener('keydown', document, keydown[type]) - }, [type]) - const clear = () => { + addCanvasMouseEventListener('mouse:move', mouseMove) setLength1(0) setLength2(0) @@ -459,8 +458,9 @@ export function useAuxiliaryDrawing(setShowAuxiliaryModal) { } const mouseDown = (e) => { - addCanvasMouseEventListener('mouse:move', mouseMove) + canvas.renderAll() const pointer = getIntersectMousePoint(e) + console.log(pointer) mousePointerArr.current.push(pointer) if (mousePointerArr.current.length === 2) { @@ -538,59 +538,66 @@ export function useAuxiliaryDrawing(setShowAuxiliaryModal) { // 보조선 절삭 const cutAuxiliary = (e) => { - const auxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine' && !obj.isFixed) + const auxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine') if (auxiliaryLines.length === 0) { return } + const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase') + + const allLines = [...auxiliaryLines] + + roofBases.forEach((roofBase) => { + roofBase.lines.forEach((line) => { + allLines.push(line) + }) + }) + auxiliaryLines.forEach((line1) => { - auxiliaryLines.forEach((line2) => { - const lines = [line1, line2] + allLines.forEach((line2) => { if (line1 === line2) { return } - const intersectionPoint = calculateIntersection(line1, line2) - if (!intersectionPoint || intersectionPoints.current.some((point) => point.x === intersectionPoint.x && point.y === intersectionPoint.y)) { + if (!intersectionPoint) { return } roofAdsorptionPoints.current.push(intersectionPoint) intersectionPoints.current.push(intersectionPoint) - lines.forEach((line) => { - const distance1 = distanceBetweenPoints({ x: line.x1, y: line.y1 }, intersectionPoint) - const distance2 = distanceBetweenPoints({ x: line.x2, y: line.y2 }, intersectionPoint) - if (distance1 === 0 || distance2 === 0) { - return - } - //historyLine에서 기존 line을 제거한다. - lineHistory.current = lineHistory.current.filter((history) => history !== line) + const distance1 = distanceBetweenPoints({ x: line1.x1, y: line1.y1 }, intersectionPoint) + const distance2 = distanceBetweenPoints({ x: line1.x2, y: line1.y2 }, intersectionPoint) - let newLine + if (distance1 === 0 || distance2 === 0) { + return + } + //historyLine에서 기존 line을 제거한다. + lineHistory.current = lineHistory.current.filter((history) => history !== line1) - if (distance1 >= distance2) { - newLine = addLine([line.x1, line.y1, intersectionPoint.x, intersectionPoint.y], { - stroke: 'black', - strokeWidth: 1, - selectable: false, - name: 'auxiliaryLine', - isFixed: true, - intersectionPoint, - }) - } else { - newLine = addLine([line.x2, line.y2, intersectionPoint.x, intersectionPoint.y], { - stroke: 'black', - strokeWidth: 1, - selectable: false, - name: 'auxiliaryLine', - isFixed: true, - intersectionPoint, - }) - } - lineHistory.current.push(newLine) - removeLine(line) - }) + let newLine + + if (distance1 >= distance2) { + newLine = addLine([line1.x1, line1.y1, intersectionPoint.x, intersectionPoint.y], { + stroke: 'black', + strokeWidth: 1, + selectable: false, + name: 'auxiliaryLine', + isFixed: true, + intersectionPoint, + }) + } else { + newLine = addLine([line1.x2, line1.y2, intersectionPoint.x, intersectionPoint.y], { + stroke: 'black', + strokeWidth: 1, + selectable: false, + name: 'auxiliaryLine', + isFixed: true, + intersectionPoint, + }) + } + lineHistory.current.push(newLine) + removeLine(line1) }) }) addCanvasMouseEventListener('mouse:move', mouseMove) @@ -600,10 +607,15 @@ export function useAuxiliaryDrawing(setShowAuxiliaryModal) { * 일변전으로 돌아가기 */ const handleRollback = () => { - const lastLine = lineHistory.current.pop() - mousePointerArr.current = [] - canvas.remove(...canvas.getObjects().filter((obj) => obj.name === 'innerPoint')) + const innerPoint = canvas.getObjects().find((obj) => obj.name === 'innerPoint') + if (innerPoint) { + mousePointerArr.current = [] + canvas.remove(innerPoint) + canvas.renderAll() + return + } + const lastLine = lineHistory.current.pop() if (lastLine) { roofAdsorptionPoints.current = roofAdsorptionPoints.current.filter( (point) => point.x !== lastLine.intersectionPoint?.x && point.y !== lastLine.intersectionPoint?.y, @@ -621,10 +633,25 @@ export function useAuxiliaryDrawing(setShowAuxiliaryModal) { return } - const roofBases = canvas.getObjects().find((obj) => obj.name === 'roofBase') + const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase') const innerLines = [...lineHistory.current] - roofBases.innerLines = [...innerLines] + roofBases.forEach((roofBase) => { + const roofInnerLines = innerLines.filter((line) => { + const turfPolygon = polygonToTurfPolygon(roofBase) + + // innerLines의 두 점이 모두 polygon 안에 있는지 확인 + const inPolygon1 = booleanPointInPolygon([line.x1, line.y1], turfPolygon) + const inPolygon2 = booleanPointInPolygon([line.x2, line.y2], turfPolygon) + + if (inPolygon1 && inPolygon2) { + line.attributes = { ...line.attributes, roofId: roofBase.id } + return true + } + }) + + roofBase.innerLines = [...roofInnerLines] + }) setShowAuxiliaryModal(false) } diff --git a/src/hooks/roofcover/useOuterLineWall.js b/src/hooks/roofcover/useOuterLineWall.js index 07dab81e..4b4987af 100644 --- a/src/hooks/roofcover/useOuterLineWall.js +++ b/src/hooks/roofcover/useOuterLineWall.js @@ -29,12 +29,20 @@ import { } from '@/store/outerLineAtom' import { calculateAngle } from '@/util/qpolygon-utils' import { fabric } from 'fabric' +import { QLine } from '@/components/fabric/QLine' +import { outlineDisplaySelector } from '@/store/settingAtom' //외벽선 그리기 export function useOuterLineWall(setShowOutlineModal) { const canvas = useRecoilValue(canvasState) - const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseEvent } = - useEvent() + const { + initEvent, + addCanvasMouseEventListener, + addDocumentEventListener, + removeAllMouseEventListeners, + removeAllDocumentEventListeners, + removeMouseEvent, + } = useEvent() const { getIntersectMousePoint } = useMouse() const { addLine, removeLine } = useLine() const { tempGridMode } = useTempGrid() @@ -46,6 +54,8 @@ export function useOuterLineWall(setShowOutlineModal) { const adsorptionRange = useRecoilValue(adsorptionRangeState) const interval = useRecoilValue(dotLineIntervalSelector) // 가로 세로 간격 + const isOutlineDisplay = useRecoilValue(outlineDisplaySelector) + const length1Ref = useRef(null) const length2Ref = useRef(null) const angle1Ref = useRef(null) @@ -75,6 +85,9 @@ export function useOuterLineWall(setShowOutlineModal) { addCanvasMouseEventListener('mouse:down', mouseDown) clear() + return () => { + initEvent() + } }, [verticalHorizontalMode, points, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, interval, tempGridMode]) useEffect(() => { @@ -215,11 +228,11 @@ export function useOuterLineWall(setShowOutlineModal) { return } - /*if (lastPoint.x === firstPoint.x && lastPoint.y === firstPoint.y) { + if (Math.abs(lastPoint.x - firstPoint.x) < 1 && Math.abs(lastPoint.y - firstPoint.y) < 1) { return } - if (lastPoint.x === firstPoint.x || lastPoint.y === firstPoint.y) { + if (Math.abs(lastPoint.x - firstPoint.x) < 1 || Math.abs(lastPoint.y - firstPoint.y) < 1) { let isAllRightAngle = true const firstPoint = points[0] @@ -238,38 +251,30 @@ export function useOuterLineWall(setShowOutlineModal) { if (isAllRightAngle) { return } - const line = new QLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], { + const line = addLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], { stroke: 'grey', strokeWidth: 1, selectable: false, name: 'helpGuideLine', + visible: isOutlineDisplay, }) - - canvas?.add(line) - addLineText(line) } else { - const guideLine1 = new QLine([lastPoint.x, lastPoint.y, lastPoint.x, firstPoint.y], { + const guideLine1 = addLine([lastPoint.x, lastPoint.y, lastPoint.x, firstPoint.y], { stroke: 'grey', strokeWidth: 1, strokeDashArray: [1, 1, 1], name: 'helpGuideLine', + visible: isOutlineDisplay, }) - const guideLine2 = new QLine([guideLine1.x2, guideLine1.y2, firstPoint.x, firstPoint.y], { + const guideLine2 = addLine([guideLine1.x2, guideLine1.y2, firstPoint.x, firstPoint.y], { stroke: 'grey', strokeWidth: 1, strokeDashArray: [1, 1, 1], name: 'helpGuideLine', + visible: isOutlineDisplay, }) - if (guideLine1.length > 0) { - canvas?.add(guideLine1) - addLineText(guideLine1) - } - - canvas?.add(guideLine2) - - addLineText(guideLine2) - }*/ + } } }, [points]) @@ -284,6 +289,7 @@ export function useOuterLineWall(setShowOutlineModal) { y1: point1.y, x2: point2.x, y2: point2.y, + visible: isOutlineDisplay, }) } diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index 6533fe79..bc55c921 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -95,7 +95,11 @@ export function useRoofAllocationSetting(setShowRoofAllocationSettingModal) { const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase') const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine') roofBases.forEach((roofBase) => { - splitPolygonWithLines(roofBase) + try { + splitPolygonWithLines(roofBase) + } catch (e) { + return + } roofBase.innerLines.forEach((line) => { canvas.remove(line) diff --git a/src/hooks/roofcover/useRoofShapePassivitySetting.js b/src/hooks/roofcover/useRoofShapePassivitySetting.js index 217e71bc..f7b8b9fd 100644 --- a/src/hooks/roofcover/useRoofShapePassivitySetting.js +++ b/src/hooks/roofcover/useRoofShapePassivitySetting.js @@ -33,6 +33,11 @@ export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingMod const [type, setType] = useState(TYPES.EAVES) + const isFix = useRef(false) + const initLines = useRef([]) + + const [isLoading, setIsLoading] = useState(false) + const buttons = [ { id: 1, name: getMessage('eaves'), type: TYPES.EAVES }, { id: 2, name: getMessage('gable'), type: TYPES.GABLE }, @@ -46,15 +51,20 @@ export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingMod if (!outerLineFix || outerLines.length === 0) { swalFire({ text: '외벽선이 없습니다.' }) setShowRoofShapePassivitySettingModal(false) + return } + setIsLoading(true) }, []) useEffect(() => { + if (!isLoading) return addCanvasMouseEventListener('mouse:down', mouseDown) const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine') - canvas.remove(wallLines) + + canvas?.remove(...wallLines) const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + initLines.current = outerLines.map((line) => ({ ...line })) outerLines.forEach((outerLine, idx) => { if (idx === 0) { currentLineRef.current = outerLine @@ -66,10 +76,11 @@ export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingMod canvas?.renderAll() return () => { + handleLineToPolygon() canvas?.discardActiveObject() initEvent() } - }, []) + }, [isLoading]) useEffect(() => { const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') @@ -166,6 +177,14 @@ export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingMod } const handleSave = () => { + isFix.current = true + handleLineToPolygon() + + setShowRoofShapePassivitySettingModal(false) + } + + const handleLineToPolygon = () => { + const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase') const exceptObjs = canvas.getObjects().filter((obj) => obj.name !== 'outerLine' && obj.parent?.name !== 'outerLine') const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') exceptObjs.forEach((obj) => { @@ -176,13 +195,28 @@ export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingMod hideLine(line) }) - const wall = addPolygonByLines(lines, { name: 'wallLine', fill: 'transparent', stroke: 'black' }) + let wall + + if (isFix.current) { + wall = addPolygonByLines(lines, { name: 'wallLine', fill: 'transparent', stroke: 'black' }) + } else { + // 그냥 닫을 경우 처리 + wall = addPolygonByLines([...initLines.current], { name: 'wallLine', fill: 'transparent', stroke: 'black' }) + lines.forEach((line, idx) => { + line.attributes = initLines.current[idx].attributes + }) + } wall.lines = [...lines] + // 기존 그려진 지붕이 없다면 + + if (isFix.current) { + // 완료 한 경우에는 지붕까지 그려줌 + const roof = drawRoofPolygon(wall) + } - const roof = drawRoofPolygon(wall) canvas.renderAll() - setShowRoofShapePassivitySettingModal(false) } + return { handleSave, handleConfirm, buttons, type, setType, TYPES, offsetRef, pitchRef, handleRollback } } diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js index 1722e287..016cd365 100644 --- a/src/hooks/roofcover/useRoofShapeSetting.js +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -244,8 +244,13 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { } } - // 기존 wallLine 제거 - canvas?.remove(canvas.getObjects().filter((obj) => obj.name === 'wallLine')) + // 기존 wallLine, roofBase 제거 + canvas + .getObjects() + .filter((obj) => obj.name === 'wallLine' || obj.name === 'roofBase') + .forEach((line) => { + canvas.remove(line) + }) const polygon = addPolygonByLines(outerLines, { name: 'wallLine' }) polygon.lines = [...outerLines] diff --git a/src/hooks/roofcover/useWallLineOffsetSetting.js b/src/hooks/roofcover/useWallLineOffsetSetting.js index 6f65b58e..b84e9ef4 100644 --- a/src/hooks/roofcover/useWallLineOffsetSetting.js +++ b/src/hooks/roofcover/useWallLineOffsetSetting.js @@ -1,4 +1,4 @@ -import { canvasState } from '@/store/canvasAtom' +import { canvasState, currentObjectState } from '@/store/canvasAtom' import { useRecoilValue } from 'recoil' import { useEffect, useRef, useState } from 'react' import { useMessage } from '@/hooks/useMessage' @@ -21,6 +21,8 @@ export function useWallLineOffsetSetting(setShowWallLineOffsetSettingModal) { const arrow1Ref = useRef(null) const arrow2Ref = useRef(null) + const currentObject = useRecoilValue(currentObjectState) + const [isLoading, setIsLoading] = useState(false) const drawLine = (point1, point2, idx, direction = currentWallLineRef.current.direction) => { @@ -87,6 +89,7 @@ export function useWallLineOffsetSetting(setShowWallLineOffsetSettingModal) { if (!isLoading) { return } + canvas?.discardActiveObject() removeOuterLineEditCircle() addCanvasMouseEventListener('mouse:down', mouseDown) if (type === TYPES.WALL_LINE_EDIT) { @@ -94,6 +97,20 @@ export function useWallLineOffsetSetting(setShowWallLineOffsetSettingModal) { } }, [type]) + useEffect(() => { + canvas + .getObjects() + .filter((obj) => obj.name === 'outerLine') + .forEach((line) => { + line.set({ stroke: 'black' }) + }) + + if (currentObject?.name === 'outerLine') { + currentObject.set({ stroke: '#EA10AC' }) + canvas.renderAll() + } + }, [currentObject]) + const removeOuterLineEditCircle = () => { canvas.remove(...canvas.getObjects().filter((obj) => obj.name === 'outerLineEditCircleStart' || obj.name === 'outerLineEditCircleEnd')) } @@ -106,7 +123,6 @@ export function useWallLineOffsetSetting(setShowWallLineOffsetSettingModal) { } currentWallLineRef.current = e.target - console.log(currentWallLineRef.current.idx, currentWallLineRef.current.direction) if (type === TYPES.WALL_LINE_EDIT) { addCircleByLine(currentWallLineRef.current) } diff --git a/src/hooks/surface/usePlacementShapeDrawing.js b/src/hooks/surface/usePlacementShapeDrawing.js index 4df37618..123e991d 100644 --- a/src/hooks/surface/usePlacementShapeDrawing.js +++ b/src/hooks/surface/usePlacementShapeDrawing.js @@ -232,11 +232,11 @@ export function usePlacementShapeDrawing(setShowPlaceShapeDrawingModal) { return } - /*if (lastPoint.x === firstPoint.x && lastPoint.y === firstPoint.y) { + if (Math.abs(lastPoint.x - firstPoint.x) < 1 && Math.abs(lastPoint.y - firstPoint.y) < 1) { return } - if (lastPoint.x === firstPoint.x || lastPoint.y === firstPoint.y) { + if (Math.abs(lastPoint.x - firstPoint.x) < 1 || Math.abs(lastPoint.y - firstPoint.y) < 1) { let isAllRightAngle = true const firstPoint = points[0] @@ -255,38 +255,27 @@ export function usePlacementShapeDrawing(setShowPlaceShapeDrawingModal) { if (isAllRightAngle) { return } - const line = new QLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], { + const line = addLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], { stroke: 'grey', strokeWidth: 1, selectable: false, name: 'helpGuideLine', }) - - canvas?.add(line) - addLineText(line) } else { - const guideLine1 = new QLine([lastPoint.x, lastPoint.y, lastPoint.x, firstPoint.y], { + const guideLine1 = addLine([lastPoint.x, lastPoint.y, lastPoint.x, firstPoint.y], { stroke: 'grey', strokeWidth: 1, strokeDashArray: [1, 1, 1], name: 'helpGuideLine', }) - const guideLine2 = new QLine([guideLine1.x2, guideLine1.y2, firstPoint.x, firstPoint.y], { + const guideLine2 = addLine([guideLine1.x2, guideLine1.y2, firstPoint.x, firstPoint.y], { stroke: 'grey', strokeWidth: 1, strokeDashArray: [1, 1, 1], name: 'helpGuideLine', }) - if (guideLine1.length > 0) { - canvas?.add(guideLine1) - addLineText(guideLine1) - } - - canvas?.add(guideLine2) - - addLineText(guideLine2) - }*/ + } } }, [points]) diff --git a/src/hooks/useAdsorptionPoint.js b/src/hooks/useAdsorptionPoint.js index 49d49714..396db98c 100644 --- a/src/hooks/useAdsorptionPoint.js +++ b/src/hooks/useAdsorptionPoint.js @@ -2,13 +2,14 @@ import { useRecoilState, useRecoilValue } from 'recoil' import { adsorptionPointAddModeState, adsorptionPointModeState, adsorptionRangeState, canvasState } from '@/store/canvasAtom' import { fabric } from 'fabric' import { useMouse } from '@/hooks/useMouse' +import { gridDisplaySelector } from '@/store/settingAtom' export function useAdsorptionPoint() { const canvas = useRecoilValue(canvasState) const [adsorptionPointAddMode, setAdsorptionPointAddMode] = useRecoilState(adsorptionPointAddModeState) const [adsorptionPointMode, setAdsorptionPointMode] = useRecoilState(adsorptionPointModeState) const [adsorptionRange, setAdsorptionRange] = useRecoilState(adsorptionRangeState) - + const isGridDisplay = useRecoilValue(gridDisplaySelector) const { getIntersectMousePoint } = useMouse() const getAdsorptionPoints = () => { @@ -28,6 +29,7 @@ export function useAdsorptionPoint() { y: pointer.y, selectable: true, name: 'adsorptionPoint', + visible: isGridDisplay, }) canvas.add(adsorptionPoint) diff --git a/src/hooks/useAxios.js b/src/hooks/useAxios.js index c125c28a..f2e8add9 100644 --- a/src/hooks/useAxios.js +++ b/src/hooks/useAxios.js @@ -40,59 +40,59 @@ export function useAxios(lang = '') { // response 추가 로직 axios.interceptors.request.use(undefined, (error) => {}) - const get = async ({ url }) => { + const get = async ({ url, option = {} }) => { return await getInstances(url) - .get(url) + .get(url, option) .then((res) => res.data) .catch(console.error) } - const promiseGet = async ({ url }) => { - return await getInstances(url).get(url) + const promiseGet = async ({ url, option = {} }) => { + return await getInstances(url).get(url, option) } - const post = async ({ url, data }) => { + const post = async ({ url, data, option = {} }) => { return await getInstances(url) - .post(url, data) + .post(url, data, option) .then((res) => res.data) .catch(console.error) } - const promisePost = async ({ url, data }) => { - return await getInstances(url).post(url, data) + const promisePost = async ({ url, data, option = {} }) => { + return await getInstances(url).post(url, data, option) } - const put = async ({ url, data }) => { + const put = async ({ url, data, option = {} }) => { return await getInstances(url) - .put(url, data) + .put(url, data, option) .then((res) => res.data) .catch(console.error) } - const promisePut = async ({ url, data }) => { - return await getInstances(url).put(url, data) + const promisePut = async ({ url, data, option = {} }) => { + return await getInstances(url).put(url, data, option) } - const patch = async ({ url, data }) => { + const patch = async ({ url, data, option = {} }) => { return await getInstances(url) - .patch(url, data) + .patch(url, data, option) .then((res) => res.data) .catch(console.error) } - const promisePatch = async ({ url, data }) => { - return await getInstances(url).patch(url, data) + const promisePatch = async ({ url, data, option = {} }) => { + return await getInstances(url).patch(url, data, option) } - const del = async ({ url }) => { + const del = async ({ url, option = {} }) => { return await getInstances(url) - .delete(url) + .delete(url, option) .then((res) => res.data) .catch(console.error) } - const promiseDel = async ({ url }) => { - return await getInstances(url).delete(url) + const promiseDel = async ({ url, option = {} }) => { + return await getInstances(url).delete(url, option) } return { get, promiseGet, post, promisePost, put, promisePut, patch, promisePatch, del, promiseDel } diff --git a/src/hooks/useEvent.js b/src/hooks/useEvent.js index 639b61b3..a84dea38 100644 --- a/src/hooks/useEvent.js +++ b/src/hooks/useEvent.js @@ -2,10 +2,11 @@ import { useEffect, useRef } from 'react' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { canvasState, canvasZoomState, currentMenuState, textModeState } from '@/store/canvasAtom' import { fabric } from 'fabric' -import { calculateDistance, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util' +import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint, polygonToTurfPolygon } from '@/util/canvas-util' import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint' import { useDotLineGrid } from '@/hooks/useDotLineGrid' import { useTempGrid } from '@/hooks/useTempGrid' +import { gridDisplaySelector } from '@/store/settingAtom' export function useEvent() { const canvas = useRecoilValue(canvasState) @@ -43,7 +44,6 @@ export function useEvent() { //default Event 추가 addCanvasMouseEventListener('mouse:move', defaultMouseMoveEvent) addCanvasMouseEventListener('mouse:out', defaultMouseOutEvent) - addDocumentEventListener('keydown', document, defaultKeyboardEvent) addDocumentEventListener('contextmenu', document, defaultContextMenuEvent) if (adsorptionPointAddMode) { addCanvasMouseEventListener('mouse:down', adsorptionPointAddModeStateEvent) @@ -152,6 +152,17 @@ export function useEvent() { } } + try { + const helpGuideLines = canvas.getObjects().filter((obj) => obj.name === 'helpGuideLine') + if (helpGuideLines.length === 2) { + const guideIntersectionPoint = calculateIntersection(helpGuideLines[0], helpGuideLines[1]) + + if (guideIntersectionPoint && distanceBetweenPoints(guideIntersectionPoint, pointer) <= adsorptionRange) { + arrivalPoint = guideIntersectionPoint + } + } + } catch (e) {} + const horizontalLine = new fabric.Line([-1 * canvas.width, arrivalPoint.y, 2 * canvas.width, arrivalPoint.y], { stroke: 'red', strokeWidth: 1, diff --git a/src/hooks/useLine.js b/src/hooks/useLine.js index f2941e33..a313d127 100644 --- a/src/hooks/useLine.js +++ b/src/hooks/useLine.js @@ -14,7 +14,7 @@ export const useLine = () => { fontFamily: fontFamily, }) - if (line.length === 0) { + if (line.length < 1) { return null } diff --git a/src/hooks/useMessage.js b/src/hooks/useMessage.js index f336f0b7..3a2fc316 100644 --- a/src/hooks/useMessage.js +++ b/src/hooks/useMessage.js @@ -1,14 +1,17 @@ +import { useEffect } from 'react' import { useRecoilValue } from 'recoil' -import { appMessageStore } from '@/store/localeAtom' +import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' -// import KO from '@/locales/ko.json' -// import JA from '@/locales/ja.json' +import KO from '@/locales/ko.json' +import JA from '@/locales/ja.json' const SESSION_STORAGE_MESSAGE_KEY = 'QCAST_MESSAGE_STORAGE' export const useMessage = () => { // const globalLocale = useRecoilValue(globalLocaleState) - const appMessageState = useRecoilValue(appMessageStore) + // const appMessageState = useRecoilValue(appMessageStore) + const globalLocale = useRecoilValue(globalLocaleStore) + const appMessageState = globalLocale === 'ko' ? KO : JA const getMessage = (key, args = []) => { // if (sessionStorage.getItem(SESSION_STORAGE_MESSAGE_KEY) === null) { diff --git a/src/hooks/usePagination.js b/src/hooks/usePagination.js index 4fc3a959..7d76d293 100644 --- a/src/hooks/usePagination.js +++ b/src/hooks/usePagination.js @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { useEffect, useState } from 'react' /** * 페이지네이션 훅 @@ -14,6 +14,10 @@ const usePagination = ({ pageNo = 1, pageSize = 10, pagePerBlock = 10, totalCoun setCurrentPage(page) } + useEffect(() => { + setCurrentPage(pageNo) + }, [pageNo]) + const pageGroup = Math.floor((currentPage - 1) / pagePerBlock) + 1 const totalPages = Math.ceil(totalCount / pageSize) const pages = Array.from({ length: totalPages }, (_, i) => i + 1) diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index 6d74cd93..b1273d82 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -1,14 +1,19 @@ +import { useEffect, useState } from 'react' import { useRecoilState } from 'recoil' +import { v4 as uuidv4 } from 'uuid' import { canvasState, currentCanvasPlanState, initCanvasPlansState, plansState } from '@/store/canvasAtom' import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' import { useSwal } from '@/hooks/useSwal' export function usePlan() { + const [planNum, setPlanNum] = useState(0) + const [canvas, setCanvas] = useRecoilState(canvasState) const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) - const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) - const [plans, setPlans] = useRecoilState(plansState) + const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) // DB에 저장된 plan + const [plans, setPlans] = useRecoilState(plansState) // 전체 plan (DB에 저장된 plan + 저장 안된 새로운 plan) + const { swalFire } = useSwal() const { getMessage } = useMessage() const { get, promisePost, promisePut, promiseDel } = useAxios() @@ -72,6 +77,9 @@ export function usePlan() { // }, 1000) } + /** + * 현재 캔버스에 그려진 데이터를 추출 + */ const currentCanvasData = () => { removeMouseLines() return addCanvas() @@ -81,8 +89,7 @@ export function usePlan() { * 실시간 캔버스 상태와 DB에 저장된 캔버스 상태를 비교하여 수정 여부를 판단 */ const checkModifiedCanvasPlan = () => { - removeMouseLines() - const canvasStatus = addCanvas() + const canvasStatus = currentCanvasData() const initPlanData = initCanvasPlans.find((plan) => plan.id === currentCanvasPlan.id) if (!initPlanData) { @@ -90,15 +97,10 @@ export function usePlan() { return JSON.parse(canvasStatus).objects.length > 0 } else { // 저장된 캔버스 - if (canvasStatus === initPlanData.canvasStatus) { - return false - } else { - // 각각 object들의 id 목록을 추출하여 비교 - const canvasObjsIds = getObjectIds(JSON.parse(canvasStatus).objects) - const dbObjsIds = getObjectIds(JSON.parse(initPlanData.canvasStatus).objects) - - return canvasObjsIds.length !== dbObjsIds.length || !canvasObjsIds.every((id, index) => id === dbObjsIds[index]) - } + // 각각 object들의 id 목록을 추출하여 비교 + const canvasObjsIds = getObjectIds(JSON.parse(canvasStatus).objects) + const dbObjsIds = getObjectIds(JSON.parse(initPlanData.canvasStatus).objects) + return canvasObjsIds.length !== dbObjsIds.length || !canvasObjsIds.every((id, index) => id === dbObjsIds[index]) } } const getObjectIds = (objects) => { @@ -112,9 +114,6 @@ export function usePlan() { * DB에 저장된 데이터를 canvas에서 사용할 수 있도록 포맷화 */ const dbToCanvasFormat = (cs) => { - // return JSON.stringify(cs.replace(/##/g, '"')) //.replace(/\\/g, ''))//.slice(1, -1)) - // JSON.stringify()를 사용하면 "가 \"로 바뀐다. 따라서, JSON.stringify를 제거 - // canvasToDbFormat()에서 \\의 상황을 없앴으므로 replace(/\\/g, '')를 제거 return cs.replace(/##/g, '"') } @@ -122,92 +121,24 @@ export function usePlan() { * canvas의 데이터를 DB에 저장할 수 있도록 포맷화 */ const canvasToDbFormat = (cs) => { - // return JSON.stringify(cs).replace(/"/g, '##') - // addCanvas()에서 JSON.stringify()를 거쳐서 나오는데, 또 감싸버려서 \가 \\로 된다. 따라서, JSON.stringify를 제거 return cs.replace(/"/g, '##') } /** - * 페이지 내 캔버스를 저장하는 함수 - * - * 1. 신규 저장 : POST - * param(body) : userId, objectNo, canvasStatus - * 2. 수정 저장 : PUT - * param(body) : id, canvasStatus + * 페이지 내 캔버스를 저장 */ const saveCanvas = async (userId) => { - removeMouseLines() - const canvasStatus = addCanvas() - - if (initCanvasPlans.some((plan) => plan.id === currentCanvasPlan.id)) { - // canvas 수정 - const planData = { - id: currentCanvasPlan.id, - canvasStatus: canvasToDbFormat(canvasStatus), - } - - return await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData }) - .then((res) => { - swalFire({ text: getMessage('common.message.save') }) - // console.log('[PUT] canvas-statuses res :::::::: %o', res) - setInitCanvasPlans((initCanvasPlans) => - initCanvasPlans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)), - ) - setPlans((plans) => plans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan))) - }) - .catch((error) => { - swalFire({ text: error.message, icon: 'error' }) - // console.error('[PUT] canvas-statuses error :::::::: %o', error) - }) - } else { - // canvas 신규 등록 - const planData = { - userId: userId, - imageName: 'image_name', // api 필수항목이여서 임시로 넣음, 이후 삭제 필요 - objectNo: currentCanvasPlan.objectNo, - canvasStatus: canvasToDbFormat(canvasStatus), - } - - return await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData }) - .then((res) => { - swalFire({ text: getMessage('common.message.save') }) - // console.log('[POST] canvas-statuses response :::::::: %o', res) - setInitCanvasPlans((initCanvasPlans) => [ - ...initCanvasPlans, - { - id: res.data, - name: currentCanvasPlan.objectNo + '-' + res.data, - userId: userId, - canvasStatus: canvasStatus, - isNew: currentCanvasPlan.id, - }, - ]) - setPlans((plans) => - plans.map((plan) => - plan.id === currentCanvasPlan.id - ? { - ...plan, - id: res.data, - name: currentCanvasPlan.objectNo + '-' + res.data, - userId: userId, - canvasStatus: canvasStatus, - isNew: currentCanvasPlan.id, - } - : plan, - ), - ) - }) - .catch((error) => { - swalFire({ text: error.message, icon: 'error' }) - // console.error('[POST] canvas-statuses res error :::::::: %o', error) - }) - } + const canvasStatus = currentCanvasData() + initCanvasPlans.some((plan) => plan.id === currentCanvasPlan.id) + ? await putCanvasStatus(canvasStatus) + : await postCanvasStatus(userId, canvasStatus) } /** - * objectNo에 해당하는 canvas 목록을 조회하는 함수 + * objectNo에 해당하는 canvas 목록을 조회 */ const getCanvasByObjectNo = async (userId, objectNo) => { + // console.log(`[GET] objectNo: ${objectNo} / userId: ${userId}`) return get({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}/${userId}` }).then((res) => res.map((item) => ({ id: item.id, @@ -220,27 +151,193 @@ export function usePlan() { } /** - * id에 해당하는 canvas 데이터를 삭제하는 함수 + * canvas 데이터를 추가 + */ + const postCanvasStatus = async (userId, canvasStatus) => { + const planData = { + userId: userId, + imageName: 'image_name', // api 필수항목이여서 임시로 넣음, 이후 삭제 필요 + objectNo: currentCanvasPlan.objectNo, + canvasStatus: canvasToDbFormat(canvasStatus), + } + await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData }) + .then((res) => { + swalFire({ text: getMessage('plan.message.save') }) + setInitCanvasPlans((initCanvasPlans) => [...initCanvasPlans, { id: res.data, canvasStatus: canvasStatus }]) + setPlans((plans) => + plans.map((plan) => + plan.id === currentCanvasPlan.id + ? { + ...plan, + id: res.data, + name: currentCanvasPlan.objectNo + '-' + res.data, + canvasStatus: canvasStatus, + } + : plan, + ), + ) + }) + .catch((error) => { + swalFire({ text: error.message, icon: 'error' }) + }) + } + + /** + * id에 해당하는 canvas 데이터를 수정 + */ + const putCanvasStatus = async (canvasStatus) => { + const planData = { + id: currentCanvasPlan.id, + canvasStatus: canvasToDbFormat(canvasStatus), + } + await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData }) + .then((res) => { + swalFire({ text: getMessage('plan.message.save') }) + setInitCanvasPlans((initCanvasPlans) => + initCanvasPlans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)), + ) + setPlans((plans) => plans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan))) + }) + .catch((error) => { + swalFire({ text: error.message, icon: 'error' }) + }) + } + + /** + * id에 해당하는 canvas 데이터를 삭제 */ const delCanvasById = (id) => { return promiseDel({ url: `/api/canvas-management/canvas-statuses/by-id/${id}` }) } /** - * objectNo에 해당하는 canvas 데이터들을 삭제하는 함수 + * objectNo에 해당하는 canvas 데이터들을 삭제 */ const delCanvasByObjectNo = (objectNo) => { return promiseDel({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}` }) } + /** + * plan 이동 + * 현재 plan의 작업상태를 확인, 저장 후 이동 + */ + const handleCurrentPlan = (userId, newCurrentId) => { + if (!currentCanvasPlan || currentCanvasPlan.id !== newCurrentId) { + if (currentCanvasPlan?.id && checkModifiedCanvasPlan()) { + swalFire({ + text: `${currentCanvasPlan.name} ` + getMessage('plan.message.confirm.save'), + type: 'confirm', + confirmFn: async () => { + await saveCanvas(userId) + updateCurrentPlan(newCurrentId) + }, + denyFn: () => { + updateCurrentPlan(newCurrentId) + }, + }) + } else { + updateCurrentPlan(newCurrentId) + } + } + } + const updateCurrentPlan = (newCurrentId) => { + setPlans((plans) => + plans.map((plan) => { + return { ...plan, isCurrent: plan.id === newCurrentId } + }), + ) + } + useEffect(() => { + setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null) + }, [plans]) + + /** + * 새로운 plan 생성 + * 현재 plan의 데이터가 있을 경우 복제 여부를 확인 + */ + const handleAddPlan = (userId, objectNo) => { + JSON.parse(currentCanvasData()).objects.length > 0 + ? swalFire({ + text: `${currentCanvasPlan.name} ` + getMessage('plan.message.confirm.copy'), + type: 'confirm', + confirmFn: () => { + addPlan(userId, objectNo, currentCanvasData()) + }, + denyFn: () => { + addPlan(userId, objectNo) + }, + }) + : addPlan(userId, objectNo) + } + const addPlan = (userId, objectNo, canvasStatus = '') => { + const id = uuidv4() + const newPlan = { + id: id, + name: `Plan ${planNum + 1}`, + objectNo: objectNo, + userId: userId, + canvasStatus: canvasStatus, + } + setPlans([...plans, newPlan]) + handleCurrentPlan(userId, id) + setPlanNum(planNum + 1) + } + + /** + * plan 삭제 + */ + const handleDeletePlan = (e, id) => { + e.stopPropagation() // 이벤트 버블링 방지 + + if (initCanvasPlans.some((plan) => plan.id === id)) { + delCanvasById(id) + .then((res) => { + swalFire({ text: getMessage('plan.message.delete') }) + setInitCanvasPlans((initCanvasPlans) => initCanvasPlans.filter((plan) => plan.id !== id)) + setPlans((plans) => plans.filter((plan) => plan.id !== id)) + }) + .catch((error) => { + swalFire({ text: error.message, icon: 'error' }) + }) + } else { + setPlans((plans) => plans.filter((plan) => plan.id !== id)) + swalFire({ text: getMessage('plan.message.delete') }) + } + + // 삭제 후 last 데이터에 포커싱 + const lastPlan = plans.filter((plan) => plan.id !== id).at(-1) + if (!lastPlan) { + setPlanNum(0) + setCurrentCanvasPlan(null) + } else if (id !== lastPlan.id) { + updateCurrentPlan(lastPlan.id) + } + } + + /** + * plan 조회 + */ + const loadCanvasPlanData = (userId, objectNo) => { + getCanvasByObjectNo(userId, objectNo).then((res) => { + // console.log('canvas 목록 ', res) + if (res.length > 0) { + setInitCanvasPlans(res) + setPlans(res) + updateCurrentPlan(res.at(-1).id) // last 데이터에 포커싱 + setPlanNum(res.length) + } else { + addPlan(userId, objectNo) + } + }) + } + return { canvas, - removeMouseLines, - currentCanvasData, + plans, saveCanvas, - addCanvas, - checkModifiedCanvasPlan, - getCanvasByObjectNo, - delCanvasById, + handleCurrentPlan, + handleAddPlan, + handleDeletePlan, + loadCanvasPlanData, } } diff --git a/src/hooks/useTempGrid.js b/src/hooks/useTempGrid.js index 8d7bac42..30847a2f 100644 --- a/src/hooks/useTempGrid.js +++ b/src/hooks/useTempGrid.js @@ -1,11 +1,13 @@ import { canvasState, tempGridModeState } from '@/store/canvasAtom' import { useRecoilState, useRecoilValue } from 'recoil' import { gridColorState } from '@/store/gridAtom' +import { gridDisplaySelector } from '@/store/settingAtom' export function useTempGrid() { const canvas = useRecoilValue(canvasState) const gridColor = useRecoilValue(gridColorState) const [tempGridMode, setTempGridMode] = useRecoilState(tempGridModeState) + const isGridDisplay = useRecoilValue(gridDisplaySelector) const tempGridModeStateLeftClickEvent = (e) => { //임의 그리드 모드일 경우 let pointer = canvas.getPointer(e.e) @@ -22,6 +24,7 @@ export function useTempGrid() { strokeDashArray: [5, 2], opacity: 0.3, direction: 'vertical', + visible: isGridDisplay, name: 'tempGrid', }) @@ -48,6 +51,7 @@ export function useTempGrid() { strokeDashArray: [5, 2], opacity: 0.3, name: 'tempGrid', + visible: isGridDisplay, direction: 'horizontal', }) diff --git a/src/locales/client.js b/src/locales/client.js deleted file mode 100644 index c4679862..00000000 --- a/src/locales/client.js +++ /dev/null @@ -1,18 +0,0 @@ -'use client' - -import { createI18nClient } from 'next-international/client' - -export const { useI18n, useScopedI18n, I18nProviderClient, useChangeLocale, defineLocale, useCurrentLocale } = createI18nClient( - { - ko: () => import('./ko'), - ja: () => import('./ja'), - }, - { - // Uncomment to set base path - // basePath: '/base', - // Uncomment to use custom segment name - // segmentName: 'locale', - // Uncomment to set fallback locale - // fallbackLocale: en, - }, -) diff --git a/src/locales/ja.js b/src/locales/ja.js deleted file mode 100644 index 5ae1b171..00000000 --- a/src/locales/ja.js +++ /dev/null @@ -1,90 +0,0 @@ -console.log('Loaded JA') - -export default { - hello: 'こんにちは', - welcome: 'こんにちは {name}!', - locale: '現在のロケールは {locale} です。', - common: { - require: '필수', - }, - site: { - name: 'Q.CAST III', - sub_name: '태양광 발전 시스템 도면관리 사이트', - }, - login: { - login: 'Login', - init_password: { - btn: '비밀번호 초기화', - title: '비밀번호 초기화', - sub_title: '비밀번호를 초기화할 아이디와 이메일 주소를 입력해 주세요.', - }, - }, - join: { - title: 'Q.CAST3 로그인ID 발행 신청', - sub1: { - title: '판매대리점 정보', - comment: '※ 등록되는 리셀러의 회사 이름을 입력하십시오. (2차점은 「○○판매주식회사(2차점:××설비주식회사)」로 기입해 주세요.)', - storeQcastNm: '판매대리점명', - storeQcastNm_placeholder: '株式会社エネルギア・ソリューション・アンド・サービス(2次店:山口住機販売有限会社)', - storeQcastNmKana: '판매대리점명 후리가나', - storeQcastNmKana_placeholder: 'カブシキガイシャエネルギア・ソリューション・アン', - postCd: '우편번호', - postCd_placeholder: '숫자 7자리', - addr: '주소', - addr_placeholder: '전각50자이내', - telNo: '전화번호', - telNo_placeholder: '00-0000-0000', - fax: 'FAX 번호', - fax_placeholder: '00-0000-0000', - }, - sub2: { - title: '담당자 정보', - userNm: '담당자명', - userNmKana: '담당자명 후리가나', - userId: '신청 ID', - email: '이메일 주소', - telNo: '전화번호', - telNo_placeholder: '00-0000-0000', - fax: 'FAX 번호', - fax_placeholder: '00-0000-0000', - category: '부서명', - }, - sub3: { - title: '견적서 제출용 회사정보', - qtCompNm: '회사명', - qtPostCd: '우편번호', - qtPostCd_placeholder: '숫자 7자리', - qtAddr: '주소', - qtAddr_placeholder: '전각50자이내', - qtEmail: '이메일 주소', - qtTelNo: '전화번호', - qtTelNo_placeholder: '00-0000-0000', - qtFax: 'FAX 번호', - qtFax_placeholder: '00-0000-0000', - }, - btn: { - approval_request: 'ID 승인요청', - }, - complete: { - title: 'Q.CAST3 로그인ID 발행신청 완료', - contents: '※ 신청한 ID가 승인되면, 담당자 정보에 입력한 이메일 주소로 로그인 관련 안내 메일이 전송됩니다.', - email_comment: '담당자 이메일 주소', - email: 'test@naver.com', - }, - }, - stuff: { - gridHeader: { - lastEditDatetime: '갱신일시', - objectNo: '물건번호', - planTotCnt: '플랜 수', - objectName: '물건명', - saleStoreId: '대리점ID', - saleStoreName: '대리점명', - address: '물건주소', - dispCompanyName: '견적처', - receiveUser: '담당자', - specDate: '사양확인', - createDatetime: '등록일', - }, - }, -} diff --git a/src/locales/ja.json b/src/locales/ja.json index 980d1400..3ccbdf40 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -247,6 +247,11 @@ "modal.object.setting.direction.select": "方向の選択", "modal.placement.surface.setting.info": "ⓘ ①の長さ入力後に対角線の長さを入力すると、②の長さを自動計算します。", "modal.placement.surface.setting.diagonal.length": "斜めの長さ", + "plan.message.confirm.save": "PLAN을 저장하시겠습니까?", + "plan.message.confirm.copy": "PLAN을 복사하시겠습니까?", + "plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?", + "plan.message.save": "저장되었습니다.", + "plan.message.delete": "삭제되었습니다.", "setting": "設定", "common.message.no.data": "No data", "common.message.no.dataDown": "ダウンロードするデータがありません", @@ -335,7 +340,7 @@ "common.message.writeToConfirm": "作成解除を実行しますか?", "common.message.password.init.success": "パスワード [{0}] に初期化されました。", "common.message.no.edit.save": "この文書は変更できません。", - "common.require": "필수", + "common.require": "必須", "commons.west": "立つ", "commons.east": "ドン", "commons.south": "立つ", @@ -380,6 +385,7 @@ "myinfo.message.save": "パスワードが変更されました。", "myinfo.message.password.error": "パスワードが間違っています。", "login": "ログイン", + "login.auto.page.text": "自動ログイン中です。", "login.id.save": "ID保存", "login.id.placeholder": "IDを入力してください。", "login.password.placeholder": "パスワードを入力してください。", @@ -497,6 +503,7 @@ "stuff.planReqPopup.search.period": "期間検索", "stuff.planReqPopup.search.schDateGbnS": "提出日", "stuff.planReqPopup.search.schDateGbnR": "受付日", + "stuff.planReqPopup.error.message1": "設計依頼を選択してください。", "stuff.search.title": "物件状況", "stuff.search.btn1": "物件登録", "stuff.search.btn2": "照会", @@ -511,6 +518,11 @@ "stuff.search.period": "期間検索", "stuff.search.schDateTypeU": "更新日", "stuff.search.schDateTypeR": "登録日", + "stuff.search.grid.title": "商品リスト", + "stuff.search.grid.all": "全体", + "stuff.search.grid.selected": "選択", + "stuff.search.grid.schSortTypeR": "最近の登録日", + "stuff.search.grid.schSortTypeU": "最近の更新日", "stuff.windSelectPopup.title": "風速選択", "stuff.windSelectPopup.table.selected": "選択", "stuff.windSelectPopup.table.windspeed": "風速", diff --git a/src/locales/ko.js b/src/locales/ko.js deleted file mode 100644 index c01b913c..00000000 --- a/src/locales/ko.js +++ /dev/null @@ -1,91 +0,0 @@ -console.log('Loaded KO') - -export default { - hello: '안녕', - welcome: '안녕 {name}!', - locale: '현재 로케일은 {locale}입니다.', - common: { - require: '필수', - }, - site: { - name: 'Q.CAST III', - sub_name: '태양광 발전 시스템 도면관리 사이트', - }, - login: { - login: '로그인', - init_password: { - btn: '비밀번호 초기화', - title: '비밀번호 초기화', - sub_title: '비밀번호를 초기화할 아이디와 이메일 주소를 입력해 주세요.', - complete_message: '비밀번호가 초기화 되었습니다. 초기화된 비밀번호는 아이디와 같습니다.', - }, - }, - join: { - title: 'Q.CAST3 로그인ID 발행 신청', - sub1: { - title: '판매대리점 정보', - comment: '※ 등록되는 리셀러의 회사 이름을 입력하십시오. (2차점은 「○○판매주식회사(2차점:××설비주식회사)」로 기입해 주세요.)', - storeQcastNm: '판매대리점명', - storeQcastNm_placeholder: '주식회사 에너지 기어 솔루션 앤 서비스 (2차점: 야마구치 주기 판매 유한회사)', - storeQcastNmKana: '판매대리점명 후리가나', - storeQcastNmKana_placeholder: '주식회사 에너지 기어 솔루션', - postCd: '우편번호', - postCd_placeholder: '숫자 7자리', - addr: '주소', - addr_placeholder: '전각50자이내', - telNo: '전화번호', - telNo_placeholder: '00-0000-0000', - fax: 'FAX 번호', - fax_placeholder: '00-0000-0000', - }, - sub2: { - title: '담당자 정보', - userNm: '담당자명', - userNmKana: '담당자명 후리가나', - userId: '신청 ID', - email: '이메일 주소', - telNo: '전화번호', - telNo_placeholder: '00-0000-0000', - fax: 'FAX 번호', - fax_placeholder: '00-0000-0000', - category: '부서명', - }, - sub3: { - title: '견적서 제출용 회사정보', - qtCompNm: '회사명', - qtPostCd: '우편번호', - qtPostCd_placeholder: '숫자 7자리', - qtAddr: '주소', - qtAddr_placeholder: '전각50자이내', - qtEmail: '이메일 주소', - qtTelNo: '전화번호', - qtTelNo_placeholder: '00-0000-0000', - qtFax: 'FAX 번호', - qtFax_placeholder: '00-0000-0000', - }, - btn: { - approval_request: 'ID 승인요청', - }, - complete: { - title: 'Q.CAST3 로그인ID 발행신청 완료', - contents: '※ 신청한 ID가 승인되면, 담당자 정보에 입력한 이메일 주소로 로그인 관련 안내 메일이 전송됩니다.', - email_comment: '담당자 이메일 주소', - email: 'test@naver.com', - }, - }, - stuff: { - gridHeader: { - lastEditDatetime: '갱신일시', - objectNo: '물건번호', - planTotCnt: '플랜 수', - objectName: '물건명', - saleStoreId: '대리점ID', - saleStoreName: '대리점명', - address: '물건주소', - dispCompanyName: '견적처', - receiveUser: '담당자', - specDate: '사양확인', - createDatetime: '등록일', - }, - }, -} diff --git a/src/locales/ko.json b/src/locales/ko.json index 21aca2be..d87551a5 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -252,6 +252,11 @@ "modal.object.setting.direction.select": "방향 선택", "modal.placement.surface.setting.info": "ⓘ ①의 길이 입력 후 대각선 길이를 입력하면 ②의 길이를 자동 계산합니다.", "modal.placement.surface.setting.diagonal.length": "대각선 길이", + "plan.message.confirm.save": "PLAN을 저장하시겠습니까?", + "plan.message.confirm.copy": "PLAN을 복사하시겠습니까?", + "plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?", + "plan.message.save": "저장되었습니다.", + "plan.message.delete": "삭제되었습니다.", "setting": "설정", "common.message.no.data": "No data", "common.message.no.dataDown": "No data to download", @@ -385,6 +390,7 @@ "myinfo.message.save": "비밀번호가 변경되었습니다.", "myinfo.message.password.error": "비밀번호가 틀렸습니다.", "login": "로그인", + "login.auto.page.text": "자동로그인 중 입니다.", "login.id.save": "ID Save", "login.id.placeholder": "아이디를 입력해주세요.", "login.password.placeholder": "비밀번호를 입력해주세요.", @@ -502,6 +508,7 @@ "stuff.planReqPopup.search.period": "기간검색", "stuff.planReqPopup.search.schDateGbnS": "제출일", "stuff.planReqPopup.search.schDateGbnR": "접수일", + "stuff.planReqPopup.error.message1": "설계의뢰를 선택해주세요.", "stuff.search.title": "물건현황", "stuff.search.btn1": "신규등록", "stuff.search.btn2": "조회", @@ -516,6 +523,11 @@ "stuff.search.period": "기간검색", "stuff.search.schDateTypeU": "갱신일", "stuff.search.schDateTypeR": "등록일", + "stuff.search.grid.title": "물건목록", + "stuff.search.grid.all": "전체", + "stuff.search.grid.selected": "선택", + "stuff.search.grid.schSortTypeR": "최근 등록일", + "stuff.search.grid.schSortTypeU": "최근 갱신일", "stuff.windSelectPopup.title": "풍속선택", "stuff.windSelectPopup.table.selected": "선택", "stuff.windSelectPopup.table.windspeed": "풍속", diff --git a/src/locales/server.js b/src/locales/server.js deleted file mode 100644 index 7bfe43f0..00000000 --- a/src/locales/server.js +++ /dev/null @@ -1,14 +0,0 @@ -import { createI18nServer } from 'next-international/server' - -export const { getI18n, getScopedI18n, getCurrentLocale, getStaticParams } = createI18nServer( - { - ko: () => import('./ko'), - ja: () => import('./ja'), - }, - { - // Uncomment to use custom segment name - // segmentName: 'locale', - // Uncomment to set fallback locale - // fallbackLocale: en, - }, -) diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index 7806b8f2..f3a81661 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -289,3 +289,8 @@ export const canGridOptionSeletor = selector({ return points.length === 0 || outerLineFix }, }) + +export const globalPitchState = atom({ + key: 'globalPitch', + default: 4, +}) diff --git a/src/store/planReqAtom.js b/src/store/planReqAtom.js index 717d506e..fddf1374 100644 --- a/src/store/planReqAtom.js +++ b/src/store/planReqAtom.js @@ -16,7 +16,7 @@ export const planReqSearchState = atom({ schStartDt: dayjs(new Date()).add(-3, 'month').format('YYYY-MM-DD'), //시작일 schEndDt: dayjs(new Date()).format('YYYY-MM-DD'), //종료일 startRow: 1, - endRow: 100, + endRow: 20, }, dangerouslyAllowMutability: true, }) diff --git a/src/store/settingAtom.js b/src/store/settingAtom.js index 6ec454be..8560c700 100644 --- a/src/store/settingAtom.js +++ b/src/store/settingAtom.js @@ -15,12 +15,12 @@ export const settingModalFirstOptionsState = atom({ { id: 9, column: 'totalDisplay', name: 'modal.canvas.setting.first.option.total', selected: false }, ], dimensionDisplay: [ - { id: 1, column: 'corridorDimension', name: 'modal.canvas.setting.first.option.corridor.dimension', selected: false }, + { id: 1, column: 'corridorDimension', name: 'modal.canvas.setting.first.option.corridor.dimension', selected: true }, { id: 2, column: 'realDimension', name: 'modal.canvas.setting.first.option.real.dimension', selected: false }, { id: 3, column: 'noneDimension', name: 'modal.canvas.setting.first.option.none.dimension', selected: false }, ], option2: [ - { id: 1, column: 'onlyBorder', name: 'modal.canvas.setting.first.option.border', selected: false }, + { id: 1, column: 'onlyBorder', name: 'modal.canvas.setting.first.option.border', selected: true }, { id: 2, column: 'lineHatch', name: 'modal.canvas.setting.first.option.line', selected: false }, { id: 3, column: 'allPainted', name: 'modal.canvas.setting.first.option.all', selected: false }, ], @@ -57,3 +57,102 @@ export const settingModalGridOptionsState = atom({ ], dangerouslyAllowMutability: true, }) + +// 디스플레이 설정 - 할당 표시 +export const allocDisplaySelector = selector({ + key: 'allocDisplaySelector', + get: ({ get }) => { + const settingModalFirstOptions = get(settingModalFirstOptionsState) + return settingModalFirstOptions.option1.find((option) => option.column === 'allocDisplay').selected + }, +}) + +// 디스플레이 설정 - 외벽선 표시 +export const outlineDisplaySelector = selector({ + key: 'outlineDisplaySelector', + get: ({ get }) => { + const settingModalFirstOptions = get(settingModalFirstOptionsState) + return settingModalFirstOptions.option1.find((option) => option.column === 'outlineDisplay').selected + }, +}) + +// 디스플레이 설정 - 그리드 표시 +export const gridDisplaySelector = selector({ + key: 'gridDisplaySelector', + get: ({ get }) => { + const settingModalFirstOptions = get(settingModalFirstOptionsState) + return settingModalFirstOptions.option1.find((option) => option.column === 'gridDisplay').selected + }, +}) + +// 디스플레이 설정 - 지붕선 표시 +export const roofLineDisplaySelector = selector({ + key: 'lineDisplaySelector', + get: ({ get }) => { + const settingModalFirstOptions = get(settingModalFirstOptionsState) + return settingModalFirstOptions.option1.find((option) => option.column === 'lineDisplay').selected + }, +}) + +// 디스플레이 설정 - 문자 표시 +export const wordDisplaySelector = selector({ + key: 'wordDisplaySelector', + get: ({ get }) => { + const settingModalFirstOptions = get(settingModalFirstOptionsState) + return settingModalFirstOptions.option1.find((option) => option.column === 'wordDisplay').selected + }, +}) + +// 디스플레이 설정 - 회로번호 표시 +export const circuitNumDisplaySelector = selector({ + key: 'circuitNumDisplaySelector', + get: ({ get }) => { + const settingModalFirstOptions = get(settingModalFirstOptionsState) + return settingModalFirstOptions.option1.find((option) => option.column === 'circuitNumDisplay').selected + }, +}) + +// 디스플레이 설정 - 흐름 방향 표시 +export const flowDisplaySelector = selector({ + key: 'flowDisplaySelector', + get: ({ get }) => { + const settingModalFirstOptions = get(settingModalFirstOptionsState) + return settingModalFirstOptions.option1.find((option) => option.column === 'flowDisplay').selected + }, +}) + +// 디스플레이 설정 - 가대 표시 +export const trestleDisplaySelector = selector({ + key: 'trestleDisplaySelector', + get: ({ get }) => { + const settingModalFirstOptions = get(settingModalFirstOptionsState) + return settingModalFirstOptions.option1.find((option) => option.column === 'trestleDisplay').selected + }, +}) + +// 디스플레이 설정 - 집계표 표시 +export const totalDisplaySelector = selector({ + key: 'totalDisplaySelector', + get: ({ get }) => { + const settingModalFirstOptions = get(settingModalFirstOptionsState) + return settingModalFirstOptions.option1.find((option) => option.column === 'totalDisplay').selected + }, +}) + +// 디스플레이 설정 - 치수 표시 +export const corridorDimensionSelector = selector({ + key: 'corridorDimensionSelector', + get: ({ get }) => { + const settingModalFirstOptions = get(settingModalFirstOptionsState) + return settingModalFirstOptions.dimensionDisplay.find((option) => option.selected) + }, +}) + +// 디스플레이 설정 - 화면 표시 +export const realDimensionSelector = selector({ + key: 'realDimensionSelector', + get: ({ get }) => { + const settingModalFirstOptions = get(settingModalFirstOptionsState) + return settingModalFirstOptions.dimensionDisplay.find((option) => option.selected) + }, +}) diff --git a/src/store/stuffAtom.js b/src/store/stuffAtom.js index ceb5def0..c47321ae 100644 --- a/src/store/stuffAtom.js +++ b/src/store/stuffAtom.js @@ -18,10 +18,6 @@ export const stuffSearchState = atom({ startRow: 1, endRow: 100, schSortType: 'R', //정렬조건 (R:최근등록일 U:최근수정일) - selObject: { - value: '', - label: '', - }, }, dangerouslyAllowMutability: true, }) diff --git a/src/styles/_contents.scss b/src/styles/_contents.scss index ee823bab..9cd8bd32 100644 --- a/src/styles/_contents.scss +++ b/src/styles/_contents.scss @@ -17,1239 +17,1287 @@ // } // } // CanvasMenu -.canvas-menu-wrap{ - position: fixed; - top: 46px; - left: 0; - display: block; - width: 100%; - padding-bottom: 0; - background-color: #383838; - transition: padding .17s ease-in-out; - z-index: 999; - .canvas-menu-inner{ - position: relative; - display: flex; - align-items: center; - padding: 0 40px 0 20px; - background-color: #2C2C2C; - z-index: 999; - .canvas-menu-list{ - display: flex; - align-items: center; - height: 100%; - .canvas-menu-item{ - display: flex; - align-items: center; - height: 100%; - button{ - display: flex; - align-items: center; - font-size: 12px; - height: 100%; - color: #fff; - font-weight: 600; - padding: 15px 20px; - opacity: 0.55; - transition: all .17s ease-in-out; - .menu-icon{ - display: block; - width: 16px; - height: 16px; - background-repeat: no-repeat; - background-position: center; - background-size: cover; - margin-right: 10px; - &.con00{background-image: url(/static/images/canvas/menu_icon00.svg);} - &.con01{background-image: url(/static/images/canvas/menu_icon01.svg);} - &.con02{background-image: url(/static/images/canvas/menu_icon02.svg);} - &.con03{background-image: url(/static/images/canvas/menu_icon03.svg);} - &.con04{background-image: url(/static/images/canvas/menu_icon04.svg);} - &.con05{background-image: url(/static/images/canvas/menu_icon05.svg);} - &.con06{background-image: url(/static/images/canvas/menu_icon06.svg);} - } - } - &.active{ - background-color: #383838; - button{ - opacity: 1; - } - } - } - } - .canvas-side-btn-wrap{ - display: flex; - align-items: center; - margin-left: auto; - .select-box{ - width: 124px; - margin-right: 5px; - > div{ - width: 100%; - } - } - .btn-from{ - display: flex; - align-items: center; - gap: 5px; - button{ - display: block; - width: 30px; - height: 30px; - border-radius: 2px; - background-color: #3D3D3D; - background-position: center; - background-repeat: no-repeat; - background-size: 15px 15px; - transition: all .17s ease-in-out; - &.btn01{background-image: url(../../public/static/images/canvas/side_icon03.svg);} - &.btn02{background-image: url(../../public/static/images/canvas/side_icon02.svg);} - &.btn03{background-image: url(../../public/static/images/canvas/side_icon01.svg);} - &.btn04{background-image: url(../../public/static/images/canvas/side_icon04.svg);} - &.btn05{background-image: url(../../public/static/images/canvas/side_icon05.svg);} - &.btn06{background-image: url(../../public/static/images/canvas/side_icon06.svg);} - &.btn07{background-image: url(../../public/static/images/canvas/side_icon07.svg);} - &.btn08{background-image: url(../../public/static/images/canvas/side_icon08.svg);} - &.btn09{background-image: url(../../public/static/images/canvas/side_icon09.svg);} - &:hover{ - background-color: #1083E3; - } - &.active{ - background-color: #1083E3; - } - } - } - .ico-btn-from{ - display: flex; - align-items: center; - gap: 5px; - button{ - .ico{ - display: block; - width: 15px; - height: 15px; - background-repeat: no-repeat; - background-position: center; - background-size: contain; - &.ico01{background-image: url(../../public/static/images/canvas/ico-flx01.svg);} - &.ico02{background-image: url(../../public/static/images/canvas/ico-flx02.svg);} - &.ico03{background-image: url(../../public/static/images/canvas/ico-flx03.svg);} - &.ico04{background-image: url(../../public/static/images/canvas/ico-flx04.svg);} - } - .name{ - font-size: 12px; - color: #fff; - } - } - &.form06{ - .name{ - font-size: 13px; - } - } - } - .vertical-horizontal{ - display: flex; - min-width: 170px; - height: 28px; - margin: 0 5px; - border-radius: 2px; - background: #373737; - line-height: 28px; - overflow: hidden; - span{ - padding: 0 10px; - font-size: 13px; - color: #fff; - } - button{ - margin-left: auto; - height: 100%; - background-color: #4B4B4B; - font-size: 13px; - font-weight: 400; - color: #fff; - padding: 0 7.5px; - transition: all .17s ease-in-out; - } - &.on{ - button{ - background-color: #1083E3; - } - } - } - .size-control{ - display: flex; - align-items: center; - justify-content: center; - gap: 10px; - background-color: #3D3D3D; - border-radius: 2px; - width: 100px; - height: 30px; - margin: 0 5px; - span{ - font-size: 13px; - color: #fff; - } - .control-btn{ - display: block; - width: 12px; - height: 12px; - background-repeat: no-repeat; - background-size: cover; - background-position: center; - &.minus{ - background-image: url(../../public/static/images/canvas/minus.svg); - } - &.plus{ - background-image: url(../../public/static/images/canvas/plus.svg); - } - } - } - } - } - .canvas-depth2-wrap{ - position: absolute; - top: -100%; - left: 0; - background-color: #383838; - width: 100%; - height: 50px; - transition: all .17s ease-in-out; - .canvas-depth2-inner{ - display: flex; - align-items: center; - padding: 0 40px; - height: 100%; - .canvas-depth2-list{ - display: flex; - align-items: center ; - height: 100%; - .canvas-depth2-item{ - display: flex; - align-items: center; - margin-right: 26px; - height: 100%; - button{ - position: relative; - opacity: 0.55; - color: #fff; - font-size: 12px; - font-weight: normal; - height: 100%; - padding-right: 12px; - } - &.active{ - button{ - opacity: 1; - font-weight: 600; - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 5px; - height: 8px; - background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center; - } - } - } - } - } - .canvas-depth2-btn-list{ - display: flex; - align-items: center; - margin-left: auto; - height: 100%; - .depth2-btn-box{ - display: flex; - align-items: center; - margin-right: 34px; - height: 100%; - transition: all .17s ease-in-out; - button{ - position: relative; - font-size: 12px; - font-weight: 400; - height: 100%; - color: #fff; - padding-right: 12px; - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 5px; - height: 8px; - background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center; - } - } - &:last-child{ - margin-right: 0; - } - &.mouse{ - opacity: 0.55; - } - } - } - } - &.active{ - top: 47px; - } - } - &.active{ - padding-bottom: 50px; - } -} - -// canvas-layout -.canvas-content{ - padding-top: 46.8px; - transition: all .17s ease-in-out; - .canvas-frame{ - height: 86.3vh; - } - &.active{ - padding-top: calc(46.8px + 50px); - .canvas-frame{ - height: 81vh; - } - } -} -.canvas-layout{ - padding-top: 37px; - .canvas-page-list{ - position: fixed; - top: 92.8px; - left: 0; - display: flex; - background-color: #1C1C1C; - border-top: 1px solid #000; - width: 100%; - transition: all .17s ease-in-out; - z-index: 999; - &.active{ - top: calc(92.8px + 50px); - } - .canvas-plane-wrap{ - display: flex; - align-items: center; - max-width: calc(100% - 45px); - .canvas-page-box{ - display: flex; - align-items: center; - background-color: #1c1c1c; - padding: 9.6px 20px; - border-right:1px solid #000; - min-width: 0; - transition: all .17s ease-in-out; - span{ - display: flex; - align-items: center; - width: 100%; - font-size: 12px; - font-family: 'Pretendard', sans-serif; - color: #AAA; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - } - .close{ - flex: none; - display: block; - width: 7px; - height: 8px; - margin-left: 15px; - background: url(../../public/static/images/canvas/plan_close_gray.svg)no-repeat center; - background-size: cover; - } - &.on{ - background-color: #fff; - span{ - font-weight: 600; - color: #101010; - } - .close{ - background: url(../../public/static/images/canvas/plan_close_black.svg)no-repeat center; - } - &:hover{ - background-color: #fff; - } - } - &:hover{ - background-color: #000; - } - } - } - .plane-add{ - display: flex; - align-items: center; - justify-content: center; - width: 45px; - padding: 13.5px 0; - background-color: #1C1C1C; - border-right: 1px solid #000; - transition: all .17s ease-in-out; - span{ - display: block; - width: 9px; - height: 9px; - background: url(../../public/static/images/canvas/plane_add.svg)no-repeat center; - background-size: cover; - } - &:hover{ - background-color: #000; - } - } - } -} - -.canvas-frame{ +.canvas-menu-wrap { + position: fixed; + top: 46px; + left: 0; + display: block; + width: 100%; + padding-bottom: 0; + background-color: #383838; + transition: padding 0.17s ease-in-out; + z-index: 999; + .canvas-menu-inner { position: relative; - // height: calc(100% - 36.5px); - background-color: #F4F4F7; - overflow: auto; - transition: all .17s ease-in-out; - // &::-webkit-scrollbar { - // width: 10px; - // height: 10px; - // background-color: #fff; - // } - // &::-webkit-scrollbar-thumb { - // background-color: #C1CCD7; - // border-radius: 30px; - // } - // &::-webkit-scrollbar-track { - // background-color: #fff; - // } - canvas{ - background-color: #fff; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - } -} - -// sub-page -.sub-header{ - position: fixed; - top: 46px; - left: 0; - width: 100%; - height: 46px; - border-bottom: 1px solid #000; - background: #2C2C2C; + display: flex; + align-items: center; + padding: 0 40px 0 20px; + background-color: #2c2c2c; z-index: 999; - .sub-header-inner{ + .canvas-menu-list { + display: flex; + align-items: center; + height: 100%; + .canvas-menu-item { display: flex; align-items: center; height: 100%; - padding: 0 100px; - .sub-header-title-wrap{ - display: flex; - align-items: center; - .title-item{ - position: relative; - padding: 0 24px; - a{ - display: flex; - align-items: center; - .icon{ - width: 22px; - height: 22px; - margin-right: 8px; - background-repeat: no-repeat; - background-position: center; - background-size: cover; - &.drawing{background-image: url(../../public/static/images/main/drawing_icon.svg);} - } - } - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 1px; - height: 16px; - background-color: #D9D9D9; - } - &:first-child{ - padding-left: 0; - } - &:last-child{ - padding-right: 0; - &:after{ - display: none; - } - } + button { + display: flex; + align-items: center; + font-size: 12px; + height: 100%; + color: #fff; + font-weight: 600; + padding: 15px 20px; + opacity: 0.55; + transition: all 0.17s ease-in-out; + .menu-icon { + display: block; + width: 16px; + height: 16px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; + margin-right: 10px; + &.con00 { + background-image: url(/static/images/canvas/menu_icon00.svg); } + &.con01 { + background-image: url(/static/images/canvas/menu_icon01.svg); + } + &.con02 { + background-image: url(/static/images/canvas/menu_icon02.svg); + } + &.con03 { + background-image: url(/static/images/canvas/menu_icon03.svg); + } + &.con04 { + background-image: url(/static/images/canvas/menu_icon04.svg); + } + &.con05 { + background-image: url(/static/images/canvas/menu_icon05.svg); + } + &.con06 { + background-image: url(/static/images/canvas/menu_icon06.svg); + } + } } - .sub-header-title{ - font-size: 16px; + &.active { + background-color: #383838; + button { + opacity: 1; + } + } + } + } + .canvas-side-btn-wrap { + display: flex; + align-items: center; + margin-left: auto; + .select-box { + width: 124px; + margin-right: 5px; + > div { + width: 100%; + } + } + .btn-from { + display: flex; + align-items: center; + gap: 5px; + button { + display: block; + width: 30px; + height: 30px; + border-radius: 2px; + background-color: #3d3d3d; + background-position: center; + background-repeat: no-repeat; + background-size: 15px 15px; + transition: all 0.17s ease-in-out; + &.btn01 { + background-image: url(../../public/static/images/canvas/side_icon03.svg); + } + &.btn02 { + background-image: url(../../public/static/images/canvas/side_icon02.svg); + } + &.btn03 { + background-image: url(../../public/static/images/canvas/side_icon01.svg); + } + &.btn04 { + background-image: url(../../public/static/images/canvas/side_icon04.svg); + } + &.btn05 { + background-image: url(../../public/static/images/canvas/side_icon05.svg); + } + &.btn06 { + background-image: url(../../public/static/images/canvas/side_icon06.svg); + } + &.btn07 { + background-image: url(../../public/static/images/canvas/side_icon07.svg); + } + &.btn08 { + background-image: url(../../public/static/images/canvas/side_icon08.svg); + } + &.btn09 { + background-image: url(../../public/static/images/canvas/side_icon09.svg); + } + &:hover { + background-color: #1083e3; + } + &.active { + background-color: #1083e3; + } + } + } + .ico-btn-from { + display: flex; + align-items: center; + gap: 5px; + button { + .ico { + display: block; + width: 15px; + height: 15px; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + &.ico01 { + background-image: url(../../public/static/images/canvas/ico-flx01.svg); + } + &.ico02 { + background-image: url(../../public/static/images/canvas/ico-flx02.svg); + } + &.ico03 { + background-image: url(../../public/static/images/canvas/ico-flx03.svg); + } + &.ico04 { + background-image: url(../../public/static/images/canvas/ico-flx04.svg); + } + } + .name { + font-size: 12px; color: #fff; - font-weight: 600; + } } - .sub-header-location{ - margin-left: auto; - display: flex; - align-items: center; - .location-item{ - position: relative; - display: flex; - align-items: center; - padding: 0 10px; - span{ - display: flex; - font-size: 12px; - color: #AAA; - font-weight: normal; - cursor: default; - } - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 4px; - height: 6px; - background: url(../../public/static/images/main/loaction_arr.svg)no-repeat center; - } - &:first-child{ - padding-left: 0; - } - &:last-child{ - padding-right: 0; - span{ - color: #fff; - } - &:after{ - display: none; - } - } - } + &.form06 { + .name { + font-size: 13px; + } } - } -} - -// sub content -.sub-content{ - padding-top: 46px; - .sub-content-inner{ - max-width: 1720px; - margin: 0 auto; - padding-top: 20px; - .sub-content-box{ - margin-bottom: 20px; - &:last-child{ - margin-bottom: 0; - } - } - } - &.estimate{ + } + .vertical-horizontal { display: flex; - flex-direction: column; - padding-top: 0; - .sub-content-inner{ - flex: 1; - width: 100%; + min-width: 170px; + height: 28px; + margin: 0 5px; + border-radius: 2px; + background: #373737; + line-height: 28px; + overflow: hidden; + span { + padding: 0 10px; + font-size: 13px; + color: #fff; } - } -} -.sub-table-box{ - padding: 20px; - border-radius: 6px; - border: 1px solid #E9EAED; - background: #FFF; - box-shadow: 0px 3px 30px 0px rgba(0, 0, 0, 0.02); - .table-box-title-wrap{ - display: flex; - align-items: center; - margin-bottom: 15px; - .title-wrap{ - display: flex; - align-items: center; - h3{ - display: block; - font-size: 15px; - color: #101010; - font-weight: 600; - margin-right: 14px; - &.product{ - margin-right: 10px; - } - } - .product_tit{ - position: relative; - font-size: 15px; - font-weight: 600; - color: #1083E3; - padding-left: 10px; - &::before{ - content: ''; - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); - width: 1px; - height: 11px; - background-color: #D9D9D9; - } - } - .option{ - padding-left: 5px; - font-size: 13px; - color: #101010; - font-weight: 400; - } - .info-wrap{ - display: flex; - align-items: center; - li{ - position: relative; - padding: 0 6px; - font-size: 12px; - color: #101010; - font-weight: normal; - span{ - font-weight: 600; - &.red{ - color: #E23D70; - } - } - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 1px; - height: 11px; - background-color: #D9D9D9; - } - &:first-child{padding-left: 0;} - &:last-child{padding-right: 0;&::after{display: none;}} - } - } + button { + margin-left: auto; + height: 100%; + background-color: #4b4b4b; + font-size: 13px; + font-weight: 400; + color: #fff; + padding: 0 7.5px; + transition: all 0.17s ease-in-out; } - } - .left-unit-box{ - margin-left: auto; - display: flex; - align-items: center; - } - .promise-gudie{ - display: block; - font-size: 13px; - font-weight: 700; - color: #101010; - margin-bottom: 20px; - } - .important{ - color: #f00; - } - .sub-center-footer{ + &.on { + button { + background-color: #1083e3; + } + } + } + .size-control { display: flex; align-items: center; justify-content: center; - margin-top: 20px; - } - .sub-right-footer{ - display: flex; - align-items: center; - justify-content: flex-end; - margin-top: 20px; - } -} -.pagination-wrap{ - margin-top: 24px; -} - -.infomation-wrap{ - margin-bottom: 30px; -} - -.infomation-box-wrap{ - display: flex; - align-items: center; - gap: 10px; - .sub-table-box{ - flex: 1 ; - } - .info-title{ - font-size: 14px; - font-weight: 500; - color: #344356; - margin-bottom: 10px; - } - .info-inner{ - position: relative; - font-size: 13px; - color: #344356; - .copy-ico{ - position: absolute; - bottom: 0; - right: 0; - width: 16px; - height: 16px; - background: url(../../public/static/images/sub/copy_ico.svg)no-repeat center; - background-size: cover; + gap: 10px; + background-color: #3d3d3d; + border-radius: 2px; + width: 100px; + height: 30px; + margin: 0 5px; + span { + font-size: 13px; + color: #fff; } + .control-btn { + display: block; + width: 12px; + height: 12px; + background-repeat: no-repeat; + background-size: cover; + background-position: center; + &.minus { + background-image: url(../../public/static/images/canvas/minus.svg); + } + &.plus { + background-image: url(../../public/static/images/canvas/plus.svg); + } + } + } } -} - -// 견적서 -.estimate-list-wrap{ - display: flex; - align-items: center; - margin-bottom: 10px; - &.one{ - .estimate-box{ - &:last-child{ - min-width: unset; - } - } - } - .estimate-box{ - flex: 1 ; - display: flex; - align-items: center; - &:last-child{ - flex: none; - min-width: 220px; - } - .estimate-tit{ - width: 105px; - height: 30px; - line-height: 30px; - background-color: #F4F4F7; - border-radius: 100px; - text-align: center; - font-size: 13px; - font-weight: 500; - color: #344356; - } - .estimate-name{ - font-size: 13px; - color: #344356; - margin-left: 14px; - font-weight: 400; - &.blue{ - font-size: 16px; - font-weight: 700; - color: #1083E3; - } - &.red{ - font-size: 16px; - font-weight: 700; - color: #D72A2A; - } - } - } - &:last-child{ - margin-bottom: 0; - } -} - -// file drag box -.drag-file-box{ - padding: 10px; - .btn-area{ - padding-bottom: 15px; - border-bottom: 1px solid #ECF0F4; - } - .drag-file-area{ - position: relative; - margin-top: 15px; - p{ - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - font-size: 13px; - color: #ccc; - font-weight: 400; - cursor: default; - } - } - .file-list{ - .file-item{ - margin-bottom: 15px; - span{ - position: relative; - font-size: 13px; - color: #45576F; - font-weight: 400; - white-space: nowrap; - padding-right: 55px; - button{ - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 15px; - height: 15px; - background: url(../../public/static/images/sub/file_delete.svg)no-repeat center; - background-size: cover; - } - } - &:last-child{ - margin-bottom: 0; - } - } - } -} - -.special-note-check-wrap{ - display: grid; - grid-template-columns: repeat(5, 1fr); - border: 1px solid #ECF0F4; - border-radius: 3px; - margin-bottom: 30px; - .special-note-check-item{ - padding: 14px 10px; - border-right: 1px solid #ECF0F4; - border-top: 1px solid #ECF0F4; - &:nth-child(5n){ - border-right: none; - } - &:nth-child(-n+5){ - border-top: none; - } - &.act{ - background-color: #F7F9FA; - } - } -} - -.calculation-estimate{ - border: 1px solid #ECF0F4; - border-radius: 3px; - padding: 24px; - max-height: 350px; - overflow-y: auto; - margin-bottom: 30px; - dl{ - margin-bottom: 35px; - &:last-child{ - margin-bottom: 0; - } - dt{ - font-size: 13px; - font-weight: 600; - color: #1083E3; - margin-bottom: 15px; - } - dd{ - font-size: 12px; - font-weight: 400; - color: #45576F; - margin-bottom: 8px; - &:last-child{ - margin-bottom: 0; - } - } - } - &::-webkit-scrollbar { - width: 4px; - background-color: transparent; - } - &::-webkit-scrollbar-thumb { - background-color: #d9dee2; - } - &::-webkit-scrollbar-track { - background-color: transparent; - } -} -.esimate-wrap{ - margin-bottom: 20px; -} - -.estimate-product-option{ - display: flex; - align-items: center; - margin-bottom: 15px; - .product-price-wrap{ - display: flex; - align-items: center; - .product-price-tit{ - font-size: 13px; - font-weight: 400; - color: #45576F; - margin-right: 10px; - } - .select-wrap{ - width: 110px; - } - } - .product-edit-wrap{ - display: flex; - align-items: center; - margin-left: auto; - .product-edit-explane{ - display: flex; - align-items: center; - margin-right: 15px; - .attachment-required{ - position: relative; - display: flex; - align-items: center; - font-size: 12px; - font-weight: 400; - color: #45576F; - padding-right: 10px; - .ico{ - width: 23px; - height: 23px; - margin-right: 5px; - background: url(../../public/static/images/sub/attachment_ico.svg)no-repeat center; - background-size: cover; - } - &::before{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 1px; - height: 12px; - background-color: #D9D9D9; - } - } - .click-check{ - display: flex; - align-items: center; - font-size: 12px; - font-weight: 400; - color: #F16A6A ; - padding-left: 10px; - .ico{ - width: 14px; - height: 14px; - margin-right: 5px; - background: url(../../public/static/images/sub/click_check_ico.svg)no-repeat center; - background-size: cover; - } - } - } - .product-edit-btn{ - display: flex; - align-items: center; - button{ - display: flex; - align-items: center; - span{ - width: 13px; - height: 13px; - margin-right: 5px; - background-size: cover; - &.plus{ - background: url(../../public/static/images/sub/plus_btn.svg)no-repeat center; - } - &.minus{ - background: url(../../public/static/images/sub/minus_btn.svg)no-repeat center; - } - } - } - } - } - -} - -// 발전시물레이션 -.chart-wrap{ - display: flex; - gap: 20px; + } + .canvas-depth2-wrap { + position: absolute; + top: -100%; + left: 0; + background-color: #383838; width: 100%; - .sub-table-box{ - height: 100%; - } - .chart-inner{ - flex: 1; - .chart-box{ - margin-bottom: 30px; - } - } - .chart-table-wrap{ + height: 50px; + transition: all 0.17s ease-in-out; + .canvas-depth2-inner { + display: flex; + align-items: center; + padding: 0 40px; + height: 100%; + .canvas-depth2-list { display: flex; - flex-direction: column; - flex: none; - width: 650px; - .sub-table-box{ - flex: 1; - &:first-child{ - margin-bottom: 20px; - } - } - } -} - -.chart-month-table{ - table{ - table-layout: fixed; - border-collapse:collapse; - border: 1px solid #ECF0F4; - border-radius: 4px; - thead{ - th{ - padding: 4.5px 0; - border-bottom: 1px solid #ECF0F4; - text-align: center; - font-size: 13px; - color: #45576F; - font-weight: 500; - background-color: #F8F9FA; - } - } - tbody{ - td{ - font-size: 13px; - color: #45576F; - text-align: center; - padding: 4.5px 0; - } - } - } -} - -.simulation-guide-wrap{ - display: flex; - padding: 20px; - .simulation-tit-wrap{ - padding-right: 40px; - border-right: 1px solid #EEEEEE; - span{ - display: block; + align-items: center; + height: 100%; + .canvas-depth2-item { + display: flex; + align-items: center; + margin-right: 26px; + height: 100%; + button { position: relative; - padding-left: 60px; - font-size: 15px; - color: #14324F; - font-weight: 600; - &::before{ + opacity: 0.55; + color: #fff; + font-size: 12px; + font-weight: normal; + height: 100%; + padding-right: 12px; + } + &.active { + button { + opacity: 1; + font-weight: 600; + &:after { content: ''; position: absolute; top: 50%; - left: 0; + right: 0; transform: translateY(-50%); - width: 40px; - height: 40px; - background: url(../../public/static/images/sub/simulation_guide.svg)no-repeat center; - background-size: cover; + width: 5px; + height: 8px; + background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center; + } } + } } - } - .simulation-guide-box{ - padding-left: 40px; - dl{ - margin-bottom: 25px; - dt{ - font-size: 13px; - color: #101010; - font-weight: 600; - margin-bottom: 5px; - } - dd{ - font-size: 12px; - color: #45576F; - font-weight: 400; - line-height: 24px; - } - &:last-child{ - margin-bottom: 0; - } - } - } -} - -.module-total{ - display: flex; - align-items: center; - background-color: #F8F9FA; - padding: 9px 0; - margin-right: 4px; - border: 1px solid #ECF0F4; - border-top: none; - .total-title{ - flex: 1; - text-align: center; - font-size: 13px; - color: #344356; - font-weight: 500; - } - .total-num{ - flex: none; - width: 121px; - text-align: center; - font-size: 15px; - color: #344356; - font-weight: 500; - } -} - -// 물건상세 -.information-help-wrap{ - display: flex; - padding: 24px; - background-color: #F4F4F4; - border-radius: 4px; - margin-bottom: 15px; - .information-help-tit-wrap{ - position: relative; + } + .canvas-depth2-btn-list { display: flex; align-items: center; - padding-right: 40px; - border-right: 1px solid #E0E0E3; - .help-tit-icon{ - width: 40px; - height: 40px; - border-radius: 50%; - margin-right: 10px; - background: #fff url(../../public/static/images/sub/information_help.svg)no-repeat center; - background-size: 20px 20px; - } - .help-tit{ - font-size: 13px; - font-weight: 600; - color: #45576F; - } - } - .information-help-guide{ - padding-left: 40px; - span{ - display: block; + margin-left: auto; + height: 100%; + .depth2-btn-box { + display: flex; + align-items: center; + margin-right: 34px; + height: 100%; + transition: all 0.17s ease-in-out; + button { + position: relative; font-size: 12px; font-weight: 400; - color: #45576F; - margin-bottom: 7px; - &:last-child{ - margin-bottom: 0; + height: 100%; + color: #fff; + padding-right: 12px; + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 5px; + height: 8px; + background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center; } + } + &:last-child { + margin-right: 0; + } + &.mouse { + opacity: 0.55; + } } + } } + &.active { + top: 47px; + } + } + &.active { + padding-bottom: 50px; + } } -.community-search-warp{ +// canvas-layout +.canvas-content { + padding-top: 46.8px; + transition: all 0.17s ease-in-out; + .canvas-frame { + height: 86.3vh; + } + &.active { + padding-top: calc(46.8px + 50px); + .canvas-frame { + height: 81vh; + } + } +} +.canvas-layout { + padding-top: 37px; + .canvas-page-list { + position: fixed; + top: 92.8px; + left: 0; + display: flex; + background-color: #1c1c1c; + border-top: 1px solid #000; + width: 100%; + transition: all 0.17s ease-in-out; + z-index: 999; + &.active { + top: calc(92.8px + 50px); + } + .canvas-plane-wrap { + display: flex; + align-items: center; + max-width: calc(100% - 45px); + .canvas-page-box { + display: flex; + align-items: center; + background-color: #1c1c1c; + padding: 9.6px 20px; + border-right: 1px solid #000; + min-width: 0; + transition: all 0.17s ease-in-out; + span { + display: flex; + align-items: center; + width: 100%; + font-size: 12px; + font-family: 'Pretendard', sans-serif; + color: #aaa; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + .close { + flex: none; + display: block; + width: 7px; + height: 8px; + margin-left: 15px; + background: url(../../public/static/images/canvas/plan_close_gray.svg) no-repeat center; + background-size: cover; + } + &.on { + background-color: #fff; + span { + font-weight: 600; + color: #101010; + } + .close { + background: url(../../public/static/images/canvas/plan_close_black.svg) no-repeat center; + } + &:hover { + background-color: #fff; + } + } + &:hover { + background-color: #000; + } + } + } + .plane-add { + display: flex; + align-items: center; + justify-content: center; + width: 45px; + padding: 13.5px 0; + background-color: #1c1c1c; + border-right: 1px solid #000; + transition: all 0.17s ease-in-out; + span { + display: block; + width: 9px; + height: 9px; + background: url(../../public/static/images/canvas/plane_add.svg) no-repeat center; + background-size: cover; + } + &:hover { + background-color: #000; + } + } + } +} + +.canvas-frame { + position: relative; + // height: calc(100% - 36.5px); + background-color: #f4f4f7; + overflow: auto; + transition: all 0.17s ease-in-out; + // &::-webkit-scrollbar { + // width: 10px; + // height: 10px; + // background-color: #fff; + // } + // &::-webkit-scrollbar-thumb { + // background-color: #C1CCD7; + // border-radius: 30px; + // } + // &::-webkit-scrollbar-track { + // background-color: #fff; + // } + canvas { + background-color: #fff; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } +} + +// sub-page +.sub-header { + position: fixed; + top: 46px; + left: 0; + width: 100%; + height: 46px; + border-bottom: 1px solid #000; + background: #2c2c2c; + z-index: 999; + .sub-header-inner { display: flex; - flex-direction: column; align-items: center; - padding: 10px 0 30px 0; - border-bottom: 1px solid #E5E5E5; - margin-bottom: 24px; - .community-search-box{ + height: 100%; + padding: 0 100px; + .sub-header-title-wrap { + display: flex; + align-items: center; + .title-item { + position: relative; + padding: 0 24px; + a { + display: flex; + align-items: center; + .icon { + width: 22px; + height: 22px; + margin-right: 8px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; + &.drawing { + background-image: url(../../public/static/images/main/drawing_icon.svg); + } + } + } + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 1px; + height: 16px; + background-color: #d9d9d9; + } + &:first-child { + padding-left: 0; + } + &:last-child { + padding-right: 0; + &:after { + display: none; + } + } + } + } + .sub-header-title { + font-size: 16px; + color: #fff; + font-weight: 600; + } + .sub-header-location { + margin-left: auto; + display: flex; + align-items: center; + .location-item { position: relative; display: flex; align-items: center; - width: 580px; - height: 45px; - padding: 0 45px 0 20px; - margin-bottom: 20px; - border-radius: 2px; - border: 1px solid #101010; - .community-input{ - width: 100%; - height: 100%; - font-size: 13px; - font-weight: 400; - color: #101010; - &::placeholder{ - color: #C8C8C8; - } + padding: 0 10px; + span { + display: flex; + font-size: 12px; + color: #aaa; + font-weight: normal; + cursor: default; } - .community-search-ico{ - position: absolute; - top: 50%; - right: 20px; - transform: translateY(-50%); - flex: none; - width: 21px; - height: 100%; - background: url(../../public/static/images/sub/community_search.svg)no-repeat center; - background-size: 21px 21px; - z-index: 3; - } - } - .community-search-keyword{ - font-size: 13px; - font-weight: 400; - color: #45576F; - span{ - font-weight: 600; - color: #F16A6A; + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 4px; + height: 6px; + background: url(../../public/static/images/main/loaction_arr.svg) no-repeat center; } + &:first-child { + padding-left: 0; + } + &:last-child { + padding-right: 0; + span { + color: #fff; + } + &:after { + display: none; + } + } + } } + } } -// 자료 다운로드 -.file-down-list{ - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 14px; - .file-down-item{ +// sub content +.sub-content { + padding-top: 46px; + .sub-content-inner { + max-width: 1720px; + margin: 0 auto; + padding-top: 20px; + .sub-content-box { + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + } + } + &.estimate { + display: flex; + flex-direction: column; + padding-top: 0; + .sub-content-inner { + flex: 1; + width: 100%; + } + } +} +.sub-table-box { + padding: 20px; + border-radius: 6px; + border: 1px solid #e9eaed; + background: #fff; + box-shadow: 0px 3px 30px 0px rgba(0, 0, 0, 0.02); + .table-box-title-wrap { + display: flex; + align-items: center; + margin-bottom: 15px; + .title-wrap { + display: flex; + align-items: center; + h3 { + display: block; + font-size: 15px; + color: #101010; + font-weight: 600; + margin-right: 14px; + &.product { + margin-right: 10px; + } + } + .product_tit { + position: relative; + font-size: 15px; + font-weight: 600; + color: #1083e3; + padding-left: 10px; + &::before { + content: ''; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + width: 1px; + height: 11px; + background-color: #d9d9d9; + } + } + .option { + padding-left: 5px; + font-size: 13px; + color: #101010; + font-weight: 400; + } + .info-wrap { display: flex; align-items: center; - padding: 24px; - border-radius: 4px; - border: 1px solid #E5E5E5; - background: #FFF; - transition: all .15s ease-in-out; - cursor: pointer; - .file-item-info{ - .item-num{ - display: inline-block; - padding: 6px 17.5px; - border-radius: 60px; - background-color: #F4F4F7; - font-size: 13px; - font-weight: 600; - color: #101010; - margin-bottom: 15px; + li { + position: relative; + padding: 0 6px; + font-size: 12px; + color: #101010; + font-weight: normal; + span { + font-weight: 600; + &.red { + color: #e23d70; } - .item-name{ - font-size: 16px; - color: #101010; - font-weight: 500; - margin-bottom: 13px; - } - .item-date{ - font-size: 13px; - font-weight: 400; - color: #344356; + } + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 1px; + height: 11px; + background-color: #d9d9d9; + } + &:first-child { + padding-left: 0; + } + &:last-child { + padding-right: 0; + &::after { + display: none; } + } } - .file-down-box{ - display: flex; - align-items: center; - flex: none; - margin-left: auto; - height: 100%; - .file-down-btn{ - width: 36px; - height: 36px; - background: url(../../public/static/images/sub/file_down_btn.svg)no-repeat center; - background-size: cover; - } - } - &:hover{ - background-color: #F4F4F7; - } + } } -} - -.file-down-nodata{ + } + .left-unit-box { + margin-left: auto; + display: flex; + align-items: center; + } + .promise-gudie { + display: block; + font-size: 13px; + font-weight: 700; + color: #101010; + margin-bottom: 20px; + } + .important { + color: #f00; + } + .sub-center-footer { display: flex; align-items: center; justify-content: center; - width: 100%; - height: 148px; - padding: 24px; - border-radius: 4px; - border: 1px solid #E5E5E5; - font-size: 16px; + margin-top: 20px; + } + .sub-right-footer { + display: flex; + align-items: center; + justify-content: flex-end; + margin-top: 20px; + } +} +.pagination-wrap { + margin-top: 24px; +} + +.infomation-wrap { + margin-bottom: 30px; +} + +.infomation-box-wrap { + display: flex; + align-items: center; + gap: 10px; + .sub-table-box { + flex: 1; + } + .info-title { + font-size: 14px; font-weight: 500; color: #344356; -} \ No newline at end of file + margin-bottom: 10px; + } + .info-inner { + position: relative; + font-size: 13px; + color: #344356; + .copy-ico { + position: absolute; + bottom: 0; + right: 0; + width: 16px; + height: 16px; + background: url(../../public/static/images/sub/copy_ico.svg) no-repeat center; + background-size: cover; + } + } +} + +// 견적서 +.estimate-list-wrap { + display: flex; + align-items: center; + margin-bottom: 10px; + &.one { + .estimate-box { + &:last-child { + min-width: unset; + } + } + } + .estimate-box { + flex: 1; + display: flex; + align-items: center; + &:last-child { + flex: none; + min-width: 220px; + } + .estimate-tit { + width: 105px; + height: 30px; + line-height: 30px; + background-color: #f4f4f7; + border-radius: 100px; + text-align: center; + font-size: 13px; + font-weight: 500; + color: #344356; + } + .estimate-name { + font-size: 13px; + color: #344356; + margin-left: 14px; + font-weight: 400; + &.blue { + font-size: 16px; + font-weight: 700; + color: #1083e3; + } + &.red { + font-size: 16px; + font-weight: 700; + color: #d72a2a; + } + } + } + &:last-child { + margin-bottom: 0; + } +} + +// file drag box +.drag-file-box { + padding: 10px; + .btn-area { + padding-bottom: 15px; + border-bottom: 1px solid #ecf0f4; + } + .drag-file-area { + position: relative; + margin-top: 15px; + p { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 13px; + color: #ccc; + font-weight: 400; + cursor: default; + } + } + .file-list { + .file-item { + margin-bottom: 15px; + span { + position: relative; + font-size: 13px; + color: #45576f; + font-weight: 400; + white-space: nowrap; + padding-right: 55px; + button { + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 15px; + height: 15px; + background: url(../../public/static/images/sub/file_delete.svg) no-repeat center; + background-size: cover; + } + } + &:last-child { + margin-bottom: 0; + } + } + } +} + +.special-note-check-wrap { + display: grid; + grid-template-columns: repeat(5, 1fr); + border: 1px solid #ecf0f4; + border-radius: 3px; + margin-bottom: 30px; + .special-note-check-item { + padding: 14px 10px; + border-right: 1px solid #ecf0f4; + border-top: 1px solid #ecf0f4; + &:nth-child(5n) { + border-right: none; + } + &:nth-child(-n + 5) { + border-top: none; + } + &.act { + background-color: #f7f9fa; + } + } +} + +.calculation-estimate { + border: 1px solid #ecf0f4; + border-radius: 3px; + padding: 24px; + max-height: 350px; + overflow-y: auto; + margin-bottom: 30px; + dl { + margin-bottom: 35px; + &:last-child { + margin-bottom: 0; + } + dt { + font-size: 13px; + font-weight: 600; + color: #1083e3; + margin-bottom: 15px; + } + dd { + font-size: 12px; + font-weight: 400; + color: #45576f; + margin-bottom: 8px; + &:last-child { + margin-bottom: 0; + } + } + } + &::-webkit-scrollbar { + width: 4px; + background-color: transparent; + } + &::-webkit-scrollbar-thumb { + background-color: #d9dee2; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } +} +.esimate-wrap { + margin-bottom: 20px; +} + +.estimate-product-option { + display: flex; + align-items: center; + margin-bottom: 15px; + .product-price-wrap { + display: flex; + align-items: center; + .product-price-tit { + font-size: 13px; + font-weight: 400; + color: #45576f; + margin-right: 10px; + } + .select-wrap { + width: 110px; + } + } + .product-edit-wrap { + display: flex; + align-items: center; + margin-left: auto; + .product-edit-explane { + display: flex; + align-items: center; + margin-right: 15px; + .attachment-required { + position: relative; + display: flex; + align-items: center; + font-size: 12px; + font-weight: 400; + color: #45576f; + padding-right: 10px; + .ico { + width: 23px; + height: 23px; + margin-right: 5px; + background: url(../../public/static/images/sub/attachment_ico.svg) no-repeat center; + background-size: cover; + } + &::before { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 1px; + height: 12px; + background-color: #d9d9d9; + } + } + .click-check { + display: flex; + align-items: center; + font-size: 12px; + font-weight: 400; + color: #f16a6a; + padding-left: 10px; + .ico { + width: 14px; + height: 14px; + margin-right: 5px; + background: url(../../public/static/images/sub/click_check_ico.svg) no-repeat center; + background-size: cover; + } + } + } + .product-edit-btn { + display: flex; + align-items: center; + button { + display: flex; + align-items: center; + span { + width: 13px; + height: 13px; + margin-right: 5px; + background-size: cover; + &.plus { + background: url(../../public/static/images/sub/plus_btn.svg) no-repeat center; + } + &.minus { + background: url(../../public/static/images/sub/minus_btn.svg) no-repeat center; + } + } + } + } + } +} + +// 발전시물레이션 +.chart-wrap { + display: flex; + gap: 20px; + width: 100%; + .sub-table-box { + height: 100%; + } + .chart-inner { + flex: 1; + .chart-box { + margin-bottom: 30px; + } + } + .chart-table-wrap { + display: flex; + flex-direction: column; + flex: none; + width: 650px; + .sub-table-box { + flex: 1; + &:first-child { + margin-bottom: 20px; + } + } + } +} + +.chart-month-table { + table { + table-layout: fixed; + border-collapse: collapse; + border: 1px solid #ecf0f4; + border-radius: 4px; + thead { + th { + padding: 4.5px 0; + border-bottom: 1px solid #ecf0f4; + text-align: center; + font-size: 13px; + color: #45576f; + font-weight: 500; + background-color: #f8f9fa; + } + } + tbody { + td { + font-size: 13px; + color: #45576f; + text-align: center; + padding: 4.5px 0; + } + } + } +} + +.simulation-guide-wrap { + display: flex; + padding: 20px; + .simulation-tit-wrap { + padding-right: 40px; + border-right: 1px solid #eeeeee; + span { + display: block; + position: relative; + padding-left: 60px; + font-size: 15px; + color: #14324f; + font-weight: 600; + &::before { + content: ''; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + width: 40px; + height: 40px; + background: url(../../public/static/images/sub/simulation_guide.svg) no-repeat center; + background-size: cover; + } + } + } + .simulation-guide-box { + padding-left: 40px; + dl { + margin-bottom: 25px; + dt { + font-size: 13px; + color: #101010; + font-weight: 600; + margin-bottom: 5px; + } + dd { + font-size: 12px; + color: #45576f; + font-weight: 400; + line-height: 24px; + } + &:last-child { + margin-bottom: 0; + } + } + } +} + +.module-total { + display: flex; + align-items: center; + background-color: #f8f9fa; + padding: 9px 0; + margin-right: 4px; + border: 1px solid #ecf0f4; + border-top: none; + .total-title { + flex: 1; + text-align: center; + font-size: 13px; + color: #344356; + font-weight: 500; + } + .total-num { + flex: none; + width: 121px; + text-align: center; + font-size: 15px; + color: #344356; + font-weight: 500; + } +} + +// 물건상세 +.information-help-wrap { + display: flex; + padding: 24px; + background-color: #f4f4f4; + border-radius: 4px; + margin-bottom: 15px; + .information-help-tit-wrap { + position: relative; + display: flex; + align-items: center; + padding-right: 40px; + border-right: 1px solid #e0e0e3; + .help-tit-icon { + width: 40px; + height: 40px; + border-radius: 50%; + margin-right: 10px; + background: #fff url(../../public/static/images/sub/information_help.svg) no-repeat center; + background-size: 20px 20px; + } + .help-tit { + font-size: 13px; + font-weight: 600; + color: #45576f; + } + } + .information-help-guide { + padding-left: 40px; + span { + display: block; + font-size: 12px; + font-weight: 400; + color: #45576f; + margin-bottom: 7px; + &:last-child { + margin-bottom: 0; + } + } + } +} + +.community-search-warp { + display: flex; + flex-direction: column; + align-items: center; + padding: 10px 0 30px 0; + border-bottom: 1px solid #e5e5e5; + margin-bottom: 24px; + .community-search-box { + position: relative; + display: flex; + align-items: center; + width: 580px; + height: 45px; + padding: 0 45px 0 20px; + margin-bottom: 20px; + border-radius: 2px; + border: 1px solid #101010; + .community-input { + width: 100%; + height: 100%; + font-size: 13px; + font-weight: 400; + color: #101010; + &::placeholder { + color: #c8c8c8; + } + } + .community-search-ico { + position: absolute; + top: 50%; + right: 20px; + transform: translateY(-50%); + flex: none; + width: 21px; + height: 100%; + background: url(../../public/static/images/sub/community_search.svg) no-repeat center; + background-size: 21px 21px; + z-index: 3; + } + } + .community-search-keyword { + font-size: 13px; + font-weight: 400; + color: #45576f; + span { + font-weight: 600; + color: #f16a6a; + } + } +} + +// 자료 다운로드 +.file-down-list { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 14px; + .file-down-item { + display: flex; + align-items: center; + padding: 24px; + border-radius: 4px; + border: 1px solid #e5e5e5; + background: #fff; + transition: all 0.15s ease-in-out; + cursor: pointer; + .file-item-info { + .item-num { + display: inline-block; + padding: 6px 17.5px; + border-radius: 60px; + background-color: #f4f4f7; + font-size: 13px; + font-weight: 600; + color: #101010; + margin-bottom: 15px; + } + .item-name { + font-size: 16px; + color: #101010; + font-weight: 500; + margin-bottom: 13px; + } + .item-date { + font-size: 13px; + font-weight: 400; + color: #344356; + } + } + .file-down-box { + display: flex; + align-items: center; + flex: none; + margin-left: auto; + height: 100%; + .file-down-btn { + width: 36px; + height: 36px; + background: url(../../public/static/images/sub/file_down_btn.svg) no-repeat center; + background-size: cover; + } + } + &:hover { + background-color: #f4f4f7; + } + } +} + +.file-down-nodata { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 148px; + padding: 24px; + border-radius: 4px; + border: 1px solid #e5e5e5; + font-size: 16px; + font-weight: 500; + color: #344356; +} diff --git a/src/styles/_main.scss b/src/styles/_main.scss index ea9b8833..6a2a06e6 100644 --- a/src/styles/_main.scss +++ b/src/styles/_main.scss @@ -1,652 +1,687 @@ // background img -.background-bord{ - position: absolute; - top: 46px; - left: 0; - width: 100%; - height: 280px; - background: url(../../public/static/images/main/main_background.png)no-repeat center; - background-size: cover; - z-index: 0; +.background-bord { + position: absolute; + top: 46px; + left: 0; + width: 100%; + height: 280px; + background: url(../../public/static/images/main/main_background.png) no-repeat center; + background-size: cover; + z-index: 0; } // main-wrap -.main-contents{ - position: relative; - z-index: 1; - padding-bottom: 15px; +.main-contents { + position: relative; + z-index: 1; + padding-bottom: 15px; } // contents -.store-id-wrap{ - display: flex; - align-items: center; - justify-content: center; - gap: 12px; - padding: 33.5px 0; - border-bottom: 1px solid rgba(255, 255, 255, 0.08); - background-color: rgba(255, 255, 255, 0.05); - .store-id-title{ - position: relative; - padding-left: 32px; - font-size: 13px; - color: #fff; - &::before{ - content: ''; - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); - width: 20px; - height: 20px; - background: url(../../public/static/images/main/id_icon.svg)no-repeat center; - } - } - .store-arr{ - display: block; - width: 7px; - height: 10px; - background: url(../../public/static/images/main/store-arr.svg) no-repeat center; - } - .store-id-name{ - font-size: 16px; - color: #fff; - font-weight: 600; +.store-id-wrap { + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + padding: 33.5px 0; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + background-color: rgba(255, 255, 255, 0.05); + .store-id-title { + position: relative; + padding-left: 32px; + font-size: 13px; + color: #fff; + &::before { + content: ''; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + width: 20px; + height: 20px; + background: url(../../public/static/images/main/id_icon.svg) no-repeat center; } + } + .store-arr { + display: block; + width: 7px; + height: 10px; + background: url(../../public/static/images/main/store-arr.svg) no-repeat center; + } + .store-id-name { + font-size: 16px; + color: #fff; + font-weight: 600; + } } // main-search-form -.main-search-wrap{ +.main-search-wrap { + display: flex; + align-items: center; + justify-content: center; + padding: 45px 0; + .search-raido-wrap { display: flex; align-items: center; - justify-content: center; - padding: 45px 0; - .search-raido-wrap{ - display: flex; - align-items: center; - gap: 16px; - margin-right: 30px; - } + gap: 16px; + margin-right: 30px; + } } -.search-input-box{ - display: flex; - align-items: center; - width: 580px; - height: 45px; - border-radius: 100px; - padding: 0 20px; - border: 1px solid rgba(255, 255, 255, 0.30); - background: rgba(31, 31, 31, 0.30); - .main-search{ - flex: 1; - height: 100%; - font-size: 13px; - color: #fff; - background-color: transparent; - outline: none; - border: none; - font-family: 'Noto Sans JP', sans-serif; - } - .search-icon{ - width: 20px; - height: 100%; - background-image: url(../../public/static/images/main/main_search.svg); - background-repeat: no-repeat; - background-position: center; - background-size: 21px 21px; - } +.search-input-box { + display: flex; + align-items: center; + width: 580px; + height: 45px; + border-radius: 100px; + padding: 0 20px; + border: 1px solid rgba(255, 255, 255, 0.3); + background: rgba(31, 31, 31, 0.3); + .main-search { + flex: 1; + height: 100%; + font-size: 13px; + color: #fff; + background-color: transparent; + outline: none; + border: none; + font-family: 'Noto Sans JP', sans-serif; + } + .search-icon { + width: 20px; + height: 100%; + background-image: url(../../public/static/images/main/main_search.svg); + background-repeat: no-repeat; + background-position: center; + background-size: 21px 21px; + } } // main-contents-inner -.main-product-list-wrap{ - max-width: 1400px; - margin: 0 auto; - .main-product-list{ +.main-product-list-wrap { + max-width: 1400px; + margin: 0 auto; + .main-product-list { + display: flex; + gap: 24px; + margin-bottom: 24px; + .product-item { + display: flex; + flex-direction: column; + padding: 40px; + border-radius: 6px; + background: #fff; + box-shadow: 0px 3px 30px 0px rgba(0, 0, 0, 0.02); + &.item01 { + flex: 1; + height: 400px; + } + &.item02 { + flex: none; + width: 451px; + height: 400px; + } + &.item03 { + flex: 1; + } + &.item04 { + flex: none; + width: 351px; + } + &.item05 { + flex: none; + width: 451px; + } + .product-item-title-wrap { display: flex; - gap: 24px; - margin-bottom: 24px; - .product-item{ + align-items: center; + .product-item-title { + display: flex; + align-items: center; + font-size: 16px; + color: #101010; + font-weight: 600; + .item-logo { + display: block; + width: 40px; + height: 40px; + border-radius: 50px; + background: #14324f; + margin-right: 12px; + background-repeat: no-repeat; + background-size: 22px 22px; + background-position: center; + &.ico01 { + background-image: url(../../public/static/images/main/product_ico01.svg); + } + &.ico02 { + background-image: url(../../public/static/images/main/product_ico02.svg); + } + &.ico03 { + background-image: url(../../public/static/images/main/product_ico03.svg); + } + &.ico04 { + background-image: url(../../public/static/images/main/product_ico04.svg); + } + &.ico05 { + background-image: url(../../public/static/images/main/product_ico05.svg); + } + } + } + .more-btn { + display: block; + width: 20px; + height: 20px; + margin-left: auto; + background: url(../../public/static/images/main/more_btn.svg) no-repeat center; + } + } + .product-item-content { + margin-top: 30px; + overflow: hidden; + .recently-list { + .recently-item { + border: 1px solid #f2f2f2; + background-color: transparent; + padding: 29.9px 20px; + margin-bottom: 5px; + cursor: pointer; + .item-inner { + display: flex; + align-items: center; + span { + position: relative; + display: block; + font-size: 13px; + color: #101010; + font-weight: 400; + padding: 0 10px; + &.time { + padding-left: 22px; + &::before { + content: ''; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + width: 14px; + height: 14px; + background: url(../../public/static/images/main/clock.svg) no-repeat center; + background-size: cover; + } + } + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 1px; + height: 10px; + background-color: #bbb; + } + &:last-child { + &:after { + display: none; + } + } + } + } + &:last-child { + margin-bottom: 5px; + } + } + } + .notice-box { + height: 100%; + overflow-y: auto; + .notice-day { + font-size: 13px; + color: #666; + font-weight: 400; + margin-bottom: 7px; + } + .notice-title { + font-size: 14px; + color: #101010; + font-weight: 600; + margin-bottom: 25px; + line-height: 24px; + word-break: keep-all; + } + .notice-contents { + font-size: 12px; + color: #666; + font-weight: 400; + line-height: 22px; + span { + position: relative; + display: block; + padding-left: 10px; + &::before { + content: ''; + position: absolute; + top: 10px; + left: 3px; + width: 3px; + height: 3px; + border-radius: 100%; + background-color: #666; + } + } + } + &::-webkit-scrollbar { + width: 4px; /* 스크롤바의 너비 */ + } + &::-webkit-scrollbar-thumb { + background: #697c8f; /* 스크롤바의 색상 */ + } + &::-webkit-scrollbar-track { + background: transparent; /*스크롤바 뒷 배경 색상*/ + } + } + .faq-item { + position: relative; + margin-bottom: 10px; + cursor: pointer; + .faq-item-inner { display: flex; - flex-direction: column; - padding: 40px; - border-radius: 6px; - background: #FFF; - box-shadow: 0px 3px 30px 0px rgba(0, 0, 0, 0.02); - &.item01{flex: 1; height: 400px;} - &.item02{flex: none; width: 451px; height: 400px;} - &.item03{flex: 1;} - &.item04{flex: none; width: 351px;} - &.item05{flex: none; width: 451px;} - .product-item-title-wrap{ - display: flex; - align-items: center; - .product-item-title{ - display: flex; - align-items: center; - font-size: 16px; - color: #101010; - font-weight: 600; - .item-logo{ - display: block; - width: 40px; - height: 40px; - border-radius: 50px; - background: #14324F; - margin-right: 12px; - background-repeat: no-repeat; - background-size: 22px 22px; - background-position: center; - &.ico01{background-image: url(../../public/static/images/main/product_ico01.svg);} - &.ico02{background-image: url(../../public/static/images/main/product_ico02.svg);} - &.ico03{background-image: url(../../public/static/images/main/product_ico03.svg);} - &.ico04{background-image: url(../../public/static/images/main/product_ico04.svg);} - &.ico05{background-image: url(../../public/static/images/main/product_ico05.svg);} - } - } - .more-btn{ - display: block; - width: 20px; - height: 20px; - margin-left: auto; - background: url(../../public/static/images/main/more_btn.svg)no-repeat center; - } + align-items: center; + + .faq-num { + flex: none; + padding: 7px 12.5px; + font-size: 13px; + color: #101010; + font-weight: 600; + border-radius: 110px; + border: 1px solid rgba(242, 242, 242, 0.95); + margin-right: 20px; } - .product-item-content{ - margin-top: 30px; - overflow: hidden; - .recently-list{ - .recently-item{ - border: 1px solid #F2F2F2; - background-color: transparent; - padding: 29.9px 20px; - margin-bottom: 5px; - cursor: pointer; - .item-inner{ - display: flex; - align-items: center; - span{ - position: relative; - display: block; - font-size: 13px; - color: #101010; - font-weight: 400; - padding: 0 10px; - &.time{ - padding-left: 22px; - &::before{ - content: ''; - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); - width: 14px; - height: 14px; - background:url(../../public/static/images/main/clock.svg)no-repeat center; - background-size: cover; - } - } - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 1px; - height: 10px; - background-color: #BBB; - } - &:last-child{ - &:after{ - display: none; - } - } - } - } - &:last-child{ - margin-bottom: 5px; - } - } - } - .notice-box{ - height: 100%; - overflow-y: auto; - .notice-day{ - font-size: 13px; - color: #666; - font-weight: 400; - margin-bottom: 7px; - } - .notice-title{ - font-size: 14px; - color: #101010; - font-weight: 600; - margin-bottom: 25px; - line-height: 24px; - word-break: keep-all; - } - .notice-contents{ - font-size: 12px; - color: #666; - font-weight: 400; - line-height: 22px; - span{ - position: relative; - display: block; - padding-left: 10px; - &::before{ - content: ''; - position: absolute; - top: 10px; - left: 3px; - width: 3px; - height: 3px; - border-radius: 100%; - background-color: #666; - } - } - } - &::-webkit-scrollbar {width: 4px; /* 스크롤바의 너비 */} - &::-webkit-scrollbar-thumb {background: #697C8F; /* 스크롤바의 색상 */} - &::-webkit-scrollbar-track {background: transparent; /*스크롤바 뒷 배경 색상*/} - } - .faq-item{ - position: relative; - margin-bottom: 10px; - cursor: pointer; - .faq-item-inner{ - display: flex; - align-items: center; - - .faq-num{ - flex: none; - padding: 7px 12.5px; - font-size: 13px; - color: #101010; - font-weight: 600; - border-radius: 110px; - border: 1px solid rgba(242, 242, 242, 0.95); - margin-right: 20px; - } - .faq-title{ - width: 0; - flex: 1 1 auto; - font-size: 13px; - color: #101010; - font-weight: 500; - padding-right: 96px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - } - .faq-day{ - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - font-size: 13px; - color: #101010; - font-weight: 400; - } - } - &:last-child{ - margin-bottom: 0; - } - } - .data-download-wrap{ - width: 100%; - .data-down{ - display: block; - width: 100%; - padding: 20px; - text-align: left; - border-radius: 4px; - background-color: #697C8F; - margin-bottom: 5px; - transition: background .17s ease-in-out; - span{ - position: relative; - display: block; - padding-right: 30px; - font-size: 13px; - color: #fff; - font-weight: 400; - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 18px; - height: 16px; - background: url(../../public/static/images/main/download.svg)no-repeat center; - background-size: cover; - } - } - &:last-child{ - margin-bottom: 0; - } - &:hover{ - background-color: #859eb6; - } - } - } - .contact-info-list{ - padding: 25px 30px; - border-radius: 4px; - background-color: #F4F4F7; - .info-item{ - display: flex; - align-items: center; - padding: 15px 0; - border-bottom: 1px solid #fff; - &:first-child{padding-top: 0;} - &:last-child{padding-bottom: 0; border: none;} - .icon-box{ - display: flex; - margin-right: 12px; - } - .infor-data{ - font-size: 13px; - color: #101010; - font-weight: 500; - } - } - } + .faq-title { + width: 0; + flex: 1 1 auto; + font-size: 13px; + color: #101010; + font-weight: 500; + padding-right: 96px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; } - } - &:last-child{ + .faq-day { + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + font-size: 13px; + color: #101010; + font-weight: 400; + } + } + &:last-child { margin-bottom: 0; + } } + .data-download-wrap { + width: 100%; + .data-down { + display: block; + width: 100%; + padding: 20px; + text-align: left; + border-radius: 4px; + background-color: #697c8f; + margin-bottom: 5px; + transition: background 0.17s ease-in-out; + span { + position: relative; + display: block; + padding-right: 30px; + font-size: 13px; + color: #fff; + font-weight: 400; + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 18px; + height: 16px; + background: url(../../public/static/images/main/download.svg) no-repeat center; + background-size: cover; + } + } + &:last-child { + margin-bottom: 0; + } + &:hover { + background-color: #859eb6; + } + } + } + .contact-info-list { + padding: 25px 30px; + border-radius: 4px; + background-color: #f4f4f7; + .info-item { + display: flex; + align-items: center; + padding: 15px 0; + border-bottom: 1px solid #fff; + &:first-child { + padding-top: 0; + } + &:last-child { + padding-bottom: 0; + border: none; + } + .icon-box { + display: flex; + margin-right: 12px; + } + .infor-data { + font-size: 13px; + color: #101010; + font-weight: 500; + } + } + } + } } + &:last-child { + margin-bottom: 0; + } + } } // loginpage -.login-wrap{ - position: relative; +.login-wrap { + position: relative; + width: 100%; + min-height: 100vh; + display: flex; + flex-direction: column; + justify-content: center; + background: url(../../public/static/images/main/login_bg.png) no-repeat center; + background-size: cover; + .login-inner { + max-width: 500px; width: 100%; - min-height: 100vh; - display: flex; - flex-direction: column; - justify-content: center; - background: url(../../public/static/images/main/login_bg.png) no-repeat center; - background-size: cover; - .login-inner{ - max-width: 500px; - width: 100%; - margin: 0 auto; - .login-logo{ - display: block; - margin-bottom: 25px; + margin: 0 auto; + .login-logo { + display: block; + margin-bottom: 25px; + } + .login-input-frame { + padding: 40px 50px; + border-radius: 6px; + background: rgba(255, 255, 255, 0.97); + box-shadow: 0px 3px 30px 0px rgba(0, 0, 0, 0.02); + .login-frame-tit { + font-size: 18px; + color: #364864; + font-weight: 400; + padding-bottom: 30px; + border-bottom: 1px solid #e5e9ef; + span { + display: block; + font-weight: 600; + margin-bottom: 5px; } - .login-input-frame{ - padding: 40px 50px; - border-radius: 6px; - background: rgba(255, 255, 255, 0.97); - box-shadow: 0px 3px 30px 0px rgba(0, 0, 0, 0.02); - .login-frame-tit{ - font-size: 18px; - color: #364864; - font-weight: 400; - padding-bottom: 30px; - border-bottom: 1px solid #E5E9EF; - span{ - display: block; - font-weight: 600; - margin-bottom: 5px; - } - &.pw-reset{ - font-size: 13px; - } - } - .login-input-wrap{ - margin-top: 30px; - .login-area{ - position: relative; - display: flex; - align-items: center; - border: 1px solid #E5E9EF; - height: 45px; - padding-left: 40px; - padding-right: 15px; - margin-bottom: 15px; - .login-input{ - flex: 1; - height: 100%; - background-color: transparent; - font-size: 13px; - font-weight: 400; - color: #6c819c; - &::placeholder{ - font-size: 13px; - font-weight: 400; - color: #D1D7E0; - } - } - &::before{ - content: ''; - position: absolute; - top: 50%; - left: 15px; - transform: translateY(-50%); - width: 10px; - height: 12px; - background-size: cover; - } - button{ - width: 20px; - height: 100%; - background-repeat: no-repeat; - background-position: center; - } - &.id{ - &::before{ - background: url(../../public/static/images/main/login_id.svg)no-repeat center; - } - .id-delete{ - background-image: url(../../public/static/images/main/id_delete.svg); - background-size: 17px 17px; - } - } - &.email{ - &::before{ - background: url(../../public/static/images/main/login_email.svg)no-repeat center; - width: 12px; - height: 9px; - } - .id-delete{ - background-image: url(../../public/static/images/main/id_delete.svg); - background-size: 17px 17px; - } - } - &.password{ - margin-bottom: 20px; - &::before{ - background: url(../../public/static/images/main/login_password.svg)no-repeat center; - } - .password-hidden{ - background-image: url(../../public/static/images/main/password_hidden.svg); - background-size: 19px 13px; - &.visible{ - background-image: url(../../public/static/images/main/password_visible.svg); - } - } - } - } - .login-btn{ - display: block; - width: 100%; - height: 45px; - background-color: #5C6773; - color: #fff; - font-size: 15px; - font-weight: 600; - border-radius: 4px; - transition: background .15s ease-in-out; - &:hover{ - background-color: #717e8d; - } - &.light{ - background-color: #fff; - border: 1px solid #5C6773; - color: #5C6773; - } - } - .login-btn-box{ - margin-bottom: 20px; - } - .pwreset-btn-box{ - display: flex; - } - .reset-password{ - width: 100%; - text-align: center; - button{ - position: relative; - font-size: 13px; - color: #364864; - font-weight: 400; - padding-right: 16px; - &::before{ - content: ''; - position: absolute; - top: calc(50% + 1px); - right: 0; - transform: translateY(-50%); - width: 6px; - height: 8px; - background: url(../../public/static/images/main/login-arr.svg)no-repeat center; - } - } - } - } + &.pw-reset { + font-size: 13px; } - .login-guide-wrap{ - position: relative; - margin-left: 10px; - margin-top: 30px; - padding-left: 15px; + } + .login-input-wrap { + margin-top: 30px; + .login-area { + position: relative; + display: flex; + align-items: center; + border: 1px solid #e5e9ef; + height: 45px; + padding-left: 40px; + padding-right: 15px; + margin-bottom: 15px; + .login-input { + flex: 1; + height: 100%; + background-color: transparent; font-size: 13px; - color: #fff; - line-height: 24px; - a{ - color: #fff; - font-weight: 600; - text-decoration: underline; + font-weight: 400; + color: #6c819c; + &::placeholder { + font-size: 13px; + font-weight: 400; + color: #d1d7e0; } - span{ - position: absolute; - top: 0; - left: 0; + } + &::before { + content: ''; + position: absolute; + top: 50%; + left: 15px; + transform: translateY(-50%); + width: 10px; + height: 12px; + background-size: cover; + } + button { + width: 20px; + height: 100%; + background-repeat: no-repeat; + background-position: center; + } + &.id { + &::before { + background: url(../../public/static/images/main/login_id.svg) no-repeat center; } + .id-delete { + background-image: url(../../public/static/images/main/id_delete.svg); + background-size: 17px 17px; + } + } + &.email { + &::before { + background: url(../../public/static/images/main/login_email.svg) no-repeat center; + width: 12px; + height: 9px; + } + .id-delete { + background-image: url(../../public/static/images/main/id_delete.svg); + background-size: 17px 17px; + } + } + &.password { + margin-bottom: 20px; + &::before { + background: url(../../public/static/images/main/login_password.svg) no-repeat center; + } + .password-hidden { + background-image: url(../../public/static/images/main/password_hidden.svg); + background-size: 19px 13px; + &.visible { + background-image: url(../../public/static/images/main/password_visible.svg); + } + } + } } + .login-btn { + display: block; + width: 100%; + height: 45px; + background-color: #5c6773; + color: #fff; + font-size: 15px; + font-weight: 600; + border-radius: 4px; + transition: background 0.15s ease-in-out; + &:hover { + background-color: #717e8d; + } + &.light { + background-color: #fff; + border: 1px solid #5c6773; + color: #5c6773; + } + } + .login-btn-box { + margin-bottom: 20px; + } + .pwreset-btn-box { + display: flex; + } + .reset-password { + width: 100%; + text-align: center; + button { + position: relative; + font-size: 13px; + color: #364864; + font-weight: 400; + padding-right: 16px; + &::before { + content: ''; + position: absolute; + top: calc(50% + 1px); + right: 0; + transform: translateY(-50%); + width: 6px; + height: 8px; + background: url(../../public/static/images/main/login-arr.svg) no-repeat center; + } + } + } + } } - .login-copyright{ - position: absolute; - bottom: 40px; - left: 50%; - transform: translateX(-50%); - font-size: 11px; + .login-guide-wrap { + position: relative; + margin-left: 10px; + margin-top: 30px; + padding-left: 15px; + font-size: 13px; + color: #fff; + line-height: 24px; + a { color: #fff; - font-weight: 500; + font-weight: 600; + text-decoration: underline; + } + span { + position: absolute; + top: 0; + left: 0; + } } + } + .login-copyright { + position: absolute; + bottom: 40px; + left: 50%; + transform: translateX(-50%); + font-size: 11px; + color: #fff; + font-weight: 500; + } } -.d-check-box{ - &.login{ - margin-bottom: 25px; - label{ - padding-left: 20px; - color: #364864; - &:before{ - width: 22px; - height: 22px; - top: -1px; - border-color: #A8B6C7; - border-radius: 3px; - transition: background .05s ease-in-out; - } - } - input[type=checkbox]:checked + label::before{ - border-color: #A8B6C7; - background-color: #A8B6C7; - } - input[type=checkbox]:checked + label::after{ - border-color: #fff; - width: 7px; - height: 11px; - top: -2px; - left: 1px; - } +.d-check-box { + &.login { + margin-bottom: 25px; + label { + padding-left: 20px; + color: #364864; + &:before { + width: 22px; + height: 22px; + top: -1px; + border-color: #a8b6c7; + border-radius: 3px; + transition: background 0.05s ease-in-out; + } } + input[type='checkbox']:checked + label::before { + border-color: #a8b6c7; + background-color: #a8b6c7; + } + input[type='checkbox']:checked + label::after { + border-color: #fff; + width: 7px; + height: 11px; + top: -2px; + left: 1px; + } + } } // 회원가입 -.center-page-wrap{ - display: flex; - flex-direction: column; - justify-content: center; +.center-page-wrap { + display: flex; + flex-direction: column; + justify-content: center; + width: 100%; + min-height: 100vh; + background-color: #f4f4f7; + overflow-x: hidden; + .center-page-inner { width: 100%; - min-height: 100vh; - background-color: #F4F4F7; - overflow-x: hidden; - .center-page-inner{ - width: 100%; - max-width: 1720px; - margin: 0 auto; - .center-page-tit{ - font-size: 18px; - font-weight: 600; - color: #101010; - margin-bottom: 24px; - } - .sub-table-box{ - &.signup{ - margin-bottom: 20px; - } - } - .sign-up-btn-wrap{ - display: flex; - justify-content: flex-end; - } - &.complete{ - max-width: 1000px; - } + max-width: 1720px; + margin: 0 auto; + .center-page-tit { + font-size: 18px; + font-weight: 600; + color: #101010; + margin-bottom: 24px; } - + .sub-table-box { + &.signup { + margin-bottom: 20px; + } + } + .sign-up-btn-wrap { + display: flex; + justify-content: flex-end; + } + &.complete { + max-width: 1000px; + } + } } // 회원가입 완료 -.complete-box-wrap{ - padding: 72px 80px; - .complete-tit{ - font-size: 18px; - font-weight: 600; - color: #101010; - margin-bottom: 17px; +.complete-box-wrap { + padding: 72px 80px; + .complete-tit { + font-size: 18px; + font-weight: 600; + color: #101010; + margin-bottom: 17px; + } + .complete-txt { + font-size: 13px; + font-weight: 400; + color: #101010; + margin-bottom: 27px; + } + .complete-email-wrap { + padding: 36px 30px; + border-radius: 2px; + background: #f4f4f7; + margin-bottom: 20px; + .email-info { + font-size: 13px; + font-weight: 400; + color: #000; + span { + color: #204af4; + font-weight: 500; + } } - .complete-txt{ - font-size: 13px; - font-weight: 400; - color: #101010; - margin-bottom: 27px; - } - .complete-email-wrap{ - padding: 36px 30px; - border-radius: 2px; - background: #F4F4F7; - margin-bottom: 20px; - .email-info{ - font-size: 13px; - font-weight: 400; - color: #000; - span{ - color: #204AF4; - font-weight: 500; - } - } - } - .complete-btn{ - display: flex; - justify-content: flex-end; - } -} \ No newline at end of file + } + .complete-btn { + display: flex; + justify-content: flex-end; + } +} diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss index 3901ba0f..f4d79550 100644 --- a/src/styles/_modal.scss +++ b/src/styles/_modal.scss @@ -4,647 +4,669 @@ $pop-bold-weight: 500; $pop-normal-size: 12px; $alert-color: #101010; -@keyframes mountpop{ - from{opacity: 0; scale: 0.95;} - to{opacity: 1; scale: 1;} +@keyframes mountpop { + from { + opacity: 0; + scale: 0.95; + } + to { + opacity: 1; + scale: 1; + } } -@keyframes unmountpop{ - from{opacity: 1; scale: 1;} - to{opacity: 0; scale: 0.95;} +@keyframes unmountpop { + from { + opacity: 1; + scale: 1; + } + to { + opacity: 0; + scale: 0.95; + } } -.normal-font{ - font-size: 12px; - font-weight: 400; - color: #fff; +.normal-font { + font-size: 12px; + font-weight: 400; + color: #fff; } -.bold-font{ - font-size: 12px; - font-weight: 500; - color: #fff; +.bold-font { + font-size: 12px; + font-weight: 500; + color: #fff; } -.modal-pop-wrap{ - position: fixed; - top: 0; - left: 0; - width: 100%; - height: -webkit-fit-content; - height: -moz-fit-content; - height: fit-content; - border: 1px solid #000; - border-radius: 4px; - background-color: #272727; - z-index: 9999999; - &.xsm{ - width: 200px; +.modal-pop-wrap { + position: fixed; + width: 100%; + height: -webkit-fit-content; + height: -moz-fit-content; + height: fit-content; + border: 1px solid #000; + border-radius: 4px; + background-color: #272727; + z-index: 9999999; + &.xsm { + width: 200px; + } + &.xxxm { + width: 240px; + } + &.xxm { + width: 270px; + } + &.xm { + width: 300px; + } + &.ssm { + width: 380px; + } + &.sm { + width: 580px; + } + &.r { + width: 400px; + } + &.lr { + width: 440px; + } + &.lrr { + width: 480px; + } + &.ml { + width: 530px; + } + &.l-2 { + width: 640px; + } + &.lx-2 { + width: 740px; + } + &.lx { + width: 770px; + } + &.l { + width: 800px; + } + &.mount { + animation: mountpop 0.17s ease-in-out forwards; + } + &.unmount { + animation: unmountpop 0.17s ease-in-out forwards; + } + &.alert { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: transparent; + border: none; + .modal-head { + background-color: transparent; + padding: 0 0 8px; + .modal-close { + width: 20px; + height: 20px; + background: url(../../public/static/images/canvas/alert_close.svg) no-repeat center; + } } - &.xxxm{ - width: 240px; - } - &.xxm{ - width: 270px; - } - &.xm{ - width: 300px; - } - &.ssm{ - width: 380px; - } - &.sm{ - width: 580px; - } - &.r{ - width: 400px; - } - &.lr{ - width: 440px; - } - &.lrr{ - width: 480px; - } - &.ml{ - width: 530px; - } - &.l-2{ - width: 640px; - } - &.lx-2{ - width: 740px; - } - &.lx{ - width: 770px; - } - &.l{ - width: 800px; - } - &.mount{ - animation: mountpop .17s ease-in-out forwards; - } - &.unmount{ - animation: unmountpop .17s ease-in-out forwards; - } - &.alert{ - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background-color: transparent; - border: none; - .modal-head{ - background-color: transparent; - padding: 0 0 8px; - .modal-close{ - width: 20px; - height: 20px; - background: url(../../public/static/images/canvas/alert_close.svg)no-repeat center; - } - } - .modal-body{ - background-color: #fff; - padding: 22px; - border-radius: 4px; - border: 1px solid #101010; - color: $alert-color; - .alert-title{ - font-size: 13px; - font-weight: 700; - color: $alert-color; - margin-bottom: 15px; - } - } - } -} -.modal-head{ - display: flex; - align-items: center; - padding: 10px 24px; - background-color: #000; - // overflow: hidden; - h1.title{ + .modal-body { + background-color: #fff; + padding: 22px; + border-radius: 4px; + border: 1px solid #101010; + color: $alert-color; + .alert-title { font-size: 13px; - color: $pop-color; font-weight: 700; - } - .modal-close{ - margin-left: auto; - color: transparent; - font-size: 0; - width: 10px; - height: 10px; - background: url(../../public/static/images/canvas/modal_close.svg)no-repeat center; - } -} -.modal-body{ - padding: 24px; - .modal-btn-wrap{ - display: flex; - align-items: center; - gap: 5px; - button{ - flex: 1; - } - &.sub{ - button{ - flex: 1 1 auto; - padding: 0; - } - margin-bottom: 14px; - } - } - .modal-check-btn-wrap{ - margin-top: 15px; - .check-wrap-title{ - font-size: $pop-normal-size; - color: $pop-color; - font-weight: 600; - &.light{ - font-weight: $pop-normal-weight; - } - } - .flex-check-box{ - display: flex; - flex-wrap: wrap; - gap: 10px; - margin-top: 15px; - &.for2{ - justify-content: flex-end; - button{ - width: calc(50% - 5px); - } - &.btn{ - gap: 5px; - button{ - width: calc(50% - 2.5px); - } - } - } - &.for-line{ - button{ - flex: 1; - } - } - } - } - .outer-line-wrap{ - border-top: 1px solid #3C3C3C; - margin-top: 10px; - padding-top: 15px; - margin-bottom: 15px; - > div{ - margin-bottom: 15px; - &:last-child{ - margin-bottom: 0; - } - } - } - .modal-guide{ - display: block; - font-size: $pop-normal-size; color: $alert-color; - font-weight: $pop-normal-weight; + margin-bottom: 15px; + } } + } } - -.adsorption-point{ +.modal-head { + display: flex; + align-items: center; + padding: 10px 24px; + background-color: #000; + // overflow: hidden; + h1.title { + font-size: 13px; + color: $pop-color; + font-weight: 700; + } + .modal-close { + margin-left: auto; + color: transparent; + font-size: 0; + width: 10px; + height: 10px; + background: url(../../public/static/images/canvas/modal_close.svg) no-repeat center; + } +} +.modal-body { + padding: 24px; + .modal-btn-wrap { display: flex; align-items: center; - background-color: #3A3A3A; - border-radius: 3px; - padding-left: 11px; - overflow: hidden; - transition: all 0.17s ease-in-out; - span{ - font-size: $pop-normal-size; - color: #898989; + gap: 5px; + button { + flex: 1; } - i{ - display: flex; - align-items: center; - padding: 0 7px; - margin-left: auto; - height: 100%; - font-size: 13px; - color: #898989; + &.sub { + button { + flex: 1 1 auto; + padding: 0; + } + margin-bottom: 14px; } - &.act{ - i{ - color: $pop-color; - background-color: #1083E3; + } + .modal-check-btn-wrap { + margin-top: 15px; + .check-wrap-title { + font-size: $pop-normal-size; + color: $pop-color; + font-weight: 600; + &.light { + font-weight: $pop-normal-weight; + } + } + .flex-check-box { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin-top: 15px; + &.for2 { + justify-content: flex-end; + button { + width: calc(50% - 5px); } + &.btn { + gap: 5px; + button { + width: calc(50% - 2.5px); + } + } + } + &.for-line { + button { + flex: 1; + } + } } + } + .outer-line-wrap { + border-top: 1px solid #3c3c3c; + margin-top: 10px; + padding-top: 15px; + margin-bottom: 15px; + > div { + margin-bottom: 15px; + &:last-child { + margin-bottom: 0; + } + } + } + .modal-guide { + display: block; + font-size: $pop-normal-size; + color: $alert-color; + font-weight: $pop-normal-weight; + } +} + +.adsorption-point { + display: flex; + align-items: center; + background-color: #3a3a3a; + border-radius: 3px; + padding-left: 11px; + overflow: hidden; + transition: all 0.17s ease-in-out; + span { + font-size: $pop-normal-size; + color: #898989; + } + i { + display: flex; + align-items: center; + padding: 0 7px; + margin-left: auto; + height: 100%; + font-size: 13px; + color: #898989; + } + &.act { + i { + color: $pop-color; + background-color: #1083e3; + } + } } // grid-option -.grid-check-form{ +.grid-check-form { + display: flex; + align-items: center; + gap: 15px; + padding-bottom: 15px; + &.border { + border-bottom: 1px solid #424242; + } +} +.grid-option-wrap { + .grid-option-box { display: flex; align-items: center; - gap: 15px; - padding-bottom: 15px; - &.border{ - border-bottom: 1px solid #424242; + background-color: transparent; + border: 1px solid #3d3d3d; + border-radius: 2px; + padding: 15px 10px; + gap: 20px; + margin-bottom: 10px; + .grid-input-form { + display: flex; + align-items: center; + span { + flex: none; + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-bold-weight; + } + .input-grid { + width: 54px; + input { + width: 100%; + } + } } + &:last-child { + margin-bottom: 0; + } + } } -.grid-option-wrap{ - .grid-option-box{ - display: flex; - align-items: center; - background-color: transparent; - border: 1px solid #3D3D3D; - border-radius: 2px; - padding: 15px 10px; - gap: 20px; - margin-bottom: 10px; - .grid-input-form{ - display: flex; - align-items: center; - span{ - flex: none; - font-size: $pop-normal-size; - color: $pop-color; - font-weight: $pop-bold-weight; - } - .input-grid{ - width: 54px; - input{ - width: 100%; - } - } - } - &:last-child{ - margin-bottom: 0; - } - } +.select-form { + .sort-select { + width: 100%; + } } -.select-form{ - .sort-select{width: 100%;} +.grid-select { + flex: 1; + &.no-flx { + flex: unset; + } + .sort-select { + width: 100%; + background-color: #313131; + min-width: auto; + font-size: 12px; + border: none; + p { + font-size: 12px; + } + > ul { + border: none; + } + } + &.right { + p { + text-align: right; + } + ul { + li { + justify-content: flex-end; + } + } + } } -.grid-select{ - flex: 1; - &.no-flx{ - flex: unset; - } - .sort-select{ - width: 100%; - background-color: #313131; - min-width: auto; - font-size: 12px; - border: none; - p{ - font-size: 12px; - } - > ul{ - border: none; - } - } - &.right{ - p{ - text-align: right; - } - ul{ - li{ - justify-content: flex-end; - } - } - } -} -.grid-btn-wrap{ - padding-top: 15px; - text-align: right; - button{ - padding: 0 10px; - } +.grid-btn-wrap { + padding-top: 15px; + text-align: right; + button { + padding: 0 10px; + } } // grid copy -.grid-option-tit{ - font-size: $pop-normal-size; - color: $pop-color; - font-weight: $pop-normal-weight; - padding-bottom: 15px; - +.grid-option-tit { + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-normal-weight; + padding-bottom: 15px; } -.grid-direction{ - display: flex; - align-items: center; - gap: 5px; - flex: 1; +.grid-direction { + display: flex; + align-items: center; + gap: 5px; + flex: 1; } -.direction{ - width: 22px; - height: 22px; - background-color: #757575; - background-image: url(../../public/static/images/canvas/grid_option_arr.svg); - background-repeat: no-repeat; - background-position: center; - background-size: 16px 15px; - border-radius: 50%; - transition: all .15s ease-in-out; - opacity: 0.6; - &.down{transform: rotate(180deg);} - &.left{transform: rotate(-90deg);} - &.right{transform: rotate(90deg);} - &:hover, - &.act{ - opacity: 1; - } +.direction { + width: 22px; + height: 22px; + background-color: #757575; + background-image: url(../../public/static/images/canvas/grid_option_arr.svg); + background-repeat: no-repeat; + background-position: center; + background-size: 16px 15px; + border-radius: 50%; + transition: all 0.15s ease-in-out; + opacity: 0.6; + &.down { + transform: rotate(180deg); + } + &.left { + transform: rotate(-90deg); + } + &.right { + transform: rotate(90deg); + } + &:hover, + &.act { + opacity: 1; + } } // grid-move -.move-form{ - p{ - font-size: $pop-normal-size; - color: $pop-color; - font-weight: $pop-bold-weight; - } +.move-form { + p { + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-bold-weight; + } } -.input-move-wrap{ - display: flex; - align-items: center; - gap: 5px; - span{ - color: $pop-color; - font-size: $pop-normal-size; - } - .input-move{ - width: 130px; - input{ - width: 100%; - } +.input-move-wrap { + display: flex; + align-items: center; + gap: 5px; + span { + color: $pop-color; + font-size: $pop-normal-size; + } + .input-move { + width: 130px; + input { + width: 100%; } + } } -.direction-move-wrap{ - flex: none; - display: grid; - grid-template-columns: 1fr 1fr; - gap: 10px; +.direction-move-wrap { + flex: none; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; } // 배치면 초기 설정 -.placement-table{ - table{ - table-layout: fixed; - tr{ - th{ - display: flex; - align-items: center; - font-size: $pop-normal-size; - color: $pop-color; - font-weight: $pop-bold-weight; - padding: 18px 0; - border-bottom: 1px solid #424242; - } - td{ - font-size: $pop-normal-size; - color: $pop-color; - border-bottom: 1px solid #424242; - padding-left: 20px; - } - &:first-child{ - td, - th{ - padding-top: 0; - } - } - } - } - .tooltip{ - position: relative; - display: block; - width: 15px; - height: 15px; - margin-left: 5px; - background: url(../../public/static/images/canvas/pop_tip.svg)no-repeat center; - background-size: cover; - } - &.light{ - padding: 0; - th,td{ - color: $alert-color; - border-bottom: none; - border-top: 1px solid #EFEFEF; - } - th{ - padding: 14px 0; - } - tr{ - &:first-child{ - td, - th{ - padding-top: 14px; - } - } - &:last-child{ - td, - th{ - padding-bottom: 0px; - } - } - } - } -} - -.pop-form-radio{ - display: flex; - align-items: center; - gap: 10px; -} -.placement-option{ - display: flex; - align-items: center; - gap: 20px; -} -.select-wrap{ - .sort-select{ - width: 100%; - } -} -.flex-ment{ - display: flex; - align-items: center; - gap: 5px; - span{ +.placement-table { + table { + table-layout: fixed; + tr { + th { + display: flex; + align-items: center; font-size: $pop-normal-size; color: $pop-color; - font-weight: $pop-normal-weight; + font-weight: $pop-bold-weight; + padding: 18px 0; + border-bottom: 1px solid #424242; + } + td { + font-size: $pop-normal-size; + color: $pop-color; + border-bottom: 1px solid #424242; + padding-left: 20px; + } + &:first-child { + td, + th { + padding-top: 0; + } + } } + } + .tooltip { + position: relative; + display: block; + width: 15px; + height: 15px; + margin-left: 5px; + background: url(../../public/static/images/canvas/pop_tip.svg) no-repeat center; + background-size: cover; + } + &.light { + padding: 0; + th, + td { + color: $alert-color; + border-bottom: none; + border-top: 1px solid #efefef; + } + th { + padding: 14px 0; + } + tr { + &:first-child { + td, + th { + padding-top: 14px; + } + } + &:last-child { + td, + th { + padding-bottom: 0px; + } + } + } + } +} + +.pop-form-radio { + display: flex; + align-items: center; + gap: 10px; +} +.placement-option { + display: flex; + align-items: center; + gap: 20px; +} +.select-wrap { + .sort-select { + width: 100%; + } +} +.flex-ment { + display: flex; + align-items: center; + gap: 5px; + span { + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-normal-weight; + } } // 외벽선 그리기 -.outline-wrap{ - padding: 24px 0; - border-top: 1px solid #424242; - - .outline-inner{ - display: flex; - align-items: center; - margin-bottom: 14px; - &:last-child{ - margin-bottom: 0; - } - .outline-form{ - // width: 50%; - margin-right: 15px; - } - } - &:last-child{ - border-bottom: 1px solid #424242; - } -} -.outline-form{ +.outline-wrap { + padding: 24px 0; + border-top: 1px solid #424242; + + .outline-inner { display: flex; align-items: center; - - span{ - width: 60px; - flex: none; - font-size: $pop-normal-size; - font-weight: $pop-bold-weight; - color: $pop-color; - margin-right: 10px; - &.thin{ - width: auto; - font-weight: $pop-normal-weight; - margin-right: 0; - } + margin-bottom: 14px; + &:last-child { + margin-bottom: 0; } + .outline-form { + // width: 50%; + margin-right: 15px; + } + } + &:last-child { + border-bottom: 1px solid #424242; + } +} +.outline-form { + display: flex; + align-items: center; - .reset-btn{ - flex: none; - width: 30px; - height: 30px; - background: transparent; - border: 1px solid #484848; - border-radius: 2px; - margin-left: 5px; - background-image: url(../../public/static/images/canvas/reset_ico.svg); - background-repeat: no-repeat; - background-size: 12px 12px; - background-position: center; - } - &:last-child{ - margin-right: 0; + span { + width: 60px; + flex: none; + font-size: $pop-normal-size; + font-weight: $pop-bold-weight; + color: $pop-color; + margin-right: 10px; + &.thin { + width: auto; + font-weight: $pop-normal-weight; + margin-right: 0; } + } + + .reset-btn { + flex: none; + width: 30px; + height: 30px; + background: transparent; + border: 1px solid #484848; + border-radius: 2px; + margin-left: 5px; + background-image: url(../../public/static/images/canvas/reset_ico.svg); + background-repeat: no-repeat; + background-size: 12px 12px; + background-position: center; + } + &:last-child { + margin-right: 0; + } } -.cul-wrap{ +.cul-wrap { + display: flex; + .outline-box { + width: 50%; + margin-right: 15px; + .outline-form { + width: 100%; + margin-bottom: 14px; + margin-right: 0; + &:last-child { + margin-bottom: 0; + } + } + } + .cul-box { display: flex; - .outline-box{ - width: 50%; - margin-right: 15px; - .outline-form{ - width: 100%; - margin-bottom: 14px; - margin-right: 0; - &:last-child{ - margin-bottom: 0; - } - } - } - .cul-box{ - display: flex; - align-items: center; - justify-content: center; - width: 50%; - background-color: #3D3D3D; - border-radius: 2px ; - } + align-items: center; + justify-content: center; + width: 50%; + background-color: #3d3d3d; + border-radius: 2px; + } } // 외벽선 속성 설정 -.properties-guide{ - font-size: $pop-normal-size; - color: #AAA; - font-weight: $pop-normal-weight; - margin-bottom: 14px; +.properties-guide { + font-size: $pop-normal-size; + color: #aaa; + font-weight: $pop-normal-weight; + margin-bottom: 14px; } -.setting-tit{ - font-size: 13px; - color: $pop-color; - font-weight: $pop-bold-weight; - margin-bottom: 10px; +.setting-tit { + font-size: 13px; + color: $pop-color; + font-weight: $pop-bold-weight; + margin-bottom: 10px; } -.properties-setting-wrap{ - &.outer{ - margin-top: 24px; - } - .setting-btn-wrap{ - display: flex; - align-items: center; - padding: 14px 0; - border-top: 1px solid #424242; - border-bottom: 1px solid #424242; - .setting-btn{ - display: block; - width: 100%; - height: 40px; - font-size: 13px; - color: #fff; - font-weight: 700; - border-radius: 2px; - transition: all .15s ease-in-out; - &.green{ - background-color: #305941; - border: 1px solid #45CD7D; - &:hover{ - background-color: #3a6b4e; - } - } - &.blue{ - background-color: #2E5360; - border: 1px solid #3FBAE6; - &:hover{ - background-color: #365f6e; - } - } - } - } -} - -// 지붕형상 설정 -.roof-shape-menu{ - display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr; - grid-template-rows: 1fr 1fr; - gap: 24px 10px; - margin-bottom: 24px; - .shape-box{ - display: flex; - align-items: center; - justify-content: center; - width: 100%; - padding: 13px; - background-color: #3D3D3D; - transition: background .15s ease-in-out; - img{ - max-width: 100%; - } - } - .shape-title{ - font-size: $pop-normal-size; - font-weight: $pop-bold-weight; - color: $pop-color; - margin-top: 10px; - text-align: center; - transition: color .15s ease-in-out; - } - .shape-menu-box{ - &.act, - &:hover{ - .shape-box{background-color: #008BFF;} - .shape-title{color: #008BFF;} - } - } -} - -.setting-box{ +.properties-setting-wrap { + &.outer { + margin-top: 24px; + } + .setting-btn-wrap { + display: flex; + align-items: center; padding: 14px 0; border-top: 1px solid #424242; border-bottom: 1px solid #424242; + .setting-btn { + display: block; + width: 100%; + height: 40px; + font-size: 13px; + color: #fff; + font-weight: 700; + border-radius: 2px; + transition: all 0.15s ease-in-out; + &.green { + background-color: #305941; + border: 1px solid #45cd7d; + &:hover { + background-color: #3a6b4e; + } + } + &.blue { + background-color: #2e5360; + border: 1px solid #3fbae6; + &:hover { + background-color: #365f6e; + } + } + } + } } -.padding-form{ - padding-left: 23px; + +// 지붕형상 설정 +.roof-shape-menu { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-rows: 1fr 1fr; + gap: 24px 10px; + margin-bottom: 24px; + .shape-box { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + padding: 13px; + background-color: #3d3d3d; + transition: background 0.15s ease-in-out; + img { + max-width: 100%; + } + } + .shape-title { + font-size: $pop-normal-size; + font-weight: $pop-bold-weight; + color: $pop-color; + margin-top: 10px; + text-align: center; + transition: color 0.15s ease-in-out; + } + .shape-menu-box { + &.act, + &:hover { + .shape-box { + background-color: #008bff; + } + .shape-title { + color: #008bff; + } + } + } +} + +.setting-box { + padding: 14px 0; + border-top: 1px solid #424242; + border-bottom: 1px solid #424242; +} +.padding-form { + padding-left: 23px; } .discrimination-box{ padding: 16px 12px; @@ -652,1131 +674,1304 @@ $alert-color: #101010; border-radius: 2px; } -.modal-bottom-border-bx{ - margin-top: 24px; - padding-bottom: 14px; - border-bottom: 1px solid #424242; +.modal-bottom-border-bx { + margin-top: 24px; + padding-bottom: 14px; + border-bottom: 1px solid #424242; } // 처마∙케라바 변경 -.eaves-keraba-table{ - display: table; - border-collapse: collapse; - .eaves-keraba-item{ - display: table-row; - .eaves-keraba-th, - .eaves-keraba-td{ - font-size: $pop-normal-size; - color: $pop-color; - font-weight: $pop-normal-weight; - display: table-cell; - vertical-align: middle; - padding-bottom: 14px; - } - .eaves-keraba-td{ - padding-left: 10px; - } - .eaves-keraba-ico{ - display: flex; - align-items: center; - justify-content: center; - padding: 5px; - background-color: #3D3D3D; - border: 1px solid #3D3D3D; - border-radius: 2px; - cursor: pointer; - &.act{ - border: 1px solid #ED0004; - } - } - &:last-child{ - .eaves-keraba-th, - .eaves-keraba-td{ - padding-bottom: 0; - } - } +.eaves-keraba-table { + display: table; + border-collapse: collapse; + .eaves-keraba-item { + display: table-row; + .eaves-keraba-th, + .eaves-keraba-td { + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-normal-weight; + display: table-cell; + vertical-align: middle; + padding-bottom: 14px; } + .eaves-keraba-td { + padding-left: 10px; + } + .eaves-keraba-ico { + display: flex; + align-items: center; + justify-content: center; + padding: 5px; + background-color: #3d3d3d; + border: 1px solid #3d3d3d; + border-radius: 2px; + cursor: pointer; + &.act { + border: 1px solid #ed0004; + } + } + &:last-child { + .eaves-keraba-th, + .eaves-keraba-td { + padding-bottom: 0; + } + } + } } -.guide{ - font-size: $pop-normal-size; - font-weight: $pop-normal-weight; - color: $pop-color; - margin-bottom: 24px; - &.sm{ - margin-bottom: 15px; - } - span{ - display: block; - } +.guide { + font-size: $pop-normal-size; + font-weight: $pop-normal-weight; + color: $pop-color; + margin-bottom: 24px; + &.sm { + margin-bottom: 15px; + } + span { + display: block; + } } // 지붕면 할당 -.allocation-select-wrap{ +.allocation-select-wrap { + display: flex; + align-items: center; + padding-bottom: 14px; + border-bottom: 1px solid #424242; + margin-bottom: 14px; + span { + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-bold-weight; + margin-right: 10px; + } + .allocation-edit { display: flex; align-items: center; - padding-bottom: 14px; - border-bottom: 1px solid #424242; - margin-bottom: 14px; - span{ - font-size: $pop-normal-size; - color: $pop-color; - font-weight: $pop-bold-weight; - margin-right: 10px; - } - .allocation-edit{ - display: flex; - align-items: center; - height: 30px; - padding: 0 10px; - margin-left: 5px; - font-size: $pop-normal-size; - color: $pop-color; - font-weight: $pop-normal-weight; - border: 1px solid #484848; - background-color: #323234; - i{ - display: block; - width: 12px; - height: 12px; - margin-right: 5px; - background: url(../../public/static/images/canvas/allocation_edit.svg)no-repeat center; - background-size: cover; - } + height: 30px; + padding: 0 10px; + margin-left: 5px; + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-normal-weight; + border: 1px solid #484848; + background-color: #323234; + i { + display: block; + width: 12px; + height: 12px; + margin-right: 5px; + background: url(../../public/static/images/canvas/allocation_edit.svg) no-repeat center; + background-size: cover; } + } } -.block-box{ - display: flex; - align-items: center; +.block-box { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 10px; + .flex-ment { gap: 10px; - margin-bottom: 10px; - .flex-ment{ - gap: 10px; - .dec{ - text-decoration: underline; - } - .delete{ - display: block; - width: 15px; - height: 15px; - background: url(../../public/static/images/canvas/allocation_delete.svg)no-repeat center; - background-size: cover; - } + .dec { + text-decoration: underline; } - &:last-child{ - margin-bottom: 0; + .delete { + display: block; + width: 15px; + height: 15px; + background: url(../../public/static/images/canvas/allocation_delete.svg) no-repeat center; + background-size: cover; } + } + &:last-child { + margin-bottom: 0; + } } -.icon-btn-wrap{ - flex: 1; - display: flex; - align-items: center; - gap: 5px; - button{ - display: flex; - align-items: center; - justify-content: center; - width: 100%; - height: 30px; - font-size: $pop-normal-size; - font-weight: $pop-normal-weight; - color: $pop-color; - border: 1px solid #646464; - border-radius: 2px; - padding: 0 10px; - transition: all .15s ease-in-out; - i{ - height: 15px; - display: block; - margin-left: 10px; - background-repeat: no-repeat; - background-position: center; - background-size: cover; - transition: all .15s ease-in-out; - &.allocation01{ - background-image: url(../../public/static/images/canvas/allocation_icon01_white.svg); - width: 15px; - } - &.allocation02{ - background-image: url(../../public/static/images/canvas/allocation_icon02_white.svg); - width: 18px; - } - } - &.act, - &:hover{ - color: #101010; - border: 1px solid #101010; - background-color: #fff; - i{ - &.allocation01{ - background-image: url(../../public/static/images/canvas/allocation_icon01_black.svg); - } - &.allocation02{ - background-image: url(../../public/static/images/canvas/allocation_icon02_black.svg); - } - } - } - } -} - -// 경사설정 -.slope-wrap{ - padding-bottom: 24px; - border-bottom: 1px solid #424242; -} - -// 면형상 배치 -.plane-shape-menu{ - display: grid; - grid-template-columns: repeat(6, 1fr); - grid-template-rows: repeat(3, 90px); - gap: 10px; - margin-bottom: 10px; - .shape-menu-box{ - border-radius: 2px; - background-color: #3D3D3D; - padding: 8px; - transition: all .15s ease-in-out; - .shape-box{ - display: flex; - justify-content: center; - align-items: center; - position: relative; - width: 100%; - height: 100%; - background-color: #313131; - border-radius: 2px; - } - &.act, - &:hover{ - background-color: #008BFF; - } - } -} - -.shape-library{ +.icon-btn-wrap { + flex: 1; + display: flex; + align-items: center; + gap: 5px; + button { display: flex; align-items: center; justify-content: center; - gap: 5px; - padding: 5px; - background-color: #3D3D3D; - margin-bottom: 24px; - .library-btn{ - width: 30px; - height: 30px; - border: 1px solid #6C6C6C; - border-radius: 2px; - background-color: transparent; - background-repeat: no-repeat; - background-position: center; - transition: all .15s ease-in-out; - &.ico01{background-image: url(../../public/static/images/canvas/shape_labrary01.svg); background-size: 14px 14px;} - &.ico02{background-image: url(../../public/static/images/canvas/shape_labrary02.svg); background-size: 13px 17px;} - &.ico03{background-image: url(../../public/static/images/canvas/shape_labrary03.svg); background-size: 17px 13px;} - &:hover{ - border-color: #1083E3; - background-color: #1083E3; - } - } -} - -.plane-shape-wrapper{ - display: flex; - gap: 10px; - .plane-box{ - padding: 10px; - border-radius: 2px; - background-color: #3D3D3D; - .plane-box-tit{ - font-size: $pop-normal-size; - font-weight: 600; - color: $pop-color; - margin-bottom: 10px; - } - &.shape-box{ - flex: 1; - .shape-box-inner{ - display: flex; - gap:10px; - min-height: 140px; - .shape-img{ - position: relative; - flex: 1; - background-color: #fff; - border-radius: 2px; - img{ - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - } - .shape-data{ - flex: none; - width: 190px; - background-color: #313131; - border-radius: 2px; - padding: 15px; - .eaves-keraba-table{ - .eaves-keraba-item{ - .eaves-keraba-th, - .eaves-keraba-td{ - padding-bottom: 10px; - } - &:last-child{ - .eaves-keraba-th, - .eaves-keraba-td{ - padding-bottom: 0px; - } - } - } - } - } - } - } - &.direction-box{ - display: flex; - flex-direction: column; - flex: none; - width: 180px; - .plane-direction-box{ - flex: 1; - display: flex; - align-items: center; - justify-content: center; - width: 100%; - padding: 10px 5px; - } - } - } -} -.plane-direction{ - width: 150px; - position: relative; - height: 120px; - span{ - position: absolute; - font-size: 12px; - font-weight: 500; - color: #B1B1B1; - &.top{top: 0; left: 50%; transform: translateX(-50%);} - &.right{top: 50%; right: 0; transform: translateY(-50%);} - &.bottom{bottom: 0; left: 50%; transform: translateX(-50%);} - &.left{top: 50%; left: 0; transform: translateY(-50%);} - } - .plane-btn{ - position: absolute; - width: 28px; - height: 28px; - background-color: #777777; - background-image: url(../../public/static/images/canvas/plane_arr.svg); - background-size: 12px 13px; - background-repeat: no-repeat; - background-position: center; - border-radius: 50%; - transition: all .15s ease-in-out; - &.up{top: 22px; left: 50%; transform: translateX(-50%);} - &.right{top: 50%; right: 32px; transform: translateY(-50%) rotate(90deg);} - &.down{bottom: 22px; left: 50%; transform: translateX(-50%) rotate(180deg);} - &.left{top: 50%; left: 32px; transform: translateY(-50%) rotate(270deg);} - &:hover, - &.act{ - background-color: #fff; - background-image: url(../../public/static/images/canvas/plane_arr_act.svg); - } - } -} - -.plane-tab-guide{ + width: 100%; + height: 30px; font-size: $pop-normal-size; font-weight: $pop-normal-weight; color: $pop-color; - margin-top: 24px; - padding-bottom: 14px; - border-bottom: 1px solid #424242; + border: 1px solid #646464; + border-radius: 2px; + padding: 0 10px; + transition: all 0.15s ease-in-out; + i { + height: 15px; + display: block; + margin-left: 10px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; + transition: all 0.15s ease-in-out; + &.allocation01 { + background-image: url(../../public/static/images/canvas/allocation_icon01_white.svg); + width: 15px; + } + &.allocation02 { + background-image: url(../../public/static/images/canvas/allocation_icon02_white.svg); + width: 18px; + } + } + &.act, + &:hover { + color: #101010; + border: 1px solid #101010; + background-color: #fff; + i { + &.allocation01 { + background-image: url(../../public/static/images/canvas/allocation_icon01_black.svg); + } + &.allocation02 { + background-image: url(../../public/static/images/canvas/allocation_icon02_black.svg); + } + } + } + } } -// 오브젝트 배치 -.mb-box{ - margin-bottom: 24px; +// 경사설정 +.slope-wrap { + padding-bottom: 24px; + border-bottom: 1px solid #424242; } -.object-direction-wrap{ - display: flex; - align-items: center; - justify-content: center; -} -.discrimination-tit{ - font-size: 13px; - color: #fff; - font-weight: 500; +// 면형상 배치 +.plane-shape-menu { + display: grid; + grid-template-columns: repeat(6, 1fr); + grid-template-rows: repeat(3, 90px); + gap: 10px; + margin-bottom: 10px; + .shape-menu-box { + border-radius: 2px; + background-color: #3d3d3d; + padding: 8px; + transition: all 0.15s ease-in-out; + .shape-box { + display: flex; + justify-content: center; + align-items: center; + position: relative; + width: 100%; + height: 100%; + background-color: #313131; + border-radius: 2px; + } + &.act, + &:hover { + background-color: #008bff; + } + } } -.object-size-wrap{ - display: flex; - min-height: 206px; - gap: 24px; - margin-top: 14px; - .object-size-img{ - position: relative; - flex: none; - width: 200px; - background-color: #fff; - img{ +.shape-library { + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + padding: 5px; + background-color: #3d3d3d; + margin-bottom: 24px; + .library-btn { + width: 30px; + height: 30px; + border: 1px solid #6c6c6c; + border-radius: 2px; + background-color: transparent; + background-repeat: no-repeat; + background-position: center; + transition: all 0.15s ease-in-out; + &.ico01 { + background-image: url(../../public/static/images/canvas/shape_labrary01.svg); + background-size: 14px 14px; + } + &.ico02 { + background-image: url(../../public/static/images/canvas/shape_labrary02.svg); + background-size: 13px 17px; + } + &.ico03 { + background-image: url(../../public/static/images/canvas/shape_labrary03.svg); + background-size: 17px 13px; + } + &:hover { + border-color: #1083e3; + background-color: #1083e3; + } + } +} + +.plane-shape-wrapper { + display: flex; + gap: 10px; + .plane-box { + padding: 10px; + border-radius: 2px; + background-color: #3d3d3d; + .plane-box-tit { + font-size: $pop-normal-size; + font-weight: 600; + color: $pop-color; + margin-bottom: 10px; + } + &.shape-box { + flex: 1; + .shape-box-inner { + display: flex; + gap: 10px; + min-height: 140px; + .shape-img { + position: relative; + flex: 1; + background-color: #fff; + border-radius: 2px; + img { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); + } } + .shape-data { + flex: none; + width: 190px; + background-color: #313131; + border-radius: 2px; + padding: 15px; + .eaves-keraba-table { + .eaves-keraba-item { + .eaves-keraba-th, + .eaves-keraba-td { + padding-bottom: 10px; + } + &:last-child { + .eaves-keraba-th, + .eaves-keraba-td { + padding-bottom: 0px; + } + } + } + } + } + } } + &.direction-box { + display: flex; + flex-direction: column; + flex: none; + width: 180px; + .plane-direction-box { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + padding: 10px 5px; + } + } + } +} +.plane-direction { + width: 150px; + position: relative; + height: 120px; + span { + position: absolute; + font-size: 12px; + font-weight: 500; + color: #b1b1b1; + &.top { + top: 0; + left: 50%; + transform: translateX(-50%); + } + &.right { + top: 50%; + right: 0; + transform: translateY(-50%); + } + &.bottom { + bottom: 0; + left: 50%; + transform: translateX(-50%); + } + &.left { + top: 50%; + left: 0; + transform: translateY(-50%); + } + } + .plane-btn { + position: absolute; + width: 28px; + height: 28px; + background-color: #777777; + background-image: url(../../public/static/images/canvas/plane_arr.svg); + background-size: 12px 13px; + background-repeat: no-repeat; + background-position: center; + border-radius: 50%; + transition: all 0.15s ease-in-out; + &.up { + top: 22px; + left: 50%; + transform: translateX(-50%); + } + &.right { + top: 50%; + right: 32px; + transform: translateY(-50%) rotate(90deg); + } + &.down { + bottom: 22px; + left: 50%; + transform: translateX(-50%) rotate(180deg); + } + &.left { + top: 50%; + left: 32px; + transform: translateY(-50%) rotate(270deg); + } + &:hover, + &.act { + background-color: #fff; + background-image: url(../../public/static/images/canvas/plane_arr_act.svg); + } + } +} + +.plane-tab-guide { + font-size: $pop-normal-size; + font-weight: $pop-normal-weight; + color: $pop-color; + margin-top: 24px; + padding-bottom: 14px; + border-bottom: 1px solid #424242; +} + +// 오브젝트 배치 +.mb-box { + margin-bottom: 24px; +} + +.object-direction-wrap { + display: flex; + align-items: center; + justify-content: center; +} +.discrimination-tit { + font-size: 13px; + color: #fff; + font-weight: 500; +} + +.object-size-wrap { + display: flex; + min-height: 206px; + gap: 24px; + margin-top: 14px; + .object-size-img { + position: relative; + flex: none; + width: 200px; + background-color: #fff; + img { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } } // 표시변경 .display-change-wrap{ margin: 24px 0; } -.warning{ - font-size: $pop-normal-size; - font-weight: $pop-normal-weight; - color: #FFAFAF; +.warning { + font-size: $pop-normal-size; + font-weight: $pop-normal-weight; + color: #ffafaf; } // 각 변 속성 변경 -.radio-grid-wrap{ - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 24px 15px; +.radio-grid-wrap { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 24px 15px; } // 면 흐름 설정 -.drawing-flow-wrap{ +.drawing-flow-wrap { + display: flex; + gap: 10px; + .discrimination-box { + flex: 1; display: flex; - gap: 10px; - .discrimination-box{ - flex: 1; - display: flex; - flex-direction: column; - .object-direction-wrap{ - flex: 1; - } + flex-direction: column; + .object-direction-wrap { + flex: 1; } + } } -.compas-box{ - display: flex; - align-items: center; - justify-content: center; +.compas-box { + display: flex; + align-items: center; + justify-content: center; } .compas-box-inner { - position: relative; - width: 200px; - height: 200px; + position: relative; + width: 200px; + height: 200px; + border-radius: 50%; + + .circle { + position: absolute; + width: 12px; + height: 12px; + border: 1px solid #fff; border-radius: 50%; - - .circle { - position: absolute; - width: 12px; - height: 12px; - border: 1px solid #fff; - border-radius: 50%; - top: 95%; - left: 50%; - transform-origin: 0 -90px; /* 중심에서 반지름 거리만큼 떨어져 위치 */ - cursor:pointer; - z-index: 3; - /* 0번을 180도 위치(아래)에, 13번을 0도 위치(위)에 배치 */ - i{ - position: absolute; - top: 12.5px; - left: 50%; - font-size: 11px; - color: #8B8B8B; - font-weight: 500; - -webkit-user-select: none; - -moz-user-select: none; - -ms-use-select: none; - user-select: none; - } - &:nth-child(1) { transform: rotate(180deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(180deg);}} - &:nth-child(2) { transform: rotate(195deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(165deg);}} - &:nth-child(3) { transform: rotate(210deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(150deg);}} - &:nth-child(4) { transform: rotate(225deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(135deg);}} - &:nth-child(5) { transform: rotate(240deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(120deg);}} - &:nth-child(6) { transform: rotate(255deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(105deg);}} - &:nth-child(7) { transform: rotate(270deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(90deg);}} - &:nth-child(8) { transform: rotate(285deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(75deg);}} - &:nth-child(9) { transform: rotate(300deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(60deg);}} - &:nth-child(10) { transform: rotate(315deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(45deg);}} - &:nth-child(11) { transform: rotate(330deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(30deg);}} - &:nth-child(12) { transform: rotate(345deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(15deg);}} - &:nth-child(13) { transform: rotate(0deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(0deg);}} - &:nth-child(14) { transform: rotate(15deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(-15deg);}} - &:nth-child(15) { transform: rotate(30deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(-30deg);}} - &:nth-child(16) { transform: rotate(45deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(-45deg);}} - &:nth-child(17) { transform: rotate(60deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(-60deg);}} - &:nth-child(18) { transform: rotate(75deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(-75deg);}} - &:nth-child(19) { transform: rotate(90deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(-90deg);}} - &:nth-child(20) { transform: rotate(105deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(-105deg);}} - &:nth-child(21) { transform: rotate(120deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(-120deg);}} - &:nth-child(22) { transform: rotate(135deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(-135deg);}} - &:nth-child(23) { transform: rotate(150deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(-150deg);}} - &:nth-child(24) { transform: rotate(165deg) translate(-50%, -50%); i{transform: translateX(-50%) rotate(-165deg);}} - &.act{ - &::after{ - content: ''; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 5px; - height: 5px; - background-color: #fff; - } - i{ - color: #fff; - } - } + top: 95%; + left: 50%; + transform-origin: 0 -90px; /* 중심에서 반지름 거리만큼 떨어져 위치 */ + cursor: pointer; + z-index: 3; + /* 0번을 180도 위치(아래)에, 13번을 0도 위치(위)에 배치 */ + i { + position: absolute; + top: 12.5px; + left: 50%; + font-size: 11px; + color: #8b8b8b; + font-weight: 500; + -webkit-user-select: none; + -moz-user-select: none; + -ms-use-select: none; + user-select: none; } - .compas{ + &:nth-child(1) { + transform: rotate(180deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(180deg); + } + } + &:nth-child(2) { + transform: rotate(195deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(165deg); + } + } + &:nth-child(3) { + transform: rotate(210deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(150deg); + } + } + &:nth-child(4) { + transform: rotate(225deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(135deg); + } + } + &:nth-child(5) { + transform: rotate(240deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(120deg); + } + } + &:nth-child(6) { + transform: rotate(255deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(105deg); + } + } + &:nth-child(7) { + transform: rotate(270deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(90deg); + } + } + &:nth-child(8) { + transform: rotate(285deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(75deg); + } + } + &:nth-child(9) { + transform: rotate(300deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(60deg); + } + } + &:nth-child(10) { + transform: rotate(315deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(45deg); + } + } + &:nth-child(11) { + transform: rotate(330deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(30deg); + } + } + &:nth-child(12) { + transform: rotate(345deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(15deg); + } + } + &:nth-child(13) { + transform: rotate(0deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(0deg); + } + } + &:nth-child(14) { + transform: rotate(15deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(-15deg); + } + } + &:nth-child(15) { + transform: rotate(30deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(-30deg); + } + } + &:nth-child(16) { + transform: rotate(45deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(-45deg); + } + } + &:nth-child(17) { + transform: rotate(60deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(-60deg); + } + } + &:nth-child(18) { + transform: rotate(75deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(-75deg); + } + } + &:nth-child(19) { + transform: rotate(90deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(-90deg); + } + } + &:nth-child(20) { + transform: rotate(105deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(-105deg); + } + } + &:nth-child(21) { + transform: rotate(120deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(-120deg); + } + } + &:nth-child(22) { + transform: rotate(135deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(-135deg); + } + } + &:nth-child(23) { + transform: rotate(150deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(-150deg); + } + } + &:nth-child(24) { + transform: rotate(165deg) translate(-50%, -50%); + i { + transform: translateX(-50%) rotate(-165deg); + } + } + &.act { + &::after { + content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); - width: 148px; - height: 148px; - border: 4px solid #fff; - border-radius: 50%; - .compas-arr{ - width: 100%; - height: 100%; - background: url(../../public/static/images/canvas/compas.svg)no-repeat center; - background-size: 122px 122px; - } + width: 5px; + height: 5px; + background-color: #fff; + } + i { + color: #fff; + } } + } + .compas { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 148px; + height: 148px; + border: 4px solid #fff; + border-radius: 50%; + .compas-arr { + width: 100%; + height: 100%; + background: url(../../public/static/images/canvas/compas.svg) no-repeat center; + background-size: 122px 122px; + } + } } - // 지붕모듈선택 -.roof-module-tab{ - display: flex; - align-items: center; - gap: 10px; - margin-bottom: 14px; - .module-tab-bx{ - flex: 1; - height: 34px; - line-height: 31px; - border: 1px solid #484848; - border-radius: 2px; - background-color: transparent; - font-size: 12px; - color: #AAA; - text-align: center; - cursor: default; - transition: all .15s ease-in-out; - &.act{ - background-color: #1083E3; - border: 1px solid #1083E3; - color: #fff; - font-weight: 500; - } - } - .tab-arr{ - display: block; - width: 9px; - height: 14px; - background-repeat: no-repeat; - background-position: center; - background-size: cover; - background-image: url(../../public/static/images/canvas/module_tab_arr.svg); - transition: all .15s ease-in-out; - &.act{ - background-image: url(../../public/static/images/canvas/module_tab_arr_white.svg); - } - } -} - -.roof-module-compas{ - margin-bottom: 24px; - .compas-box-inner{ - width: 280px; - height: 253px; - .circle{ - top: 86%; - &:nth-child(1), - &:nth-child(7), - &:nth-child(13), - &:nth-child(19){ - &::before{ - content: ''; - position: absolute; - top: 20px; - left: 50%; - transform: translateX(-50%); - width: 1px; - height: 6px; - background-color: #8B8B8B; - } - } - i{ - top: 32px; - } - &.act{ - i{color: #8B8B8B;} - } - } - } -} -.center-wrap{ - display: flex; - flex-direction: column; - align-items: center; - gap: 20px; -} - -.module-table-flex-wrap{ - display: flex; - gap: 10px; - .outline-form{ - flex: 1; - } -} - -.module-box-tab{ - display: flex; - .module-btn{ - flex: 1; - border-top: 1px solid #505050; - border-bottom: 1px solid #505050; - border-right: 1px solid #505050; - background-color: #454545; - color: #fff; - height: 30px; - font-size: 12px; - font-weight: 400; - transition: all .15s ease-in-out; - &:first-child{ - border-left: 1px solid #505050; - } - &.act{ - border-color: #fff; - background-color: #fff; - color: #101010; - } - } -} - -.module-table-box{ +.roof-module-tab { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 14px; + .module-tab-bx { flex: 1; - background-color: #3D3D3D; + height: 34px; + line-height: 31px; + border: 1px solid #484848; border-radius: 2px; - .module-table-inner{ - padding: 10px; - .outline-form{ - span{ - width: auto; - } - } - .module-table-tit{ - padding: 10px 0; - font-size: 12px; - color: #fff; - border-bottom: 1px solid #4D4D4D; - } - .eaves-keraba-table{ - width: 100%; - margin-top: 15px; - .eaves-keraba-th{ - width: 72px; - } - .eaves-keraba-th, - .eaves-keraba-td{ - padding-bottom: 5px; - } - } - .self-table-tit{ - font-size: 12px; - font-weight: 500; - color: #fff; - padding-bottom: 15px; - } + background-color: transparent; + font-size: 12px; + color: #aaa; + text-align: center; + cursor: default; + transition: all 0.15s ease-in-out; + &.act { + background-color: #1083e3; + border: 1px solid #1083e3; + color: #fff; + font-weight: 500; } - .warning-guide{ - padding: 20px; - .warning{ - color: #FFCACA; - max-height: 55px; - overflow-y: auto; - padding-right: 30px; - &::-webkit-scrollbar { - width: 4px; - background-color: transparent; - } - &::-webkit-scrollbar-thumb { - background-color: #D9D9D9; - } - &::-webkit-scrollbar-track { - background-color: transparent; - } - } + } + .tab-arr { + display: block; + width: 9px; + height: 14px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; + background-image: url(../../public/static/images/canvas/module_tab_arr.svg); + transition: all 0.15s ease-in-out; + &.act { + background-image: url(../../public/static/images/canvas/module_tab_arr_white.svg); } + } } -.module-self-table{ - display: table; - border-top: 1px solid #4D4D4D; - border-collapse: collapse; - width: 100%; - .self-table-item{ - display: table-row; - .self-item-td, - .self-item-th{ - display: table-cell; - vertical-align: middle; - border-bottom: 1px solid #4D4D4D; +.roof-module-compas { + margin-bottom: 24px; + .compas-box-inner { + width: 280px; + height: 253px; + .circle { + top: 86%; + &:nth-child(1), + &:nth-child(7), + &:nth-child(13), + &:nth-child(19) { + &::before { + content: ''; + position: absolute; + top: 20px; + left: 50%; + transform: translateX(-50%); + width: 1px; + height: 6px; + background-color: #8b8b8b; } - .self-item-th{ - width: 60px; - font-size: 12px; - font-weight: 500; - color: #fff; - } - .self-item-td{ - font-size: 12px; - font-weight: 400; - color: #fff; - padding: 15px 20px; + } + i { + top: 32px; + } + &.act { + i { + color: #8b8b8b; } + } } + } +} +.center-wrap { + display: flex; + flex-direction: column; + align-items: center; + gap: 20px; } -.self-table-flx{ - display: flex; - align-items: center; - margin-top: 15px; - button{ +.module-table-flex-wrap { + display: flex; + gap: 10px; + .outline-form { + flex: 1; + } +} + +.module-box-tab { + display: flex; + .module-btn { + flex: 1; + border-top: 1px solid #505050; + border-bottom: 1px solid #505050; + border-right: 1px solid #505050; + background-color: #454545; + color: #fff; + height: 30px; + font-size: 12px; + font-weight: 400; + transition: all 0.15s ease-in-out; + &:first-child { + border-left: 1px solid #505050; + } + &.act { + border-color: #fff; + background-color: #fff; + color: #101010; + } + } +} + +.module-table-box { + flex: 1; + background-color: #3d3d3d; + border-radius: 2px; + .module-table-inner { + padding: 10px; + .outline-form { + span { + width: auto; + } + } + .module-table-tit { + padding: 10px 0; + font-size: 12px; + color: #fff; + border-bottom: 1px solid #4d4d4d; + } + .eaves-keraba-table { + width: 100%; + margin-top: 15px; + .eaves-keraba-th { + width: 72px; + } + .eaves-keraba-th, + .eaves-keraba-td { + padding-bottom: 5px; + } + } + .self-table-tit { + font-size: 12px; + font-weight: 500; + color: #fff; + padding-bottom: 15px; + } + } + .warning-guide { + padding: 20px; + .warning { + color: #ffcaca; + max-height: 55px; + overflow-y: auto; + padding-right: 30px; + &::-webkit-scrollbar { + width: 4px; + background-color: transparent; + } + &::-webkit-scrollbar-thumb { + background-color: #d9d9d9; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } + } + } +} + +.module-self-table { + display: table; + border-top: 1px solid #4d4d4d; + border-collapse: collapse; + width: 100%; + .self-table-item { + display: table-row; + .self-item-td, + .self-item-th { + display: table-cell; + vertical-align: middle; + border-bottom: 1px solid #4d4d4d; + } + .self-item-th { + width: 60px; + font-size: 12px; + font-weight: 500; + color: #fff; + } + .self-item-td { + font-size: 12px; + font-weight: 400; + color: #fff; + padding: 15px 20px; + } + } +} + +.self-table-flx { + display: flex; + align-items: center; + margin-top: 15px; + button { + margin-left: auto; + } +} +.hexagonal-wrap { + .hexagonal-item { + padding: 15px 0; + border-bottom: 1px solid #4d4d4d; + &:first-child { + padding-top: 0; + } + &:last-child { + padding-bottom: 0; + border: none; + } + .hexagonal-flx-auto { + display: flex; + justify-content: space-between; + } + .hexagonal-flx { + display: flex; + align-items: center; + button { margin-left: auto; + } } -} -.hexagonal-wrap{ - .hexagonal-item{ - padding: 15px 0; - border-bottom: 1px solid #4D4D4D; - &:first-child{ - padding-top: 0; - } - &:last-child{ - padding-bottom: 0; - border: none; - } - .hexagonal-flx-auto{ - display: flex; - justify-content: space-between; - } - .hexagonal-flx{ - display: flex; - align-items: center; - button{ - margin-left: auto; - } - } - } + } } // 회로 및 가대설정 -.circuit-check-inner{ - padding: 5px 0; +.circuit-check-inner { + padding: 5px 0; } -.x-scroll-table{ - overflow-x: auto; - padding-bottom: 5px; - .roof-module-table{ - min-width: 1200px; - } - &::-webkit-scrollbar { - height: 4px; - background-color: transparent; - } - &::-webkit-scrollbar-thumb { - background-color: #D9D9D9; - } - &::-webkit-scrollbar-track { - background-color: transparent; - } +.x-scroll-table { + overflow-x: auto; + padding-bottom: 5px; + .roof-module-table { + min-width: 1200px; + } + &::-webkit-scrollbar { + height: 4px; + background-color: transparent; + } + &::-webkit-scrollbar-thumb { + background-color: #d9d9d9; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } } -.circuit-right-wrap{ - display: flex; - justify-content: flex-end; +.circuit-right-wrap { + display: flex; + justify-content: flex-end; } -.circuit-data-form{ +.circuit-data-form { + display: flex; + flex-direction: column; + gap: 5px; + min-height: 60px; + padding: 12px; + border: 1px solid rgba(255, 255, 255, 0.2); + span { + display: inline-flex; + align-items: center; + .del { + display: block; + margin-left: 10px; + width: 15px; + height: 15px; + background: url(../../public/static/images/canvas/circuit_del.svg) no-repeat center; + background-size: cover; + } + } +} +.circuit-table-tit { + color: #fff; + font-size: 12px; + font-weight: 600; + padding: 11px 10px; + background-color: #474747; + border: 1px solid #505050; + border-bottom: none; +} + +.circuit-overflow { + max-height: 400px; + overflow-y: auto; + margin-bottom: 15px; + &::-webkit-scrollbar { + width: 4px; + background-color: transparent; + } + &::-webkit-scrollbar-thumb { + background-color: #d9d9d9; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } +} + +.circuit-table-flx-wrap { + display: flex; + gap: 10px; + margin-bottom: 10px; + .circuit-table-flx-box { + flex: 1; display: flex; flex-direction: column; - gap: 5px; - min-height: 60px; - padding: 12px; - border: 1px solid rgba(255, 255, 255, 0.20); - span{ - display: inline-flex; - align-items: center; - .del{ - display: block; - margin-left: 10px; - width: 15px; - height: 15px; - background: url(../../public/static/images/canvas/circuit_del.svg)no-repeat center; - background-size: cover; - } + .bottom-wrap { + margin-top: auto; } -} -.circuit-table-tit{ - color: #fff; - font-size: 12px; - font-weight: 600; - padding: 11px 10px; - background-color: #474747; - border: 1px solid #505050; - border-bottom: none; + .roof-module-table { + table { + table-layout: fixed; + } + } + } } -.circuit-overflow{ - max-height: 400px; - overflow-y: auto; - margin-bottom: 15px; - &::-webkit-scrollbar { - width: 4px; - background-color: transparent; - } - &::-webkit-scrollbar-thumb { - background-color: #D9D9D9; - } - &::-webkit-scrollbar-track { - background-color: transparent; - } -} - -.circuit-table-flx-wrap{ - display: flex; - gap: 10px; - margin-bottom: 10px; - .circuit-table-flx-box{ - flex: 1; - display: flex; - flex-direction: column; - .bottom-wrap{ - margin-top: auto; - } - .roof-module-table{ - table{ - table-layout: fixed; - } - } - } -} - -.circuit-count-input{ - display: flex; - align-items: center; - gap: 10px; +.circuit-count-input { + display: flex; + align-items: center; + gap: 10px; } // 모듈부가기능 -.additional-radio-wrap{ - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 15px 0; - margin-bottom: 24px; +.additional-radio-wrap { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 15px 0; + margin-bottom: 24px; } -.additional-wrap{ - padding: 24px 0; - border-top: 1px solid #424242; +.additional-wrap { + padding: 24px 0; + border-top: 1px solid #424242; } -.additional-color-wrap{ +.additional-color-wrap { + display: flex; + align-items: center; + padding: 5px 0; + gap: 15px; + .additional-color-box { display: flex; align-items: center; - padding: 5px 0; - gap: 15px; - .additional-color-box{ - display: flex; - align-items: center; - gap: 8px; - .additional-color{ - display: block; - width: 16px; - height: 16px; - &.pink{ - border: 2px solid #ce1c9c; - background-color: #16417D; - } - &.white{ - border: 2px solid #FFF; - background-color: #001027; - } - } + gap: 8px; + .additional-color { + display: block; + width: 16px; + height: 16px; + &.pink { + border: 2px solid #ce1c9c; + background-color: #16417d; + } + &.white { + border: 2px solid #fff; + background-color: #001027; + } } + } } // color setting -.color-setting-wrap{ - padding-bottom: 15px; - border-bottom: 1px solid #424242; - .color-tit{ - font-size: 13px; +.color-setting-wrap { + padding-bottom: 15px; + border-bottom: 1px solid #424242; + .color-tit { + font-size: 13px; + font-weight: 500; + color: #ffffff; + margin-bottom: 10px; + } + .color-picker { + .react-colorful { + width: 100%; + height: auto; + gap: 20px; + .react-colorful__pointer { + width: 15px; + height: 15px; + border: 4px solid #fff; + } + .react-colorful__saturation { + border-radius: 2px; + height: 200px; + border-bottom: 5px solid #000; + } + .react-colorful__last-control { + border-radius: 2px; + height: 10px; + } + } + .hex-color-box { + display: flex; + align-items: center; + margin-top: 15px; + .color-box-tit { + font-size: 12px; + color: #fff; font-weight: 500; - color: #ffffff; - margin-bottom: 10px; + margin-right: 10px; + } + .color-hex-input { + width: 150px; + margin-right: 5px; + input { + width: 100%; + } + } + .color-box { + display: block; + width: 30px; + height: 30px; + border-radius: 4px; + } } - .color-picker{ - .react-colorful{ - width: 100%; - height: auto; - gap: 20px; - .react-colorful__pointer{ - width: 15px; - height: 15px; - border: 4px solid #Fff; - } - .react-colorful__saturation{ - border-radius: 2px; - height: 200px; - border-bottom: 5px solid #000; - } - .react-colorful__last-control{ - border-radius: 2px; - height: 10px; - } - } - .hex-color-box{ - display: flex; - align-items: center; - margin-top: 15px; - .color-box-tit{ - font-size: 12px; - color: #fff; - font-weight: 500; - margin-right: 10px; - } - .color-hex-input{ - width: 150px; - margin-right: 5px; - input{ - width: 100%; - } - } - .color-box{ - display: block; - width: 30px; - height: 30px; - border-radius: 4px; - } - } - .default-color-wrap{ - margin-top: 25px; - .default-tit{ - font-size: 12px; - font-weight: 500; - color: #fff; - margin-bottom: 10px; - } - .color-button-wrap{ - display: grid; - grid-template-columns: repeat(8, 1fr); - gap: 21px; - .default-color{ - display: block; - width: 100%; - height: 30px; - border-radius: 4px; - } - } - } - } -} - -// 글꼴 설정 팝업 -.font-option-warp{ - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 15px 5px; - margin-bottom: 15px; - .font-option-item{ - .option-item-tit{ - font-size: 12px; - font-weight: 500; - color: #fff; - margin-bottom: 10px; - } - } -} -.font-ex-wrap{ - margin-bottom: 15px; - .font-ex-tit{ + .default-color-wrap { + margin-top: 25px; + .default-tit { font-size: 12px; font-weight: 500; color: #fff; margin-bottom: 10px; + } + .color-button-wrap { + display: grid; + grid-template-columns: repeat(8, 1fr); + gap: 21px; + .default-color { + display: block; + width: 100%; + height: 30px; + border-radius: 4px; + } + } } - .font-ex-box{ - display: flex; - align-items: center; - justify-content: center; - width: 100%; - min-height: 80px; - background-color: #fff; + } +} + +// 글꼴 설정 팝업 +.font-option-warp { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 15px 5px; + margin-bottom: 15px; + .font-option-item { + .option-item-tit { + font-size: 12px; + font-weight: 500; + color: #fff; + margin-bottom: 10px; } - + } +} +.font-ex-wrap { + margin-bottom: 15px; + .font-ex-tit { + font-size: 12px; + font-weight: 500; + color: #fff; + margin-bottom: 10px; + } + .font-ex-box { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 80px; + background-color: #fff; + } } // 치수선 설정 -.font-btn-wrap{ - margin-bottom: 15px; - button{ - width: 100%; - height: 30px; - line-height: 28px; - } +.font-btn-wrap { + margin-bottom: 15px; + button { + width: 100%; + height: 30px; + line-height: 28px; + } } -.line-color-wrap{ - margin-bottom: 15px; - .color-btn{ +.line-color-wrap { + margin-bottom: 15px; + .color-btn { + display: block; + width: 100%; + height: 30px; + border-radius: 2px; + } +} + +.form-box { + width: 100%; + background-color: #fff; + padding: 10px 0 20px; + .line-form { + position: relative; + width: 102px; + height: 40px; + margin: 0 auto; + border-left: 1px dashed #101010; + border-right: 1px dashed #101010; + .line-font-box { + position: absolute; + bottom: -3px; + left: 0; + width: 100%; + text-align: center; + .font { + display: block; + padding-bottom: 6px; + color: #101010; + } + .line { + position: relative; display: block; width: 100%; - height: 30px; - border-radius: 2px; - } -} - -.form-box{ - width: 100%; - background-color: #fff; - padding: 10px 0 20px; - .line-form{ - position: relative; - width: 102px; - height: 40px; - margin: 0 auto; - border-left: 1px dashed #101010; - border-right: 1px dashed #101010; - .line-font-box{ - position: absolute; - bottom: -3px; - left: 0; - width: 100%; - text-align: center; - .font{ - display: block; - padding-bottom: 6px; - color: #101010; - } - .line{ - position: relative; - display: block; - width: 100%; - height: 1px; - border-radius: 30px; - &::before{ - content: ''; - position: absolute; - top: 50%; - transform: translateY(-50%) rotate(45deg); - left: 1px; - width: 9px; - height: 9px; - border: 1px solid; - border-color: inherit; - border-top: none; - border-right: none; - } - &::after{ - content: ''; - position: absolute; - top: 50%; - transform: translateY(-50%) rotate(45deg); - right: 1px; - width: 9px; - height: 9px; - border: 1px solid; - border-color: inherit; - border-bottom: none; - border-left: none; - } - } + height: 1px; + border-radius: 30px; + &::before { + content: ''; + position: absolute; + top: 50%; + transform: translateY(-50%) rotate(45deg); + left: 1px; + width: 9px; + height: 9px; + border: 1px solid; + border-color: inherit; + border-top: none; + border-right: none; } + &::after { + content: ''; + position: absolute; + top: 50%; + transform: translateY(-50%) rotate(45deg); + right: 1px; + width: 9px; + height: 9px; + border: 1px solid; + border-color: inherit; + border-bottom: none; + border-left: none; + } + } } + } } // 사이즈 변경 -.size-inner-warp{ - position: relative; +.size-inner-warp { + position: relative; } -.size-check-wrap{ - position: relative; - display: block; - width: 132px; - height: 132px; - margin: 0 auto; - .size-btn{ - position: absolute; - width: 16px; - height: 16px; - border: 1px solid #fff; - border-radius: 50%; - &.act{ - &::after{ - content: ''; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 8px; - height: 8px; - background-color: #fff; - border-radius: 50%; - } - } - &:nth-child(1){ top: 0; left: 0; } - &:nth-child(2){ top: 0; right: 0; } - &:nth-child(3){ bottom: 0; left: 0; } - &:nth-child(4){ bottom: 0; right: 0; } - } - .size-box{ +.size-check-wrap { + position: relative; + display: block; + width: 132px; + height: 132px; + margin: 0 auto; + .size-btn { + position: absolute; + width: 16px; + height: 16px; + border: 1px solid #fff; + border-radius: 50%; + &.act { + &::after { + content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); - width: 100px; - height: 100px; + width: 8px; + height: 8px; background-color: #fff; + border-radius: 50%; + } } -} - -.size-option-top{ - margin-bottom: 15px; -} -.size-option-side{ + &:nth-child(1) { + top: 0; + left: 0; + } + &:nth-child(2) { + top: 0; + right: 0; + } + &:nth-child(3) { + bottom: 0; + left: 0; + } + &:nth-child(4) { + bottom: 0; + right: 0; + } + } + .size-box { position: absolute; top: 50%; - left: 0; - transform: translateY(-50%); + left: 50%; + transform: translate(-50%, -50%); + width: 100px; + height: 100px; + background-color: #fff; + } } -.size-option-wrap{ - width: 88px; - margin: 0 auto; - .size-option{ - display: flex; - align-items: center; - input{ - width: 100%; - flex: 1; - } - span{ - flex: none; - } + +.size-option-top { + margin-bottom: 15px; +} +.size-option-side { + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); +} +.size-option-wrap { + width: 88px; + margin: 0 auto; + .size-option { + display: flex; + align-items: center; + input { + width: 100%; + flex: 1; } -} \ No newline at end of file + span { + flex: none; + } + } +} diff --git a/src/styles/_reset.scss b/src/styles/_reset.scss index d483c7b7..ef4cee0d 100644 --- a/src/styles/_reset.scss +++ b/src/styles/_reset.scss @@ -1,891 +1,1027 @@ * { - -webkit-text-size-adjust:none; - -moz-text-size-adjust:none; - -ms-text-size-adjust:none; - text-size-adjust: none; - box-sizing: content-box + -webkit-text-size-adjust: none; + -moz-text-size-adjust: none; + -ms-text-size-adjust: none; + text-size-adjust: none; + box-sizing: content-box; } -*, ::after, ::before { - box-sizing: border-box; +*, +::after, +::before { + box-sizing: border-box; } -html, body{ - width: 100%; - height: 100%; - font-size: 16px; +html, +body { + width: 100%; + height: 100%; + font-size: 16px; } -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, img, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -b, u, i, center, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, canvas, details, embed, -figure, figcaption, footer, header, hgroup, -menu, nav, output, ruby, section, summary, -time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font: inherit; - vertical-align: baseline; - font-family: 'Noto Sans JP', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-smooth: never; +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, +figure, +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; + font-family: 'Noto Sans JP', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-smooth: never; } /* HTML5 display-role reset for older browsers */ -article, aside, details, figcaption, figure, -footer, header, hgroup, menu, nav, section { - display: block; +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section { + display: block; } body { - line-height: 1.4; + line-height: 1.4; +} +body:first-of-type caption { + display: none; } -body:first-of-type caption { display:none;} -ol, ul { - list-style: none; +ol, +ul { + list-style: none; } -blockquote, q { - quotes: none; +blockquote, +q { + quotes: none; } -blockquote:before, blockquote:after, -q:before, q:after { - content: ''; - content: none; +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ''; + content: none; } table { - width: 100%; - border-collapse: separate; - border-spacing:0; - border:0 none; + width: 100%; + border-collapse: separate; + border-spacing: 0; + border: 0 none; } -caption, th, td { - text-align:left; - font-weight: normal; - border:0; +caption, +th, +td { + text-align: left; + font-weight: normal; + border: 0; } -a { - cursor:pointer; - color:#000; +a { + cursor: pointer; + color: #000; } -a, a:hover, a:active { - text-decoration:none; - -webkit-tap-highlight-color: transparent; +a, +a:hover, +a:active { + text-decoration: none; + -webkit-tap-highlight-color: transparent; } /*form_style*/ -input, select, textarea, button, a, label { - -webkit-tap-highlight-color:rgba(0,0,0,0); +input, +select, +textarea, +button, +a, +label { + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } -button,input[type=text], input[type=button] { - -webkit-appearance: none; - -webkit-border-radius: 0; - -webkit-appearance:none; - appearance: none; - border-radius: 0 +button, +input[type='text'], +input[type='button'] { + -webkit-appearance: none; + -webkit-border-radius: 0; + -webkit-appearance: none; + appearance: none; + border-radius: 0; } -input[type=checkbox], input[type=radio] { - box-sizing: border-box; - padding: 0; +input[type='checkbox'], +input[type='radio'] { + box-sizing: border-box; + padding: 0; } -input, select, button { - border:0 none; - outline:none; - margin:0; +input, +select, +button { + border: 0 none; + outline: none; + margin: 0; } select { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } select::-ms-expand { - display: none; + display: none; } ::-webkit-input-placeholder { - line-height:1; - font-weight:300; - font-size:0.938rem; - letter-spacing:-0.6px; - color:#8b8b8b; + line-height: 1; + font-weight: 300; + font-size: 0.938rem; + letter-spacing: -0.6px; + color: #8b8b8b; } -.log-box ::-webkit-input-placeholder{ - color:#8b8b8b; +.log-box ::-webkit-input-placeholder { + color: #8b8b8b; } -button{ - background: transparent; - font-family: 'Noto Sans JP', sans-serif; - border: none; - padding: 0; - margin: 0; - line-height: 1.4; - color: inherit; - outline: none; - cursor: pointer; +button { + background: transparent; + font-family: 'Noto Sans JP', sans-serif; + border: none; + padding: 0; + margin: 0; + line-height: 1.4; + color: inherit; + outline: none; + cursor: pointer; } -.pre{ - font-family: 'Pretendard', sans-serif !important; +.pre { + font-family: 'Pretendard', sans-serif !important; } // margin -.mt5{margin-top: 5px !important;} -.mt10{margin-top: 10px !important;} -.mt15{margin-top: 15px !important;} -.mb5{margin-bottom: 5px !important;} -.mb10{margin-bottom: 10px !important;} -.mb15{margin-bottom: 15px !important;} -.mr5{margin-right: 5px !important;} -.mr10{margin-right: 10px !important;} -.mr15{margin-right: 15px !important;} -.ml5{margin-left: 5px !important;} -.ml10{margin-left: 10px !important;} -.ml15{margin-left: 15px !important;} - -// align -.al-l{text-align: left !important;} -.al-r{text-align: right !important;} -.al-c{text-align: center !important;} - - -// button -.btn-frame{ - display: inline-block; - padding: 0 7px; - height: 34px; - line-height: 34px; - border-radius: 2px; - color: #fff; - font-size: 12px; - font-weight: 400; - border: 1px solid #000; - text-align: center; - font-family: 'Pretendard', sans-serif; - transition: all .17s ease-in-out; - cursor: pointer; - &.block{ - width: 100%; - } - &.small{ - font-family: 'Noto Sans JP', sans-serif; - height: 30px; - line-height: 30px; - font-size: 13px; - } - - &.deepgray{ - background-color: #2C2C2C; - border: 1px solid #484848; - } - &.gray{ - background-color: #3C3C3C; - border: 1px solid #545454; - } - &.dark{ - background-color: #1C1C1C; - border: 1px solid #484848; - } - &.modal{ - font-family: 'Noto Sans JP', sans-serif; - background-color: #272727; - border: 1px solid #484848; - color: #aaa; - &:hover{ - background-color: #1083E3; - border: 1px solid #1083E3; - color: #fff; - font-weight: 500; - } - } - &.sub-tab{ - height: 30px; - padding: 0 10px; - line-height: 28px; - font-family: 'Noto Sans JP', sans-serif; - background-color: #2D2D2D; - border: 1px solid #393939; - color: #aaa; - &.act, - &:hover{ - background-color: #414E6C; - border: 1px solid #414E6C; - color: #fff; - font-weight: 500; - } - } - &.roof{ - height: 30px; - padding: 0 10px; - line-height: 28px; - font-family: 'Noto Sans JP', sans-serif; - background-color: transparent; - border: 1px solid #484848; - color: #fff; - &.blue{ - background-color: #414E6C; - border: 1px solid #414E6C; - &:hover{ - background-color: #414E6C; - border: 1px solid #414E6C; - } - } - &.white{ - background-color: #fff; - border: 1px solid #fff; - color: #101010; - &:hover{ - background-color: #fff; - border: 1px solid #fff; - color: #101010; - } - } - &:hover{ - font-weight: 400; - background-color: transparent; - border: 1px solid #484848; - color: #fff; - } - } - &.self{ - height: 30px; - padding: 0 10px; - line-height: 28px; - font-family: 'Noto Sans JP', sans-serif; - background-color: transparent; - border: 1px solid #676767; - color: #AAAAAA; - &:hover{ - background-color: #272727; - border-color: #676767; - font-weight: 400; - } - } - &:hover, - &.act{ - background-color: #1083E3; - border: 1px solid #1083E3; - color: #fff; - font-weight: 500; - } - &.block{ - display: block; - width: 100%; - } - &.ico-flx{ - display: flex; - align-items: center; - .ico{ - margin-right: 10px; - } - &:hover, - &.act{ - font-weight: 400; - } - } +.mt5 { + margin-top: 5px !important; +} +.mt10 { + margin-top: 10px !important; +} +.mt15 { + margin-top: 15px !important; +} +.mb5 { + margin-bottom: 5px !important; +} +.mb10 { + margin-bottom: 10px !important; +} +.mb15 { + margin-bottom: 15px !important; +} +.mr5 { + margin-right: 5px !important; +} +.mr10 { + margin-right: 10px !important; +} +.mr15 { + margin-right: 15px !important; +} +.ml5 { + margin-left: 5px !important; +} +.ml10 { + margin-left: 10px !important; +} +.ml15 { + margin-left: 15px !important; } -.btn-origin{ - display: inline-block; +// align +.al-l { + text-align: left !important; +} +.al-r { + text-align: right !important; +} +.al-c { + text-align: center !important; +} + +// button +.btn-frame { + display: inline-block; + padding: 0 7px; + height: 34px; + line-height: 34px; + border-radius: 2px; + color: #fff; + font-size: 12px; + font-weight: 400; + border: 1px solid #000; + text-align: center; + font-family: 'Pretendard', sans-serif; + transition: all 0.17s ease-in-out; + cursor: pointer; + &.block { + width: 100%; + } + &.small { + font-family: 'Noto Sans JP', sans-serif; + height: 30px; + line-height: 30px; + font-size: 13px; + } + + &.deepgray { + background-color: #2c2c2c; + border: 1px solid #484848; + } + &.gray { + background-color: #3c3c3c; + border: 1px solid #545454; + } + &.dark { + background-color: #1c1c1c; + border: 1px solid #484848; + } + &.modal { + font-family: 'Noto Sans JP', sans-serif; + background-color: #272727; + border: 1px solid #484848; + color: #aaa; + &:hover { + background-color: #1083e3; + border: 1px solid #1083e3; + color: #fff; + font-weight: 500; + } + } + &.sub-tab { height: 30px; padding: 0 10px; - border-radius: 2px; - background-color: #101010; + line-height: 28px; + font-family: 'Noto Sans JP', sans-serif; + background-color: #2d2d2d; + border: 1px solid #393939; + color: #aaa; + &.act, + &:hover { + background-color: #414e6c; + border: 1px solid #414e6c; + color: #fff; + font-weight: 500; + } + } + &.roof { + height: 30px; + padding: 0 10px; + line-height: 28px; + font-family: 'Noto Sans JP', sans-serif; + background-color: transparent; + border: 1px solid #484848; color: #fff; - font-size: 13px; - font-weight: 400; - transition: all .15s ease-in-out; - &.navy{ - background-color: #304961; - &:hover{ - background-color: #233546; - } + &.blue { + background-color: #414e6c; + border: 1px solid #414e6c; + &:hover { + background-color: #414e6c; + border: 1px solid #414e6c; + } } - &.grey{ - background-color: #94A0AD; - &:hover{ - background-color: #607F9A; - } - } - &.green{ - background-color: #A6BBA8; - &:hover{ - background-color: #98af9b; - } - } - &.white{ - border: 1px solid #94A0AD; + &.white { + background-color: #fff; + border: 1px solid #fff; + color: #101010; + &:hover { background-color: #fff; - color: #94A0AD; - &:hover{ - background-color: #fff; - } + border: 1px solid #fff; + color: #101010; + } } + &:hover { + font-weight: 400; + background-color: transparent; + border: 1px solid #484848; + color: #fff; + } + } + &.self { + height: 30px; + padding: 0 10px; + line-height: 28px; + font-family: 'Noto Sans JP', sans-serif; + background-color: transparent; + border: 1px solid #676767; + color: #aaaaaa; + &:hover { + background-color: #272727; + border-color: #676767; + font-weight: 400; + } + } + &:hover, + &.act { + background-color: #1083e3; + border: 1px solid #1083e3; + color: #fff; + font-weight: 500; + } + &.block { + display: block; + width: 100%; + } + &.ico-flx { + display: flex; + align-items: center; + .ico { + margin-right: 10px; + } + &:hover, + &.act { + font-weight: 400; + } + } +} + +.btn-origin { + display: inline-block; + height: 30px; + padding: 0 10px; + border-radius: 2px; + background-color: #101010; + color: #fff; + font-size: 13px; + font-weight: 400; + transition: all 0.15s ease-in-out; + &.navy { + background-color: #304961; + &:hover { + background-color: #233546; + } + } + &.grey { + background-color: #94a0ad; + &:hover { + background-color: #607f9a; + } + } + &.green { + background-color: #a6bba8; + &:hover { + background-color: #98af9b; + } + } + &.white { + border: 1px solid #94a0ad; + background-color: #fff; + color: #94a0ad; + &:hover { + background-color: #fff; + } + } } // select -.sort-select{ - position: relative; - display: inline-block; - min-width: 100px; - height: 30px; - line-height: 30px; - padding: 0 25px 0 10px; - background-color: #373737; - border: 1px solid #3F3F3F; - border-radius: 2px; - border-top-left-radius: 2px; +.sort-select { + position: relative; + display: inline-block; + min-width: 100px; + height: 30px; + line-height: 30px; + padding: 0 25px 0 10px; + background-color: #373737; + border: 1px solid #3f3f3f; + border-radius: 2px; + border-top-left-radius: 2px; + color: #fff; + cursor: pointer; + p { + font-size: 13px; color: #fff; - cursor: pointer; - p{ - font-size: 13px; + height: 100%; + } + .select-item-wrap { + position: absolute; + top: 100%; + left: -1px; + clip-path: inset(0 0 100% 0); + width: calc(100% + 2px); + padding: 8px 0; + max-height: 100px; + overflow-y: auto; + background-color: #373737; + border: 1px solid #3f3f3f; + border-radius: 2px; + transition: all 0.17s ease-in-out; + visibility: hidden; + z-index: 999; + .select-item { + display: flex; + align-items: center; + padding: 8px 20px; + line-height: 1.4; + transition: all 0.17s ease-in-out; + button { + font-size: 12px; color: #fff; - height: 100%; + line-height: 1.4; + } + &:hover { + background-color: #2c2c2c; + } } - .select-item-wrap{ - position: absolute; - top: 100%; - left: -1px; - clip-path:inset(0 0 100% 0); - width: calc(100% + 2px); - padding: 8px 0; - max-height: 100px; - overflow-y: auto; - background-color: #373737; - border: 1px solid #3F3F3F; - border-radius: 2px; - transition: all 0.17s ease-in-out; - visibility: hidden; - z-index: 999; - .select-item{ - display: flex; - align-items: center; - padding: 8px 20px; - line-height: 1.4; - transition: all .17s ease-in-out; - button{ - font-size: 12px; - color: #fff; - line-height: 1.4; - } - &:hover{ - background-color: #2C2C2C; - } - } - &::-webkit-scrollbar { - width: 2px; - background-color: transparent; - - } - &::-webkit-scrollbar-thumb { - background-color: #5a5a5a; - border-radius: 10px; - } - &::-webkit-scrollbar-track { - background-color: transparent; - } + &::-webkit-scrollbar { + width: 2px; + background-color: transparent; } - &::after{ - content: ''; - position: absolute; - top: 50%; - right: 7px; - transform: translateY(-50%); - width: 10px; - height: 6px; - background: url(/static/images/common/select-arr.svg) no-repeat center; - background-size: cover; - transition: all .17s ease-in-out; + &::-webkit-scrollbar-thumb { + background-color: #5a5a5a; + border-radius: 10px; } - &.active{ - .select-item-wrap{ - clip-path: inset(0 0 0 0); - visibility: visible; - } - &:after{ - transform: translateY(-50%) rotate(-180deg); - } + &::-webkit-scrollbar-track { + background-color: transparent; } + } + &::after { + content: ''; + position: absolute; + top: 50%; + right: 7px; + transform: translateY(-50%); + width: 10px; + height: 6px; + background: url(/static/images/common/select-arr.svg) no-repeat center; + background-size: cover; + transition: all 0.17s ease-in-out; + } + &.active { + .select-item-wrap { + clip-path: inset(0 0 0 0); + visibility: visible; + } + &:after { + transform: translateY(-50%) rotate(-180deg); + } + } } -.select-light{ - position: relative; +.select-light { + position: relative; + display: block; + width: 100%; + height: 30px; + background: #fff url(../../public/static/images/common/select_light_arr.svg) calc(100% - 11px) center no-repeat; + background-size: 10px 6px; + border: 1px solid #eee; + padding: 0 30px 0 10px; + font-size: 13px; + color: #45576f; + font-family: 'Noto Sans JP', sans-serif; + cursor: pointer; + &:disabled { + opacity: 1; + background-color: #fafafa; + color: #999; + cursor: default; + } + &.black { + color: #101010; + } + &.dark { + background: #323234 url(../../public/static/images/common/select_dark_arr.svg) calc(100% - 11px) center no-repeat; + color: #898989; + font-size: 12px; + border-radius: 2px; + border: none; + } +} + +// input +.form-input { + label { + display: block; + color: #aaa; + font-size: 12px; + font-weight: 500; + margin-bottom: 10px; + } +} +input[type='password'], +input[type='number'], +input[type='text'] { + &.input-origin { + display: inline-block; + height: 30px; + line-height: 30px; + border-radius: 2px; + background-color: #323234; + color: #fff; + font-size: 12px; + font-weight: 500; + font-family: 'Pretendard', sans-serif; + padding: 0 10px; + letter-spacing: 0px; + text-align: right; + &::placeholder { + opacity: 1; + font-size: 12px; + letter-spacing: 0px; + } + &.block { + width: 100%; + } + &:read-only { + color: #aaa; + } + &.plane { + font-family: 'Noto Sans JP', sans-serif; + border: 1px solid #525252; + background-color: transparent; + } + } + &.input-light { display: block; width: 100%; height: 30px; - background: #FFF url(../../public/static/images/common/select_light_arr.svg) calc(100% - 11px) center no-repeat; - background-size: 10px 6px; + padding: 0 10px; border: 1px solid #eee; - padding: 0 30px 0 10px; - font-size: 13px; - color: #45576F; + border-radius: 2px; + background-color: #fff; font-family: 'Noto Sans JP', sans-serif; - cursor: pointer; - &:disabled{ - opacity: 1; - background-color: #FAFAFA; - color: #999; - cursor: default; - } - &.black{ - color: #101010; - } - &.dark{ - background: #323234 url(../../public/static/images/common/select_dark_arr.svg) calc(100% - 11px) center no-repeat; - color: #898989; - font-size: 12px; - border-radius: 2px; - border: none; + font-size: 13px; + color: #45576f; + font-weight: normal; + transition: border-color 0.17s ease-in-out; + text-align: left; + &:read-only { + background-color: #fafafa; + color: #999999; } + } } - -// input -.form-input{ - label{ - display: block; - color: #aaa; - font-size: 12px; - font-weight: 500; - margin-bottom: 10px; - } -} -input[type=password], -input[type=number], -input[type=text]{ - &.input-origin{ - display: inline-block; - height: 30px; - line-height: 30px; - border-radius: 2px; - background-color: #323234; - color: #fff; - font-size: 12px; - font-weight: 500; - font-family: 'Pretendard', sans-serif; - padding: 0 10px; - letter-spacing: 0px; - text-align: right; - &::placeholder{ - opacity: 1; - font-size: 12px; - letter-spacing: 0px; - } - &.block{ - width: 100%; - } - &:read-only{ - color: #AAA; - } - &.plane{ - font-family: 'Noto Sans JP', sans-serif; - border: 1px solid #525252; - background-color: transparent; - } - } - &.input-light{ - display: block; - width: 100%; - height: 30px; - padding: 0 10px; - border: 1px solid #eee; - border-radius: 2px; - background-color: #fff; - font-family: 'Noto Sans JP', sans-serif; - font-size: 13px; - color: #45576F; - font-weight: normal; - transition: border-color .17s ease-in-out; - text-align: left; - &:read-only{ - background-color: #FAFAFA; - color: #999999; - } - } -} - - - // check-btn -.check-btn{ - display: flex; - align-items: center; - height: 30px; - background-color: #3A3A3A; - border-radius: 3px; - transition: all .17s ease-in-out; - .check-area{ - flex: none; - width: 30px; - height: 100%; - border-right: 1px solid #272727; - background: url(../../public/static/images/canvas/check-grey.svg)no-repeat center; - background-size: 11px 9px; +.check-btn { + display: flex; + align-items: center; + height: 30px; + background-color: #3a3a3a; + border-radius: 3px; + transition: all 0.17s ease-in-out; + .check-area { + flex: none; + width: 30px; + height: 100%; + border-right: 1px solid #272727; + background: url(../../public/static/images/canvas/check-grey.svg) no-repeat center; + background-size: 11px 9px; + } + .title-area { + padding: 0 10px; + font-size: 12px; + color: #898989; + font-weight: 400; + } + &.block { + width: 100%; + } + &:hover, + &.act { + background-color: #fff; + .check-area { + border-right: 1px solid #101010; + background: url(../../public/static/images/canvas/check-black.svg) no-repeat center; } - .title-area{ - padding: 0 10px; - font-size: 12px; - color: #898989; - font-weight: 400; - } - &.block{ - width: 100%; - } - &:hover, - &.act{ - background-color: #fff; - .check-area{ - border-right: 1px solid #101010; - background: url(../../public/static/images/canvas/check-black.svg)no-repeat center; - } - .title-area{ - color: #101010; - font-weight: 600; - } + .title-area { + color: #101010; + font-weight: 600; } + } } // arr-btn -.arr-btn{ - display: block; - height: 30px; - border-radius: 3px; - background-color: #3A3A3A; - padding: 0 11px; - text-align: left; - transition: all .17s ease-in-out; - span{ - position: relative; - font-size: 12px; - color: #898989; - font-weight: 400; - padding-right: 15px; - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 5px; - height: 8px; - background: url(../../public/static/images/canvas/arr_btn_ico.svg)no-repeat center; - } +.arr-btn { + display: block; + height: 30px; + border-radius: 3px; + background-color: #3a3a3a; + padding: 0 11px; + text-align: left; + transition: all 0.17s ease-in-out; + span { + position: relative; + font-size: 12px; + color: #898989; + font-weight: 400; + padding-right: 15px; + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 5px; + height: 8px; + background: url(../../public/static/images/canvas/arr_btn_ico.svg) no-repeat center; + } + } + &:hover, + &.act { + background-color: #fff; + span { + color: #101010; + font-weight: 500; + &:after { + background: url(../../public/static/images/canvas/arr_btn_ico_black.svg) no-repeat center; + } + } + } + &.dark { + text-align: center; + background-color: #272727; + border: 1px solid #484848; + span { + color: #fff; + &:after { + background: url(../../public/static/images/canvas/arr_btn_ico_white.svg) no-repeat center; + } } &:hover, - &.act{ - background-color: #fff; - span{ - color: #101010; - font-weight: 500; - &:after{ - background: url(../../public/static/images/canvas/arr_btn_ico_black.svg)no-repeat center; - } - } - } - &.dark{ - text-align: center; - background-color: #272727; - border: 1px solid #484848; - span{ - color: #Fff; - &:after{ - background: url(../../public/static/images/canvas/arr_btn_ico_white.svg)no-repeat center; - } - } - &:hover, - &.act{ - background-color: #1083E3; - border: 1px solid #1083E3; - } + &.act { + background-color: #1083e3; + border: 1px solid #1083e3; } + } } // radio .d-check-radio, -.d-check-box{ - line-height: 1.1; +.d-check-box { + line-height: 1.1; + cursor: pointer; + input[type='checkbox'], + input[type='radio'] { + position: static; + margin-left: 0; cursor: pointer; - input[type=checkbox], - input[type=radio]{ - position: static; - margin-left: 0; - cursor: pointer; - opacity: 0; - z-index: 1; - flex: 0 0 auto; + opacity: 0; + z-index: 1; + flex: 0 0 auto; + } + label { + position: relative; + padding-left: 10px; + margin-bottom: 0; + word-break: break-all; + line-height: 1.2; + display: inline; + vertical-align: top; + color: #fff; + font-size: 13px; + font-weight: 400; + cursor: pointer; + } + &.light { + label { + color: #45576f; } - label{ - position: relative; - padding-left: 10px; - margin-bottom: 0; - word-break: break-all; - line-height: 1.2; - display: inline; - vertical-align: top; - color: #fff; - font-size: 13px; - font-weight: 400; - cursor: pointer; - } - &.light{ - label{ - color: #45576F; - } - } - &.no-text{ - label{ - padding-left: 0; - } + } + &.no-text { + label { + padding-left: 0; } + } } .d-check-radio { - label{ - &::before{ - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 17px; - height: 17px; - top:2px; - left: 0; - margin-left: -12px; - border: 1px solid #999999; - border-radius: 100%; - background-color: transparent; - text-align:center; - font-size:13px; - line-height:1.4; - transition: border 0.15s ease-in-out, color 0.15s ease-in-out; - } - &::after{ - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 9px; - height: 9px; - top:6px; - left: 4px; - margin-left: -12px; - border: none; - border-radius: 100%; - background-color: #fff; - text-align:center; - font-size:13px; - line-height:1.4; - opacity: 0; - visibility: hidden; - transition: opacity 0.15s ease-in-out, color 0.15s ease-in-out; - } + label { + &::before { + cursor: pointer; + content: ''; + display: inline-block; + position: absolute; + width: 17px; + height: 17px; + top: 2px; + left: 0; + margin-left: -12px; + border: 1px solid #999999; + border-radius: 100%; + background-color: transparent; + text-align: center; + font-size: 13px; + line-height: 1.4; + transition: + border 0.15s ease-in-out, + color 0.15s ease-in-out; } - &.light{ - label{ - &:before{ - border-color: #D6D6D7; - } - &:after{ - background-color: #697C8F; - } - } + &::after { + cursor: pointer; + content: ''; + display: inline-block; + position: absolute; + width: 9px; + height: 9px; + top: 6px; + left: 4px; + margin-left: -12px; + border: none; + border-radius: 100%; + background-color: #fff; + text-align: center; + font-size: 13px; + line-height: 1.4; + opacity: 0; + visibility: hidden; + transition: + opacity 0.15s ease-in-out, + color 0.15s ease-in-out; } - input[type=radio]:checked + label::after{ - opacity: 1; - visibility: visible; + } + &.light { + label { + &:before { + border-color: #d6d6d7; + } + &:after { + background-color: #697c8f; + } } - &.pop{ - label{ - font-size: 12px; - &:before{ - width: 16px; - height: 16px; - border-color: #fff; - } - &:after{ - width: 8px; - height: 8px; - background-color: #fff; - } - } + } + input[type='radio']:checked + label::after { + opacity: 1; + visibility: visible; + } + &.pop { + label { + font-size: 12px; + &:before { + width: 16px; + height: 16px; + border-color: #fff; + } + &:after { + width: 8px; + height: 8px; + background-color: #fff; + } } + } } // check-box -.d-check-box{ - label{ - &.red{color: #FFCACA;} - &::before{ - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 17px; - height: 17px; - top: 2px; - left: 0; - margin-left: -12px; - border: 1px solid #D6D6D7; - background-color: #fff; - transition: border 0.15s ease-in-out, color 0.15s ease-in-out; - } - &:after{ - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 16px; - height: 16px; - top:0; - left: 0; - margin-left: -.8rem; - transition: border 0.05s ease-in-out, color 0.05s ease-in-out; - } +.d-check-box { + label { + &.red { + color: #ffcaca; } - input[type=checkbox]:checked + label::after{ - content: ""; - display: inline-block; - position: absolute; - top: 1px; - left: -1px; - width: 5px; - height: 8px; - border: 2px solid #697C8F; - border-left: none; - border-top: none; - transform: translate(7.75px,4.5px) rotate(45deg); - -ms-transform: translate(7.75px,4.5px) rotate(45deg); + &::before { + cursor: pointer; + content: ''; + display: inline-block; + position: absolute; + width: 17px; + height: 17px; + top: 2px; + left: 0; + margin-left: -12px; + border: 1px solid #d6d6d7; + background-color: #fff; + transition: + border 0.15s ease-in-out, + color 0.15s ease-in-out; } - &.pop{ - label{ - &:before{ - background-color: transparent; - } - } - input[type=checkbox]:checked + label::after{ - border-color: #fff; - } - &.no-text{ - label{ - padding-left: 0; - } - } + &:after { + cursor: pointer; + content: ''; + display: inline-block; + position: absolute; + width: 16px; + height: 16px; + top: 0; + left: 0; + margin-left: -0.8rem; + transition: + border 0.05s ease-in-out, + color 0.05s ease-in-out; } - &.sel{ - input[type=checkbox]:checked + label{ - color: #D7C863; - } - input[type=checkbox]:checked + label::before, - input[type=checkbox]:checked + label::after{ - border-color: #D7C863; - } + } + input[type='checkbox']:checked + label::after { + content: ''; + display: inline-block; + position: absolute; + top: 1px; + left: -1px; + width: 5px; + height: 8px; + border: 2px solid #697c8f; + border-left: none; + border-top: none; + transform: translate(7.75px, 4.5px) rotate(45deg); + -ms-transform: translate(7.75px, 4.5px) rotate(45deg); + } + &.pop { + label { + &:before { + background-color: transparent; + } } + input[type='checkbox']:checked + label::after { + border-color: #fff; + } + &.no-text { + label { + padding-left: 0; + } + } + } + &.sel { + input[type='checkbox']:checked + label { + color: #d7c863; + } + input[type='checkbox']:checked + label::before, + input[type='checkbox']:checked + label::after { + border-color: #d7c863; + } + } } // date-picker -.date-picker{ - svg{display: none;} - .react-datepicker-wrapper{ - width: 100%; - } - input[type=text]{ - display: block; - width: 100%; - height: 30px; - padding: 0 34px 0 10px; - border-radius: 2px; - border: 1px solid #eee; - font-size: 13px; - color: #45576F; - font-weight: normal; - font-family: 'Noto Sans JP', sans-serif; - background: #fff url(../../public/static/images/common/datepicker.svg) calc(100% - 11px) center no-repeat; - background-size: 14px 15px; - cursor: pointer; - } +.date-picker { + svg { + display: none; + } + .react-datepicker-wrapper { + width: 100%; + } + input[type='text'] { + display: block; + width: 100%; + height: 30px; + padding: 0 34px 0 10px; + border-radius: 2px; + border: 1px solid #eee; + font-size: 13px; + color: #45576f; + font-weight: normal; + font-family: 'Noto Sans JP', sans-serif; + background: #fff url(../../public/static/images/common/datepicker.svg) calc(100% - 11px) center no-repeat; + background-size: 14px 15px; + cursor: pointer; + } } // react select -.react-select-custom{ - width: 100%; - .custom__control{ - height: 30px; - min-height: unset; - border-radius: 2px; - border-color: #EEE; - background-color: #fff; - &:hover{ - border-color: #EEE; - } +.react-select-custom { + width: 100%; + .custom__control { + height: 30px; + min-height: unset; + border-radius: 2px; + border-color: #eee; + background-color: #fff; + &:hover { + border-color: #eee; } - .custom__control--is-focused{ - border-color: #EEE; - box-shadow: unset; - &:hover{ - border-color: #EEE; + } + .custom__control--is-focused { + border-color: #eee; + box-shadow: unset; + &:hover { + border-color: #eee; + } + } + .custom__value-container { + height: 100%; + padding: 0 10px; + } + .custom__placeholder, + .custom__single-value { + margin: 0; + } + .custom__single-value { + font-size: 13px; + color: #45576f; + font-weight: 400; + } + .custom__placeholder { + font-size: 13px; + color: #bbbbbb; + font-weight: 400; + } + .custom__indicator { + padding: 0; + svg { + display: none; + } + } + .custom__clear-indicator { + width: 30px; + height: 100%; + background: url(../../public/static/images/common/select_del.svg) no-repeat center; + background-size: 8px 8px; + } + .custom__dropdown-indicator { + width: 30px; + height: 100%; + background: url(../../public/static/images/common/select_light_arr.svg) no-repeat center; + } - } + .custom__menu { + margin: 1px 0; + border-radius: 2px; + overflow: hidden; + } + .custom__menu-list { + padding: 0; + } + .custom__option { + font-size: 13px; + padding: 7px 10px; + color: #45576f; + } + .custom__option--is-selected { + color: #fff; + } + // disable + &.custom--is-disabled { + .custom__control { + background-color: #fafafa; } - .custom__value-container { - height: 100%; - padding: 0 10px; + .custom__single-value { + color: #999999; } - .custom__placeholder, - .custom__single-value{ - margin: 0; - } - .custom__single-value{ - font-size: 13px; - color: #45576F; - font-weight: 400; - } - .custom__placeholder{ - font-size: 13px; - color: #bbbbbb; - font-weight: 400; - } - .custom__indicator{ - padding: 0; - svg{ - display: none; - } - } - .custom__clear-indicator{ - width: 30px; - height: 100%; - background: url(../../public/static/images/common/select_del.svg) no-repeat center; - background-size: 8px 8px; - } - .custom__dropdown-indicator{ - width: 30px; - height: 100%; - background: url(../../public/static/images/common/select_light_arr.svg) no-repeat center; - } - - .custom__menu { - margin: 1px 0; - border-radius: 2px; - overflow: hidden; - } - .custom__menu-list { - padding: 0; - } - .custom__option{ - font-size: 13px; - padding: 7px 10px; - color: #45576F; - } - .custom__option--is-selected{ - color: #fff; - } - // disable - &.custom--is-disabled{ - .custom__control{ - background-color: #FAFAFA ; - } - .custom__single-value{ - color: #999999; - } - } -} \ No newline at end of file + } +} diff --git a/src/styles/style.scss b/src/styles/style.scss index 1841ebb9..39343d54 100644 --- a/src/styles/style.scss +++ b/src/styles/style.scss @@ -1 +1,5 @@ -@import '_main.scss'; \ No newline at end of file +@import '_main.scss'; + +.locale-switch { + cursor: pointer; +} diff --git a/src/util/board-utils.js b/src/util/board-utils.js index a129c4d4..c41ba22a 100644 --- a/src/util/board-utils.js +++ b/src/util/board-utils.js @@ -8,8 +8,10 @@ export const handleFileDown = async (file) => { const params = new URLSearchParams({ encodeFileNo: file.encodeFileNo, }) + const options = { responseType: 'blob' } const apiUrl = `${url}?${params.toString()}` - await promiseGet({ url: apiUrl, responseType: 'blob' }) + + await promiseGet({ url: apiUrl, option: options }) .then((resultData) => { if (resultData) { const blob = new Blob([resultData.data], { type: resultData.headers['content-type'] || 'application/octet-stream' }) @@ -25,7 +27,7 @@ export const handleFileDown = async (file) => { } }) .catch((error) => { - alert(error.response.data.message) + alert('File does not exist.') }) } diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index 17c30f07..20b6ec66 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -744,67 +744,6 @@ export const polygonToTurfPolygon = (polygon) => { ) } -export const splitDormerTriangle = (triangle, direction) => { - const halfWidth = triangle.width / 2 - - let leftPoints = [] - let rightPoints = [] - let leftPointOffset = [] - let rightPointOffset = [] - - if (direction === 'down') { - leftPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left - halfWidth, y: triangle.top + triangle.height }, - { x: triangle.left, y: triangle.top + triangle.height }, - ] - - rightPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left, y: triangle.top + triangle.height }, - { x: triangle.left + halfWidth, y: triangle.top + triangle.height }, - ] - } else if (direction === 'up') { - leftPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left - halfWidth, y: triangle.top - triangle.height }, - { x: triangle.left, y: triangle.top - triangle.height }, - ] - - rightPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left, y: triangle.top - triangle.height }, - { x: triangle.left + halfWidth, y: triangle.top - triangle.height }, - ] - } else if (direction === 'left') { - leftPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left - triangle.height, y: triangle.top - halfWidth }, - { x: triangle.left - triangle.height, y: triangle.top }, - ] - - rightPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left - triangle.height, y: triangle.top }, - { x: triangle.left - triangle.height, y: triangle.top + halfWidth }, - ] - } else if (direction === 'right') { - leftPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left + triangle.height, y: triangle.top }, - { x: triangle.left + triangle.height, y: triangle.top + triangle.height }, - ] - - rightPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left + triangle.height, y: triangle.top }, - { x: triangle.left + triangle.height, y: triangle.top - triangle.height }, - ] - } - - return [leftPoints, rightPoints] -} - export const triangleToPolygon = (triangle) => { const points = [] const halfWidth = triangle.width / 2 @@ -853,7 +792,7 @@ export function setSurfaceShapePattern(polygon) { patternSourceCanvas.width = polygon.width * ratio patternSourceCanvas.height = polygon.height * ratio const ctx = patternSourceCanvas.getContext('2d') - const offset = roofStyle === 1 ? 0 : patternSize.width / 2 + let offset = roofStyle === 1 ? 0 : patternSize.width / 2 const rows = Math.floor(patternSourceCanvas.height / patternSize.height) const cols = Math.floor(patternSourceCanvas.width / patternSize.width) @@ -861,23 +800,46 @@ export function setSurfaceShapePattern(polygon) { ctx.strokeStyle = 'green' ctx.lineWidth = 0.4 - for (let row = 0; row <= rows; row++) { - const y = row * patternSize.height - - ctx.beginPath() - ctx.moveTo(0, y) // 선 시작점 - ctx.lineTo(patternSourceCanvas.width, y) // 선 끝점 - ctx.stroke() - + if (polygon.direction === 'east' || polygon.direction === 'west') { + offset = roofStyle === 1 ? 0 : patternSize.height / 2 for (let col = 0; col <= cols; col++) { - const x = col * patternSize.width + (row % 2 === 0 ? 0 : offset) - const yStart = row * patternSize.height - const yEnd = yStart + patternSize.height - + const x = col * patternSize.width + const yStart = 0 + const yEnd = patternSourceCanvas.height ctx.beginPath() ctx.moveTo(x, yStart) // 선 시작점 ctx.lineTo(x, yEnd) // 선 끝점 ctx.stroke() + + for (let row = 0; row <= rows; row++) { + const y = row * patternSize.height + (col % 2 === 0 ? 0 : offset) + const xStart = col * patternSize.width + const xEnd = xStart + patternSize.width + ctx.beginPath() + ctx.moveTo(xStart, y) // 선 시작점 + ctx.lineTo(xEnd, y) // 선 끝점 + ctx.stroke() + } + } + } else { + for (let row = 0; row <= rows; row++) { + const y = row * patternSize.height + + ctx.beginPath() + ctx.moveTo(0, y) // 선 시작점 + ctx.lineTo(patternSourceCanvas.width, y) // 선 끝점 + ctx.stroke() + + for (let col = 0; col <= cols; col++) { + const x = col * patternSize.width + (row % 2 === 0 ? 0 : offset) + const yStart = row * patternSize.height + const yEnd = yStart + patternSize.height + + ctx.beginPath() + ctx.moveTo(x, yStart) // 선 시작점 + ctx.lineTo(x, yEnd) // 선 끝점 + ctx.stroke() + } } } diff --git a/yarn.lock b/yarn.lock index 1472f5ac..c8c53b57 100644 --- a/yarn.lock +++ b/yarn.lock @@ -273,7 +273,7 @@ resolved "https://registry.npmjs.org/@bedrock-layout/use-stateful-ref/-/use-stateful-ref-1.4.1.tgz" integrity sha512-4eKO2KdQEXcR5LI4QcxqlJykJUDQJWDeWYAukIn6sRQYoabcfI5kDl61PUi6FR6o8VFgQ8IEP7HleKqWlSe8SQ== -"@emotion/babel-plugin@^11.11.0", "@emotion/babel-plugin@^11.12.0": +"@emotion/babel-plugin@^11.12.0": version "11.12.0" resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz#7b43debb250c313101b3f885eba634f1d723fcc2" integrity sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw== @@ -290,7 +290,7 @@ source-map "^0.5.7" stylis "4.2.0" -"@emotion/cache@^11.11.0", "@emotion/cache@^11.13.0", "@emotion/cache@^11.4.0": +"@emotion/cache@^11.13.0", "@emotion/cache@^11.4.0": version "11.13.1" resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.1.tgz#fecfc54d51810beebf05bf2a161271a1a91895d7" integrity sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw== @@ -306,32 +306,11 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b" integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g== -"@emotion/is-prop-valid@^1.2.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz#8d5cf1132f836d7adbe42cf0b49df7816fc88240" - integrity sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw== - dependencies: - "@emotion/memoize" "^0.9.0" - "@emotion/memoize@^0.9.0": version "0.9.0" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102" integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ== -"@emotion/react@11.11.0": - version "11.11.0" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.0.tgz#408196b7ef8729d8ad08fc061b03b046d1460e02" - integrity sha512-ZSK3ZJsNkwfjT3JpDAWJZlrGD81Z3ytNDsxw1LKq1o+xkmO5pnWfr6gmCC8gHEFf3nSSX/09YrG67jybNPxSUw== - dependencies: - "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.11.0" - "@emotion/cache" "^11.11.0" - "@emotion/serialize" "^1.1.2" - "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" - "@emotion/utils" "^1.2.1" - "@emotion/weak-memoize" "^0.3.1" - hoist-non-react-statics "^3.3.1" - "@emotion/react@^11.8.1": version "11.13.3" resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.13.3.tgz#a69d0de2a23f5b48e0acf210416638010e4bd2e4" @@ -346,7 +325,7 @@ "@emotion/weak-memoize" "^0.4.0" hoist-non-react-statics "^3.3.1" -"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.1": +"@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.1": version "1.3.2" resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.2.tgz#e1c1a2e90708d5d85d81ccaee2dfeb3cc0cccf7a" integrity sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA== @@ -362,38 +341,21 @@ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c" integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg== -"@emotion/styled@11.11.0": - version "11.11.0" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.0.tgz#26b75e1b5a1b7a629d7c0a8b708fbf5a9cdce346" - integrity sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng== - dependencies: - "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.11.0" - "@emotion/is-prop-valid" "^1.2.1" - "@emotion/serialize" "^1.1.2" - "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" - "@emotion/utils" "^1.2.1" - "@emotion/unitless@^0.10.0": version "0.10.0" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.10.0.tgz#2af2f7c7e5150f497bdabd848ce7b218a27cf745" integrity sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg== -"@emotion/use-insertion-effect-with-fallbacks@^1.0.1", "@emotion/use-insertion-effect-with-fallbacks@^1.1.0": +"@emotion/use-insertion-effect-with-fallbacks@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz#1a818a0b2c481efba0cf34e5ab1e0cb2dcb9dfaf" integrity sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw== -"@emotion/utils@^1.2.1", "@emotion/utils@^1.4.0", "@emotion/utils@^1.4.1": +"@emotion/utils@^1.4.0", "@emotion/utils@^1.4.1": version "1.4.1" resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.1.tgz#b3adbb43de12ee2149541c4f1337d2eb7774f0ad" integrity sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA== -"@emotion/weak-memoize@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" - integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== - "@emotion/weak-memoize@^0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6" @@ -5955,14 +5917,6 @@ react-draggable@^4.4.6: clsx "^1.1.1" prop-types "^15.8.1" -react-dropdown-select@^4.11.3: - version "4.11.3" - resolved "https://registry.yarnpkg.com/react-dropdown-select/-/react-dropdown-select-4.11.3.tgz#b23b8906f3bedc9d6a1a2125af936b34d4057158" - integrity sha512-/mOGSqqhmKsxxrmotLM+qn1Ss3nxGN6QnYusyQ7f0wizsWrc7ZmbcZhGRtwkJwpL6JYDQVTn19EYxJU1XfXrDA== - dependencies: - "@emotion/react" "11.11.0" - "@emotion/styled" "11.11.0" - react-hook-form@^7.53.0: version "7.53.0" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.53.0.tgz#3cf70951bf41fa95207b34486203ebefbd3a05ab"