popupManager 개발 중

This commit is contained in:
minsik 2024-10-18 13:36:32 +09:00
parent 07e11f3148
commit 15af4655a3
22 changed files with 784 additions and 107 deletions

View File

@ -15,6 +15,7 @@ import './globals.css'
import '../styles/style.scss' import '../styles/style.scss'
import '../styles/contents.scss' import '../styles/contents.scss'
import Dimmed from '@/components/ui/Dimmed' import Dimmed from '@/components/ui/Dimmed'
import PopupManager from '@/components/common/popupManager/PopupManager'
// const inter = Inter({ subsets: ['latin'] }) // const inter = Inter({ subsets: ['latin'] })
@ -81,6 +82,7 @@ export default async function RootLayout({ children }) {
)} )}
<ToastContainer /> <ToastContainer />
<QModal /> <QModal />
<PopupManager />
</body> </body>
</html> </html>
</RecoilRootWrapper> </RecoilRootWrapper>

View File

@ -39,7 +39,7 @@ import QEmptyContextMenu from '@/components/common/context-menu/QEmptyContextMen
import InitSettingsModal from './InitSettingsModal' import InitSettingsModal from './InitSettingsModal'
import GridSettingsModal from './GridSettingsModal' import GridSettingsModal from './GridSettingsModal'
import { SurfaceShapeModal } from '@/components/ui/SurfaceShape' import { SurfaceShapeModal } from '@/components/ui/SurfaceShape'
import { changeAllHipAndGableRoof, drawDirectionStringToArrow } from '@/util/qpolygon-utils' import { drawDirectionStringToArrow } from '@/util/qpolygon-utils'
import ThumbnailList from '@/components/ui/ThumbnailLIst' import ThumbnailList from '@/components/ui/ThumbnailLIst'
import ObjectPlacement from '@/components/ui/ObjectPlacement' import ObjectPlacement from '@/components/ui/ObjectPlacement'
import { globalLocaleStore } from '@/store/localeAtom' import { globalLocaleStore } from '@/store/localeAtom'

View File

@ -1,11 +1,30 @@
import { HexColorPicker } from 'react-colorful' import { HexColorPicker } from 'react-colorful'
import { useMessage } from '@/hooks/useMessage'
export default function ColorPicker(props) { export default function ColorPicker(props) {
const { color, setColor } = props const { color, setColor } = props
const { getMessage } = useMessage()
const defaultColors = ['#EA575D', '#F29955', '#F2C957', '#32975D', '#3D7FED', '#828282', '#ffffff', '#000000']
return ( return (
<> <>
<HexColorPicker color={color} onChange={setColor} /> <div>
<HexColorPicker color={color} onChange={setColor} />
</div>
<div className="hex-color-box">
<div className="color-box-tit">HEX</div>
<div className="color-hex-input">
<input type="text" className="input-origin" value={color} onChange={(e) => setColor(e.target.value)} />
</div>
<div className="color-box" style={{ backgroundColor: color }}></div>
</div>
<div className="default-color-wrap">
<div className="default-tit">{getMessage('modal.color.picker.default.color')}</div>
<div className="color-button-wrap">
{defaultColors.map((color, index) => (
<button key={index} className="default-color" style={{ backgroundColor: color }} onClick={() => setColor(color)}></button>
))}
</div>
</div>
</> </>
) )
} }

View File

@ -0,0 +1,44 @@
import WithDraggable from '@/components/common/draggable/WithDraggable'
import ColorPicker from '@/components/common/color-picker/ColorPicker'
import { useMessage } from '@/hooks/useMessage'
import { useEffect, useState } from 'react'
export default function ColorPickerModal(props) {
const { isShow, setIsShow, pos = { x: 800, y: -950 }, color = '#ff0000', setColor } = props
const { getMessage } = useMessage()
const [originColor, setOriginColor] = useState(color)
useEffect(() => {
setOriginColor(color)
}, [isShow])
return (
<WithDraggable isShow={isShow} pos={pos}>
<div className={`modal-pop-wrap lr`}>
<div className="modal-head">
<h1 className="title">{getMessage('modal.color.picker.title')}</h1>
<button className="modal-close" onClick={() => setIsShow(false)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="color-setting-wrap">
<div className="color-tit">COLOR PICKER</div>
<div className="color-picker">
<ColorPicker color={originColor} setColor={setOriginColor} />
</div>
</div>
<div className="grid-btn-wrap">
<button
className="btn-frame modal act"
onClick={() => {
setColor(originColor)
setIsShow(false)
}}
>
{getMessage('common.message.save')}
</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -0,0 +1,69 @@
import WithDraggable from '@/components/common/draggable/withDraggable'
import QSelectBox from '@/components/common/select/QSelectBox'
const SelectOption = [{ name: '原寸' }, { name: '原寸' }, { name: '原寸' }, { name: '原寸' }]
export default function FontSetting(props) {
const { setShowFontSettingModal } = props
console.log(
Array.from({ length: 10 }).map((_, index) => {
return { name: 5 + index }
}),
)
return (
<WithDraggable isShow={true} pos={{ x: 800, y: -950 }}>
<div className={`modal-pop-wrap r`}>
<div className="modal-head">
<h1 className="title">フォント </h1>
<button className="modal-close" onClick={() => setShowFontSettingModal(false)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="slope-wrap">
<div className="font-option-warp">
<div className="font-option-item">
<div className="option-item-tit">文字(F)</div>
<div className="grid-select">
<QSelectBox title={'MS PGothic'} option={SelectOption} />
</div>
</div>
<div className="font-option-item">
<div className="option-item-tit">フォントスタイル(Y)</div>
<div className="grid-select">
<QSelectBox title={'いつもの'} option={SelectOption} />
</div>
</div>
<div className="font-option-item">
<div className="option-item-tit">サイズ(S)</div>
<div className="grid-select">
<QSelectBox
title={'8'}
options={Array.from({ length: 9 }).map((_, index) => {
return { id: index, name: 8 * (index + 1) }
})}
/>
</div>
</div>
<div className="font-option-item">
<div className="option-item-tit">フォン</div>
<div className="grid-select">
<QSelectBox title={'黒'} option={SelectOption} />
</div>
</div>
</div>
<div className="font-ex-wrap">
<div className="font-ex-tit">見る</div>
<div className="font-ex-box">
<span style={{ fontSize: '12px', fontWeight: '400', color: '#101010' }}>Aaあぁアァ</span>
</div>
</div>
<div className="normal-font">ントですプリンタと画面 でも同じフォントを使用します.</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">ストレージ</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -0,0 +1,8 @@
'use client'
import { useRecoilState } from 'recoil'
import { popupState } from '@/store/popupAtom'
export default function PopupManager() {
const [popup, setPopup] = useRecoilState(popupState)
return <>{popup.children?.map((child) => child.component)}</>
}

View File

@ -8,11 +8,18 @@ import QContextMenu from '@/components/common/context-menu/QContextMenu'
import { useContextMenu } from '@/hooks/useContextMenu' import { useContextMenu } from '@/hooks/useContextMenu'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { currentObjectState } from '@/store/canvasAtom' import { currentObjectState } from '@/store/canvasAtom'
import { useCanvasEvent } from '@/hooks/useCanvasEvent'
export default function CanvasFrame({ plan }) { export default function CanvasFrame({ plan }) {
const canvasRef = useRef(null) const canvasRef = useRef(null)
const { canvas } = useCanvas('canvas') const { canvas } = useCanvas('canvas')
const { contextMenu, currentContextMenu, setCurrentContextMenu } = useContextMenu() const { handleZoomClear } = useCanvasEvent()
const { contextMenu, currentContextMenu, setCurrentContextMenu } = useContextMenu({
externalFn: {
handleZoomClear,
},
})
const currentObject = useRecoilValue(currentObjectState) const currentObject = useRecoilValue(currentObjectState)
useEffect(() => { useEffect(() => {
@ -44,7 +51,17 @@ export default function CanvasFrame({ plan }) {
{contextMenu.map((menus, index) => ( {contextMenu.map((menus, index) => (
<ul key={index}> <ul key={index}>
{menus.map((menu) => ( {menus.map((menu) => (
<li onClick={(e) => setCurrentContextMenu(menu)}>{menu.name}</li> <li
key={menu.id}
onClick={(e) => {
if (menu.fn) {
menu.fn()
}
setCurrentContextMenu(menu)
}}
>
{menu.name}
</li>
))} ))}
</ul> </ul>
))} ))}

View File

@ -19,6 +19,10 @@ import { MENU } from '@/common/common'
import KO from '@/locales/ko.json' import KO from '@/locales/ko.json'
import JA from '@/locales/ja.json' import JA from '@/locales/ja.json'
import { settingModalFirstOptionsState } from '@/store/settingAtom' import { settingModalFirstOptionsState } from '@/store/settingAtom'
import { useCanvasEvent } from '@/hooks/useCanvasEvent'
import { popupState } from '@/store/popupAtom'
import SettingModal01 from '@/components/floor-plan/modal/setting01/SettingModal01'
import { usePopup } from '@/hooks/usePopup'
const canvasMenus = [ const canvasMenus = [
{ index: 0, name: 'plan.menu.plan.drawing', icon: 'con00', title: MENU.PLAN_DRAWING }, { index: 0, name: 'plan.menu.plan.drawing', icon: 'con00', title: MENU.PLAN_DRAWING },
@ -52,6 +56,7 @@ export default function CanvasMenu(props) {
setShowPropertiesSettingModal, setShowPropertiesSettingModal,
} = props } = props
const { addPopup, closePopup } = usePopup()
const [menuNumber, setMenuNumber] = useState(null) const [menuNumber, setMenuNumber] = useState(null)
const [type, setType] = useState('') const [type, setType] = useState('')
@ -61,6 +66,7 @@ export default function CanvasMenu(props) {
const setPoints = useSetRecoilState(outerLinePointsState) const setPoints = useSetRecoilState(outerLinePointsState)
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
const { handleZoomClear } = useCanvasEvent()
const globalLocale = useRecoilValue(globalLocaleStore) const globalLocale = useRecoilValue(globalLocaleStore)
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
@ -69,7 +75,7 @@ export default function CanvasMenu(props) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { saveCanvas } = usePlan() const { saveCanvas } = usePlan()
const { swalFire } = useSwal() const { swalFire } = useSwal()
const [popup, setPopup] = useRecoilState(popupState)
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }] const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
const onClickNav = (menu) => { const onClickNav = (menu) => {
setMenuNumber(menu.index) setMenuNumber(menu.index)
@ -143,13 +149,13 @@ export default function CanvasMenu(props) {
setPoints([]) setPoints([])
canvas?.clear() canvas?.clear()
} }
//
const handleZoomClear = () => { // const handleZoomClear = () => {
setCanvasZoom(100) // setCanvasZoom(100)
canvas.set({ zoom: 1 }) // canvas.set({ zoom: 1 })
canvas.viewportTransform = [1, 0, 0, 1, 0, 0] // canvas.viewportTransform = [1, 0, 0, 1, 0, 0]
canvas.renderAll() // canvas.renderAll()
} // }
useEffect(() => { useEffect(() => {
if (globalLocale === 'ko') { if (globalLocale === 'ko') {
@ -196,7 +202,8 @@ export default function CanvasMenu(props) {
<QSelectBox title={'瓦53A'} option={SelectOption} /> <QSelectBox title={'瓦53A'} option={SelectOption} />
</div> </div>
<div className="btn-from"> <div className="btn-from">
<button className="btn04" onClick={() => setShowCanvasSettingModal(true)}></button> {/*<button className="btn04" onClick={() => setShowCanvasSettingModal(true)}></button>*/}
<button className="btn04" onClick={() => addPopup(<SettingModal01 />)}></button>
<button className="btn05"></button> <button className="btn05"></button>
<button className="btn06"></button> <button className="btn06"></button>
</div> </div>

View File

@ -1,19 +1,17 @@
'use client' 'use client'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { globalLocaleStore } from '@/store/localeAtom' import { globalLocaleStore } from '@/store/localeAtom'
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom' import { settingModalFirstOptionsState, settingModalGridOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
import '@/styles/contents.scss' import '@/styles/contents.scss'
import CanvasMenu from '@/components/floor-plan/CanvasMenu' import CanvasMenu from '@/components/floor-plan/CanvasMenu'
import SettingModal01 from '@/components/floor-plan/modal/setting01/SettingModal01'
import CanvasLayout from '@/components/floor-plan/CanvasLayout' import CanvasLayout from '@/components/floor-plan/CanvasLayout'
import DotLineGrid from '@/components/floor-plan/modal/grid/DotLineGrid' import DotLineGrid from '@/components/floor-plan/modal/grid/DotLineGrid'
import WallLineSetting from '@/components/floor-plan/modal/outerlinesetting/WallLineSetting' import WallLineSetting from '@/components/floor-plan/modal/outerlinesetting/WallLineSetting'
import PropertiesSetting from '@/components/floor-plan/modal/outerlinesetting/PropertiesSetting' import PropertiesSetting from '@/components/floor-plan/modal/outerlinesetting/PropertiesSetting'
import PlacementShapeSetting from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting' import PlacementShapeSetting from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
import GridColorSetting from './modal/grid/GridColorSetting'
import RoofShapeSetting from '@/components/floor-plan/modal/roofShape/RoofShapeSetting' import RoofShapeSetting from '@/components/floor-plan/modal/roofShape/RoofShapeSetting'
import PlacementShapeDrawing from '@/components/floor-plan/modal/placementShape/PlacementShapeDrawing' import PlacementShapeDrawing from '@/components/floor-plan/modal/placementShape/PlacementShapeDrawing'
import Slope from '@/components/floor-plan/modal/Slope' import Slope from '@/components/floor-plan/modal/Slope'
@ -28,6 +26,8 @@ import MovementSetting from '@/components/floor-plan/modal/movement/MovementSett
import RoofAllocationSetting from '@/components/floor-plan/modal/roofAllocation/RoofAllocationSetting' import RoofAllocationSetting from '@/components/floor-plan/modal/roofAllocation/RoofAllocationSetting'
import BasicSetting from '@/components/floor-plan/modal/basic/BasicSetting' import BasicSetting from '@/components/floor-plan/modal/basic/BasicSetting'
import CircuitTrestleSetting from '@/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting' import CircuitTrestleSetting from '@/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting'
import FontSetting from '@/components/common/font/FontSetting'
import { gridColorState } from '@/store/gridAtom'
export default function FloorPlan() { export default function FloorPlan() {
const [showCanvasSettingModal, setShowCanvasSettingModal] = useState(false) const [showCanvasSettingModal, setShowCanvasSettingModal] = useState(false)
@ -58,10 +58,15 @@ export default function FloorPlan() {
const [showGridCopyModal, setShowGridCopyModal] = useState(false) const [showGridCopyModal, setShowGridCopyModal] = useState(false)
const [showGridMoveModal, setShowGridMoveModal] = useState(false) const [showGridMoveModal, setShowGridMoveModal] = useState(false)
const [showColorPickerModal, setShowColorPickerModal] = useState(false) const [showColorPickerModal, setShowColorPickerModal] = useState(false)
const [color, setColor] = useRecoilState(gridColorState)
const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState)
const [showFontSettingModal, setShowFontSettingModal] = useState(false)
const canvasSettingProps = { const canvasSettingProps = {
setShowCanvasSettingModal, setShowCanvasSettingModal,
setShowDotLineGridModal, setShowDotLineGridModal,
setShowColorPickerModal, setShowColorPickerModal,
setShowFontSettingModal,
} }
const outlineProps = { const outlineProps = {
@ -127,6 +132,9 @@ export default function FloorPlan() {
const gridColorProps = { const gridColorProps = {
setShowColorPickerModal, setShowColorPickerModal,
color,
setColor,
setSettingModalGridOptions,
} }
const propertiesSettingProps = { const propertiesSettingProps = {
@ -141,12 +149,13 @@ export default function FloorPlan() {
<CanvasMenu {...modalProps} /> <CanvasMenu {...modalProps} />
<div className="canvas-content"> <div className="canvas-content">
<CanvasLayout /> <CanvasLayout />
{showCanvasSettingModal && <SettingModal01 {...canvasSettingProps} />} {/*{showCanvasSettingModal && <SettingModal01 {...canvasSettingProps} />}*/}
{showOutlineModal && <WallLineSetting {...outlineProps} />} {showOutlineModal && <WallLineSetting {...outlineProps} />}
{showDotLineGridModal && <DotLineGrid {...dotLineProps} />} {showDotLineGridModal && <DotLineGrid {...dotLineProps} />}
{showColorPickerModal && <GridColorSetting {...gridColorProps} />} {/*{showColorPickerModal && <GridColorSetting {...gridColorProps} />}*/}
{showFontSettingModal && <FontSetting setShowFontSettingModal={setShowFontSettingModal} />}
{showPropertiesSettingModal && <PropertiesSetting {...propertiesSettingProps} />} {showPropertiesSettingModal && <PropertiesSetting {...propertiesSettingProps} />}
{/*<DimensionLineSetting setShowFontSettingModal={setShowFontSettingModal} setShowColorPickerModal={setShowColorPickerModal} />*/}
{showPlaceShapeModal && <PlacementShapeSetting setShowPlaceShapeModal={setShowPlaceShapeModal} />} {showPlaceShapeModal && <PlacementShapeSetting setShowPlaceShapeModal={setShowPlaceShapeModal} />}
{showRoofShapeSettingModal && <RoofShapeSetting setShowRoofShapeSettingModal={setShowRoofShapeSettingModal} />} {showRoofShapeSettingModal && <RoofShapeSetting setShowRoofShapeSettingModal={setShowRoofShapeSettingModal} />}
{showRoofShapePassivitySettingModal && ( {showRoofShapePassivitySettingModal && (

View File

@ -1,4 +1,3 @@
import { useState } from 'react'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable' import WithDraggable from '@/components/common/draggable/WithDraggable'
import RightAngle from '@/components/floor-plan/modal/lineTypes/RightAngle' import RightAngle from '@/components/floor-plan/modal/lineTypes/RightAngle'
@ -6,7 +5,6 @@ import DoublePitch from '@/components/floor-plan/modal/lineTypes/DoublePitch'
import Angle from '@/components/floor-plan/modal/lineTypes/Angle' import Angle from '@/components/floor-plan/modal/lineTypes/Angle'
import Diagonal from '@/components/floor-plan/modal/lineTypes/Diagonal' import Diagonal from '@/components/floor-plan/modal/lineTypes/Diagonal'
import { OUTER_LINE_TYPE } from '@/store/outerLineAtom' import { OUTER_LINE_TYPE } from '@/store/outerLineAtom'
import { useOuterLineWall } from '@/hooks/roofcover/useOuterLineWall'
import OuterLineWall from '@/components/floor-plan/modal/lineTypes/OuterLineWall' import OuterLineWall from '@/components/floor-plan/modal/lineTypes/OuterLineWall'
import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing' import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing'
@ -152,7 +150,7 @@ export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) {
{getMessage('modal.cover.outline.rollback')} {getMessage('modal.cover.outline.rollback')}
</button> </button>
<button className="btn-frame modal act" onClick={() => handleFix(setShowAuxiliaryModal)}> <button className="btn-frame modal act" onClick={() => handleFix(setShowAuxiliaryModal)}>
{getMessage('modal.cover.outline.fix')} {getMessage('apply')}
</button> </button>
</div> </div>
</div> </div>

View File

@ -1,39 +0,0 @@
import WithDraggable from '@/components/common/draggable/WithDraggable'
import ColorPicker from '@/components/common/color-picker/ColorPicker'
import { useRecoilState, useSetRecoilState } from 'recoil'
import { gridColorState } from '@/store/gridAtom'
import { useMessage } from '@/hooks/useMessage'
import { useEffect } from 'react'
import { settingModalGridOptionsState } from '@/store/settingAtom'
export default function GridColorSetting(props) {
const { setShowColorPickerModal } = props
const [color, setColor] = useRecoilState(gridColorState)
const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState)
const { getMessage } = useMessage()
useEffect(() => {
return () => {
setSettingModalGridOptions((prev) => {
const newSettingOptions = [...prev]
newSettingOptions[3].selected = false
return [...newSettingOptions]
})
}
}, [])
return (
<WithDraggable isShow={true} pos={{ x: 1300, y: -660 }}>
<div className={`modal-pop-wrap ssm mount`}>
<div className="modal-head">
<h1 className="title">{getMessage('modal.canvas.setting.grid.color.setting')}</h1>
<button className="modal-close" onClick={() => setShowColorPickerModal(false)}>
닫기
</button>
</div>
<div className="modal-body">
<ColorPicker color={color} setColor={setColor} />
</div>
</div>
</WithDraggable>
)
}

View File

@ -1,27 +1,45 @@
import React, { useEffect } from 'react' import React, { useEffect, useState } from 'react'
import { useRecoilState } from 'recoil' import { useRecoilState, useSetRecoilState } from 'recoil'
import { settingModalGridOptionsState } from '@/store/settingAtom' import { settingModalGridOptionsState } from '@/store/settingAtom'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { adsorptionPointAddModeState } from '@/store/canvasAtom' import { adsorptionPointAddModeState } from '@/store/canvasAtom'
import { useTempGrid } from '@/hooks/useTempGrid' import { useTempGrid } from '@/hooks/useTempGrid'
import { gridColorState } from '@/store/gridAtom' import { gridColorState } from '@/store/gridAtom'
import { useColor } from 'react-color-palette' import { useColor } from 'react-color-palette'
import ColorPickerModal from '@/components/common/color-picker/ColorPickerModal'
export default function GridOption(props) { export default function GridOption(props) {
const { setShowDotLineGridModal, setShowColorPickerModal } = props const { setShowDotLineGridModal } = props
const [gridOptions, setGridOptions] = useRecoilState(settingModalGridOptionsState) const [gridOptions, setGridOptions] = useRecoilState(settingModalGridOptionsState)
const [gridColor, setGridColor] = useRecoilState(gridColorState)
const [adsorptionPointAddMode, setAdsorptionPointAddMode] = useRecoilState(adsorptionPointAddModeState) const [adsorptionPointAddMode, setAdsorptionPointAddMode] = useRecoilState(adsorptionPointAddModeState)
const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { tempGridMode, setTempGridMode } = useTempGrid() const { tempGridMode, setTempGridMode } = useTempGrid()
const [gridColor, setGridColor] = useRecoilState(gridColorState)
const [color, setColor] = useColor(gridColor) const [color, setColor] = useColor(gridColor)
const [showColorPickerModal, setShowColorPickerModal] = useState(false)
useEffect(() => { useEffect(() => {
console.log('GridOption useEffect 실행') console.log('GridOption useEffect 실행')
console.log(color)
setGridColor(color.hex) setGridColor(color.hex)
}, [color]) }, [color])
useEffect(() => {
gridOptions[3].selected = showColorPickerModal
setGridOptions([...gridOptions])
}, [showColorPickerModal])
useEffect(() => {
return () => {
setSettingModalGridOptions((prev) => {
const newSettingOptions = [...prev]
newSettingOptions[3].selected = false
return [...newSettingOptions]
})
}
}, [])
const onClickOption = (option) => { const onClickOption = (option) => {
const newGridOptions = [...gridOptions] const newGridOptions = [...gridOptions]
newGridOptions.map((item) => { newGridOptions.map((item) => {
@ -54,6 +72,7 @@ export default function GridOption(props) {
if (option.id === 4) { if (option.id === 4) {
// //
console.log(option)
if (option.selected) { if (option.selected) {
setShowColorPickerModal(true) setShowColorPickerModal(true)
} else { } else {
@ -64,6 +83,17 @@ export default function GridOption(props) {
setGridOptions(newGridOptions) setGridOptions(newGridOptions)
} }
const colorPickerProps = {
color: gridColor,
setColor: setGridColor,
isShow: showColorPickerModal,
setIsShow: setShowColorPickerModal,
pos: {
x: -515,
y: -214,
},
}
return ( return (
<> <>
<div className="modal-check-btn-wrap"> <div className="modal-check-btn-wrap">
@ -77,6 +107,7 @@ export default function GridOption(props) {
))} ))}
</div> </div>
</div> </div>
<ColorPickerModal {...colorPickerProps} />
</> </>
) )
} }

View File

@ -5,8 +5,9 @@ import React, { useEffect, useState } from 'react'
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { adsorptionPointModeState, adsorptionRangeState } from '@/store/canvasAtom' import { adsorptionPointModeState, adsorptionRangeState } from '@/store/canvasAtom'
import DimensionLineSetting from '@/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting'
export default function SecondOption() { export default function SecondOption({ setShowFontSettingModal }) {
const [objectNo, setObjectNo] = useState('test123240912001') // const [objectNo, setObjectNo] = useState('test123240912001') //
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState) const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
@ -18,6 +19,15 @@ export default function SecondOption() {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { get, post } = useAxios() const { get, post } = useAxios()
const { swalFire } = useSwal() const { swalFire } = useSwal()
const [showDimensionLineSettingModal, setShowDimensionLineSettingModal] = useState(false)
const dimensionLineSettingProps = {
isShow: showDimensionLineSettingModal,
setIsShow: setShowDimensionLineSettingModal,
pos: {
x: -515,
y: -214,
},
}
// //
useEffect(() => { useEffect(() => {
@ -31,7 +41,10 @@ export default function SecondOption() {
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` }) const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] })) const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] }))
const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] })) const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] }))
const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item, selected: res[item.column] })) const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({
...item,
selected: res[item.column],
}))
const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item })) const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] })) const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
@ -51,7 +64,14 @@ export default function SecondOption() {
const onClickOption = async (option) => { const onClickOption = async (option) => {
// option4 // option4
const updatedOption4 = option4.map((item) => (item.id === option.id ? { ...item, selected: true } : { ...item, selected: false })) const updatedOption4 = option4.map((item) =>
item.id === option.id
? { ...item, selected: true }
: {
...item,
selected: false,
},
)
setSettingModalFirstOptions({ option1, option2, dimensionDisplay }) setSettingModalFirstOptions({ option1, option2, dimensionDisplay })
setSettingModalSecondOptions({ option3, option4: updatedOption4 }) setSettingModalSecondOptions({ option3, option4: updatedOption4 })
@ -117,6 +137,7 @@ export default function SecondOption() {
} }
setAdsorptionRange(option.range) setAdsorptionRange(option.range)
} }
return ( return (
<> <>
<div className="modal-check-btn-wrap"> <div className="modal-check-btn-wrap">
@ -124,7 +145,7 @@ export default function SecondOption() {
<div className="flex-check-box for2"> <div className="flex-check-box for2">
{settingModalSecondOptions && {settingModalSecondOptions &&
settingModalSecondOptions.option3.map((item) => ( settingModalSecondOptions.option3.map((item) => (
<button key={item.id} className="arr-btn"> <button key={item.id} className="arr-btn" onClick={() => setShowFontSettingModal(true)}>
<span>{getMessage(item.name)}</span> <span>{getMessage(item.name)}</span>
</button> </button>
))} ))}
@ -142,7 +163,7 @@ export default function SecondOption() {
))} ))}
</div> </div>
<div className="flex-check-box for-line"> <div className="flex-check-box for-line">
<button className="arr-btn"> <button className="arr-btn" onClick={() => setShowDimensionLineSettingModal(true)}>
<span>{getMessage('modal.canvas.setting.font.plan.absorption.dimension.line')}</span> <span>{getMessage('modal.canvas.setting.font.plan.absorption.dimension.line')}</span>
</button> </button>
<button className="arr-btn"> <button className="arr-btn">
@ -159,6 +180,7 @@ export default function SecondOption() {
</button> </button>
</div> </div>
</div> </div>
<DimensionLineSetting {...dimensionLineSettingProps} />
</> </>
) )
} }

View File

@ -10,7 +10,7 @@ import { canGridOptionSeletor } from '@/store/canvasAtom'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
export default function SettingModal01(props) { export default function SettingModal01(props) {
const { setShowCanvasSettingModal, setShowDotLineGridModal, setShowColorPickerModal } = props const { setShowCanvasSettingModal, setShowDotLineGridModal, setShowFontSettingModal } = props
const [buttonAct, setButtonAct] = useState(1) const [buttonAct, setButtonAct] = useState(1)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const canGridOptionSeletorValue = useRecoilValue(canGridOptionSeletor) const canGridOptionSeletorValue = useRecoilValue(canGridOptionSeletor)
@ -20,34 +20,36 @@ export default function SettingModal01(props) {
} }
return ( return (
<WithDraggable isShow={true} pos={{ x: 1300, y: -950 }}> <>
<div className={`modal-pop-wrap sm mount`}> <WithDraggable isShow={true} pos={{ x: 1300, y: -950 }}>
<div className="modal-head"> <div className={`modal-pop-wrap sm mount`}>
<h1 className="title">{getMessage('modal.canvas.setting')}</h1> <div className="modal-head">
<button className="modal-close" onClick={() => setShowCanvasSettingModal(false)}> <h1 className="title">{getMessage('modal.canvas.setting')}</h1>
닫기 <button className="modal-close" onClick={() => setShowCanvasSettingModal(false)}>
</button> 닫기
</div>
<div className="modal-body">
<div className="modal-btn-wrap">
<button className={`btn-frame modal ${buttonAct === 1 ? 'act' : ''}`} onClick={() => handleBtnClick(1)}>
{getMessage('modal.canvas.setting.display')}
</button> </button>
<button className={`btn-frame modal ${buttonAct === 2 ? 'act' : ''}`} onClick={() => handleBtnClick(2)}>
{getMessage('modal.canvas.setting.font.plan')}
</button>
{canGridOptionSeletorValue && (
<button className={`btn-frame modal ${buttonAct === 3 ? 'act' : ''}`} onClick={() => handleBtnClick(3)}>
{getMessage('modal.canvas.setting.grid')}
</button>
)}
</div> </div>
{buttonAct === 1 && <FirstOption />} <div className="modal-body">
{buttonAct === 2 && <SecondOption />} <div className="modal-btn-wrap">
{buttonAct === 3 && <GridOption setShowDotLineGridModal={setShowDotLineGridModal} setShowColorPickerModal={setShowColorPickerModal} />} <button className={`btn-frame modal ${buttonAct === 1 ? 'act' : ''}`} onClick={() => handleBtnClick(1)}>
{getMessage('modal.canvas.setting.display')}
</button>
<button className={`btn-frame modal ${buttonAct === 2 ? 'act' : ''}`} onClick={() => handleBtnClick(2)}>
{getMessage('modal.canvas.setting.font.plan')}
</button>
{canGridOptionSeletorValue && (
<button className={`btn-frame modal ${buttonAct === 3 ? 'act' : ''}`} onClick={() => handleBtnClick(3)}>
{getMessage('modal.canvas.setting.grid')}
</button>
)}
</div>
{buttonAct === 1 && <FirstOption />}
{buttonAct === 2 && <SecondOption setShowFontSettingModal={setShowFontSettingModal} />}
{buttonAct === 3 && <GridOption setShowDotLineGridModal={setShowDotLineGridModal} />}
</div>
</div> </div>
</div> </WithDraggable>
</WithDraggable> </>
) )
} }

View File

@ -0,0 +1,51 @@
import WithDraggable from '@/components/common/draggable/withDraggable'
export default function DimensionLineSetting(props) {
const { isShow, setIsShow, pos = { x: 800, y: -950 }, setShowFontSettingModal, setShowColorPickerModal } = props
return (
<WithDraggable isShow={isShow} pos={pos}>
<div className={`modal-pop-wrap xxxm`}>
<div className="modal-head">
<h1 className="title">寸法線 設定 </h1>
<button className="modal-close">닫기</button>
</div>
<div className="modal-body">
<div className="font-btn-wrap">
<button className="btn-frame modal" onClick={() => setShowFontSettingModal(true)}>
フォント設定
</button>
</div>
<div className="line-color-wrap">
<div className="outline-form mb10">
<span style={{ width: 'auto' }}>寸法線の線太さ</span>
<div className="input-grid mr5" style={{ width: '66px' }}>
<input type="text" className="input-origin block" defaultValue={1} />
</div>
<span className="thin">pixel</span>
</div>
<div className="outline-form">
<span style={{ width: 'auto' }}>寸法線の線の色</span>
<button className="color-btn" style={{ backgroundColor: '#ff0000' }} onClick={() => setShowColorPickerModal(true)}></button>
</div>
</div>
<div className="font-ex-wrap">
<div className="font-ex-tit">見る</div>
<div className="form-box">
<div className="line-form">
<div className="line-font-box">
<span className="font" style={{ fontSize: '12px', fontWeight: '400' }}>
9,999
</span>
<span className="line" style={{ backgroundColor: '#ff0000', borderColor: '#ff0000', height: '1px' }}></span>
</div>
</div>
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">ストレージ</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -1,15 +1,17 @@
import { useState } from 'react' import { useState } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasSizeState, currentObjectState, fontFamilyState, fontSizeState } from '@/store/canvasAtom' import { canvasSizeState, canvasState, canvasZoomState, currentObjectState, fontFamilyState, fontSizeState } from '@/store/canvasAtom'
import { QPolygon } from '@/components/fabric/QPolygon' import { QPolygon } from '@/components/fabric/QPolygon'
// 캔버스에 필요한 이벤트 // 캔버스에 필요한 이벤트
export function useCanvasEvent() { export function useCanvasEvent() {
const [canvas, setCanvasForEvent] = useState(null) const canvas = useRecoilValue(canvasState)
const [canvasForEvent, setCanvasForEvent] = useState(null)
const [currentObject, setCurrentObject] = useRecoilState(currentObjectState) const [currentObject, setCurrentObject] = useRecoilState(currentObjectState)
const canvasSize = useRecoilValue(canvasSizeState) const canvasSize = useRecoilValue(canvasSizeState)
const fontSize = useRecoilValue(fontSizeState) const fontSize = useRecoilValue(fontSizeState)
const fontFamily = useRecoilValue(fontFamilyState) const fontFamily = useRecoilValue(fontFamilyState)
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
// 기본적인 이벤트 필요시 추가 // 기본적인 이벤트 필요시 추가
const attachDefaultEventOnCanvas = () => { const attachDefaultEventOnCanvas = () => {
@ -167,7 +169,6 @@ export function useCanvasEvent() {
const whiteList = ['mouseLine', 'guideLine'] const whiteList = ['mouseLine', 'guideLine']
if (whiteList.includes(e.target.name)) { if (whiteList.includes(e.target.name)) {
return
} }
}, },
} }
@ -336,8 +337,16 @@ export function useCanvasEvent() {
}) })
} }
const handleZoomClear = () => {
setCanvasZoom(100)
canvas.set({ zoom: 1 })
canvas.viewportTransform = [1, 0, 0, 1, 0, 0]
canvas.renderAll()
}
return { return {
setCanvasForEvent, setCanvasForEvent,
attachDefaultEventOnCanvas, attachDefaultEventOnCanvas,
handleZoomClear,
} }
} }

View File

@ -1,16 +1,18 @@
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { currentMenuState } from '@/store/canvasAtom' import { currentMenuState, currentObjectState } from '@/store/canvasAtom'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { MENU } from '@/common/common' import { MENU } from '@/common/common'
import AuxiliaryMove from '@/components/floor-plan/modal/auxiliary/AuxiliaryMove' import AuxiliaryMove from '@/components/floor-plan/modal/auxiliary/AuxiliaryMove'
import AuxiliarySize from '@/components/floor-plan/modal/auxiliary/AuxiliarySize' import AuxiliarySize from '@/components/floor-plan/modal/auxiliary/AuxiliarySize'
export function useContextMenu() { export function useContextMenu({ externalFn }) {
const currentMenu = useRecoilValue(currentMenuState) const currentMenu = useRecoilValue(currentMenuState)
const [contextMenu, setContextMenu] = useState([[]]) const [contextMenu, setContextMenu] = useState([[]])
const [currentContextMenu, setCurrentContextMenu] = useState(null) const [currentContextMenu, setCurrentContextMenu] = useState(null)
const currentObject = useRecoilValue(currentObjectState)
useEffect(() => { const currentMenuSetting = () => {
console.log(currentMenu)
switch (currentMenu) { switch (currentMenu) {
case MENU.PLAN_DRAWING: case MENU.PLAN_DRAWING:
setContextMenu([ setContextMenu([
@ -50,6 +52,13 @@ export function useContextMenu() {
case MENU.ROOF_COVERING.DEFAULT: case MENU.ROOF_COVERING.DEFAULT:
setContextMenu([ setContextMenu([
[ [
{
id: 'refresh',
name: '새로고침',
fn: () => {
externalFn.handleZoomClear()
},
},
{ {
id: 'roofMaterialPlacement', id: 'roofMaterialPlacement',
name: '지붕재 배치', name: '지붕재 배치',
@ -150,8 +159,121 @@ export function useContextMenu() {
setContextMenu([]) setContextMenu([])
break break
} }
}
useEffect(() => {
currentMenuSetting()
}, [currentMenu]) }, [currentMenu])
useEffect(() => {
console.log('currentObject', currentObject)
console.log('currentMenu', currentMenu)
if (currentObject?.name) {
console.log(currentObject)
switch (currentObject.name) {
case 'triangleDormer':
setContextMenu([
[
{
id: 'sizeEdit',
name: '사이즈 변경',
},
{
id: 'dormerRemove',
name: '삭제(D)',
},
{
id: 'dormerMove',
name: '이동(M)',
},
{
id: 'dormerCopy',
name: '복사(C)',
},
{
id: 'roofMaterialEdit',
name: '지붕재 변경',
},
{
id: 'dormerOffset',
name: '도머 오프셋',
},
],
])
break
case 'roof':
setContextMenu([
[
{
id: 'sizeEdit',
name: '사이즈 변경',
},
{
id: 'roofMaterialRemove',
name: '삭제(D)',
},
{
id: 'roofMaterialMove',
name: '이동(M)',
},
{
id: 'roofMaterialCopy',
name: '복사(C)',
},
],
[
{
id: 'roofMaterialEdit',
name: '지붕재 변경',
},
{
id: 'linePropertyEdit',
name: '각 변 속성 변경',
},
{
id: 'flowDirectionEdit',
name: '흐름 뱡향 변경',
},
],
])
break
case 'opening':
setContextMenu([
[
{
id: 'sizeEdit',
name: '사이즈 변경',
},
{
id: 'openingRemove',
name: '삭제(D)',
},
{
id: 'openingMove',
name: '이동(M)',
},
{
id: 'openingCopy',
name: '복사(C)',
},
{
id: 'openingOffset',
name: '개구 오프셋',
},
],
])
break
default:
currentMenuSetting()
}
} else {
currentMenuSetting()
}
}, [currentObject])
useEffect(() => {
console.log(currentContextMenu)
}, [currentContextMenu])
return { return {
contextMenu, contextMenu,
currentContextMenu, currentContextMenu,

26
src/hooks/usePopup.js Normal file
View File

@ -0,0 +1,26 @@
import { useRecoilState } from 'recoil'
import { popupState } from '@/store/popupAtom'
import { v4 as uuidv4 } from 'uuid'
import { useEffect } from 'react'
export function usePopup() {
const [popup, setPopup] = useRecoilState(popupState)
useEffect(() => {
console.log(popup)
}, [popup])
const addPopup = (component) => {
setPopup({ children: [...popup.children, { id: uuidv4(), component: component }] })
}
const closePopup = (id) => {
setPopup({ children: popup.children.filter((child) => child.id !== id) })
}
return {
popup,
setPopup,
addPopup,
closePopup,
}
}

View File

@ -247,6 +247,8 @@
"modal.object.setting.direction.select": "方向の選択", "modal.object.setting.direction.select": "方向の選択",
"modal.placement.surface.setting.info": "ⓘ ①の長さ入力後に対角線の長さを入力すると、②の長さを自動計算します。", "modal.placement.surface.setting.info": "ⓘ ①の長さ入力後に対角線の長さを入力すると、②の長さを自動計算します。",
"modal.placement.surface.setting.diagonal.length": "斜めの長さ", "modal.placement.surface.setting.diagonal.length": "斜めの長さ",
"modal.color.picker.title": "色の設定",
"modal.color.picker.default.color": "基本色",
"setting": "設定", "setting": "設定",
"common.message.no.data": "No data", "common.message.no.data": "No data",
"common.message.no.dataDown": "ダウンロードするデータがありません", "common.message.no.dataDown": "ダウンロードするデータがありません",

View File

@ -252,6 +252,8 @@
"modal.object.setting.direction.select": "방향 선택", "modal.object.setting.direction.select": "방향 선택",
"modal.placement.surface.setting.info": "ⓘ ①의 길이 입력 후 대각선 길이를 입력하면 ②의 길이를 자동 계산합니다.", "modal.placement.surface.setting.info": "ⓘ ①의 길이 입력 후 대각선 길이를 입력하면 ②의 길이를 자동 계산합니다.",
"modal.placement.surface.setting.diagonal.length": "대각선 길이", "modal.placement.surface.setting.diagonal.length": "대각선 길이",
"modal.color.picker.title": "색 설정",
"modal.color.picker.default.color": "기본색상",
"setting": "설정", "setting": "설정",
"common.message.no.data": "No data", "common.message.no.data": "No data",
"common.message.no.dataDown": "No data to download", "common.message.no.dataDown": "No data to download",

13
src/store/popupAtom.js Normal file
View File

@ -0,0 +1,13 @@
import { atom } from 'recoil'
/*
* id: uuid
* component: Popup Component
* */
export const popupState = atom({
key: 'popupState',
default: {
children: [],
},
dangerouslyAllowMutability: true,
})

View File

@ -34,6 +34,9 @@ $alert-color: #101010;
border-radius: 4px; border-radius: 4px;
background-color: #272727; background-color: #272727;
z-index: 9999999; z-index: 9999999;
&.xsm{
width: 200px;
}
&.xxxm{ &.xxxm{
width: 240px; width: 240px;
} }
@ -1505,7 +1508,7 @@ $alert-color: #101010;
width: 16px; width: 16px;
height: 16px; height: 16px;
&.pink{ &.pink{
border: 2px solid #EA10AC; border: 2px solid #ce1c9c;
background-color: #16417D; background-color: #16417D;
} }
&.white{ &.white{
@ -1514,4 +1517,264 @@ $alert-color: #101010;
} }
} }
} }
}
// color setting
.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;
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{
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;
}
}
.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: 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-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{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100px;
height: 100px;
background-color: #fff;
}
}
.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;
}
span{
flex: none;
}
}
} }