Merge branch 'dev' into dev-yj
This commit is contained in:
commit
8bc69f73d0
1
docs/diagrams/canvas-setting.codediagram
Normal file
1
docs/diagrams/canvas-setting.codediagram
Normal file
File diff suppressed because one or more lines are too long
1
docs/diagrams/배치면초기설정.codediagram
Normal file
1
docs/diagrams/배치면초기설정.codediagram
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"id":-1,"name":"Onboarding diagram","userId":-1,"createdAt":"","updatedAt":"","content":{"items":[{"uid":"HduNR37Az-","position":{"x":690,"y":-270},"sizes":{"width":400,"height":168},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"type":"text","text":"배치면 초기설정 "},{"type":"text","marks":[{"type":"bold"}],"text":"☀️"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"플랜당 필수 설정"}]}]},{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"필수로 설정이 저장되어야 하기 때문에 닫기 버튼 없음"}]}]},{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"저장 버튼으로 update 처리"}]}]}]}]},"color":{"bgColor":"hsla(211, 33%, 22%, 1)","bgName":"blue"},"nodeType":"block"},{"uid":"eB4rr9xOVw","position":{"x":500,"y":-40},"sizes":{"width":810,"height":182.5},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"src/components/floor-plan/modal/placementShape/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"PlacementShapeSetting.jsx"}]},{"type":"paragraph","content":[{"type":"text","marks":[{"type":"bold"}],"text":"배치면 초기 설정 팝업"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, planNo, openPoint }) {"}]}]},"nodeType":"block"},{"uid":"dzN8hw1chO","position":{"x":990,"y":310},"sizes":{"width":550,"height":361},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"src/hooks/option/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"useCanvasSetting.js"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"/**\n * 기본설정(PlacementShapeSetting) 조회 및 초기화\n */\nconst fetchBasicSettings = async (planNo, openPoint) => {"}]},{"type":"paragraph"},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":false},"content":[{"type":"text","text":"/**\n * 기본설정(PlacementShapeSetting) 저장\n */\nconst basicSettingSave = async (params) => {"}]}]},"nodeType":"block"},{"uid":"YX7IHZIiqg","position":{"x":330,"y":310},"sizes":{"width":590,"height":259.5},"autoheight":true,"blockContent":{"content":[{"type":"filePathNode","attrs":{"pathToFile":"src/hooks/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"usePlan.js"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"/**\n * 플랜 삭제 시 배치면 초기설정 데이터 삭제\n *\n * @param {string} objectNo - 물건번호\n * @param {string} planNo - 플랜번호\n */\nconst deleteBasicSettings = async (objectNo, planNo) => {"}]}]},"nodeType":"block"}],"configs":{"centerX":47.05904869941878,"centerY":349.9825354968084,"zoomLevel":1.017264811197917},"arrowData":{"arrowsMap":{"arrow-point-bI0wBh3Ufk-bottom-point-PSPLIYKa9J-top":{"to":"point-PSPLIYKa9J-top","from":"point-bI0wBh3Ufk-bottom","label":"Normal Box","direction":"ft","selectable":true},"arrow-point-bI0wBh3Ufk-bottom-point-ytXK_ayIc1-top":{"to":"point-ytXK_ayIc1-top","from":"point-bI0wBh3Ufk-bottom","label":"Code Box","direction":"ft","selectable":true},"arrow-point-hyyRZE3E8u-right-point-6ZopTaEaDZ-left":{"to":"point-6ZopTaEaDZ-left","from":"point-hyyRZE3E8u-right","label":"call","direction":"ft","selectable":true}},"pointsMap":{"point-PSPLIYKa9J-top":{"x":805.9999797489683,"y":60,"id":"point-PSPLIYKa9J-top","direction":"top"},"point-ytXK_ayIc1-top":{"x":205.99999493724206,"y":60,"id":"point-ytXK_ayIc1-top","direction":"top"},"point-6ZopTaEaDZ-left":{"x":220,"y":605.9999898744841,"id":"point-6ZopTaEaDZ-left","direction":"left"},"point-hyyRZE3E8u-right":{"x":100,"y":606,"id":"point-hyyRZE3E8u-right","direction":"right"},"point-bI0wBh3Ufk-bottom":{"x":515.9999797489683,"y":-40,"id":"point-bI0wBh3Ufk-bottom","direction":"bottom"}},"edgesMap":{"edge-eB4rr9xOVw-eB4rr9xOVw-bottom-YX7IHZIiqg-YX7IHZIiqg-top":{"uid":"edge-eB4rr9xOVw-eB4rr9xOVw-bottom-YX7IHZIiqg-YX7IHZIiqg-top","fromNodeId":"eB4rr9xOVw","fromHandleId":"eB4rr9xOVw-bottom","toNodeId":"YX7IHZIiqg","toHandleId":"YX7IHZIiqg-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-eB4rr9xOVw-eB4rr9xOVw-bottom-dzN8hw1chO-dzN8hw1chO-top":{"uid":"edge-eB4rr9xOVw-eB4rr9xOVw-bottom-dzN8hw1chO-dzN8hw1chO-top","fromNodeId":"eB4rr9xOVw","fromHandleId":"eB4rr9xOVw-bottom","toNodeId":"dzN8hw1chO","toHandleId":"dzN8hw1chO-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}}}}}}
|
||||||
@ -1,22 +0,0 @@
|
|||||||
'use server'
|
|
||||||
|
|
||||||
import fs from 'fs/promises'
|
|
||||||
|
|
||||||
import { NextResponse } from 'next/server'
|
|
||||||
import { writeImage, writeImageBuffer } from '@/lib/fileAction'
|
|
||||||
|
|
||||||
export async function GET(req) {
|
|
||||||
const path = 'public/plan-map-images'
|
|
||||||
const q = req.nextUrl.searchParams.get('q')
|
|
||||||
const fileNm = req.nextUrl.searchParams.get('fileNm')
|
|
||||||
const zoom = req.nextUrl.searchParams.get('zoom')
|
|
||||||
const targetUrl = `https://maps.googleapis.com/maps/api/staticmap?center=${q}&zoom=${zoom}&maptype=satellite&size=640x640&scale=1&key=AIzaSyDO7nVR1N_D2tKy60hgGFavpLaXkHpiHpc`
|
|
||||||
const decodeUrl = decodeURIComponent(targetUrl)
|
|
||||||
|
|
||||||
const response = await fetch(decodeUrl)
|
|
||||||
const data = await response.arrayBuffer()
|
|
||||||
const buffer = Buffer.from(data)
|
|
||||||
await writeImage(fileNm, buffer)
|
|
||||||
|
|
||||||
return NextResponse.json({ fileNm: `${fileNm}.png` })
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
'use server'
|
|
||||||
|
|
||||||
import { NextResponse } from 'next/server'
|
|
||||||
import { writeImage } from '@/lib/fileAction'
|
|
||||||
|
|
||||||
export async function POST(req) {
|
|
||||||
const formData = await req.formData()
|
|
||||||
const file = formData.get('file')
|
|
||||||
const fileName = formData.get('fileName')
|
|
||||||
const arrayBuffer = await file.arrayBuffer()
|
|
||||||
const buffer = Buffer.from(arrayBuffer)
|
|
||||||
await writeImage(fileName, buffer)
|
|
||||||
|
|
||||||
return NextResponse.json({ fileNm: `${fileName}.png` })
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
import { NextResponse } from 'next/server'
|
|
||||||
|
|
||||||
const defaultData = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'John Doe',
|
|
||||||
email: 'john.doe@example.com',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'Jane Lee',
|
|
||||||
email: 'jane.lee@example.com',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export async function GET(req, res) {
|
|
||||||
return NextResponse.json(defaultData)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const POST = async (req, res) => {
|
|
||||||
const { id, name, email } = await req.json()
|
|
||||||
const newData = { id, name, email }
|
|
||||||
console.log('🚀 ~ POST ~ newData:', newData)
|
|
||||||
return NextResponse.json([...defaultData, newData])
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
import Playground from '@/components/Playground'
|
|
||||||
|
|
||||||
export default async function PlaygroundPage() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Playground />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
import Hero from '@/components/Hero'
|
|
||||||
import Roof from '@/components/Roof'
|
|
||||||
|
|
||||||
export default async function RoofPage() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Hero title="Drawing on canvas 2D Roof" />
|
|
||||||
<div className="flex flex-col justify-center my-8">
|
|
||||||
<Roof />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import Roof2 from '@/components/Roof2'
|
|
||||||
|
|
||||||
export default async function Roof2Page() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="flex flex-col justify-center my-8 pt-20">
|
|
||||||
<Roof2 />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
import Hero from '@/components/Hero'
|
|
||||||
import Settings from '@/components/Settings'
|
|
||||||
|
|
||||||
export default async function SettingsPage() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Hero title="Canvas Setting" />
|
|
||||||
<div className="flex flex-col justify-center my-8">
|
|
||||||
<Settings />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,273 +0,0 @@
|
|||||||
import { useEffect, useRef, useState } from 'react'
|
|
||||||
import { Button, Checkbox, CheckboxGroup, RadioGroup, Radio, Input } from '@nextui-org/react'
|
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
|
||||||
import { modalContent, modalState } from '@/store/modalAtom'
|
|
||||||
import { guideLineState, horiGuideLinesState, vertGuideLinesState } from '@/store/canvasAtom'
|
|
||||||
import { fabric } from 'fabric'
|
|
||||||
import { ColorPicker, useColor } from 'react-color-palette'
|
|
||||||
import 'react-color-palette/css'
|
|
||||||
import { gridColorState } from '@/store/gridAtom'
|
|
||||||
|
|
||||||
export default function GridSettingsModal(props) {
|
|
||||||
const { canvasProps } = props
|
|
||||||
const [isCustomGridSetting, setIsCustomGridSetting] = useState(true)
|
|
||||||
const [gridCheckedValue, setGridCheckValue] = useState([])
|
|
||||||
const [ratioValue, setRatioValue] = useState('1')
|
|
||||||
const moduleLength = useRef(null) //모듈 mm 길이 입력
|
|
||||||
const customModuleHoriLength = useRef(null)
|
|
||||||
const customModuleVertLength = useRef(null)
|
|
||||||
|
|
||||||
const [open, setOpen] = useRecoilState(modalState)
|
|
||||||
const [guideLine, setGuideLine] = useRecoilState(guideLineState)
|
|
||||||
const [horiGuideLines, setHoriGuideLines] = useRecoilState(horiGuideLinesState)
|
|
||||||
const [vertGuideLines, setVertGuideLines] = useRecoilState(vertGuideLinesState)
|
|
||||||
|
|
||||||
const gridSettingArray = []
|
|
||||||
|
|
||||||
const gridColor = useRecoilValue(gridColorState)
|
|
||||||
const [colorPickerShow, setColorPickerShow] = useState(false)
|
|
||||||
|
|
||||||
const boxStyle = {
|
|
||||||
width: '50px',
|
|
||||||
height: '30px',
|
|
||||||
border: '1px solid black',
|
|
||||||
backgroundColor: guideColor.hex,
|
|
||||||
}
|
|
||||||
useEffect(() => {
|
|
||||||
moduleLength.current.value = 90
|
|
||||||
customModuleHoriLength.current.value = 90
|
|
||||||
customModuleVertLength.current.value = 90
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setIsCustomGridSetting(ratioValue !== 'custom')
|
|
||||||
}, [ratioValue])
|
|
||||||
|
|
||||||
const drawGridSettings = () => {
|
|
||||||
//기존에 선택된 데이터가 있으면 그 데이터를 포함한다
|
|
||||||
if (!(Object.keys(guideLine).length === 0 && guideLine.constructor === Object)) {
|
|
||||||
gridSettingArray.push(...guideLine)
|
|
||||||
}
|
|
||||||
|
|
||||||
let moduleHoriLength = moduleLength.current.value //가로 간격
|
|
||||||
let moduleVertLength = moduleLength.current.value //새로 간격
|
|
||||||
|
|
||||||
if (ratioValue === 'custom') {
|
|
||||||
moduleHoriLength = customModuleHoriLength.current.value
|
|
||||||
moduleVertLength = customModuleVertLength.current.value
|
|
||||||
} else {
|
|
||||||
moduleHoriLength = moduleHoriLength / ratioValue
|
|
||||||
moduleVertLength = moduleVertLength / ratioValue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gridCheckedValue.includes('line')) {
|
|
||||||
const horizontalLineArray = []
|
|
||||||
const verticalLineArray = []
|
|
||||||
|
|
||||||
for (let i = 0; i < canvasProps.height / moduleVertLength + 1; i++) {
|
|
||||||
const horizontalLine = new fabric.Line(
|
|
||||||
[0, i * moduleVertLength - moduleVertLength / 2, canvasProps.width, i * moduleVertLength - moduleVertLength / 2],
|
|
||||||
{
|
|
||||||
stroke: gridColor,
|
|
||||||
strokeWidth: 1,
|
|
||||||
selectable: true,
|
|
||||||
lockMovementX: true,
|
|
||||||
lockMovementY: true,
|
|
||||||
lockRotation: true,
|
|
||||||
lockScalingX: true,
|
|
||||||
lockScalingY: true,
|
|
||||||
name: 'guideLine',
|
|
||||||
strokeDashArray: [5, 2],
|
|
||||||
opacity: 0.3,
|
|
||||||
direction: 'horizontal',
|
|
||||||
},
|
|
||||||
)
|
|
||||||
canvasProps.add(horizontalLine)
|
|
||||||
horizontalLineArray.push(horizontalLine)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < canvasProps.width / moduleHoriLength + 1; i++) {
|
|
||||||
const verticalLine = new fabric.Line(
|
|
||||||
[i * moduleHoriLength - moduleHoriLength / 2, 0, i * moduleHoriLength - moduleHoriLength / 2, canvasProps.height],
|
|
||||||
{
|
|
||||||
stroke: gridColor,
|
|
||||||
strokeWidth: 1,
|
|
||||||
selectable: true,
|
|
||||||
lockMovementX: true,
|
|
||||||
lockMovementY: true,
|
|
||||||
lockRotation: true,
|
|
||||||
lockScalingX: true,
|
|
||||||
lockScalingY: true,
|
|
||||||
name: 'guideLine',
|
|
||||||
strokeDashArray: [5, 2],
|
|
||||||
opacity: 0.3,
|
|
||||||
direction: 'vertical',
|
|
||||||
},
|
|
||||||
)
|
|
||||||
canvasProps.add(verticalLine)
|
|
||||||
verticalLineArray.push(verticalLine)
|
|
||||||
}
|
|
||||||
canvasProps.renderAll()
|
|
||||||
|
|
||||||
const snapDistance = 10
|
|
||||||
|
|
||||||
const recoilObj = {
|
|
||||||
guideMode: 'guideLine',
|
|
||||||
horizontalLineArray,
|
|
||||||
verticalLineArray,
|
|
||||||
moduleVertLength: moduleVertLength,
|
|
||||||
moduleHoriLength: moduleHoriLength,
|
|
||||||
}
|
|
||||||
gridSettingArray.push(recoilObj)
|
|
||||||
const newHoriGuideLines = [...horiGuideLines]
|
|
||||||
horizontalLineArray.forEach((line) => {
|
|
||||||
newHoriGuideLines.push(line)
|
|
||||||
})
|
|
||||||
const newVertGuideLines = [...vertGuideLines]
|
|
||||||
verticalLineArray.forEach((line) => {
|
|
||||||
newVertGuideLines.push(line)
|
|
||||||
})
|
|
||||||
setHoriGuideLines(newHoriGuideLines)
|
|
||||||
setVertGuideLines(newVertGuideLines)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gridCheckedValue.includes('dot')) {
|
|
||||||
const circle = new fabric.Circle({
|
|
||||||
radius: 2,
|
|
||||||
fill: 'white',
|
|
||||||
stroke: guideColor.hex,
|
|
||||||
strokeWidth: 0.7,
|
|
||||||
originX: 'center',
|
|
||||||
originY: 'center',
|
|
||||||
selectable: false,
|
|
||||||
lockMovementX: true,
|
|
||||||
lockMovementY: true,
|
|
||||||
lockRotation: true,
|
|
||||||
lockScalingX: true,
|
|
||||||
lockScalingY: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
const patternSourceCanvas = new fabric.StaticCanvas(null, {
|
|
||||||
width: moduleHoriLength,
|
|
||||||
height: moduleVertLength,
|
|
||||||
})
|
|
||||||
|
|
||||||
patternSourceCanvas.add(circle)
|
|
||||||
|
|
||||||
circle.set({
|
|
||||||
left: patternSourceCanvas.width / 2,
|
|
||||||
top: patternSourceCanvas.height / 2,
|
|
||||||
})
|
|
||||||
|
|
||||||
patternSourceCanvas.renderAll()
|
|
||||||
|
|
||||||
const pattern = new fabric.Pattern({
|
|
||||||
source: patternSourceCanvas.getElement(),
|
|
||||||
repeat: 'repeat',
|
|
||||||
})
|
|
||||||
|
|
||||||
const backgroundPolygon = new fabric.Polygon(
|
|
||||||
[
|
|
||||||
{ x: 0, y: 0 },
|
|
||||||
{ x: canvasProps.width, y: 0 },
|
|
||||||
{ x: canvasProps.width, y: canvasProps.height },
|
|
||||||
{ x: 0, y: canvasProps.height },
|
|
||||||
],
|
|
||||||
{
|
|
||||||
fill: pattern,
|
|
||||||
selectable: false,
|
|
||||||
name: 'guideDot',
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
canvasProps.add(backgroundPolygon)
|
|
||||||
backgroundPolygon.sendToBack()
|
|
||||||
canvasProps.renderAll()
|
|
||||||
|
|
||||||
const recoilObj = {
|
|
||||||
guideMode: 'guideDot',
|
|
||||||
moduleVertLength: moduleVertLength,
|
|
||||||
moduleHoriLength: moduleHoriLength,
|
|
||||||
}
|
|
||||||
|
|
||||||
gridSettingArray.push(recoilObj)
|
|
||||||
}
|
|
||||||
canvasProps.renderAll()
|
|
||||||
setGuideLine(gridSettingArray)
|
|
||||||
}
|
|
||||||
|
|
||||||
const removeGuideLines = () => {
|
|
||||||
if (!(Object.keys(guideLine).length === 0 && guideLine.constructor === Object)) {
|
|
||||||
const guideLines = canvasProps._objects.filter((obj) => obj.name === 'guideLine' || obj.name === 'guideDot')
|
|
||||||
guideLines?.forEach((item) => canvasProps.remove(item))
|
|
||||||
canvasProps.renderAll()
|
|
||||||
setGuideLine([])
|
|
||||||
setHoriGuideLines([])
|
|
||||||
setVertGuideLines([])
|
|
||||||
} else {
|
|
||||||
alert('그리드가 없습니다.')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div>
|
|
||||||
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
|
|
||||||
<label style={{ display: 'block', marginBottom: '5px' }}>
|
|
||||||
<CheckboxGroup label="그리드 설정" value={gridCheckedValue} defaultChecked={gridCheckedValue} onValueChange={setGridCheckValue}>
|
|
||||||
<Checkbox value="dot">점 그리드</Checkbox>
|
|
||||||
<Checkbox value="line">점선 그리드</Checkbox>
|
|
||||||
</CheckboxGroup>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
|
|
||||||
<Input type="number" label="모듈" ref={moduleLength} />
|
|
||||||
mm
|
|
||||||
</div>
|
|
||||||
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
|
|
||||||
<RadioGroup label="비율 설정" value={ratioValue} defaultValue={ratioValue} onValueChange={setRatioValue}>
|
|
||||||
<Radio value="1">원치수</Radio>
|
|
||||||
<Radio value="2">1/2</Radio>
|
|
||||||
<Radio value="4">1/4</Radio>
|
|
||||||
<Radio value="10">1/10</Radio>
|
|
||||||
<Radio value="custom">임의간격</Radio>
|
|
||||||
</RadioGroup>
|
|
||||||
</div>
|
|
||||||
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
|
|
||||||
가이드컬러 <div style={boxStyle} onClick={() => setColorPickerShow(!colorPickerShow)}></div>
|
|
||||||
</div>
|
|
||||||
{colorPickerShow && (
|
|
||||||
<ColorPicker color={guideColor} onChange={setGuideColor} hideInput={['hsv', 'rgb', 'hex']} height={100} hideAlpha={true} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
|
|
||||||
<Checkbox value="linked" isDisabled={isCustomGridSetting}>
|
|
||||||
종횡연동
|
|
||||||
</Checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
|
|
||||||
<Input type="number" label="가로간격" ref={customModuleHoriLength} min={0} isDisabled={isCustomGridSetting} />
|
|
||||||
mm
|
|
||||||
</div>
|
|
||||||
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
|
|
||||||
<Input type="number" label="세로간격" ref={customModuleVertLength} min={0} isDisabled={isCustomGridSetting} />
|
|
||||||
mm
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex gap-4 items-center">
|
|
||||||
<Button size="sm">초기화</Button>
|
|
||||||
<Button size="sm" color="secondary" onClick={drawGridSettings} isDisabled={gridCheckedValue.length === 0}>
|
|
||||||
저장
|
|
||||||
</Button>
|
|
||||||
<Button size="sm" onClick={() => setOpen(!open)}>
|
|
||||||
취소
|
|
||||||
</Button>
|
|
||||||
<Button size="sm" onClick={() => removeGuideLines()}>
|
|
||||||
그리드 삭제
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
import Link from 'next/link'
|
|
||||||
|
|
||||||
export default function Headers() {
|
|
||||||
return (
|
|
||||||
<div className="w-full">
|
|
||||||
<nav className="container relative flex flex-wrap items-center justify-between mx-auto p-8">
|
|
||||||
<Link href="/" className="font-bold text-3xl">
|
|
||||||
Home
|
|
||||||
</Link>
|
|
||||||
<div className="space-x-4 text-xl">
|
|
||||||
<Link href="/intro">Intro</Link>
|
|
||||||
<Link href="/playground">Playground</Link>
|
|
||||||
<Link href="/initSettingsModal">Basic Settings</Link>
|
|
||||||
<Link href="/settings">Canvas Settings</Link>
|
|
||||||
<Link href="/roof">Roof</Link>
|
|
||||||
<Link href="/roof2">Roof2</Link>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
export default function Hero(props) {
|
|
||||||
return (
|
|
||||||
<div className="pt-48 flex justify-center">
|
|
||||||
<h1 className="text-4xl archivo-black-regular">{props.title}</h1>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,253 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { useEffect, useState, memo, useCallback } from 'react'
|
|
||||||
import { Button, Checkbox, CheckboxGroup, RadioGroup, Radio, Input, Select, SelectItem } from '@nextui-org/react'
|
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
|
||||||
import { modalContent, modalState } from '@/store/modalAtom'
|
|
||||||
import { canvasSettingState } from '@/store/canvasAtom'
|
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
|
||||||
|
|
||||||
export default function InitSettingsModal(props) {
|
|
||||||
const [objectNo, setObjectNo] = useState('test123240909003') // 후에 삭제 필요
|
|
||||||
const [open, setOpen] = useRecoilState(modalState)
|
|
||||||
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
|
|
||||||
const [roofMaterials, setRoofMaterials] = useState([])
|
|
||||||
const [basicSetting, setBasicSettings] = useState({
|
|
||||||
roofDrawingSet: '1',
|
|
||||||
roofSizeSet: '1',
|
|
||||||
roofAngleSet: 'slope',
|
|
||||||
roofs: [{ roofSeq: '1', roofType: '3', roofWidth: '200', roofHeight: '200', roofGap: '0', roofLayout: 'parallel' }],
|
|
||||||
})
|
|
||||||
|
|
||||||
const modelProps = {
|
|
||||||
open,
|
|
||||||
setOpen,
|
|
||||||
}
|
|
||||||
|
|
||||||
const { get, post } = useAxios()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${objectNo}` }).then((res) => {
|
|
||||||
if (res.length == 0) return
|
|
||||||
|
|
||||||
// 'roofs' 배열을 생성하여 각 항목을 추가
|
|
||||||
const roofsRow = res.map((item) => {
|
|
||||||
return {
|
|
||||||
roofDrawingSet: String(item.roofDrawingSet),
|
|
||||||
roofSizeSet: String(item.roofSizeSet),
|
|
||||||
roofAngleSet: item.roofAngleSet,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const roofsArray = res.some((item) => !item.roofSeq)
|
|
||||||
? //최초 지붕재 추가 정보의 경우 roofsArray를 초기화 설정
|
|
||||||
[{ roofSeq: '1', roofType: '3', roofWidth: '200', roofHeight: '200', roofGap: '0', roofLayout: 'parallel' }]
|
|
||||||
: res.map((item) => ({
|
|
||||||
roofSeq: String(item.roofSeq),
|
|
||||||
roofType: String(item.roofType),
|
|
||||||
roofWidth: String(item.roofWidth),
|
|
||||||
roofHeight: String(item.roofHeight),
|
|
||||||
roofGap: String(item.roofGap),
|
|
||||||
roofLayout: item.roofLayout,
|
|
||||||
}))
|
|
||||||
|
|
||||||
// 나머지 데이터와 함께 'roofs' 배열을 patternData에 넣음
|
|
||||||
const patternData = {
|
|
||||||
roofDrawingSet: roofsRow[0].roofDrawingSet, // 첫 번째 항목의 값을 사용
|
|
||||||
roofSizeSet: roofsRow[0].roofSizeSet, // 첫 번째 항목의 값을 사용
|
|
||||||
roofAngleSet: roofsRow[0].roofAngleSet, // 첫 번째 항목의 값을 사용
|
|
||||||
roofs: roofsArray, // 만들어진 roofs 배열
|
|
||||||
}
|
|
||||||
|
|
||||||
// 데이터 설정
|
|
||||||
setBasicSettings({ ...patternData })
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!(Object.keys(canvasSetting).length === 0 && canvasSetting.constructor === Object)) {
|
|
||||||
setBasicSettings({ ...canvasSetting })
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
//기본 설정값 변경 함수
|
|
||||||
const handleBasicSetting = (event) => {
|
|
||||||
const newBasicSetting = { ...basicSetting, [event.target.name]: event.target.value }
|
|
||||||
setBasicSettings(newBasicSetting)
|
|
||||||
}
|
|
||||||
|
|
||||||
//배열 값 변경 함수
|
|
||||||
const handleRoofSettings = (id, event) => {
|
|
||||||
// 기본 세팅에서 roofs 배열을 복사
|
|
||||||
const updatedRoofs = [...basicSetting.roofs]
|
|
||||||
|
|
||||||
// roofSeq가 id와 일치하는 항목의 인덱스 찾기
|
|
||||||
const index = updatedRoofs.findIndex((roof) => roof.roofSeq === id)
|
|
||||||
|
|
||||||
if (index !== -1) {
|
|
||||||
// 해당 인덱스의 항목을 수정
|
|
||||||
updatedRoofs[index] = {
|
|
||||||
...updatedRoofs[index],
|
|
||||||
[event.target.name]: event.target.value,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 수정된 배열을 상태에 반영
|
|
||||||
setBasicSettings((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
roofs: updatedRoofs,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//저장
|
|
||||||
const submitCanvasConfig = async () => {
|
|
||||||
if (!objectNo) {
|
|
||||||
alert('object_no를 입력하세요.')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const patternData = {
|
|
||||||
objectNo,
|
|
||||||
roofDrawingSet: basicSetting.roofDrawingSet,
|
|
||||||
roofSizeSet: basicSetting.roofSizeSet,
|
|
||||||
roofAngleSet: basicSetting.roofAngleSet,
|
|
||||||
roofMaterialsAddList: basicSetting.roofs,
|
|
||||||
}
|
|
||||||
await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData })
|
|
||||||
|
|
||||||
//Recoil 설정
|
|
||||||
setCanvasSetting({ ...basicSetting })
|
|
||||||
|
|
||||||
// 저장 후 재조회
|
|
||||||
//await handleSelect()
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="container mx-auto mt-10 p-6 bg-white shadow-lg rounded-lg">
|
|
||||||
<div className="text-lg font-semibold mb-4">배치면 초기설정</div>
|
|
||||||
|
|
||||||
<div className="mb-6">
|
|
||||||
<div className="flex space-x-4">
|
|
||||||
<RadioGroup
|
|
||||||
label="도면 작성방법"
|
|
||||||
name="roofDrawingSet"
|
|
||||||
orientation="horizontal"
|
|
||||||
value={basicSetting.roofDrawingSet}
|
|
||||||
onChange={handleBasicSetting}
|
|
||||||
>
|
|
||||||
<Radio value="1">치수 입력에 의한 물건작성</Radio>
|
|
||||||
</RadioGroup>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-6">
|
|
||||||
<div className="flex space-x-4">
|
|
||||||
<RadioGroup
|
|
||||||
label="치수 입력방법"
|
|
||||||
name="roofSizeSet"
|
|
||||||
orientation="horizontal"
|
|
||||||
value={basicSetting.roofSizeSet}
|
|
||||||
onChange={handleBasicSetting}
|
|
||||||
>
|
|
||||||
<Radio value="1">복사도 입력</Radio>
|
|
||||||
<Radio value="2">실측값 입력</Radio>
|
|
||||||
<Radio value="3">육지붕</Radio>
|
|
||||||
</RadioGroup>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-6">
|
|
||||||
<div className="flex space-x-4">
|
|
||||||
<RadioGroup
|
|
||||||
label="지붕각도 설정"
|
|
||||||
name="roofAngleSet"
|
|
||||||
orientation="horizontal"
|
|
||||||
value={basicSetting.roofAngleSet}
|
|
||||||
onChange={handleBasicSetting}
|
|
||||||
>
|
|
||||||
<Radio value="slope">경사</Radio>
|
|
||||||
<Radio value="angle">각도</Radio>
|
|
||||||
</RadioGroup>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<RadioGroup label="지붕재 추가(단위 : mm)" />
|
|
||||||
{/* Roofs Array Rendering */}
|
|
||||||
{basicSetting.roofs &&
|
|
||||||
basicSetting.roofs.map((roof, index) => {
|
|
||||||
return (
|
|
||||||
<div key={index} className="mb-4 flex flex-wrap items-center space-x-4" style={{ border: '1px solid black' }}>
|
|
||||||
<span> 타입 : </span>
|
|
||||||
<Select
|
|
||||||
aria-label="roofMaterial"
|
|
||||||
className={'w-52'}
|
|
||||||
name="roofType"
|
|
||||||
onChange={(e) => handleRoofSettings(roof.roofSeq, e)}
|
|
||||||
items={roofMaterials}
|
|
||||||
defaultSelectedKeys={roof.roofType ? [roof.roofType] : []}
|
|
||||||
selectedKeys={roof.roofType}
|
|
||||||
value={roof.roofType}
|
|
||||||
>
|
|
||||||
{(roofMaterial) => (
|
|
||||||
<SelectItem key={roofMaterial.id} value={roofMaterial.id}>
|
|
||||||
{roofMaterial.name}
|
|
||||||
</SelectItem>
|
|
||||||
)}
|
|
||||||
</Select>
|
|
||||||
<span> 너비 : </span>
|
|
||||||
<Input
|
|
||||||
type="text"
|
|
||||||
name="roofWidth"
|
|
||||||
placeholder="너비"
|
|
||||||
value={roof.roofWidth}
|
|
||||||
className="w-24"
|
|
||||||
onChange={(e) => handleRoofSettings(roof.roofSeq, e)}
|
|
||||||
/>
|
|
||||||
mm
|
|
||||||
<span> 높이 : </span>
|
|
||||||
<Input
|
|
||||||
type="text"
|
|
||||||
name="roofHeight"
|
|
||||||
placeholder="높이"
|
|
||||||
value={roof.roofHeight}
|
|
||||||
className="w-24"
|
|
||||||
onChange={(e) => handleRoofSettings(roof.roofSeq, e)}
|
|
||||||
/>
|
|
||||||
mm
|
|
||||||
<span> 서까래 간격 : </span>
|
|
||||||
<Input
|
|
||||||
type="text"
|
|
||||||
name="roofGap"
|
|
||||||
placeholder="간격"
|
|
||||||
value={roof.roofGap}
|
|
||||||
className="w-24"
|
|
||||||
onChange={(e) => handleRoofSettings(roof.roofSeq, e)}
|
|
||||||
/>
|
|
||||||
mm
|
|
||||||
<div className="flex space-x-4">
|
|
||||||
<RadioGroup
|
|
||||||
orientation="horizontal"
|
|
||||||
name="roofLayout"
|
|
||||||
value={roof.roofLayout}
|
|
||||||
defaultValue="parallel"
|
|
||||||
onChange={(e) => handleRoofSettings(roof.roofSeq, e)}
|
|
||||||
>
|
|
||||||
<Radio value="parallel">병렬식</Radio>
|
|
||||||
<Radio value="cascade">계단식</Radio>
|
|
||||||
</RadioGroup>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
|
|
||||||
<div className="flex gap-4 items-right">
|
|
||||||
<Button size="sm" color="secondary" onClick={submitCanvasConfig}>
|
|
||||||
저장
|
|
||||||
</Button>
|
|
||||||
<Button size="sm" onClick={() => setOpen(!open)}>
|
|
||||||
취소
|
|
||||||
</Button>
|
|
||||||
<input type="text" placeholder="Object No 입력" value={objectNo} onChange={(e) => setObjectNo(e.target.value)} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,919 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { useRef, useState, useEffect, useContext } from 'react'
|
|
||||||
import Image from 'next/image'
|
|
||||||
import { useRecoilState } from 'recoil'
|
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
import { FaAnglesUp } from 'react-icons/fa6'
|
|
||||||
import { FaAnglesDown } from 'react-icons/fa6'
|
|
||||||
import { Button } from '@nextui-org/react'
|
|
||||||
import ColorPicker from './common/color-picker/ColorPicker'
|
|
||||||
import { cadFileNameState, googleMapFileNameState, useCadFileState, useGoogleMapFileState } from '@/store/canvasAtom'
|
|
||||||
|
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
|
||||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
|
||||||
import { convertDwgToPng } from '@/lib/cadAction'
|
|
||||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
|
||||||
import QInput from './common/input/Qinput'
|
|
||||||
import QSelect from './common/select/QSelect'
|
|
||||||
import QPagination from './common/pagination/QPagination'
|
|
||||||
import QSelectBox from './common/select/QSelectBox'
|
|
||||||
import SampleReducer from './sample/SampleReducer'
|
|
||||||
|
|
||||||
import styles from './playground.module.css'
|
|
||||||
import useSWR from 'swr'
|
|
||||||
import useSWRMutation from 'swr/mutation'
|
|
||||||
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
|
||||||
import { canvasPopupStatusStore } from '@/store/canvasPopupStatusAtom'
|
|
||||||
import { moduleSelectionDataPlanListState } from '@/store/selectedModuleOptions'
|
|
||||||
import { useRouter } from 'next/navigation'
|
|
||||||
import { QcastContext } from '@/app/QcastProvider'
|
|
||||||
|
|
||||||
export default function Playground() {
|
|
||||||
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
|
|
||||||
const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState)
|
|
||||||
const [useGoogleMapFile, setUseGoogleMapFile] = useRecoilState(useGoogleMapFileState)
|
|
||||||
const [googleMapFileName, setGoogleMapFileName] = useRecoilState(googleMapFileNameState)
|
|
||||||
const fileRef = useRef(null)
|
|
||||||
const queryRef = useRef(null)
|
|
||||||
const [zoom, setZoom] = useState(20)
|
|
||||||
const { get, promiseGet, post, promisePost, getFetcher, postFetcher } = useAxios()
|
|
||||||
const testVar = process.env.NEXT_PUBLIC_TEST
|
|
||||||
const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL
|
|
||||||
const { getMessage } = useMessage()
|
|
||||||
const { swalFire } = useSwal()
|
|
||||||
const { getRoofMaterialList, getModuleTypeItemList, getTrestleList, getConstructionList, getTrestleDetailList } = useMasterController()
|
|
||||||
|
|
||||||
const [color, setColor] = useState('#ff0000')
|
|
||||||
|
|
||||||
const [textInput, setTextInput] = useState('')
|
|
||||||
const [numberInput, setNumberInput] = useState('')
|
|
||||||
const [radioInput, setRadioInput] = useState('')
|
|
||||||
const [checkboxInput, setCheckboxInput] = useState([])
|
|
||||||
const [selectedValue, setSelectedValue] = useState('')
|
|
||||||
|
|
||||||
const [users, setUsers] = useState([])
|
|
||||||
|
|
||||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const { setIsGlobalLoading } = useContext(QcastContext)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setIsGlobalLoading(false)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
console.log('textInput:', textInput)
|
|
||||||
}, [textInput])
|
|
||||||
useEffect(() => {
|
|
||||||
console.log('numberInput:', numberInput)
|
|
||||||
}, [numberInput])
|
|
||||||
useEffect(() => {
|
|
||||||
console.log('radioInput:', radioInput)
|
|
||||||
}, [radioInput])
|
|
||||||
useEffect(() => {
|
|
||||||
console.log('checkboxInput:', checkboxInput)
|
|
||||||
}, [checkboxInput])
|
|
||||||
useEffect(() => {
|
|
||||||
console.log('selectedValue:', selectedValue)
|
|
||||||
}, [selectedValue])
|
|
||||||
|
|
||||||
const handleUsers = async () => {
|
|
||||||
// const users = await get('/api/user/find-all')
|
|
||||||
const params = {
|
|
||||||
url: '/api/user/find-all',
|
|
||||||
}
|
|
||||||
const users = await get(params)
|
|
||||||
console.log('users', users)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleConvert = async () => {
|
|
||||||
console.log('file', fileRef.current.files[0])
|
|
||||||
|
|
||||||
const formData = new FormData()
|
|
||||||
formData.append('file', fileRef.current.files[0])
|
|
||||||
|
|
||||||
await promisePost({ url: converterUrl, data: formData })
|
|
||||||
.then((res) => {
|
|
||||||
console.log('response: ', res)
|
|
||||||
convertDwgToPng(res.data.Files[0].FileName, res.data.Files[0].FileData)
|
|
||||||
setUseCadFile(true)
|
|
||||||
setCadFileName(res.data.Files[0].FileName)
|
|
||||||
swalFire({ text: '파일 변환 완료' })
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error(err)
|
|
||||||
swalFire({ text: '파일 변환 실패' })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDownImage = async (fileName = '') => {
|
|
||||||
const fileNm = fileName === '' ? uuidv4() : fileName
|
|
||||||
const queryString = queryRef.current.value === '' ? '서울시 서대문구 연세로5다길 22-3 발리빌라 3층' : queryRef.current.value
|
|
||||||
const res = await get({ url: `http://localhost:3000/api/html2canvas?q=${queryString}&fileNm=${fileNm}&zoom=${zoom}` })
|
|
||||||
console.log('res', res)
|
|
||||||
setGoogleMapFileName(res.fileNm)
|
|
||||||
swalFire({ text: '이미지 저장 완료' })
|
|
||||||
setUseGoogleMapFile(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleZoom = async (type) => {
|
|
||||||
if (type === 'up') {
|
|
||||||
setZoom((prevState) => prevState + 1)
|
|
||||||
} else {
|
|
||||||
setZoom((prevState) => prevState - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
await handleDownImage()
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
author: 'SWYOO',
|
|
||||||
contents: '버튼 정리(템플릿 적용)',
|
|
||||||
date: '2024.07.16',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
author: 'SWYOO',
|
|
||||||
contents: 'README.md 파일 이미지 경로 수정',
|
|
||||||
date: '2024.07.17',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
author: 'SWYOO',
|
|
||||||
contents: '',
|
|
||||||
date: '',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const handleSwalAlert = () => {
|
|
||||||
swalFire({
|
|
||||||
text: '알림 테스트입니다.',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const paginationProps = {
|
|
||||||
pageNo: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
pagePerBlock: 10,
|
|
||||||
totalCount: 26,
|
|
||||||
handleChangePage: (page) => {
|
|
||||||
console.log('page', page)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
console.log('users:', users)
|
|
||||||
}, [users])
|
|
||||||
|
|
||||||
const codes = [
|
|
||||||
{
|
|
||||||
clHeadCd: '203800',
|
|
||||||
clCode: 'HEI_455',
|
|
||||||
clCodeNm: '세로 455mm이하',
|
|
||||||
clPriority: 1,
|
|
||||||
name: '세로 455mm이하',
|
|
||||||
id: 'HEI_455',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
clHeadCd: '203800',
|
|
||||||
clCode: 'HEI_500',
|
|
||||||
clCodeNm: '세로 500mm이하',
|
|
||||||
clPriority: 2,
|
|
||||||
name: '세로 500mm이하',
|
|
||||||
id: 'HEI_500',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
clHeadCd: '203800',
|
|
||||||
clCode: 'HEI_606',
|
|
||||||
clCodeNm: '세로 606mm이하',
|
|
||||||
clPriority: 3,
|
|
||||||
name: '세로 606mm이하',
|
|
||||||
id: 'HEI_606',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
clHeadCd: '203800',
|
|
||||||
clCode: 'WID_606',
|
|
||||||
clCodeNm: '가로 606mm이하',
|
|
||||||
clPriority: 4,
|
|
||||||
name: '가로 606mm이하',
|
|
||||||
id: 'WID_606',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
clHeadCd: '203800',
|
|
||||||
clCode: 'ETC',
|
|
||||||
clCodeNm: '기타',
|
|
||||||
clPriority: 5,
|
|
||||||
name: '기타',
|
|
||||||
id: 'ETC',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const [myData, setMyData] = useState({
|
|
||||||
roofMatlCd: 'ROOF_ID_WA_53A',
|
|
||||||
roofMatlNm: '화와 A',
|
|
||||||
roofMatlNmJp: '和瓦A',
|
|
||||||
widAuth: 'R',
|
|
||||||
widBase: '265.000',
|
|
||||||
lenAuth: 'R',
|
|
||||||
lenBase: '235.000',
|
|
||||||
roofPchAuth: null,
|
|
||||||
roofPchBase: null,
|
|
||||||
raftAuth: 'C',
|
|
||||||
raftBaseCd: 'HEI_455',
|
|
||||||
id: 'ROOF_ID_WA_53A',
|
|
||||||
name: '화와 A',
|
|
||||||
selected: true,
|
|
||||||
nameJp: '和瓦A',
|
|
||||||
length: 235,
|
|
||||||
width: 265,
|
|
||||||
layout: 'P',
|
|
||||||
hajebichi: null,
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleChangeMyData = () => {
|
|
||||||
setMyData({ ...myData, raftBaseCd: 'HEI_500' })
|
|
||||||
}
|
|
||||||
|
|
||||||
const [myData2, setMyData2] = useState({})
|
|
||||||
|
|
||||||
const handleChangeMyData2 = () => {
|
|
||||||
setMyData2({
|
|
||||||
roofMatlCd: 'ROOF_ID_WA_53A',
|
|
||||||
roofMatlNm: '화와 A',
|
|
||||||
roofMatlNmJp: '和瓦A',
|
|
||||||
widAuth: 'R',
|
|
||||||
widBase: '265.000',
|
|
||||||
lenAuth: 'R',
|
|
||||||
lenBase: '235.000',
|
|
||||||
roofPchAuth: null,
|
|
||||||
roofPchBase: null,
|
|
||||||
raftAuth: 'C',
|
|
||||||
raftBaseCd: 'HEI_455',
|
|
||||||
id: 'ROOF_ID_WA_53A',
|
|
||||||
name: '화와 A',
|
|
||||||
selected: true,
|
|
||||||
nameJp: '和瓦A',
|
|
||||||
length: 235,
|
|
||||||
width: 265,
|
|
||||||
layout: 'P',
|
|
||||||
hajebichi: null,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// const [callFlag, setCallFlag] = useState(false)
|
|
||||||
// const { data: tutoData, error, isLoading } = useSWR('http://localhost:8080/api/tutorial', getFetcher)
|
|
||||||
// const { data: tutoData, error, isLoading } = useSWR(callFlag ? 'http://localhost:8080/api/tutorial' : null, getFetcher)
|
|
||||||
// const { trigger, isMutating } = useSWRMutation('http://localhost:8080/api/tutorial', postFetcher)
|
|
||||||
|
|
||||||
// if (isLoading) {
|
|
||||||
// return <div>Loading...</div>
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (error) {
|
|
||||||
// return <div>Error...</div>
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const [moduleSelectionDataPlanListStore, setModuleSelectionDataPlanListStore] = useRecoilState(moduleSelectionDataPlanListState)
|
|
||||||
// useEffect(() => {
|
|
||||||
// console.log('🚀 ~ Playground ~ moduleSelectionDataPlanListStore:', moduleSelectionDataPlanListStore)
|
|
||||||
// }, [moduleSelectionDataPlanListStore])
|
|
||||||
// const { trigger: canvasPopupStatusTrigger } = useCanvasPopupStatusController({ objectNo: 'R201T01241120001', planNo: 2, popupType: 2 })
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="container mx-auto p-4 m-4 border">
|
|
||||||
<div className={styles.test}>이 영역은 테스트입니다.</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<button
|
|
||||||
className="btn-frame deepgray"
|
|
||||||
onClick={() => {
|
|
||||||
getRoofMaterialList()
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
지붕재 목록 조회 API 호출
|
|
||||||
</button>{' '}
|
|
||||||
<button
|
|
||||||
className="btn-frame deepgray"
|
|
||||||
onClick={() => {
|
|
||||||
getModuleTypeItemList(['ROOF_ID_HIRA_SEME', 'ROOF_ID_ROOGA'])
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
모듈 타입별 아이템 목록 조회 API 호출
|
|
||||||
</button>{' '}
|
|
||||||
<button
|
|
||||||
className="btn-frame deepgray"
|
|
||||||
onClick={() => {
|
|
||||||
getTrestleList({ moduleTpCd: '', roofMatlCd: '', raftBaseCd: '', trestleMkrCd: '', constMthdCd: '', roofBaseCd: '' }) //임시 데이터
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
가대 목록 조회 API 호출
|
|
||||||
</button>{' '}
|
|
||||||
<button
|
|
||||||
className="btn-frame deepgray"
|
|
||||||
onClick={() => {
|
|
||||||
getConstructionList({
|
|
||||||
//임시 데이터
|
|
||||||
moduleTpCd: 'testData_1',
|
|
||||||
roofMatlCd: 'testData_2',
|
|
||||||
trestleMkrCd: 'testData_3',
|
|
||||||
constMthdCd: 'testData_4',
|
|
||||||
roofBaseCd: 'testData_5',
|
|
||||||
illuminationTp: 'testData_6',
|
|
||||||
instHt: 'testData_7',
|
|
||||||
stdWindSpeed: 'testData_8',
|
|
||||||
stdSnowLd: 'testData_9',
|
|
||||||
inclCd: 'testData_10',
|
|
||||||
raftBaseCd: '',
|
|
||||||
roofPitch: 30,
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
시공법 목록 조회 API 호출
|
|
||||||
</button>{' '}
|
|
||||||
<button
|
|
||||||
className="btn-frame deepgray"
|
|
||||||
onClick={() => {
|
|
||||||
getTrestleDetailList({
|
|
||||||
//임시 데이터
|
|
||||||
moduleTpCd: 'testData_1',
|
|
||||||
roofMatlCd: 'testData_2',
|
|
||||||
trestleMkrCd: 'testData_3',
|
|
||||||
constMthdCd: 'testData_4',
|
|
||||||
roofBaseCd: 'testData_5',
|
|
||||||
illuminationTp: 'testData_6',
|
|
||||||
instHt: 'testData_7',
|
|
||||||
stdWindSpeed: 'testData_8',
|
|
||||||
stdSnowLd: 'testData_9',
|
|
||||||
inclCd: 'testData_10',
|
|
||||||
constTp: 'testData_11',
|
|
||||||
mixMatlNo: 30,
|
|
||||||
roofPitch: 0,
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
가대 상세 조회 API 호출
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="m-2">
|
|
||||||
<button
|
|
||||||
className="btn-frame deepgray"
|
|
||||||
onClick={() => {
|
|
||||||
setTextInput('')
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
QInput TextInput DATA RESET
|
|
||||||
</button>
|
|
||||||
<QInput type="text" placeholder="placeholder" value={textInput} onChange={setTextInput} />
|
|
||||||
<QInput type="text" placeholder="read only" value={textInput} onChange={setTextInput} readOnly="true" />
|
|
||||||
<br />
|
|
||||||
<button
|
|
||||||
className="btn-frame deepgray"
|
|
||||||
onClick={() => {
|
|
||||||
setNumberInput('')
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
QInput NumberInput DATA RESET
|
|
||||||
</button>
|
|
||||||
<QInput type="number" placeholder="placeholder" value={numberInput} onChange={setNumberInput} />
|
|
||||||
<QInput type="number" placeholder="read only" value={numberInput} onChange={setNumberInput} readOnly="true" />
|
|
||||||
<br />
|
|
||||||
<button
|
|
||||||
className="btn-frame deepgray"
|
|
||||||
onClick={() => {
|
|
||||||
setRadioInput('')
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
QInput Radio DATA RESET
|
|
||||||
</button>
|
|
||||||
<QInput
|
|
||||||
type="radio"
|
|
||||||
value={radioInput}
|
|
||||||
onChange={setRadioInput}
|
|
||||||
options={[
|
|
||||||
{ id: 'r01', value: 'option1', name: 'Option 1' },
|
|
||||||
{ id: 'r02', value: 'option2', name: 'Option 2' },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
<br />
|
|
||||||
<button
|
|
||||||
className="btn-frame deepgray"
|
|
||||||
onClick={() => {
|
|
||||||
setCheckboxInput([])
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
QInput Checkbox DATA RESET
|
|
||||||
</button>
|
|
||||||
<QInput
|
|
||||||
type="checkbox"
|
|
||||||
value={checkboxInput}
|
|
||||||
onChange={setCheckboxInput}
|
|
||||||
options={[
|
|
||||||
{ id: 'c01', value: 'checkbox1', name: 'Checkbox 1' },
|
|
||||||
{ id: 'c02', value: 'checkbox2', name: 'Checkbox 2' },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="m-2">
|
|
||||||
<br />
|
|
||||||
<button
|
|
||||||
className="btn-frame deepgray"
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedValue([])
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
QSelect DATA RESET
|
|
||||||
</button>
|
|
||||||
<QSelect
|
|
||||||
value={selectedValue}
|
|
||||||
onChange={setSelectedValue}
|
|
||||||
// placeholder="동물을 선택하세요"
|
|
||||||
options={[
|
|
||||||
{ id: 's01', value: 'cat', name: '고양이' },
|
|
||||||
{ id: 's02', value: 'dog', name: '개' },
|
|
||||||
{ id: 's03', value: 'lion', name: '사자' },
|
|
||||||
{ id: 's04', value: 'tiger', name: '호랑이' },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
<QSelect
|
|
||||||
value={selectedValue}
|
|
||||||
onChange={setSelectedValue}
|
|
||||||
placeholder="동물을 선택하세요"
|
|
||||||
options={[
|
|
||||||
{ id: 's01', value: 'cat', name: '고양이' },
|
|
||||||
{ id: 's02', value: 'dog', name: '개' },
|
|
||||||
{ id: 's03', value: 'lion', name: '사자' },
|
|
||||||
{ id: 's04', value: 'tiger', name: '호랑이' },
|
|
||||||
]}
|
|
||||||
disabled="true"
|
|
||||||
/>
|
|
||||||
<QSelect
|
|
||||||
value={selectedValue}
|
|
||||||
onChange={setSelectedValue}
|
|
||||||
placeholder="동물을 선택하세요"
|
|
||||||
options={[
|
|
||||||
{ id: 's01', value: 'cat', name: '고양이' },
|
|
||||||
{ id: 's02', value: 'dog', name: '개' },
|
|
||||||
{ id: 's03', value: 'lion', name: '사자' },
|
|
||||||
{ id: 's04', value: 'tiger', name: '호랑이' },
|
|
||||||
]}
|
|
||||||
dark="true"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="w-full bg-orange-300 m-2">{testVar}</div>
|
|
||||||
<div>
|
|
||||||
<div className="m-2">
|
|
||||||
<Button onClick={handleUsers}>Button</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="test">
|
|
||||||
<p className="text-white">Sass 테스트입니다.</p>
|
|
||||||
</div>
|
|
||||||
<div dangerouslySetInnerHTML={{ __html: getMessage('welcome', ['<span style="color: red">test</span>']) }}></div>
|
|
||||||
<div>
|
|
||||||
<h1>React ColorPicker</h1>
|
|
||||||
<ColorPicker color={color} setColor={setColor} />
|
|
||||||
<div className="p-4">{color}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h1 className="text-2xl">캐드 파일 이미지 사용</h1>
|
|
||||||
<input type="file" name="file" ref={fileRef} />
|
|
||||||
<div>
|
|
||||||
<Button onClick={handleConvert}>Convert</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h1 className="text-2xl">구글 맵 이미지 사용</h1>
|
|
||||||
<input type="text" ref={queryRef} className="w-80 border-medium my-2" />
|
|
||||||
<div>
|
|
||||||
<Button onClick={handleDownImage}>Google map Download to Image</Button>
|
|
||||||
</div>
|
|
||||||
{useGoogleMapFile && (
|
|
||||||
<>
|
|
||||||
<div className="my-2">
|
|
||||||
<p className="text-lg">Zoom Controller : {zoom}</p>
|
|
||||||
<Button startContent={<FaAnglesUp />} className="mx-2" onClick={() => handleZoom('up')}></Button>
|
|
||||||
<Button startContent={<FaAnglesDown />} className="mx-2" onClick={() => handleZoom('down')}></Button>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Image src={`/mapImages/${googleMapFileName}`} width={640} height={640} />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Button onClick={() => swalFire({ text: 'alert 테스트입니다.' })}>Sweetalert - alert</Button>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Button onClick={() => swalFire({ text: 'alert 아이콘 테스트입니다.', icon: 'error' })}>Sweetalert - alert - error</Button>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Button
|
|
||||||
onClick={() =>
|
|
||||||
swalFire({
|
|
||||||
html: `confirm 테스트입니다.<br />당신은 바보입니까?`,
|
|
||||||
type: 'confirm',
|
|
||||||
confirmFn: () => {
|
|
||||||
alert('test')
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Sweetalert - confirm
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<QPagination {...paginationProps} />
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
promiseGet({ url: 'http://localhost:8080/api/user' }).then((res) => setUsers(res.data))
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
axios get test
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
const result = promisePost({
|
|
||||||
url: 'http://localhost:8080/api/user',
|
|
||||||
data: {
|
|
||||||
firstName: 'Yoo',
|
|
||||||
lastName: 'Sangwook',
|
|
||||||
email: 'yoo1757@naver.com',
|
|
||||||
age: 46,
|
|
||||||
},
|
|
||||||
}).then((res) => console.log('res', res))
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
axios post test
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<QSelectBox options={codes} value={myData} sourceKey="id" targetKey="raftBaseCd" showKey="clCodeNm" />
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Button onClick={handleChangeMyData}>QSelectBox value change!!</Button>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<QSelectBox options={codes} value={myData2} sourceKey="id" targetKey="raftBaseCd" showKey="clCodeNm" />
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Button onClick={handleChangeMyData2}>QSelectBox dynamic data bind change!!</Button>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<QSelectBox title="초기값 테스트" options={[]} value={{}} sourceKey="id" targetKey="raftBaseCd" showKey="clCodeNm" />
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<SampleReducer />
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Button onClick={() => setManagementState({ ...managementState, objectNo: '1234567890' })}>GlobalDataProvider 테스트</Button>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Button onClick={() => setManagementState({})}>GlobalDataProvider 초기화</Button>
|
|
||||||
</div>
|
|
||||||
{/* <div className="my-2">
|
|
||||||
<p>{managementStateLoaded?.objectNo}</p>
|
|
||||||
</div> */}
|
|
||||||
<div className="my-2">
|
|
||||||
<Button onClick={() => swalFire({ text: 'alert 테스트입니다.', type: 'alert', confirmFn: () => console.log('Alert!!!') })}>
|
|
||||||
Sweetalert - alert
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
{/* <div className="my-2">
|
|
||||||
{tutoData &&
|
|
||||||
tutoData.map((item) => (
|
|
||||||
<div key={item.id}>
|
|
||||||
{item.name} / {item.email}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Button onClick={() => setCallFlag(true)}>getFetcher call</Button>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Button disabled={isMutating} onClick={() => trigger({ id: 3, name: 'seulda kim', email: 'seulda.kim@interplug.co.kr' })}>
|
|
||||||
insert data
|
|
||||||
</Button>
|
|
||||||
</div> */}
|
|
||||||
<div className="my-2">
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
canvasPopupStatusTrigger({
|
|
||||||
common: {
|
|
||||||
illuminationTp: '3',
|
|
||||||
instHt: '10',
|
|
||||||
stdWindSpeed: 'WL_32',
|
|
||||||
stdSnowLd: '5',
|
|
||||||
moduleTpCd: 'A1',
|
|
||||||
moduleItemId: '106796',
|
|
||||||
},
|
|
||||||
roofConstructions: [
|
|
||||||
{
|
|
||||||
roofIndex: 0,
|
|
||||||
addRoof: {
|
|
||||||
roofMatlCd: 'ROOF_ID_WA_53A',
|
|
||||||
roofMatlNm: '일본기와 A',
|
|
||||||
roofMatlNmJp: '和瓦A',
|
|
||||||
widAuth: 'R',
|
|
||||||
widBase: '265.000',
|
|
||||||
lenAuth: 'R',
|
|
||||||
lenBase: '235.000',
|
|
||||||
roofPchAuth: null,
|
|
||||||
roofPchBase: null,
|
|
||||||
raftAuth: 'C',
|
|
||||||
raftBaseCd: 'HEI_455',
|
|
||||||
id: 'ROOF_ID_WA_53A',
|
|
||||||
name: '일본기와 A',
|
|
||||||
selected: true,
|
|
||||||
index: 0,
|
|
||||||
nameJp: '和瓦A',
|
|
||||||
length: 235,
|
|
||||||
width: 265,
|
|
||||||
raft: 'HEI_455',
|
|
||||||
layout: 'P',
|
|
||||||
hajebichi: 0,
|
|
||||||
pitch: 7,
|
|
||||||
angle: 21.8,
|
|
||||||
roofSizeSet: '1',
|
|
||||||
roofAngleSet: 'slope',
|
|
||||||
},
|
|
||||||
trestle: {
|
|
||||||
moduleTpCd: 'A1',
|
|
||||||
moduleTpCdNm: 'A1type',
|
|
||||||
moduleTpCdJp: 'A1type',
|
|
||||||
roofMatlCd: 'ROOF_ID_WA_53A',
|
|
||||||
roofMatlCdNm: '일본기와 A',
|
|
||||||
roofMatlCdJp: '和瓦A',
|
|
||||||
trestleMkrCd: 'ROOF_TECHRI',
|
|
||||||
trestleMkrCdNm: '지붕 기술 연구소',
|
|
||||||
trestleMkrCdJp: '屋根技術研究所',
|
|
||||||
constMthdCd: 'CST026',
|
|
||||||
constMthdCdNm: 'YG 앵커 랙 있음',
|
|
||||||
constMthdCdJp: 'YGアンカー ラック有り',
|
|
||||||
roofBaseCd: 'RFB001',
|
|
||||||
roofBaseCdNm: '구조용 합판 9mm 이상',
|
|
||||||
roofBaseCdJp: '構造用合板9mm以上',
|
|
||||||
rackYn: null,
|
|
||||||
priority: 1,
|
|
||||||
},
|
|
||||||
construction: {
|
|
||||||
constTp: 'WORK_LV_ID_1',
|
|
||||||
constTpNm: '표준 시공',
|
|
||||||
constTpJp: '標準施工',
|
|
||||||
constPossYn: 'Y',
|
|
||||||
plvrYn: 'Y',
|
|
||||||
cvrYn: 'Y',
|
|
||||||
cvrLmtRow: 9999,
|
|
||||||
snowGdPossYn: 'Y',
|
|
||||||
roofIndex: 0,
|
|
||||||
setupCover: true,
|
|
||||||
setupSnowCover: true,
|
|
||||||
selectedIndex: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
roofIndex: 1,
|
|
||||||
addRoof: {
|
|
||||||
roofMatlCd: 'ROOF_ID_WA_53B',
|
|
||||||
roofMatlNm: '일본기와 B',
|
|
||||||
roofMatlNmJp: '和瓦B',
|
|
||||||
widAuth: 'R',
|
|
||||||
widBase: '275.000',
|
|
||||||
lenAuth: 'R',
|
|
||||||
lenBase: '225.000',
|
|
||||||
roofPchAuth: null,
|
|
||||||
roofPchBase: null,
|
|
||||||
raftAuth: 'C',
|
|
||||||
raftBaseCd: 'HEI_455',
|
|
||||||
id: 'ROOF_ID_WA_53B',
|
|
||||||
name: '일본기와 B',
|
|
||||||
selected: true,
|
|
||||||
index: 1,
|
|
||||||
nameJp: '和瓦B',
|
|
||||||
length: 225,
|
|
||||||
width: 275,
|
|
||||||
raft: 'HEI_455',
|
|
||||||
layout: 'P',
|
|
||||||
hajebichi: 0,
|
|
||||||
pitch: 5,
|
|
||||||
angle: 21.8,
|
|
||||||
roofSizeSet: '1',
|
|
||||||
roofAngleSet: 'slope',
|
|
||||||
},
|
|
||||||
trestle: {
|
|
||||||
moduleTpCd: 'A1',
|
|
||||||
moduleTpCdNm: 'A1type',
|
|
||||||
moduleTpCdJp: 'A1type',
|
|
||||||
roofMatlCd: 'ROOF_ID_WA_53B',
|
|
||||||
roofMatlCdNm: '일본기와 B',
|
|
||||||
roofMatlCdJp: '和瓦B',
|
|
||||||
trestleMkrCd: 'DAIDO HUNT',
|
|
||||||
trestleMkrCdNm: '다이도 헌트',
|
|
||||||
trestleMkrCdJp: 'ダイドーハント',
|
|
||||||
constMthdCd: 'CST016',
|
|
||||||
constMthdCdNm: '지지 기와Ⅱ-B 랙 있음',
|
|
||||||
constMthdCdJp: '支持瓦Ⅱ-B ラック有り',
|
|
||||||
roofBaseCd: 'RFB002',
|
|
||||||
roofBaseCdNm: 'OSB12mm 이상',
|
|
||||||
roofBaseCdJp: 'OSB12mm以上',
|
|
||||||
rackYn: null,
|
|
||||||
priority: 95,
|
|
||||||
},
|
|
||||||
construction: {
|
|
||||||
constTp: 'WORK_LV_ID_1',
|
|
||||||
constTpNm: '표준 시공',
|
|
||||||
constTpJp: '標準施工',
|
|
||||||
constPossYn: 'Y',
|
|
||||||
plvrYn: 'Y',
|
|
||||||
cvrYn: 'Y',
|
|
||||||
cvrLmtRow: 9999,
|
|
||||||
snowGdPossYn: 'Y',
|
|
||||||
roofIndex: 1,
|
|
||||||
setupCover: false,
|
|
||||||
setupSnowCover: true,
|
|
||||||
selectedIndex: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
roofIndex: 2,
|
|
||||||
addRoof: {
|
|
||||||
roofMatlCd: 'ROOF_ID_HIRA_C',
|
|
||||||
roofMatlNm: '평판기와 C',
|
|
||||||
roofMatlNmJp: '平板瓦C',
|
|
||||||
widAuth: 'R',
|
|
||||||
widBase: '305.000',
|
|
||||||
lenAuth: 'R',
|
|
||||||
lenBase: '280.000',
|
|
||||||
roofPchAuth: null,
|
|
||||||
roofPchBase: null,
|
|
||||||
raftAuth: 'C',
|
|
||||||
raftBaseCd: 'HEI_455',
|
|
||||||
id: 'ROOF_ID_HIRA_C',
|
|
||||||
name: '평판기와 C',
|
|
||||||
selected: true,
|
|
||||||
index: 2,
|
|
||||||
nameJp: '平板瓦C',
|
|
||||||
length: 280,
|
|
||||||
width: 305,
|
|
||||||
raft: 'HEI_455',
|
|
||||||
layout: 'P',
|
|
||||||
hajebichi: 0,
|
|
||||||
pitch: 4,
|
|
||||||
angle: 21.8,
|
|
||||||
roofSizeSet: '1',
|
|
||||||
roofAngleSet: 'slope',
|
|
||||||
},
|
|
||||||
trestle: {
|
|
||||||
moduleTpCd: 'A1',
|
|
||||||
moduleTpCdNm: 'A1type',
|
|
||||||
moduleTpCdJp: 'A1type',
|
|
||||||
roofMatlCd: 'ROOF_ID_HIRA_C',
|
|
||||||
roofMatlCdNm: '평판기와 C',
|
|
||||||
roofMatlCdJp: '平板瓦C',
|
|
||||||
trestleMkrCd: 'ROOF_TECHRI',
|
|
||||||
trestleMkrCdNm: '지붕 기술 연구소',
|
|
||||||
trestleMkrCdJp: '屋根技術研究所',
|
|
||||||
constMthdCd: 'CST034',
|
|
||||||
constMthdCdNm: '지지 기와 C 랙 있음',
|
|
||||||
constMthdCdJp: '支持瓦C ラック有り',
|
|
||||||
roofBaseCd: 'RFB001',
|
|
||||||
roofBaseCdNm: '구조용 합판 9mm 이상',
|
|
||||||
roofBaseCdJp: '構造用合板9mm以上',
|
|
||||||
rackYn: null,
|
|
||||||
priority: 122,
|
|
||||||
},
|
|
||||||
construction: {
|
|
||||||
constTp: 'WORK_LV_ID_1',
|
|
||||||
constTpNm: '표준 시공',
|
|
||||||
constTpJp: '標準施工',
|
|
||||||
constPossYn: 'Y',
|
|
||||||
plvrYn: 'Y',
|
|
||||||
cvrYn: 'Y',
|
|
||||||
cvrLmtRow: 9999,
|
|
||||||
snowGdPossYn: 'Y',
|
|
||||||
roofIndex: 2,
|
|
||||||
setupCover: false,
|
|
||||||
setupSnowCover: false,
|
|
||||||
selectedIndex: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
roofIndex: 3,
|
|
||||||
addRoof: {
|
|
||||||
roofMatlCd: 'ROOF_ID_HIRA_D',
|
|
||||||
roofMatlNm: '평판기와 D',
|
|
||||||
roofMatlNmJp: '平板瓦D',
|
|
||||||
widAuth: 'R',
|
|
||||||
widBase: '305.000',
|
|
||||||
lenAuth: 'R',
|
|
||||||
lenBase: '280.000',
|
|
||||||
roofPchAuth: null,
|
|
||||||
roofPchBase: null,
|
|
||||||
raftAuth: 'C',
|
|
||||||
raftBaseCd: 'HEI_455',
|
|
||||||
id: 'ROOF_ID_HIRA_D',
|
|
||||||
name: '평판기와 D',
|
|
||||||
selected: true,
|
|
||||||
index: 3,
|
|
||||||
nameJp: '平板瓦D',
|
|
||||||
length: 280,
|
|
||||||
width: 305,
|
|
||||||
raft: 'HEI_455',
|
|
||||||
layout: 'P',
|
|
||||||
hajebichi: 0,
|
|
||||||
pitch: 8,
|
|
||||||
angle: 21.8,
|
|
||||||
roofSizeSet: '1',
|
|
||||||
roofAngleSet: 'slope',
|
|
||||||
},
|
|
||||||
trestle: {
|
|
||||||
moduleTpCd: 'A1',
|
|
||||||
moduleTpCdNm: 'A1type',
|
|
||||||
moduleTpCdJp: 'A1type',
|
|
||||||
roofMatlCd: 'ROOF_ID_HIRA_D',
|
|
||||||
roofMatlCdNm: '평판기와 D',
|
|
||||||
roofMatlCdJp: '平板瓦D',
|
|
||||||
trestleMkrCd: 'DAIDO HUNT',
|
|
||||||
trestleMkrCdNm: '다이도 헌트',
|
|
||||||
trestleMkrCdJp: 'ダイドーハント',
|
|
||||||
constMthdCd: 'CST018',
|
|
||||||
constMthdCdNm: '지지 기와Ⅱ-D 랙 있음',
|
|
||||||
constMthdCdJp: '支持瓦Ⅱ-D ラック有り',
|
|
||||||
roofBaseCd: 'RFB002',
|
|
||||||
roofBaseCdNm: 'OSB12mm 이상',
|
|
||||||
roofBaseCdJp: 'OSB12mm以上',
|
|
||||||
rackYn: null,
|
|
||||||
priority: 203,
|
|
||||||
},
|
|
||||||
construction: {
|
|
||||||
constTp: 'WORK_LV_ID_3',
|
|
||||||
constTpNm: '강화 시공',
|
|
||||||
constTpJp: '強化施工',
|
|
||||||
constPossYn: 'Y',
|
|
||||||
plvrYn: 'Y',
|
|
||||||
cvrYn: 'Y',
|
|
||||||
cvrLmtRow: 9999,
|
|
||||||
snowGdPossYn: 'Y',
|
|
||||||
roofIndex: 3,
|
|
||||||
setupCover: false,
|
|
||||||
setupSnowCover: false,
|
|
||||||
selectedIndex: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
module: {
|
|
||||||
itemId: '106796',
|
|
||||||
itemNm: 'Q.TRON M-G2.4+ 430',
|
|
||||||
goodsNo: 'Q.TRON M-G2.4+ 430',
|
|
||||||
itemTp: 'A1',
|
|
||||||
mixMatlNo: null,
|
|
||||||
mixItemTpYn: 'N',
|
|
||||||
itemList: [
|
|
||||||
{
|
|
||||||
itemId: '106796',
|
|
||||||
itemNm: 'Q.TRON M-G2.4+ 430',
|
|
||||||
goodsNo: 'Q.TRON M-G2.4+ 430',
|
|
||||||
itemTp: 'A1',
|
|
||||||
color: '#BEF781',
|
|
||||||
longAxis: '1722.000',
|
|
||||||
shortAxis: '1134.000',
|
|
||||||
thickness: '30.000',
|
|
||||||
wpOut: '430',
|
|
||||||
mixMatlNo: null,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'Q.TRON M-G2.4+ 430',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Test Data insert
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
const params = {
|
|
||||||
pid: 1,
|
|
||||||
objectNo: 'RT01250131002',
|
|
||||||
}
|
|
||||||
router.push(`/floor-plan/estimate/5?pid=${params.pid}&objectNo=${params.objectNo}`)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
견적서 페이지 이동
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,351 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { useEffect } from 'react'
|
|
||||||
import { addDistanceTextToPolygon, getDistance } from '@/util/canvas-util'
|
|
||||||
import { useCanvas } from '@/hooks/useCanvas'
|
|
||||||
import { fabric } from 'fabric'
|
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
|
|
||||||
export default function Roof() {
|
|
||||||
const {
|
|
||||||
canvas,
|
|
||||||
addShape,
|
|
||||||
handleUndo,
|
|
||||||
handleRedo,
|
|
||||||
handleClear,
|
|
||||||
handleCopy,
|
|
||||||
handleDelete,
|
|
||||||
handleSave,
|
|
||||||
handlePaste,
|
|
||||||
handleRotate,
|
|
||||||
attachCustomControlOnPolygon,
|
|
||||||
saveImage,
|
|
||||||
handleFlip,
|
|
||||||
} = useCanvas('canvas')
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let circle = new fabric.Circle({
|
|
||||||
radius: 40,
|
|
||||||
fill: 'rgba(200, 0, 0, 0.3)',
|
|
||||||
originX: 'center',
|
|
||||||
originY: 'center',
|
|
||||||
})
|
|
||||||
|
|
||||||
let text = new fabric.Textbox('AJLoveChina', {
|
|
||||||
originX: 'center',
|
|
||||||
originY: 'center',
|
|
||||||
textAlign: 'center',
|
|
||||||
fontSize: 12,
|
|
||||||
})
|
|
||||||
|
|
||||||
let group = new fabric.Group([circle, text], {
|
|
||||||
left: 100,
|
|
||||||
top: 100,
|
|
||||||
originX: 'center',
|
|
||||||
originY: 'center',
|
|
||||||
})
|
|
||||||
|
|
||||||
group.on('mousedblclick', () => {
|
|
||||||
// textForEditing is temporary obj,
|
|
||||||
// and will be removed after editing
|
|
||||||
console.log(text.type)
|
|
||||||
let textForEditing = new fabric.Textbox(text.text, {
|
|
||||||
originX: 'center',
|
|
||||||
originY: 'center',
|
|
||||||
textAlign: text.textAlign,
|
|
||||||
fontSize: text.fontSize,
|
|
||||||
|
|
||||||
left: group.left,
|
|
||||||
top: group.top,
|
|
||||||
})
|
|
||||||
|
|
||||||
// hide group inside text
|
|
||||||
text.visible = false
|
|
||||||
// note important, text cannot be hidden without this
|
|
||||||
group.addWithUpdate()
|
|
||||||
|
|
||||||
textForEditing.visible = true
|
|
||||||
// do not give controls, do not allow move/resize/rotation on this
|
|
||||||
textForEditing.hasConstrols = false
|
|
||||||
|
|
||||||
// now add this temporary obj to canvas
|
|
||||||
canvas.add(textForEditing)
|
|
||||||
canvas.setActiveObject(textForEditing)
|
|
||||||
// make the cursor showing
|
|
||||||
textForEditing.enterEditing()
|
|
||||||
textForEditing.selectAll()
|
|
||||||
|
|
||||||
// editing:exited means you click outside of the textForEditing
|
|
||||||
textForEditing.on('editing:exited', () => {
|
|
||||||
let newVal = textForEditing.text
|
|
||||||
let oldVal = text.text
|
|
||||||
|
|
||||||
// then we check if text is changed
|
|
||||||
if (newVal !== oldVal) {
|
|
||||||
text.set({
|
|
||||||
text: newVal,
|
|
||||||
visible: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
// comment before, you must call this
|
|
||||||
group.addWithUpdate()
|
|
||||||
|
|
||||||
// we do not need textForEditing anymore
|
|
||||||
textForEditing.visible = false
|
|
||||||
canvas?.remove(textForEditing)
|
|
||||||
|
|
||||||
// optional, buf for better user experience
|
|
||||||
canvas?.setActiveObject(group)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
canvas?.add(group)
|
|
||||||
}, [canvas])
|
|
||||||
|
|
||||||
const addRect = () => {
|
|
||||||
const rect = new fabric.Rect({
|
|
||||||
height: 200,
|
|
||||||
width: 200,
|
|
||||||
top: 10,
|
|
||||||
left: 10,
|
|
||||||
opacity: 0.4,
|
|
||||||
fill: randomColor(),
|
|
||||||
stroke: 'red',
|
|
||||||
name: uuidv4(),
|
|
||||||
})
|
|
||||||
|
|
||||||
addShape(rect)
|
|
||||||
}
|
|
||||||
|
|
||||||
const addHorizontalLine = () => {
|
|
||||||
const { x1, y1, x2, y2 } = { x1: 20, y1: 100, x2: 220, y2: 100 }
|
|
||||||
/**
|
|
||||||
* 시작X,시작Y,도착X,도착Y 좌표
|
|
||||||
*/
|
|
||||||
const horizontalLine = new fabric.Line([x1, y1, x2, y2], {
|
|
||||||
name: uuidv4(),
|
|
||||||
stroke: 'red',
|
|
||||||
strokeWidth: 3,
|
|
||||||
selectable: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
const text = new fabric.Text(getDistance(x1, y1, x2, y2).toString(), {
|
|
||||||
fontSize: 20,
|
|
||||||
left: (x2 - x1) / 2,
|
|
||||||
top: y1 - 20,
|
|
||||||
})
|
|
||||||
|
|
||||||
const group = new fabric.Group([horizontalLine, text], {
|
|
||||||
left: 20,
|
|
||||||
top: 20,
|
|
||||||
})
|
|
||||||
|
|
||||||
// addShape(horizontalLine)
|
|
||||||
addShape(group)
|
|
||||||
console.log(JSON.stringify(canvas))
|
|
||||||
}
|
|
||||||
|
|
||||||
const addVerticalLine = () => {
|
|
||||||
const verticalLine = new fabric.Line([10, 10, 10, 100], {
|
|
||||||
name: uuidv4(),
|
|
||||||
stroke: 'red',
|
|
||||||
strokeWidth: 3,
|
|
||||||
selectable: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
addShape(verticalLine)
|
|
||||||
}
|
|
||||||
|
|
||||||
const addTriangle = () => {
|
|
||||||
const triangle = new fabric.Triangle({
|
|
||||||
name: uuidv4(),
|
|
||||||
top: 50,
|
|
||||||
left: 50,
|
|
||||||
width: 100,
|
|
||||||
stroke: randomColor(),
|
|
||||||
strokeWidth: 3,
|
|
||||||
})
|
|
||||||
|
|
||||||
addShape(triangle)
|
|
||||||
}
|
|
||||||
|
|
||||||
const addTrapezoid = () => {
|
|
||||||
const trapezoid = new fabric.Polygon(
|
|
||||||
[
|
|
||||||
{ x: 100, y: 100 }, // 좌상단
|
|
||||||
{ x: 500, y: 100 }, // 우상단
|
|
||||||
{ x: 750, y: 700 }, // 우하단
|
|
||||||
{ x: 250, y: 400 }, // 좌하단
|
|
||||||
],
|
|
||||||
{
|
|
||||||
name: uuidv4(),
|
|
||||||
stroke: 'red',
|
|
||||||
opacity: 0.4,
|
|
||||||
strokeWidth: 3,
|
|
||||||
selectable: true,
|
|
||||||
objectCaching: false,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
attachCustomControlOnPolygon(trapezoid)
|
|
||||||
const group = addDistanceTextToPolygon(trapezoid)
|
|
||||||
addGroupClickEvent(group)
|
|
||||||
canvas?.add(group)
|
|
||||||
canvas?.renderAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
// group에 클릭 이벤트를 추가하여 클릭 시 group을 제거하고 object들만 남기는 함수
|
|
||||||
function addGroupClickEvent(group) {
|
|
||||||
group.on('selected', (e) => {
|
|
||||||
console.log(e)
|
|
||||||
})
|
|
||||||
group.on('mousedblclick', (e) => {
|
|
||||||
// textForEditing is temporary obj,
|
|
||||||
// and will be removed after editing
|
|
||||||
const pointer = canvas?.getPointer(e.e) // 마우스 클릭 위치 가져오기
|
|
||||||
let minDistance = Infinity
|
|
||||||
let closestTextbox = null
|
|
||||||
const groupPoint = group.getCenterPoint()
|
|
||||||
group.getObjects().forEach(function (object) {
|
|
||||||
if (object.type === 'textbox') {
|
|
||||||
// 객체가 TextBox인지 확인
|
|
||||||
|
|
||||||
const objectCenter = object.getCenterPoint() // TextBox 객체의 중심점 가져오기
|
|
||||||
const dx = objectCenter.x + groupPoint.x - pointer.x
|
|
||||||
const dy = objectCenter.y + groupPoint.y - pointer.y
|
|
||||||
const distance = Math.sqrt(dx * dx + dy * dy) // 마우스 클릭 위치와 TextBox 객체 사이의 거리 계산
|
|
||||||
|
|
||||||
if (distance < minDistance) {
|
|
||||||
// 가장 짧은 거리를 가진 TextBox 객체 찾기
|
|
||||||
minDistance = distance
|
|
||||||
closestTextbox = object
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
let textForEditing = new fabric.Textbox(closestTextbox.text, {
|
|
||||||
originX: 'center',
|
|
||||||
originY: 'center',
|
|
||||||
textAlign: closestTextbox.textAlign,
|
|
||||||
fontSize: closestTextbox.fontSize,
|
|
||||||
left: closestTextbox.left + groupPoint.x,
|
|
||||||
top: closestTextbox.top + groupPoint.y,
|
|
||||||
})
|
|
||||||
|
|
||||||
// hide group inside text
|
|
||||||
closestTextbox.visible = false
|
|
||||||
// note important, text cannot be hidden without this
|
|
||||||
group.addWithUpdate()
|
|
||||||
|
|
||||||
textForEditing.visible = true
|
|
||||||
// do not give controls, do not allow move/resize/rotation on this
|
|
||||||
textForEditing.hasConstrols = false
|
|
||||||
|
|
||||||
// now add this temporary obj to canvas
|
|
||||||
canvas?.add(textForEditing)
|
|
||||||
canvas?.setActiveObject(textForEditing)
|
|
||||||
// make the cursor showing
|
|
||||||
textForEditing?.enterEditing()
|
|
||||||
textForEditing?.selectAll()
|
|
||||||
|
|
||||||
// editing:exited means you click outside of the textForEditing
|
|
||||||
textForEditing?.on('editing:exited', () => {
|
|
||||||
let newVal = textForEditing.text
|
|
||||||
|
|
||||||
// then we check if text is changed
|
|
||||||
closestTextbox.set({
|
|
||||||
text: newVal,
|
|
||||||
visible: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
// comment before, you must call this
|
|
||||||
group.addWithUpdate()
|
|
||||||
|
|
||||||
// we do not need textForEditing anymore
|
|
||||||
textForEditing.visible = false
|
|
||||||
canvas?.remove(textForEditing)
|
|
||||||
|
|
||||||
// optional, buf for better user experience
|
|
||||||
canvas?.setActiveObject(group)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// IText를 수정할 때 해당 값을 길이로 갖는 다른 polygon을 생성하고 다시 그룹화하는 함수
|
|
||||||
function addTextModifiedEvent(text, polygon, index) {
|
|
||||||
text.on('editing:exited', function () {})
|
|
||||||
}
|
|
||||||
|
|
||||||
const randomColor = () => {
|
|
||||||
return '#' + Math.round(Math.random() * 0xffffff).toString(16)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="flex justify-center my-8 w-full">
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-blue-500 text-white" onClick={addRect}>
|
|
||||||
ADD RECTANGLE
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-blue-500 text-white" onClick={addHorizontalLine}>
|
|
||||||
ADD HORIZONTAL LINE
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-blue-500 text-white" onClick={addVerticalLine}>
|
|
||||||
ADD VERTICALITY LINE
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-blue-500 text-white" onClick={addTriangle}>
|
|
||||||
ADD TRIANGLE
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-blue-500 text-white" onClick={addTrapezoid}>
|
|
||||||
ADD TRAPEZOID
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-black text-white" onClick={handleCopy}>
|
|
||||||
COPY shape
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-red-500 text-white" onClick={handleDelete}>
|
|
||||||
DELETE
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-red-500 text-white" onClick={handleClear}>
|
|
||||||
CLEAR
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-green-500 text-white" onClick={handleUndo}>
|
|
||||||
UNDO
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-green-300 text-white" onClick={handleRedo}>
|
|
||||||
REDO
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-black text-white" onClick={handleSave}>
|
|
||||||
저장
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-black text-white" onClick={handlePaste}>
|
|
||||||
붙여넣기
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-black text-white" onClick={() => handleRotate()}>
|
|
||||||
45도 회전
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="w-30 mx-2 p-2 rounded bg-black text-white"
|
|
||||||
onClick={() => {
|
|
||||||
saveImage('제목')
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
이미지 저장
|
|
||||||
</button>
|
|
||||||
<button className="w-30 mx-2 p-2 rounded bg-black text-white" onClick={handleFlip}>
|
|
||||||
도형반전
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="flex justify-center"
|
|
||||||
style={{
|
|
||||||
border: '1px solid',
|
|
||||||
width: 1000,
|
|
||||||
height: 1000,
|
|
||||||
margin: 'auto',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<canvas id="canvas" />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,324 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import React, { useEffect, useState } from 'react'
|
|
||||||
import { Button } from '@nextui-org/react'
|
|
||||||
|
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
|
||||||
|
|
||||||
import { useRecoilState } from 'recoil'
|
|
||||||
import { customSettingsState } from '@/store/canvasAtom'
|
|
||||||
import { modalContent, modalState } from '@/store/modalAtom'
|
|
||||||
|
|
||||||
import ColorPicker from './common/color-picker/ColorPicker'
|
|
||||||
|
|
||||||
export default function Settings() {
|
|
||||||
const [objectNo, setObjectNo] = useState('test123240829010')
|
|
||||||
const [error, setError] = useState(null)
|
|
||||||
const [customSettings, setCustomSettings] = useRecoilState(customSettingsState)
|
|
||||||
|
|
||||||
const [color, setColor] = useState('#ff0000')
|
|
||||||
|
|
||||||
const [open, setOpen] = useRecoilState(modalState)
|
|
||||||
const [contents, setContent] = useRecoilState(modalContent)
|
|
||||||
|
|
||||||
const { get, post } = useAxios()
|
|
||||||
|
|
||||||
const handleSavePopup = () => {
|
|
||||||
console.log('color ', color)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleClosePopup = () => {
|
|
||||||
setContent('')
|
|
||||||
setOpen(false)
|
|
||||||
console.log('colorSetting ', color)
|
|
||||||
}
|
|
||||||
|
|
||||||
const colorSetting = (
|
|
||||||
<>
|
|
||||||
<br />
|
|
||||||
<h1>React ColorPicker</h1>
|
|
||||||
<ColorPicker color={color} setColor={setColor} />
|
|
||||||
<div className="p-4">{color}</div>
|
|
||||||
<div>
|
|
||||||
<button onClick={handleSavePopup}>저장</button> <p />
|
|
||||||
<button onClick={handleClosePopup}>취소</button>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
const customStyles = {
|
|
||||||
overlay: {
|
|
||||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
||||||
},
|
|
||||||
content: {
|
|
||||||
width: '300px',
|
|
||||||
height: '400px',
|
|
||||||
margin: 'auto',
|
|
||||||
borderRadius: '4px',
|
|
||||||
boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
|
|
||||||
padding: '20px',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 상태를 하나의 객체로 관리
|
|
||||||
const [settings, setSettings] = useState({
|
|
||||||
display1: Array(11).fill(false), // 화면 표시1
|
|
||||||
display2: Array(3).fill(false), // 화면 표시2
|
|
||||||
rangeSetting: 0, // 흡착 범위 설정
|
|
||||||
gridSettings: Array(5).fill(false), // 그리드 설정
|
|
||||||
})
|
|
||||||
|
|
||||||
const gridItems = {
|
|
||||||
display1: [
|
|
||||||
'할당 표시',
|
|
||||||
'도면 표시',
|
|
||||||
'그리드 표시',
|
|
||||||
'문자 표시',
|
|
||||||
'흐름방향 표시',
|
|
||||||
'복도치수 표시',
|
|
||||||
'실제치수 표시',
|
|
||||||
'치수 표시 없음',
|
|
||||||
'가대 표시',
|
|
||||||
'좌표 표시',
|
|
||||||
'도면전환 표시',
|
|
||||||
],
|
|
||||||
display2: ['테두리만', '라인해치', 'All Painted'],
|
|
||||||
rangeSetting: ['극소', '소', '중', '대'],
|
|
||||||
gridSettings: ['임의 그리드', '실선 그리드', '점 그리드', '그리드 색 설정', '흡착점 추가'],
|
|
||||||
}
|
|
||||||
|
|
||||||
// 초기 조회
|
|
||||||
useEffect(() => {
|
|
||||||
if (!objectNo) {
|
|
||||||
alert('object_no를 입력하세요.')
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
// 클릭 시 상태 변경 함수
|
|
||||||
const handleToggle = (type, index) => {
|
|
||||||
// '실선 그리드' 클릭 시 팝업 열기
|
|
||||||
if (type === 'gridSettings' && gridItems.gridSettings[index] === '실선 그리드') {
|
|
||||||
//openGridPopup()
|
|
||||||
}
|
|
||||||
|
|
||||||
// '그리드 색 설정' 클릭 시 팝업 열기
|
|
||||||
if (type === 'gridSettings' && gridItems.gridSettings[index] === '그리드 색 설정') {
|
|
||||||
//setSelectedGridSetting(gridItems.gridSettings[index])
|
|
||||||
//setIsPopupOpen(true)
|
|
||||||
//return prevSettings // 설정은 변경하지 않음
|
|
||||||
|
|
||||||
setOpen(true)
|
|
||||||
setContent({ ...colorSetting })
|
|
||||||
}
|
|
||||||
|
|
||||||
setSettings((prevSettings) => {
|
|
||||||
// prevSettings[type]이 배열인지 확인하고, 그렇지 않은 경우 빈 배열로 초기화
|
|
||||||
let updated = Array.isArray(prevSettings[type]) ? [...prevSettings[type]] : []
|
|
||||||
|
|
||||||
if (type === 'rangeSetting') {
|
|
||||||
return { ...prevSettings, [type]: index }
|
|
||||||
}
|
|
||||||
|
|
||||||
updated[index] = updated[index] === false ? true : false
|
|
||||||
return { ...prevSettings, [type]: updated }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// '실선 그리드' 클릭 시 팝업을 열기 위한 함수
|
|
||||||
const openGridPopup = () => {
|
|
||||||
const popupWidth = 500
|
|
||||||
const popupHeight = 300
|
|
||||||
|
|
||||||
// 팝업 창 위치를 화면 중앙으로 조정하기 위해 계산
|
|
||||||
const left = window.innerWidth / 2 - popupWidth / 2
|
|
||||||
const top = window.innerHeight / 2 - popupHeight / 2
|
|
||||||
|
|
||||||
// 새 창 열기
|
|
||||||
window
|
|
||||||
.open
|
|
||||||
//'./components/intro', // 팝업으로 띄울 페이지의 URL
|
|
||||||
//'_blank', // 새 창으로 열기
|
|
||||||
//`width=${popupWidth},height=${popupHeight},top=${top},left=${left}`, // 크기와 위치 지정
|
|
||||||
()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Canvas Setting 조회 및 초기화
|
|
||||||
const handleSelect = async () => {
|
|
||||||
try {
|
|
||||||
if (!objectNo) {
|
|
||||||
alert('object_no를 입력하세요.')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
|
|
||||||
|
|
||||||
// 데이터가 없는 경우
|
|
||||||
if (!res) {
|
|
||||||
console.warn('조회 결과가 없습니다.')
|
|
||||||
// 기본값을 설정하거나 사용자에게 알림 표시
|
|
||||||
setSettings({
|
|
||||||
display1: Array(11).fill(false), // 화면 표시1 기본값
|
|
||||||
display2: Array(3).fill(false), // 화면 표시2 기본값
|
|
||||||
rangeSetting: 0, // 흡착 범위 설정 기본값
|
|
||||||
gridSettings: Array(5).fill(false), // 그리드 설정 기본값
|
|
||||||
})
|
|
||||||
|
|
||||||
alert('조회된 데이터가 없습니다. 기본 설정이 적용됩니다.')
|
|
||||||
return // 이후 코드 실행을 중단
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
display1: [
|
|
||||||
res.assignDisplay,
|
|
||||||
res.drawDisplay,
|
|
||||||
res.gridDisplay,
|
|
||||||
res.charDisplay,
|
|
||||||
res.flowDisplay,
|
|
||||||
res.hallwayDimenDisplay,
|
|
||||||
res.actualDimenDisplay,
|
|
||||||
res.noDimenDisplay,
|
|
||||||
res.trestleDisplay,
|
|
||||||
res.coordiDisplay,
|
|
||||||
res.drawConverDisplay,
|
|
||||||
],
|
|
||||||
display2: [res.onlyBorder, res.lineHatch, res.allPainted],
|
|
||||||
rangeSetting: res.adsorpRangeSetting,
|
|
||||||
gridSettings: [res.randomGrid, res.solidGrid, res.dotGrid, res.gridColorSet, res.adsorpPointAdd],
|
|
||||||
}
|
|
||||||
|
|
||||||
// 데이터 설정
|
|
||||||
setSettings({
|
|
||||||
display1: data.display1,
|
|
||||||
display2: data.display2,
|
|
||||||
rangeSetting: data.rangeSetting,
|
|
||||||
gridSettings: data.gridSettings,
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Data fetching error:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Canvas Setting 저장
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
if (!objectNo) {
|
|
||||||
alert('object_no를 입력하세요.')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const patternData = {
|
|
||||||
objectNo,
|
|
||||||
assignDisplay: settings.display1[0],
|
|
||||||
drawDisplay: settings.display1[1],
|
|
||||||
gridDisplay: settings.display1[2],
|
|
||||||
charDisplay: settings.display1[3],
|
|
||||||
flowDisplay: settings.display1[4],
|
|
||||||
hallwayDimenDisplay: settings.display1[5],
|
|
||||||
actualDimenDisplay: settings.display1[6],
|
|
||||||
noDimenDisplay: settings.display1[7],
|
|
||||||
trestleDisplay: settings.display1[8],
|
|
||||||
coordiDisplay: settings.display1[9],
|
|
||||||
drawConverDisplay: settings.display1[10],
|
|
||||||
onlyBorder: settings.display2[0],
|
|
||||||
lineHatch: settings.display2[1],
|
|
||||||
allPainted: settings.display2[2],
|
|
||||||
adsorpRangeSetting: settings.rangeSetting,
|
|
||||||
randomGrid: settings.gridSettings[0],
|
|
||||||
solidGrid: settings.gridSettings[1],
|
|
||||||
dotGrid: settings.gridSettings[2],
|
|
||||||
gridColorSet: settings.gridSettings[3],
|
|
||||||
adsorpPointAdd: settings.gridSettings[4],
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('patternData', patternData)
|
|
||||||
|
|
||||||
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData })
|
|
||||||
|
|
||||||
//Recoil 설정
|
|
||||||
setCustomSettings({ ...patternData })
|
|
||||||
|
|
||||||
// 저장 후 재조회
|
|
||||||
await handleSelect()
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="container mx-auto p-4 m-4 border">
|
|
||||||
<div align="right">
|
|
||||||
<input type="text" placeholder="Object No 입력" value={objectNo} onChange={(e) => setObjectNo(e.target.value)} />
|
|
||||||
<Button onClick={handleSelect}>조회</Button>
|
|
||||||
<Button onClick={handleSubmit}>저장</Button>
|
|
||||||
</div>
|
|
||||||
<div className="container mx-auto p-4 m-4 border">
|
|
||||||
<h1>[디스플레이 설정]</h1>
|
|
||||||
<h1>* 도면에 표시할 항목을 클릭하면 적용 됩니다.</h1>
|
|
||||||
<div className="grid-container2">
|
|
||||||
{gridItems.display1.map((item, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={`grid-item ${settings.display1[index] === true ? 'selected' : 'unselected'}`}
|
|
||||||
onClick={() => handleToggle('display1', index)}
|
|
||||||
>
|
|
||||||
{settings.display1[index]} {item}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<br />
|
|
||||||
<h1>* 화면 표시</h1>
|
|
||||||
<div className="grid-container3">
|
|
||||||
{gridItems.display2.map((item, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={`grid-item ${settings.display2[index] === true ? 'selected' : 'unselected'}`}
|
|
||||||
onClick={() => handleToggle('display2', index)}
|
|
||||||
>
|
|
||||||
{settings.display2[index]} {item}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<h1>[글꼴/도면크기 설정]</h1>
|
|
||||||
<h1>* 글꼴 및 크기 변경</h1>
|
|
||||||
<div className="grid-container2">
|
|
||||||
<div className="grid-item">문자 글꼴 변경</div>
|
|
||||||
<div className="grid-item">흐름방향 글꼴 변경</div>
|
|
||||||
<div className="grid-item">치수 글꼴 변경</div>
|
|
||||||
<div className="grid-item">회로번호 글꼴 변경</div>
|
|
||||||
</div>
|
|
||||||
``
|
|
||||||
<h1>* 흡착 범위 설정</h1>
|
|
||||||
<div className="grid-container4">
|
|
||||||
{gridItems.rangeSetting.map((item, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={`grid-item ${settings.rangeSetting === index ? 'selected' : 'unselected'}`}
|
|
||||||
onClick={() => handleToggle('rangeSetting', index)}
|
|
||||||
>
|
|
||||||
{item}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="grid-container3">
|
|
||||||
<div className="grid-item">치수선 설정</div>
|
|
||||||
<div className="grid-item">도면 크기 설정</div>
|
|
||||||
<div className="grid-item">흡착점 ON</div>
|
|
||||||
</div>
|
|
||||||
<h1>[그리드 설정]</h1>
|
|
||||||
<div>
|
|
||||||
<ColorPicker color={color} setColor={setColor} />
|
|
||||||
<div className="p-4">{color}</div>
|
|
||||||
</div>
|
|
||||||
<div className="grid-container2">
|
|
||||||
{gridItems.gridSettings.map((item, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={`grid-item ${settings.gridSettings[index] === true ? 'selected' : 'unselected'}`}
|
|
||||||
onClick={() => handleToggle('gridSettings', index)}
|
|
||||||
>
|
|
||||||
{settings.gridSettings[index]} {item}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -87,7 +87,7 @@ export default function Estimate({}) {
|
|||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
const { closeAll } = usePopup()
|
const { closeAll } = usePopup()
|
||||||
const { setMenuNumber } = useCanvasMenu()
|
const { setSelectedMenu } = useCanvasMenu()
|
||||||
//새로 추가한 첨부파일 props
|
//새로 추가한 첨부파일 props
|
||||||
const fileUploadProps = {
|
const fileUploadProps = {
|
||||||
uploadFiles: files,
|
uploadFiles: files,
|
||||||
@ -142,7 +142,7 @@ export default function Estimate({}) {
|
|||||||
}, [selectedPlan])
|
}, [selectedPlan])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMenuNumber(5)
|
setSelectedMenu('estimate')
|
||||||
initEstimate()
|
initEstimate()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|||||||
@ -3,11 +3,14 @@
|
|||||||
import { useRef } from 'react'
|
import { useRef } from 'react'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
|
|
||||||
export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
|
export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
|
||||||
const fileInputRef = useRef(null)
|
const fileInputRef = useRef(null)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
|
const { swalFire } = useSwal()
|
||||||
|
|
||||||
const handleButtonClick = (e) => {
|
const handleButtonClick = (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
fileInputRef.current.click()
|
fileInputRef.current.click()
|
||||||
@ -20,9 +23,16 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
|
|||||||
|
|
||||||
const fileList = []
|
const fileList = []
|
||||||
let passFlag = true
|
let passFlag = true
|
||||||
|
const allowedFileTypes = [
|
||||||
|
'image/',
|
||||||
|
'application/pdf',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
'application/vnd.ms-excel',
|
||||||
|
]
|
||||||
Array.from(e.target.files).forEach((file) => {
|
Array.from(e.target.files).forEach((file) => {
|
||||||
let fileType = file.type
|
//엑셀, pdf, 이미지
|
||||||
if (!fileType.includes('image')) {
|
const fileType = file.type
|
||||||
|
if (!allowedFileTypes.some((type) => fileType.includes(type))) {
|
||||||
passFlag = false
|
passFlag = false
|
||||||
} else {
|
} else {
|
||||||
fileList.push({ data: file, id: uuidv4() })
|
fileList.push({ data: file, id: uuidv4() })
|
||||||
@ -30,30 +40,11 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!passFlag) {
|
if (!passFlag) {
|
||||||
alert(getMessage('estimate.detail.fileList.extCheck'))
|
swalFire({ text: getMessage('estimate.detail.fileList.extCheck'), type: 'alert', icon: 'error' })
|
||||||
}
|
}
|
||||||
|
|
||||||
// const { files } = e.target
|
|
||||||
// const file = files[0]
|
|
||||||
// const fileType = file.type
|
|
||||||
// if (!fileType.includes('image')) {
|
|
||||||
// return alert(getMessage('estimate.detail.fileList.extCheck'))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// setUploadFiles([...uploadFiles, { data: e.target.files[0], id: uuidv4() }])
|
|
||||||
//다중으로 변경
|
|
||||||
setUploadFiles([...uploadFiles, ...fileList])
|
setUploadFiles([...uploadFiles, ...fileList])
|
||||||
e.target.value = ''
|
e.target.value = ''
|
||||||
// const formData = new FormData()
|
|
||||||
// formData.append('file', e.target.files[0])
|
|
||||||
// formData.append('objectNo', objectNo) // 받아와야 하는 값
|
|
||||||
// formData.append('planNo', planNo) // 받아와야 하는 값
|
|
||||||
// formData.append('category', category) // 받아와야 하는 값
|
|
||||||
// formData.append('userId', session.userId)
|
|
||||||
|
|
||||||
// await promisePost({ url: '/api/file/fileUpload', data: formData }).then((res) => {
|
|
||||||
// if (res.data > 0) setUploadFiles([...files, { name: e.target.files[0].name, id: uuidv4() }])
|
|
||||||
// })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteFile = (id) => {
|
const deleteFile = (id) => {
|
||||||
@ -65,10 +56,17 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
|
|||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const fileList = []
|
const fileList = []
|
||||||
let passFlag = true
|
let passFlag = true
|
||||||
|
const allowedFileTypes = [
|
||||||
|
'image/',
|
||||||
|
'application/pdf',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
'application/vnd.ms-excel',
|
||||||
|
]
|
||||||
|
|
||||||
Array.from(e.dataTransfer.files).forEach((file) => {
|
Array.from(e.dataTransfer.files).forEach((file) => {
|
||||||
|
//엑셀, pdf, 이미지
|
||||||
let fileType = file.type
|
let fileType = file.type
|
||||||
if (!fileType.includes('image')) {
|
if (!allowedFileTypes.some((type) => fileType.includes(type))) {
|
||||||
passFlag = false
|
passFlag = false
|
||||||
} else {
|
} else {
|
||||||
fileList.push({ data: file, id: uuidv4() })
|
fileList.push({ data: file, id: uuidv4() })
|
||||||
@ -76,7 +74,7 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!passFlag) {
|
if (!passFlag) {
|
||||||
alert(getMessage('estimate.detail.fileList.extCheck'))
|
swalFire({ text: getMessage('estimate.detail.fileList.extCheck'), type: 'alert', icon: 'error' })
|
||||||
}
|
}
|
||||||
|
|
||||||
setUploadFiles([...uploadFiles, ...fileList])
|
setUploadFiles([...uploadFiles, ...fileList])
|
||||||
@ -103,16 +101,7 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
|
|||||||
<label className="file-upload" htmlFor="img" onClick={handleButtonClick}>
|
<label className="file-upload" htmlFor="img" onClick={handleButtonClick}>
|
||||||
{getMessage('estimate.detail.fileList.btn')}
|
{getMessage('estimate.detail.fileList.btn')}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input type="file" multiple name="file" ref={fileInputRef} style={{ display: 'none' }} onChange={(e) => onChangeFiles(e)} />
|
||||||
type="file"
|
|
||||||
multiple
|
|
||||||
name="file"
|
|
||||||
id="img"
|
|
||||||
accept="image/*"
|
|
||||||
ref={fileInputRef}
|
|
||||||
style={{ display: 'none' }}
|
|
||||||
onChange={(e) => onChangeFiles(e)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="drag-file-area"
|
className="drag-file-area"
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { globalLocaleStore } from '@/store/localeAtom'
|
|||||||
export default function CanvasLayout({ children }) {
|
export default function CanvasLayout({ children }) {
|
||||||
// const { menuNumber } = props
|
// const { menuNumber } = props
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
const { menuNumber } = useCanvasMenu()
|
const { selectedMenu } = useCanvasMenu()
|
||||||
const { session } = useContext(SessionContext)
|
const { session } = useContext(SessionContext)
|
||||||
const { floorPlanState } = useContext(FloorPlanContext)
|
const { floorPlanState } = useContext(FloorPlanContext)
|
||||||
const { objectNo, pid } = floorPlanState
|
const { objectNo, pid } = floorPlanState
|
||||||
@ -30,7 +30,7 @@ export default function CanvasLayout({ children }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="canvas-layout">
|
<div className="canvas-layout">
|
||||||
<div className={`canvas-page-list ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
<div className={`canvas-page-list ${['outline', 'surface', 'module'].includes(selectedMenu) ? 'active' : ''}`}>
|
||||||
<div className="canvas-plane-wrap">
|
<div className="canvas-plane-wrap">
|
||||||
{plans.map((plan, index) => (
|
{plans.map((plan, index) => (
|
||||||
<button
|
<button
|
||||||
|
|||||||
@ -38,7 +38,7 @@ import {
|
|||||||
} from '@/store/settingAtom'
|
} from '@/store/settingAtom'
|
||||||
import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom'
|
import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom'
|
||||||
import { commonUtilsState } from '@/store/commonUtilsAtom'
|
import { commonUtilsState } from '@/store/commonUtilsAtom'
|
||||||
import { menusState, menuTypeState } from '@/store/menuAtom'
|
import { menusState } from '@/store/menuAtom'
|
||||||
import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||||
import { pwrGnrSimTypeState } from '@/store/simulatorAtom'
|
import { pwrGnrSimTypeState } from '@/store/simulatorAtom'
|
||||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||||
@ -51,12 +51,11 @@ import { QcastContext } from '@/app/QcastProvider'
|
|||||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
export default function CanvasMenu(props) {
|
export default function CanvasMenu(props) {
|
||||||
const { menuNumber, setMenuNumber } = props
|
const { selectedMenu, setSelectedMenu } = props
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { addPopup } = usePopup()
|
const { addPopup } = usePopup()
|
||||||
const canvasMenus = useRecoilValue(menusState)
|
const canvasMenus = useRecoilValue(menusState)
|
||||||
const [type, setType] = useRecoilState(menuTypeState)
|
|
||||||
const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
|
const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
|
||||||
const setAppMessageState = useSetRecoilState(appMessageStore)
|
const setAppMessageState = useSetRecoilState(appMessageStore)
|
||||||
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
||||||
@ -165,8 +164,8 @@ export default function CanvasMenu(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onClickNav = async (menu) => {
|
const onClickNav = async (menu) => {
|
||||||
switch (menu.index) {
|
switch (menu.type) {
|
||||||
case 0:
|
case 'drawing':
|
||||||
swalFire({
|
swalFire({
|
||||||
text: getMessage('stuff.detail.move.confirmMsg'),
|
text: getMessage('stuff.detail.move.confirmMsg'),
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
@ -176,17 +175,15 @@ export default function CanvasMenu(props) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 1:
|
case 'placement':
|
||||||
setType('placementShape')
|
|
||||||
onClickPlacementInitialMenu()
|
onClickPlacementInitialMenu()
|
||||||
await reloadCanvasStatus(objectNo, pid)
|
await reloadCanvasStatus(objectNo, pid)
|
||||||
break
|
break
|
||||||
case 2:
|
case 'outline':
|
||||||
setType('outline')
|
|
||||||
await reloadCanvasStatus(objectNo, pid)
|
await reloadCanvasStatus(objectNo, pid)
|
||||||
break
|
break
|
||||||
case 3:
|
case 'surface':
|
||||||
if (menuNumber > menu.index) {
|
if (selectedMenu > menu.index) {
|
||||||
const modules = canvas.getObjects().filter((module) => module.name === POLYGON_TYPE.MODULE)
|
const modules = canvas.getObjects().filter((module) => module.name === POLYGON_TYPE.MODULE)
|
||||||
|
|
||||||
if (modules.length > 0) {
|
if (modules.length > 0) {
|
||||||
@ -212,7 +209,6 @@ export default function CanvasMenu(props) {
|
|||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
onClickNav(menu)
|
onClickNav(menu)
|
||||||
}
|
}
|
||||||
setType('surface')
|
|
||||||
},
|
},
|
||||||
denyFn: () => {
|
denyFn: () => {
|
||||||
return
|
return
|
||||||
@ -220,24 +216,23 @@ export default function CanvasMenu(props) {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
setType('surface')
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setType('surface')
|
setSelectedMenu(menu.type)
|
||||||
}
|
}
|
||||||
await reloadCanvasStatus(objectNo, pid)
|
await reloadCanvasStatus(objectNo, pid)
|
||||||
break
|
break
|
||||||
case 4:
|
case 4:
|
||||||
if (menuNumber < menu.index) {
|
if (selectedMenu < menu.index) {
|
||||||
if (!checkMenuAndCanvasState()) {
|
if (!checkMenuAndCanvasState()) {
|
||||||
swalFire({ text: getMessage('menu.validation.canvas.roof') })
|
swalFire({ text: getMessage('menu.validation.canvas.roof') })
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
setType('module')
|
setSelectedMenu('module')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
router.push(`/floor-plan?pid=${pid}&objectNo=${objectNo}`)
|
router.push(`/floor-plan?pid=${pid}&objectNo=${objectNo}`)
|
||||||
setType('module')
|
setSelectedMenu('module')
|
||||||
}
|
}
|
||||||
await reloadCanvasStatus(objectNo, pid)
|
await reloadCanvasStatus(objectNo, pid)
|
||||||
break
|
break
|
||||||
@ -247,11 +242,11 @@ export default function CanvasMenu(props) {
|
|||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const estimateDetail = res.data
|
const estimateDetail = res.data
|
||||||
if (estimateDetail.estimateDate !== null) {
|
if (estimateDetail.estimateDate !== null) {
|
||||||
setMenuNumber(menu.index)
|
setSelectedMenu(menu.type)
|
||||||
setCurrentMenu(menu.title)
|
setCurrentMenu(menu.title)
|
||||||
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
|
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
router.push(`/floor-plan/estimate/${menu.index}?pid=${selectedPlan.planNo}&objectNo=${objectNo}`)
|
router.push(`/floor-plan/estimate/${menu.type}?pid=${selectedPlan.planNo}&objectNo=${objectNo}`)
|
||||||
if (pathname === '/floor-plan/estimate/5') {
|
if (pathname === '/floor-plan/estimate/5') {
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
}
|
}
|
||||||
@ -268,7 +263,7 @@ export default function CanvasMenu(props) {
|
|||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const estimateDetail = res.data
|
const estimateDetail = res.data
|
||||||
if (estimateDetail.estimateDate !== null && estimateDetail.docNo) {
|
if (estimateDetail.estimateDate !== null && estimateDetail.docNo) {
|
||||||
setMenuNumber(menu.index)
|
setSelectedMenu(menu.type)
|
||||||
setCurrentMenu(menu.title)
|
setCurrentMenu(menu.title)
|
||||||
router.push(`/floor-plan/simulator/${menu.index}?pid=${selectedPlan.planNo}&objectNo=${objectNo}`)
|
router.push(`/floor-plan/simulator/${menu.index}?pid=${selectedPlan.planNo}&objectNo=${objectNo}`)
|
||||||
if (pathname === '/floor-plan/simulator/6') {
|
if (pathname === '/floor-plan/simulator/6') {
|
||||||
@ -283,14 +278,14 @@ export default function CanvasMenu(props) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if (menu.index !== 6 && menu.index !== 0 && menu.index !== 5) {
|
if (menu.type !== 'simulation' && menu.type !== 'estimate' && menu.type !== 'drawing') {
|
||||||
setMenuNumber(menu.index)
|
setSelectedMenu(menu.type)
|
||||||
setCurrentMenu(menu.title)
|
setCurrentMenu(menu.title)
|
||||||
}
|
}
|
||||||
if (pathname !== '/floor-plan') {
|
if (pathname !== '/floor-plan') {
|
||||||
// if (menu.index !== 0 ) {
|
// if (menu.index !== 0 ) {
|
||||||
//견적서 or 발전시뮬레이션 탭에서 같은 탭 클릭시 화면 이동했다 돌아오지않도록..
|
//견적서 or 발전시뮬레이션 탭에서 같은 탭 클릭시 화면 이동했다 돌아오지않도록..
|
||||||
if (menu.index !== 0 && menu.index !== 5 && menu.index !== 6) {
|
if (menu.type !== 'drawing' && menu.type !== 'estimate' && menu.type !== 'simulation') {
|
||||||
router.push(`/floor-plan?pid=${pid}&objectNo=${objectNo}`)
|
router.push(`/floor-plan?pid=${pid}&objectNo=${objectNo}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,10 +308,10 @@ export default function CanvasMenu(props) {
|
|||||||
const settingsModalOptions = useRecoilState(settingModalFirstOptionsState)
|
const settingsModalOptions = useRecoilState(settingModalFirstOptionsState)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (menuNumber === 1) {
|
if (selectedMenu === 'placement') {
|
||||||
onClickPlacementInitialMenu()
|
onClickPlacementInitialMenu()
|
||||||
}
|
}
|
||||||
if (menuNumber === 3) {
|
if (selectedMenu === 'surface') {
|
||||||
const moduleSurfacesArray = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
const moduleSurfacesArray = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||||
if (moduleSurfacesArray.length > 0) {
|
if (moduleSurfacesArray.length > 0) {
|
||||||
initRoofs()
|
initRoofs()
|
||||||
@ -327,7 +322,7 @@ export default function CanvasMenu(props) {
|
|||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [menuNumber, type])
|
}, [selectedMenu])
|
||||||
|
|
||||||
// 저장버튼(btn08) 클릭 시 호출되는 함수
|
// 저장버튼(btn08) 클릭 시 호출되는 함수
|
||||||
const handleSaveCanvas = async () => {
|
const handleSaveCanvas = async () => {
|
||||||
@ -424,26 +419,13 @@ export default function CanvasMenu(props) {
|
|||||||
} else {
|
} else {
|
||||||
setAppMessageState(JA)
|
setAppMessageState(JA)
|
||||||
}
|
}
|
||||||
}, [type, globalLocale])
|
}, [globalLocale])
|
||||||
|
|
||||||
/*useEffect(() => {
|
|
||||||
if (menuNumber === 1) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setMenuNumber(1)
|
|
||||||
// if ([2, 3].some((num) => num === canvasSetting?.roofSizeSet)) {
|
|
||||||
// setMenuNumber(3)
|
|
||||||
// setType('surface')
|
|
||||||
// setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
|
|
||||||
// } else {
|
|
||||||
// setMenuNumber(2)
|
|
||||||
// setType('outline')
|
|
||||||
// setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
|
||||||
// }
|
|
||||||
}, [basicSetting])*/
|
|
||||||
|
|
||||||
const checkMenuState = (menu) => {
|
const checkMenuState = (menu) => {
|
||||||
return (['2', '3'].includes(canvasSetting?.roofSizeSet) && menu.index === 2) || (menuNumber === 4 && [1, 2].includes(menu.index))
|
return (
|
||||||
|
(['2', '3'].includes(canvasSetting?.roofSizeSet) && menu.type === 'surface') ||
|
||||||
|
(selectedMenu === 'module' && ['drawing', 'placement'].includes(menu.type))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -552,17 +534,17 @@ export default function CanvasMenu(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`canvas-menu-wrap ${[2, 3, 4].some((num) => num === menuNumber) ? 'active' : ''}`}>
|
<div className={`canvas-menu-wrap ${['outline', 'surface', 'module'].some((num) => num === selectedMenu) ? 'active' : ''}`}>
|
||||||
<div className="canvas-menu-inner">
|
<div className="canvas-menu-inner">
|
||||||
<ul className="canvas-menu-list">
|
<ul className="canvas-menu-list">
|
||||||
{canvasMenus.map((menu) => {
|
{canvasMenus.map((menu) => {
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
key={`canvas-menu-${menu.index}`}
|
key={`canvas-menu-${menu.type}`}
|
||||||
className={`canvas-menu-item ${menuNumber === menu.index ? 'active' : ''}`}
|
className={`canvas-menu-item ${selectedMenu === menu.type ? 'active' : ''}`}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (['2', '3'].includes(canvasSetting?.roofSizeSet) && menu.index === 2) return
|
if (['2', '3'].includes(canvasSetting?.roofSizeSet) && menu.type === 'surface') return
|
||||||
if (menuNumber === 4 && [1, 2].includes(menu.index)) return
|
if (selectedMenu === 'module' && ['drawing', 'placement'].includes(menu.type)) return
|
||||||
await onClickNav(menu)
|
await onClickNav(menu)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -575,7 +557,7 @@ export default function CanvasMenu(props) {
|
|||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
<div className="canvas-side-btn-wrap">
|
<div className="canvas-side-btn-wrap">
|
||||||
{![5, 6].some((num) => num === menuNumber) && (
|
{!['estimate', 'simulation'].some((num) => num === selectedMenu) && (
|
||||||
<>
|
<>
|
||||||
{
|
{
|
||||||
<div className={`vertical-horizontal ${verticalHorizontalMode ? 'on' : ''}`}>
|
<div className={`vertical-horizontal ${verticalHorizontalMode ? 'on' : ''}`}>
|
||||||
@ -646,7 +628,7 @@ export default function CanvasMenu(props) {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{menuNumber === 5 && (
|
{selectedMenu === 'estimate' && (
|
||||||
<>
|
<>
|
||||||
<div className="ico-btn-from">
|
<div className="ico-btn-from">
|
||||||
<button
|
<button
|
||||||
@ -708,7 +690,7 @@ export default function CanvasMenu(props) {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{menuNumber === 6 && (
|
{selectedMenu === 'simulation' && (
|
||||||
<>
|
<>
|
||||||
<div className="ico-btn-from">
|
<div className="ico-btn-from">
|
||||||
<button type="button" className="btn-frame gray ico-flx" onClick={() => handleExcelPdfFileDown('EXCEL', '2')}>
|
<button type="button" className="btn-frame gray ico-flx" onClick={() => handleExcelPdfFileDown('EXCEL', '2')}>
|
||||||
@ -724,8 +706,8 @@ export default function CanvasMenu(props) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={`canvas-depth2-wrap ${[2, 3, 4].some((num) => num === menuNumber) ? 'active' : ''}`}>
|
<div className={`canvas-depth2-wrap ${['outline', 'surface', 'module'].some((num) => num === selectedMenu) ? 'active' : ''}`}>
|
||||||
{[2, 3, 4].some((num) => num === menuNumber) && <MenuDepth01 />}
|
{['outline', 'surface', 'module'].some((num) => num === selectedMenu) && <MenuDepth01 />}
|
||||||
</div>
|
</div>
|
||||||
{/* 견적서(menuNumber=== 5) 상세화면인경우 문서다운로드 팝업 */}
|
{/* 견적서(menuNumber=== 5) 상세화면인경우 문서다운로드 팝업 */}
|
||||||
{estimatePopupOpen && (
|
{estimatePopupOpen && (
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export default function FloorPlan({ children }) {
|
|||||||
const pid = searchParams.get('pid')
|
const pid = searchParams.get('pid')
|
||||||
|
|
||||||
const { closeAll } = usePopup()
|
const { closeAll } = usePopup()
|
||||||
const { menuNumber, setMenuNumber } = useCanvasMenu()
|
const { selectedMenu, setSelectedMenu } = useCanvasMenu()
|
||||||
const { fetchSettings } = useCanvasSetting()
|
const { fetchSettings } = useCanvasSetting()
|
||||||
const resetCurrentMenu = useResetRecoilState(currentMenuState)
|
const resetCurrentMenu = useResetRecoilState(currentMenuState)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -54,15 +54,17 @@ export default function FloorPlan({ children }) {
|
|||||||
}, [correntObjectNo])
|
}, [correntObjectNo])
|
||||||
|
|
||||||
const modalProps = {
|
const modalProps = {
|
||||||
menuNumber,
|
selectedMenu,
|
||||||
setMenuNumber,
|
setSelectedMenu,
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="canvas-wrap">
|
<div className="canvas-wrap">
|
||||||
<CanvasMenu {...modalProps} />
|
<CanvasMenu {...modalProps} />
|
||||||
<div className={`canvas-content ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>{children}</div>
|
<div className={`canvas-content ${selectedMenu === 'outline' || selectedMenu === 'surface' || selectedMenu === 'module' ? 'active' : ''}`}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -6,32 +6,37 @@ import { useMessage } from '@/hooks/useMessage'
|
|||||||
import useMenu from '@/hooks/common/useMenu'
|
import useMenu from '@/hooks/common/useMenu'
|
||||||
import { canvasState, currentMenuState } from '@/store/canvasAtom'
|
import { canvasState, currentMenuState } from '@/store/canvasAtom'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { menuTypeState, subMenusState } from '@/store/menuAtom'
|
import { subMenusState } from '@/store/menuAtom'
|
||||||
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
|
|
||||||
export default function MenuDepth01() {
|
export default function MenuDepth01() {
|
||||||
const type = useRecoilValue(menuTypeState)
|
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { handleMenu } = useMenu()
|
const { handleMenu } = useMenu()
|
||||||
|
const { selectedMenu, setSelectedMenu } = useCanvasMenu()
|
||||||
const [currentMenu, setCurrentMenu] = useRecoilState(currentMenuState)
|
const [currentMenu, setCurrentMenu] = useRecoilState(currentMenuState)
|
||||||
const subMenus = useRecoilValue(subMenusState)
|
const subMenus = useRecoilValue(subMenusState)
|
||||||
|
|
||||||
const onClickMenu = ({ id, menu }) => {
|
const onClickMenu = ({ id, menu }) => {
|
||||||
if (menu === currentMenu) {
|
if (menu === currentMenu) {
|
||||||
handleMenu(type)
|
handleMenu(selectedMenu)
|
||||||
} else {
|
} else {
|
||||||
setCurrentMenu(menu)
|
setCurrentMenu(menu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleMenu(type)
|
console.log(subMenus[selectedMenu])
|
||||||
|
}, [selectedMenu])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleMenu(selectedMenu)
|
||||||
canvas?.discardActiveObject()
|
canvas?.discardActiveObject()
|
||||||
}, [currentMenu])
|
}, [currentMenu])
|
||||||
return (
|
return (
|
||||||
<div className="canvas-depth2-inner">
|
<div className="canvas-depth2-inner">
|
||||||
<ul className="canvas-depth2-list">
|
<ul className="canvas-depth2-list">
|
||||||
{subMenus[type]?.map((menu) => {
|
{subMenus[selectedMenu]?.map((menu) => {
|
||||||
return (
|
return (
|
||||||
<li key={menu.id} className={`canvas-depth2-item ${menu.menu === currentMenu ? 'active' : ''}`}>
|
<li key={menu.id} className={`canvas-depth2-item ${menu.menu === currentMenu ? 'active' : ''}`}>
|
||||||
<button onClick={() => onClickMenu(menu)}>{getMessage(menu.name)}</button>
|
<button onClick={() => onClickMenu(menu)}>{getMessage(menu.name)}</button>
|
||||||
|
|||||||
@ -220,8 +220,8 @@ export default function PassivityCircuitAllocation(props) {
|
|||||||
goodsNo: model.goodsNo,
|
goodsNo: model.goodsNo,
|
||||||
serQtyList: [
|
serQtyList: [
|
||||||
{
|
{
|
||||||
serQty: result[index + 1].maxValue,
|
serQty: result[(index + 1).toString()].maxValue,
|
||||||
paralQty: result[index + 1].count,
|
paralQty: result[(index + 1).toString()].count,
|
||||||
rmdYn: 'Y',
|
rmdYn: 'Y',
|
||||||
usePossYn: 'Y',
|
usePossYn: 'Y',
|
||||||
roofSurfaceList: roofSurfaceList,
|
roofSurfaceList: roofSurfaceList,
|
||||||
|
|||||||
@ -63,20 +63,21 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
/**
|
/**
|
||||||
* 지붕재 초기값
|
* 지붕재 초기값
|
||||||
*/
|
*/
|
||||||
const defaultRoofSettings = {
|
const DEFAULT_ROOF_SETTINGS = {
|
||||||
roofSizeSet: '1', // 기본 치수 입력 방법
|
roofSizeSet: '1',
|
||||||
roofAngleSet: 'slope', // 기본 지붕 각도 설정
|
roofAngleSet: 'slope',
|
||||||
angle: 21.8,
|
angle: 21.8,
|
||||||
hajebichi: '',
|
hajebichi: null,
|
||||||
id: 'ROOF_ID_WA_53A',
|
id: 'ROOF_ID_WA_53A',
|
||||||
index: 0,
|
index: 0,
|
||||||
layout: ROOF_MATERIAL_LAYOUT.PARALLEL,
|
layout: ROOF_MATERIAL_LAYOUT.PARALLEL,
|
||||||
lenAuth: 'R',
|
lenAuth: 'R',
|
||||||
lenBase: '235.000',
|
lenBase: '235.000',
|
||||||
length: '235',
|
length: 235,
|
||||||
name: '일본기와 A',
|
name: '일본기와 A',
|
||||||
nameJp: '和瓦A',
|
nameJp: '和瓦A',
|
||||||
pitch: 4,
|
pitch: 4,
|
||||||
|
planNo: planNo,
|
||||||
raft: '',
|
raft: '',
|
||||||
raftAuth: 'C',
|
raftAuth: 'C',
|
||||||
raftBaseCd: 'HEI_455',
|
raftBaseCd: 'HEI_455',
|
||||||
@ -89,12 +90,12 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
selected: true,
|
selected: true,
|
||||||
widAuth: 'R',
|
widAuth: 'R',
|
||||||
widBase: '265.000',
|
widBase: '265.000',
|
||||||
width: '265',
|
width: 265,
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
/**
|
/**
|
||||||
* 메뉴에서 배치면초기설정 선택 시 조회
|
* 메뉴에서 배치면초기설정 선택 시 조회 후 화면 오픈
|
||||||
*/
|
*/
|
||||||
if (openPoint && openPoint === 'canvasMenus') fetchBasicSettings(planNo, openPoint)
|
if (openPoint && openPoint === 'canvasMenus') fetchBasicSettings(planNo, openPoint)
|
||||||
}, [])
|
}, [])
|
||||||
@ -103,18 +104,16 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
if (addedRoofs.length > 0) {
|
if (addedRoofs.length > 0) {
|
||||||
const raftCodeList = findCommonCode('203800')
|
const raftCodeList = findCommonCode('203800')
|
||||||
setRaftCodes(raftCodeList)
|
setRaftCodes(raftCodeList)
|
||||||
|
setCurrentRoof({ ...addedRoofs[0], planNo: planNo, roofSizeSet: String(basicSetting.roofSizeSet), roofAngleSet: basicSetting.roofAngleSet })
|
||||||
/**
|
|
||||||
* 데이터 설정 확인 후 데이터가 없으면 기본 데이터 설정
|
|
||||||
*/
|
|
||||||
if (addedRoofs.length > 0) {
|
|
||||||
setCurrentRoof({ ...addedRoofs[0], planNo: basicSetting.planNo })
|
|
||||||
} else {
|
} else {
|
||||||
setCurrentRoof(defaultRoofSettings)
|
/** 데이터 설정 확인 후 데이터가 없으면 기본 데이터 설정 */
|
||||||
}
|
setCurrentRoof({ ...DEFAULT_ROOF_SETTINGS })
|
||||||
}
|
}
|
||||||
}, [addedRoofs])
|
}, [addedRoofs])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 배치면초기설정 정보 변경 시 basicSettings 설정
|
||||||
|
*/
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!currentRoof) return
|
if (!currentRoof) return
|
||||||
setBasicSettings({
|
setBasicSettings({
|
||||||
@ -256,7 +255,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
id={item.id}
|
id={item.id}
|
||||||
name={item.name}
|
name={item.name}
|
||||||
value={item.value}
|
value={item.value}
|
||||||
checked={currentRoof?.roofSizeSet === item.value}
|
checked={String(currentRoof?.roofSizeSet) === item.value}
|
||||||
onChange={(e) => setCurrentRoof({ ...currentRoof, roofSizeSet: e.target.value })}
|
onChange={(e) => setCurrentRoof({ ...currentRoof, roofSizeSet: e.target.value })}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={item.id}>{getMessage(item.message)}</label>
|
<label htmlFor={item.id}>{getMessage(item.message)}</label>
|
||||||
@ -279,7 +278,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
id={item.id}
|
id={item.id}
|
||||||
name={item.name}
|
name={item.name}
|
||||||
value={item.value}
|
value={item.value}
|
||||||
checked={currentRoof?.roofAngleSet === item.value}
|
checked={String(currentRoof?.roofAngleSet) === item.value}
|
||||||
onChange={(e) => setCurrentRoof({ ...currentRoof, roofAngleSet: e.target.value })}
|
onChange={(e) => setCurrentRoof({ ...currentRoof, roofAngleSet: e.target.value })}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={item.id}>{getMessage(item.message)}</label>
|
<label htmlFor={item.id}>{getMessage(item.message)}</label>
|
||||||
|
|||||||
@ -38,7 +38,7 @@ export default function StuffDetail() {
|
|||||||
|
|
||||||
const [showButton, setShowButton] = useState('') //임시저장, 저장, 삭제 버튼 컨트롤
|
const [showButton, setShowButton] = useState('') //임시저장, 저장, 삭제 버튼 컨트롤
|
||||||
|
|
||||||
const { setMenuNumber } = useCanvasMenu()
|
const { setSelectedMenu } = useCanvasMenu()
|
||||||
|
|
||||||
//공통코드
|
//공통코드
|
||||||
const { commonCode, findCommonCode } = useCommonCode()
|
const { commonCode, findCommonCode } = useCommonCode()
|
||||||
@ -308,7 +308,7 @@ export default function StuffDetail() {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setFloorPlanObjectNo({ floorPlanObjectNo: params.data.objectNo })
|
setFloorPlanObjectNo({ floorPlanObjectNo: params.data.objectNo })
|
||||||
setIsGlobalLoading(true)
|
setIsGlobalLoading(true)
|
||||||
setMenuNumber(5)
|
setSelectedMenu('estimate')
|
||||||
router.push(`/floor-plan/estimate/5?pid=${params.data.planNo}&objectNo=${params.data.objectNo}`)
|
router.push(`/floor-plan/estimate/5?pid=${params.data.planNo}&objectNo=${params.data.objectNo}`)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -1653,7 +1653,7 @@ export default function StuffDetail() {
|
|||||||
pid: planNo,
|
pid: planNo,
|
||||||
objectNo: objectNo,
|
objectNo: objectNo,
|
||||||
}
|
}
|
||||||
setMenuNumber(null)
|
setSelectedMenu(null)
|
||||||
const url = `/floor-plan?${queryStringFormatter(param)}`
|
const url = `/floor-plan?${queryStringFormatter(param)}`
|
||||||
router.push(url)
|
router.push(url)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export default function StuffSubHeader({ type }) {
|
|||||||
|
|
||||||
const [buttonStyle, setButtonStyle] = useState('')
|
const [buttonStyle, setButtonStyle] = useState('')
|
||||||
|
|
||||||
const { setMenuNumber } = useCanvasMenu()
|
const { setSelectedMenu } = useCanvasMenu()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.scrollTo(0, 0)
|
window.scrollTo(0, 0)
|
||||||
@ -55,7 +55,7 @@ export default function StuffSubHeader({ type }) {
|
|||||||
objectNo: objectNo,
|
objectNo: objectNo,
|
||||||
}
|
}
|
||||||
|
|
||||||
setMenuNumber(null)
|
setSelectedMenu(null)
|
||||||
const url = `/floor-plan?${queryStringFormatter(param)}`
|
const url = `/floor-plan?${queryStringFormatter(param)}`
|
||||||
|
|
||||||
router.push(url)
|
router.push(url)
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
.test {
|
|
||||||
@apply bg-red-500;
|
|
||||||
@apply text-2xl;
|
|
||||||
}
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { menuNumberState } from '@/store/menuAtom'
|
import { selectedMenuState } from '@/store/menuAtom'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
@ -6,28 +6,12 @@ import { usePolygon } from '@/hooks/usePolygon'
|
|||||||
import { POLYGON_TYPE } from '@/common/common'
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
|
|
||||||
export const useCanvasMenu = () => {
|
export const useCanvasMenu = () => {
|
||||||
const [menuNumber, setMenuNumber] = useRecoilState(menuNumberState)
|
const [selectedMenu, setSelectedMenu] = useRecoilState(selectedMenuState)
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { drawDirectionArrow } = usePolygon()
|
const { drawDirectionArrow } = usePolygon()
|
||||||
|
|
||||||
/*useEffect(() => {
|
|
||||||
/!*
|
|
||||||
* 모듈,회로 구성을 벗어나면 방향 표시 초기화 필요
|
|
||||||
* *!/
|
|
||||||
if (!canvas) return
|
|
||||||
if (![4, 5].includes(menuNumber)) {
|
|
||||||
canvas
|
|
||||||
.getObjects()
|
|
||||||
.filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
|
||||||
.forEach((obj) => {
|
|
||||||
obj.set('moduleCompass', null)
|
|
||||||
// drawDirectionArrow(obj)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, [menuNumber])*/
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
menuNumber,
|
selectedMenu,
|
||||||
setMenuNumber,
|
setSelectedMenu,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,6 @@ import { useAxios } from '@/hooks/useAxios'
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import { getQueryString } from '@/util/common-utils'
|
import { getQueryString } from '@/util/common-utils'
|
||||||
import { trestleRequest, constructionRequest, trestleDetailRequest } from '@/models/apiModels'
|
|
||||||
import { POST } from '@/app/api/image-upload/route'
|
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
|
||||||
import { useRecoilValue } from 'recoil'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 마스터 컨트롤러 훅
|
* 마스터 컨트롤러 훅
|
||||||
|
|||||||
@ -49,7 +49,7 @@ export const useTrestle = () => {
|
|||||||
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
|
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
|
||||||
const roofMaterialIndex = parent.roofMaterial.index
|
const roofMaterialIndex = parent.roofMaterial.index
|
||||||
if (+roofSizeSet === 3) {
|
if (+roofSizeSet === 3) {
|
||||||
return true
|
return
|
||||||
}
|
}
|
||||||
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
|
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
|
||||||
if (!construction) {
|
if (!construction) {
|
||||||
|
|||||||
@ -33,7 +33,6 @@ import { useColor } from 'react-color-palette'
|
|||||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
import { useMasterController } from '@/hooks/common/useMasterController'
|
||||||
import PlacementShapeSetting, { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
|
import PlacementShapeSetting, { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
|
||||||
import { useCanvasMenu } from '../common/useCanvasMenu'
|
import { useCanvasMenu } from '../common/useCanvasMenu'
|
||||||
import { menuTypeState } from '@/store/menuAtom'
|
|
||||||
import { usePopup } from '../usePopup'
|
import { usePopup } from '../usePopup'
|
||||||
import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
|
import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
|
||||||
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
||||||
@ -43,21 +42,19 @@ import { v4 as uuidv4 } from 'uuid'
|
|||||||
|
|
||||||
const defaultDotLineGridSetting = {
|
const defaultDotLineGridSetting = {
|
||||||
INTERVAL: {
|
INTERVAL: {
|
||||||
type: 2, // 1: 가로,세로 간격 수동, 2: 비율 간격
|
type: 2 /* 1: 가로,세로 간격 수동, 2: 비율 간격 */,
|
||||||
ratioInterval: 910,
|
ratioInterval: 910,
|
||||||
verticalInterval: 910,
|
verticalInterval: 910,
|
||||||
horizontalInterval: 910,
|
horizontalInterval: 910,
|
||||||
dimension: 1, // 치수
|
dimension: 1 /* 치수 */,
|
||||||
},
|
},
|
||||||
DOT: false,
|
DOT: false,
|
||||||
LINE: false,
|
LINE: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
// let previousRoofMaterialsYn = 'N' // 지붕재 select 정보 비교 후 변경된 것이 없으면 1회만 실행
|
|
||||||
|
|
||||||
export function useCanvasSetting() {
|
export function useCanvasSetting() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
/* canvas가 null이 아닐 때에만 getObjects 호출 */
|
/** canvas가 null이 아닐 때에만 getObjects 호출 */
|
||||||
const canvasObjects = canvas ? canvas.getObjects() : []
|
const canvasObjects = canvas ? canvas.getObjects() : []
|
||||||
const [correntObjectNo, setCorrentObjectNo] = useRecoilState(correntObjectNoState)
|
const [correntObjectNo, setCorrentObjectNo] = useRecoilState(correntObjectNoState)
|
||||||
|
|
||||||
@ -88,7 +85,7 @@ export function useCanvasSetting() {
|
|||||||
)
|
)
|
||||||
const [gridColor, setGridColor] = useRecoilState(gridColorState)
|
const [gridColor, setGridColor] = useRecoilState(gridColorState)
|
||||||
const [color, setColor] = useColor(gridColor ?? '#FF0000')
|
const [color, setColor] = useColor(gridColor ?? '#FF0000')
|
||||||
const { menuNumber, setMenuNumber } = useCanvasMenu()
|
const { selectedMenu, setSelectedMenu } = useCanvasMenu()
|
||||||
|
|
||||||
const [settingsData, setSettingsData] = useState({
|
const [settingsData, setSettingsData] = useState({
|
||||||
...settingModalFirstOptions,
|
...settingModalFirstOptions,
|
||||||
@ -116,17 +113,16 @@ export function useCanvasSetting() {
|
|||||||
const [roofMaterials, setRoofMaterials] = useRecoilState(roofMaterialsAtom)
|
const [roofMaterials, setRoofMaterials] = useRecoilState(roofMaterialsAtom)
|
||||||
const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState)
|
const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState)
|
||||||
const [fetchRoofMaterials, setFetchRoofMaterials] = useRecoilState(fetchRoofMaterialsState)
|
const [fetchRoofMaterials, setFetchRoofMaterials] = useRecoilState(fetchRoofMaterialsState)
|
||||||
const [type, setType] = useRecoilState(menuTypeState)
|
|
||||||
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
||||||
|
|
||||||
const resetModuleSelectionData = useResetRecoilState(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
|
const resetModuleSelectionData = useResetRecoilState(moduleSelectionDataState) /* 다음으로 넘어가는 최종 데이터 */
|
||||||
const resetSelectedModules = useResetRecoilState(selectedModuleState) //선택된 모듈
|
const resetSelectedModules = useResetRecoilState(selectedModuleState) /* 선택된 모듈 */
|
||||||
|
|
||||||
const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
|
const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
|
||||||
|
|
||||||
const [raftCodes, setRaftCodes] = useState([]) // 서까래 정보
|
const [raftCodes, setRaftCodes] = useState([]) /* 서까래 정보 */
|
||||||
const { findCommonCode } = useCommonCode()
|
const { findCommonCode } = useCommonCode()
|
||||||
const [currentRoof, setCurrentRoof] = useState(null) // 현재 선택된 지붕재 정보
|
const [currentRoof, setCurrentRoof] = useState(null) /* 현재 선택된 지붕재 정보 */
|
||||||
const { addPopup } = usePopup()
|
const { addPopup } = usePopup()
|
||||||
const [popupId, setPopupId] = useState(uuidv4())
|
const [popupId, setPopupId] = useState(uuidv4())
|
||||||
|
|
||||||
@ -144,7 +140,7 @@ export function useCanvasSetting() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const tempFetchRoofMaterials = !fetchRoofMaterials
|
const tempFetchRoofMaterials = !fetchRoofMaterials
|
||||||
|
|
||||||
/* 초 1회만 실행하도록 처리 */
|
/** 초 1회만 실행하도록 처리 */
|
||||||
setFetchRoofMaterials(tempFetchRoofMaterials)
|
setFetchRoofMaterials(tempFetchRoofMaterials)
|
||||||
if (tempFetchRoofMaterials) {
|
if (tempFetchRoofMaterials) {
|
||||||
addRoofMaterials()
|
addRoofMaterials()
|
||||||
@ -176,7 +172,23 @@ export function useCanvasSetting() {
|
|||||||
angle: item.angle ? parseInt(item.angle) : 21.8,
|
angle: item.angle ? parseInt(item.angle) : 21.8,
|
||||||
}))
|
}))
|
||||||
setRoofMaterials(roofLists)
|
setRoofMaterials(roofLists)
|
||||||
const selectedRoofMaterial = roofLists[0]
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (addedRoofs.length > 0 && addedRoofs[0].planNo === basicSetting.planNo) {
|
||||||
|
const raftCodeList = findCommonCode('203800')
|
||||||
|
setRaftCodes(raftCodeList)
|
||||||
|
setCurrentRoof({
|
||||||
|
...addedRoofs[0],
|
||||||
|
planNo: addedRoofs[0].planNo,
|
||||||
|
roofSizeSet: String(basicSetting.roofSizeSet),
|
||||||
|
roofAngleSet: basicSetting.roofAngleSet,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [addedRoofs])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const selectedRoofMaterial = roofMaterials[0]
|
||||||
|
|
||||||
if (addedRoofs.length === 0) {
|
if (addedRoofs.length === 0) {
|
||||||
const newAddedRoofs = []
|
const newAddedRoofs = []
|
||||||
@ -184,19 +196,7 @@ export function useCanvasSetting() {
|
|||||||
setAddedRoofs(newAddedRoofs)
|
setAddedRoofs(newAddedRoofs)
|
||||||
}
|
}
|
||||||
setBasicSettings({ ...basicSetting, selectedRoofMaterial: selectedRoofMaterial })
|
setBasicSettings({ ...basicSetting, selectedRoofMaterial: selectedRoofMaterial })
|
||||||
}
|
}, [roofMaterials])
|
||||||
|
|
||||||
/**
|
|
||||||
* 배치면 초기설정 화면이 열리지 않아도 데이터 set 하기 위해서 추가
|
|
||||||
*/
|
|
||||||
useEffect(() => {
|
|
||||||
if (addedRoofs.length > 0) {
|
|
||||||
const raftCodeList = findCommonCode('203800')
|
|
||||||
setRaftCodes(raftCodeList)
|
|
||||||
|
|
||||||
setCurrentRoof({ ...addedRoofs[0] })
|
|
||||||
}
|
|
||||||
}, [addedRoofs])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!canvas) {
|
if (!canvas) {
|
||||||
@ -369,9 +369,9 @@ export function useCanvasSetting() {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
/* 메뉴에서 배치면 초기설정 클릭 시 실행하지 않음 */
|
/** 메뉴에서 배치면 초기설정 클릭 시 실행하지 않음 */
|
||||||
if (openPoint === null) {
|
if (openPoint === null) {
|
||||||
/* 배치면 초기설정 미저장 상태이면 화면 열기 */
|
/** 배치면 초기설정 미저장 상태이면 화면 열기 */
|
||||||
const placementInitialProps = {
|
const placementInitialProps = {
|
||||||
id: popupId,
|
id: popupId,
|
||||||
pos: {
|
pos: {
|
||||||
@ -385,7 +385,7 @@ export function useCanvasSetting() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 데이터 설정 */
|
/** 데이터 설정 */
|
||||||
const addRoofs = []
|
const addRoofs = []
|
||||||
for (let i = 0; i < roofsArray.length; i++) {
|
for (let i = 0; i < roofsArray.length; i++) {
|
||||||
roofMaterials?.map((material) => {
|
roofMaterials?.map((material) => {
|
||||||
@ -440,6 +440,19 @@ export function useCanvasSetting() {
|
|||||||
// setCanvasSetting({ ...basicSetting })
|
// setCanvasSetting({ ...basicSetting })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 저장/복사저장 시 지붕 크기에 따른 메뉴 설정
|
||||||
|
*/
|
||||||
|
const setMenuByRoofSize = (roofSizeSet) => {
|
||||||
|
if (['2', '3'].includes(String(roofSizeSet))) {
|
||||||
|
setSelectedMenu('surface')
|
||||||
|
setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
|
||||||
|
} else {
|
||||||
|
setSelectedMenu('outline')
|
||||||
|
setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 기본설정(PlacementShapeSetting) 저장
|
* 기본설정(PlacementShapeSetting) 저장
|
||||||
*/
|
*/
|
||||||
@ -471,31 +484,23 @@ export function useCanvasSetting() {
|
|||||||
|
|
||||||
await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => {
|
await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => {
|
||||||
swalFire({ text: getMessage(res.returnMessage) })
|
swalFire({ text: getMessage(res.returnMessage) })
|
||||||
/* BasicSettings Recoil 설정 */
|
/** BasicSettings Recoil 설정 */
|
||||||
setBasicSettings({ ...params })
|
setBasicSettings({ ...params })
|
||||||
})
|
})
|
||||||
|
|
||||||
/* CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */
|
/** CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */
|
||||||
setCanvasSetting({
|
setCanvasSetting({
|
||||||
...basicSetting,
|
...basicSetting,
|
||||||
roofSizeSet: String(params.roofSizeSet),
|
roofSizeSet: String(params.roofSizeSet),
|
||||||
})
|
})
|
||||||
|
|
||||||
/* 메뉴 설정 */
|
/** 메뉴 설정 */
|
||||||
if (['2', '3'].includes(params.roofSizeSet)) {
|
setMenuByRoofSize(params.roofSizeSet)
|
||||||
setMenuNumber(3)
|
|
||||||
setType('surface')
|
|
||||||
setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
|
|
||||||
} else {
|
|
||||||
setMenuNumber(2)
|
|
||||||
setType('outline')
|
|
||||||
setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 배치면초기설정 조회 */
|
/** 배치면초기설정 조회 */
|
||||||
fetchBasicSettings(params.planNo, 'basicSettingSave')
|
fetchBasicSettings(params.planNo, 'basicSettingSave')
|
||||||
|
|
||||||
/* 모듈 선택 데이터 초기화 */
|
/** 모듈 선택 데이터 초기화 */
|
||||||
resetModuleSelectionData()
|
resetModuleSelectionData()
|
||||||
moduleSelectedDataTrigger({ common: {}, module: {}, roofConstructions: [] })
|
moduleSelectedDataTrigger({ common: {}, module: {}, roofConstructions: [] })
|
||||||
const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE)
|
const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||||
@ -536,27 +541,19 @@ export function useCanvasSetting() {
|
|||||||
swalFire({ text: getMessage(res.returnMessage) })
|
swalFire({ text: getMessage(res.returnMessage) })
|
||||||
})
|
})
|
||||||
|
|
||||||
/* CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */
|
/** CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */
|
||||||
setCanvasSetting({
|
setCanvasSetting({
|
||||||
...basicSetting,
|
...basicSetting,
|
||||||
roofSizeSet: String(params.roofSizeSet),
|
roofSizeSet: String(params.roofSizeSet),
|
||||||
})
|
})
|
||||||
|
|
||||||
/* 메뉴 설정 */
|
/** 메뉴 설정 */
|
||||||
if (['2', '3'].includes(params?.roofSizeSet)) {
|
setMenuByRoofSize(params.roofSizeSet)
|
||||||
setMenuNumber(3)
|
|
||||||
setType('surface')
|
|
||||||
setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
|
|
||||||
} else {
|
|
||||||
setMenuNumber(2)
|
|
||||||
setType('outline')
|
|
||||||
setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 배치면초기설정 조회 */
|
/** 배치면초기설정 조회 */
|
||||||
fetchBasicSettings(Number(params.planNo), 'basicSettingSave')
|
fetchBasicSettings(Number(params.planNo), 'basicSettingSave')
|
||||||
|
|
||||||
/* 모듈 선택 데이터 초기화 */
|
/** 모듈 선택 데이터 초기화 */
|
||||||
resetModuleSelectionData()
|
resetModuleSelectionData()
|
||||||
moduleSelectedDataTrigger({ common: {}, module: {}, roofConstructions: [] })
|
moduleSelectedDataTrigger({ common: {}, module: {}, roofConstructions: [] })
|
||||||
const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE)
|
const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||||
@ -582,24 +579,16 @@ export function useCanvasSetting() {
|
|||||||
const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
|
const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
|
||||||
const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item }))
|
const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item }))
|
||||||
|
|
||||||
/**
|
/** 흡착점 ON/OFF */
|
||||||
* 흡착점 ON/OFF
|
|
||||||
*/
|
|
||||||
setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: res.adsorpPoint })
|
setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: res.adsorpPoint })
|
||||||
|
|
||||||
/**
|
/** 치수선 설정 */
|
||||||
* 치수선 설정
|
|
||||||
*/
|
|
||||||
setDimensionLineSettings({ ...dimensionLineSettings, pixel: res.originPixel, color: res.originColor })
|
setDimensionLineSettings({ ...dimensionLineSettings, pixel: res.originPixel, color: res.originColor })
|
||||||
|
|
||||||
/**
|
/** 도면크기 설정 */
|
||||||
* 도면크기 설정
|
|
||||||
*/
|
|
||||||
setPlanSizeSettingMode({ ...planSizeSettingMode, originHorizon: res.originHorizon, originVertical: res.originVertical })
|
setPlanSizeSettingMode({ ...planSizeSettingMode, originHorizon: res.originHorizon, originVertical: res.originVertical })
|
||||||
|
|
||||||
/**
|
/** 데이터 설정 */
|
||||||
* 데이터 설정
|
|
||||||
*/
|
|
||||||
setSettingModalFirstOptions({
|
setSettingModalFirstOptions({
|
||||||
...settingModalFirstOptions,
|
...settingModalFirstOptions,
|
||||||
option1: optionData1,
|
option1: optionData1,
|
||||||
@ -614,45 +603,35 @@ export function useCanvasSetting() {
|
|||||||
|
|
||||||
const fontPatternData = {
|
const fontPatternData = {
|
||||||
commonText: {
|
commonText: {
|
||||||
/**
|
/** 문자 글꼴 조회 데이터 */
|
||||||
* 문자 글꼴 조회 데이터
|
|
||||||
*/
|
|
||||||
fontFamily: getFonts(res.wordFont),
|
fontFamily: getFonts(res.wordFont),
|
||||||
fontWeight: getFontStyles(res.wordFontStyle),
|
fontWeight: getFontStyles(res.wordFontStyle),
|
||||||
fontSize: getFontSizes(res.wordFontSize),
|
fontSize: getFontSizes(res.wordFontSize),
|
||||||
fontColor: getFontColors(res.wordFontColor),
|
fontColor: getFontColors(res.wordFontColor),
|
||||||
},
|
},
|
||||||
flowText: {
|
flowText: {
|
||||||
/**
|
/** 흐름방향 글꼴 조회 데이터 */
|
||||||
* 흐름방향 글꼴 조회 데이터
|
|
||||||
*/
|
|
||||||
fontFamily: getFonts(res.flowFont),
|
fontFamily: getFonts(res.flowFont),
|
||||||
fontWeight: getFontStyles(res.flowFontStyle),
|
fontWeight: getFontStyles(res.flowFontStyle),
|
||||||
fontSize: getFontSizes(res.flowFontSize),
|
fontSize: getFontSizes(res.flowFontSize),
|
||||||
fontColor: getFontColors(res.flowFontColor),
|
fontColor: getFontColors(res.flowFontColor),
|
||||||
},
|
},
|
||||||
dimensionLineText: {
|
dimensionLineText: {
|
||||||
/**
|
/** 치수 글꼴 조회 데이터 */
|
||||||
* 치수 글꼴 조회 데이터
|
|
||||||
*/
|
|
||||||
fontFamily: getFonts(res.dimensioFont),
|
fontFamily: getFonts(res.dimensioFont),
|
||||||
fontWeight: getFontStyles(res.dimensioFontStyle),
|
fontWeight: getFontStyles(res.dimensioFontStyle),
|
||||||
fontSize: getFontSizes(res.dimensioFontSize),
|
fontSize: getFontSizes(res.dimensioFontSize),
|
||||||
fontColor: getFontColors(res.dimensioFontColor),
|
fontColor: getFontColors(res.dimensioFontColor),
|
||||||
},
|
},
|
||||||
circuitNumberText: {
|
circuitNumberText: {
|
||||||
/**
|
/** 회로번호 글꼴 조회 데이터 */
|
||||||
* 회로번호 글꼴 조회 데이터
|
|
||||||
*/
|
|
||||||
fontFamily: getFonts(res.circuitNumFont),
|
fontFamily: getFonts(res.circuitNumFont),
|
||||||
fontWeight: getFontStyles(res.circuitNumFontStyle),
|
fontWeight: getFontStyles(res.circuitNumFontStyle),
|
||||||
fontSize: getFontSizes(res.circuitNumFontSize),
|
fontSize: getFontSizes(res.circuitNumFontSize),
|
||||||
fontColor: getFontColors(res.circuitNumFontColor),
|
fontColor: getFontColors(res.circuitNumFontColor),
|
||||||
},
|
},
|
||||||
lengthText: {
|
lengthText: {
|
||||||
/**
|
/** 치수선 글꼴 조회 데이터 */
|
||||||
* 치수선 글꼴 조회 데이터
|
|
||||||
*/
|
|
||||||
fontFamily: getFonts(res.lengthFont),
|
fontFamily: getFonts(res.lengthFont),
|
||||||
fontWeight: getFontStyles(res.lengthFontStyle),
|
fontWeight: getFontStyles(res.lengthFontStyle),
|
||||||
fontSize: getFontSizes(res.lengthFontSize),
|
fontSize: getFontSizes(res.lengthFontSize),
|
||||||
@ -660,14 +639,10 @@ export function useCanvasSetting() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** 조회된 글꼴 데이터 set */
|
||||||
* 조회된 글꼴 데이터 set
|
|
||||||
*/
|
|
||||||
setGlobalFont(fontPatternData)
|
setGlobalFont(fontPatternData)
|
||||||
|
|
||||||
/**
|
/** 점/선 그리드 */
|
||||||
* 점/선 그리드
|
|
||||||
*/
|
|
||||||
const patternData = {
|
const patternData = {
|
||||||
INTERVAL: {
|
INTERVAL: {
|
||||||
type: res.gridType,
|
type: res.gridType,
|
||||||
@ -682,47 +657,31 @@ export function useCanvasSetting() {
|
|||||||
|
|
||||||
setDotLineGridSettingState(patternData)
|
setDotLineGridSettingState(patternData)
|
||||||
|
|
||||||
/**
|
/** 그리드 색 설정 */
|
||||||
* 그리드 색 설정
|
|
||||||
*/
|
|
||||||
setGridColor(res.gridColor)
|
setGridColor(res.gridColor)
|
||||||
} else {
|
} else {
|
||||||
//조회된 글꼴 데이터가 없는 경우 (데이터 초기화)
|
/** 조회된 글꼴 데이터가 없는 경우 (데이터 초기화) */
|
||||||
|
|
||||||
/**
|
/** 흡착점 ON/OFF */
|
||||||
* 흡착점 ON/OFF
|
|
||||||
*/
|
|
||||||
setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: false })
|
setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: false })
|
||||||
|
|
||||||
/**
|
/** 치수선 설정 */
|
||||||
* 치수선 설정
|
|
||||||
*/
|
|
||||||
resetDimensionLineSettings()
|
resetDimensionLineSettings()
|
||||||
|
|
||||||
/**
|
/** 도면크기 설정 */
|
||||||
* 도면크기 설정
|
|
||||||
*/
|
|
||||||
resetPlanSizeSettingMode()
|
resetPlanSizeSettingMode()
|
||||||
|
|
||||||
/**
|
/** 데이터 설정 */
|
||||||
* 데이터 설정
|
|
||||||
*/
|
|
||||||
resetSettingModalFirstOptions()
|
resetSettingModalFirstOptions()
|
||||||
resetSettingModalSecondOptions()
|
resetSettingModalSecondOptions()
|
||||||
|
|
||||||
/**
|
/** 데이터 초기화 */
|
||||||
* 데이터 초기화
|
|
||||||
*/
|
|
||||||
resetGlobalFont()
|
resetGlobalFont()
|
||||||
|
|
||||||
/**
|
/** 점/선 그리드 */
|
||||||
* 점/선 그리드
|
|
||||||
*/
|
|
||||||
setDotLineGridSettingState({ ...defaultDotLineGridSetting })
|
setDotLineGridSettingState({ ...defaultDotLineGridSetting })
|
||||||
|
|
||||||
/**
|
/** 그리드 색 설정 */
|
||||||
* 그리드 색 설정
|
|
||||||
*/
|
|
||||||
setGridColor('#FF0000')
|
setGridColor('#FF0000')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -736,9 +695,7 @@ export function useCanvasSetting() {
|
|||||||
* CanvasSetting 옵션 클릭 후 저장
|
* CanvasSetting 옵션 클릭 후 저장
|
||||||
*/
|
*/
|
||||||
const onClickOption2 = async () => {
|
const onClickOption2 = async () => {
|
||||||
/**
|
/** 서버에 전송할 데이터 */
|
||||||
* 서버에 전송할 데이터
|
|
||||||
*/
|
|
||||||
const dataToSend = {
|
const dataToSend = {
|
||||||
firstOption1: option1.map((item) => ({
|
firstOption1: option1.map((item) => ({
|
||||||
column: item.column,
|
column: item.column,
|
||||||
@ -759,13 +716,9 @@ export function useCanvasSetting() {
|
|||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
const patternData = {
|
const patternData = {
|
||||||
/**
|
/** 견적서 번호 */
|
||||||
* 견적서 번호
|
|
||||||
*/
|
|
||||||
objectNo: correntObjectNo,
|
objectNo: correntObjectNo,
|
||||||
/**
|
/** 디스플레이 설정(다중) */
|
||||||
* 디스플레이 설정(다중)
|
|
||||||
*/
|
|
||||||
allocDisplay: dataToSend.firstOption1[0].selected,
|
allocDisplay: dataToSend.firstOption1[0].selected,
|
||||||
outlineDisplay: dataToSend.firstOption1[1].selected,
|
outlineDisplay: dataToSend.firstOption1[1].selected,
|
||||||
gridDisplay: dataToSend.firstOption1[2].selected,
|
gridDisplay: dataToSend.firstOption1[2].selected,
|
||||||
@ -776,85 +729,62 @@ export function useCanvasSetting() {
|
|||||||
trestleDisplay: dataToSend.firstOption1[7].selected,
|
trestleDisplay: dataToSend.firstOption1[7].selected,
|
||||||
imageDisplay: dataToSend.firstOption1[8].selected,
|
imageDisplay: dataToSend.firstOption1[8].selected,
|
||||||
totalDisplay: dataToSend.firstOption1[9].selected,
|
totalDisplay: dataToSend.firstOption1[9].selected,
|
||||||
/**
|
/** 차수 표시(단 건) */
|
||||||
* 차수 표시(단 건)
|
|
||||||
*/
|
|
||||||
corridorDimension: dataToSend.firstOption3[0].selected,
|
corridorDimension: dataToSend.firstOption3[0].selected,
|
||||||
realDimension: dataToSend.firstOption3[1].selected,
|
realDimension: dataToSend.firstOption3[1].selected,
|
||||||
noneDimension: dataToSend.firstOption3[2].selected,
|
noneDimension: dataToSend.firstOption3[2].selected,
|
||||||
/**
|
/** 화면 표시(단 건) */
|
||||||
* 화면 표시(단 건)
|
|
||||||
*/
|
|
||||||
onlyBorder: dataToSend.firstOption2[0].selected,
|
onlyBorder: dataToSend.firstOption2[0].selected,
|
||||||
lineHatch: dataToSend.firstOption2[1].selected,
|
lineHatch: dataToSend.firstOption2[1].selected,
|
||||||
allPainted: dataToSend.firstOption2[2].selected,
|
allPainted: dataToSend.firstOption2[2].selected,
|
||||||
/**
|
/** 흡착범위 설정(단 건) */
|
||||||
* 흡착범위 설정(단 건)
|
|
||||||
*/
|
|
||||||
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
|
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
|
||||||
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
|
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
|
||||||
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
|
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
|
||||||
adsorpRangeLarge: dataToSend.secondOption2[3].selected,
|
adsorpRangeLarge: dataToSend.secondOption2[3].selected,
|
||||||
|
/** 흡착점 ON/OFF */
|
||||||
/**
|
|
||||||
* 흡착점 ON/OFF
|
|
||||||
*/
|
|
||||||
adsorpPoint: adsorptionPointMode.adsorptionPoint,
|
adsorpPoint: adsorptionPointMode.adsorptionPoint,
|
||||||
//??: adsorptionRange, 사용여부 확인 필요
|
//??: adsorptionRange, 사용여부 확인 필요
|
||||||
|
|
||||||
/**
|
/** 문자 글꼴 설정 */
|
||||||
* 글꼴 설정
|
|
||||||
*/
|
|
||||||
//문자 글꼴
|
|
||||||
wordFont: globalFont.commonText.fontFamily?.value ?? 'MS PGothic',
|
wordFont: globalFont.commonText.fontFamily?.value ?? 'MS PGothic',
|
||||||
wordFontStyle: globalFont.commonText.fontWeight?.value ?? 'normal',
|
wordFontStyle: globalFont.commonText.fontWeight?.value ?? 'normal',
|
||||||
wordFontSize: globalFont.commonText.fontSize?.value ?? 16,
|
wordFontSize: globalFont.commonText.fontSize?.value ?? 16,
|
||||||
wordFontColor: globalFont.commonText.fontColor?.value ?? 'black',
|
wordFontColor: globalFont.commonText.fontColor?.value ?? 'black',
|
||||||
|
|
||||||
/**
|
/** 흐름방향 글꼴 설정 */
|
||||||
* 흐름방향 글꼴
|
|
||||||
*/
|
|
||||||
flowFont: globalFont.flowText.fontFamily?.value ?? 'MS PGothic',
|
flowFont: globalFont.flowText.fontFamily?.value ?? 'MS PGothic',
|
||||||
flowFontStyle: globalFont.flowText.fontWeight?.value ?? 'normal',
|
flowFontStyle: globalFont.flowText.fontWeight?.value ?? 'normal',
|
||||||
flowFontSize: globalFont.flowText.fontSize?.value ?? 16,
|
flowFontSize: globalFont.flowText.fontSize?.value ?? 16,
|
||||||
flowFontColor: globalFont.flowText.fontColor?.value ?? 'black',
|
flowFontColor: globalFont.flowText.fontColor?.value ?? 'black',
|
||||||
|
|
||||||
/**
|
/** 치수 글꼴 설정 */
|
||||||
* 치수 글꼴
|
|
||||||
*/
|
|
||||||
dimensioFont: globalFont.dimensionLineText.fontFamily?.value ?? 'MS PGothic',
|
dimensioFont: globalFont.dimensionLineText.fontFamily?.value ?? 'MS PGothic',
|
||||||
dimensioFontStyle: globalFont.dimensionLineText.fontWeight?.value ?? 'normal',
|
dimensioFontStyle: globalFont.dimensionLineText.fontWeight?.value ?? 'normal',
|
||||||
dimensioFontSize: globalFont.dimensionLineText.fontSize?.value ?? 16,
|
dimensioFontSize: globalFont.dimensionLineText.fontSize?.value ?? 16,
|
||||||
dimensioFontColor: globalFont.dimensionLineText.fontColor?.value ?? 'black',
|
dimensioFontColor: globalFont.dimensionLineText.fontColor?.value ?? 'black',
|
||||||
|
|
||||||
/**
|
/** 회로번호 글꼴 설정 */
|
||||||
* 회로번호 글꼴
|
|
||||||
*/
|
|
||||||
circuitNumFont: globalFont.circuitNumberText.fontFamily?.value ?? 'MS PGothic',
|
circuitNumFont: globalFont.circuitNumberText.fontFamily?.value ?? 'MS PGothic',
|
||||||
circuitNumFontStyle: globalFont.circuitNumberText.fontWeight?.value ?? 'normal',
|
circuitNumFontStyle: globalFont.circuitNumberText.fontWeight?.value ?? 'normal',
|
||||||
circuitNumFontSize: globalFont.circuitNumberText.fontSize?.value ?? 16,
|
circuitNumFontSize: globalFont.circuitNumberText.fontSize?.value ?? 16,
|
||||||
circuitNumFontColor: globalFont.circuitNumberText.fontColor?.value ?? 'black',
|
circuitNumFontColor: globalFont.circuitNumberText.fontColor?.value ?? 'black',
|
||||||
|
|
||||||
/**
|
/** 치수선 글꼴 설정 */
|
||||||
* 치수선 글꼴
|
|
||||||
*/
|
|
||||||
lengthFont: globalFont.lengthText.fontFamily?.value ?? 'MS PGothic',
|
lengthFont: globalFont.lengthText.fontFamily?.value ?? 'MS PGothic',
|
||||||
lengthFontStyle: globalFont.lengthText.fontWeight?.value ?? 'normal',
|
lengthFontStyle: globalFont.lengthText.fontWeight?.value ?? 'normal',
|
||||||
lengthFontSize: globalFont.lengthText.fontSize?.value ?? 16,
|
lengthFontSize: globalFont.lengthText.fontSize?.value ?? 16,
|
||||||
lengthFontColor: globalFont.lengthText.fontColor?.value ?? 'black',
|
lengthFontColor: globalFont.lengthText.fontColor?.value ?? 'black',
|
||||||
|
|
||||||
/**
|
/** 치수선 설정 */
|
||||||
* 치수선 설정
|
|
||||||
*/
|
|
||||||
originPixel: dimensionLineSettings.pixel,
|
originPixel: dimensionLineSettings.pixel,
|
||||||
originColor: dimensionLineSettings.color,
|
originColor: dimensionLineSettings.color,
|
||||||
|
|
||||||
/**
|
/** 도면크기 설정 */
|
||||||
* 도면크기 설정
|
|
||||||
*/
|
|
||||||
originHorizon: planSizeSettingMode.originHorizon,
|
originHorizon: planSizeSettingMode.originHorizon,
|
||||||
originVertical: planSizeSettingMode.originVertical,
|
originVertical: planSizeSettingMode.originVertical,
|
||||||
|
|
||||||
|
/** 점/선 그리드 */
|
||||||
dotGridDisplay: dotLineGridSetting.DOT,
|
dotGridDisplay: dotLineGridSetting.DOT,
|
||||||
lineGridDisplay: dotLineGridSetting.LINE,
|
lineGridDisplay: dotLineGridSetting.LINE,
|
||||||
gridType: dotLineGridSetting.INTERVAL.type,
|
gridType: dotLineGridSetting.INTERVAL.type,
|
||||||
@ -863,6 +793,7 @@ export function useCanvasSetting() {
|
|||||||
gridRatio: dotLineGridSetting.INTERVAL.ratioInterval / 10,
|
gridRatio: dotLineGridSetting.INTERVAL.ratioInterval / 10,
|
||||||
gridDimen: dotLineGridSetting.INTERVAL.dimension,
|
gridDimen: dotLineGridSetting.INTERVAL.dimension,
|
||||||
|
|
||||||
|
/** 그리드 색 설정 */
|
||||||
gridColor: gridColor,
|
gridColor: gridColor,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -875,13 +806,10 @@ export function useCanvasSetting() {
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
//swalFire({ text: getMessage(res.returnMessage) })
|
//swalFire({ text: getMessage(res.returnMessage) })
|
||||||
|
|
||||||
/**
|
/** Canvas 디스플레이 설정 시 해당 옵션 적용 */
|
||||||
* Canvas 디스플레이 설정 시 해당 옵션 적용
|
|
||||||
*/
|
|
||||||
frontSettings()
|
frontSettings()
|
||||||
/**
|
|
||||||
* 저장 후 재조회
|
/** 저장 후 재조회 */
|
||||||
*/
|
|
||||||
fetchSettings()
|
fetchSettings()
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@ -912,8 +840,8 @@ export function useCanvasSetting() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 옵션명
|
* 옵션명 optionName
|
||||||
* 옵션상태
|
* 옵션상태 optionSelected
|
||||||
*/
|
*/
|
||||||
let optionName
|
let optionName
|
||||||
let optionSelected
|
let optionSelected
|
||||||
@ -948,15 +876,11 @@ export function useCanvasSetting() {
|
|||||||
optionName = ['backGroundImage']
|
optionName = ['backGroundImage']
|
||||||
break
|
break
|
||||||
case 'totalDisplay':
|
case 'totalDisplay':
|
||||||
/**
|
/** 작업할 필요 없음 */
|
||||||
* 작업할 필요 없음
|
|
||||||
*/
|
|
||||||
optionName = []
|
optionName = []
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
/**
|
/** 표시 선택 상태(true/false)*/
|
||||||
* 표시 선택 상태(true/false)
|
|
||||||
*/
|
|
||||||
optionSelected = option1[i].selected
|
optionSelected = option1[i].selected
|
||||||
|
|
||||||
canvasObjects
|
canvasObjects
|
||||||
|
|||||||
@ -19,7 +19,6 @@ import ActualSizeSetting from '@/components/floor-plan/modal/roofAllocation/Actu
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import useMenu from '@/hooks/common/useMenu'
|
import useMenu from '@/hooks/common/useMenu'
|
||||||
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
import { menuTypeState } from '@/store/menuAtom'
|
|
||||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||||
import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
|
import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
@ -37,8 +36,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
const [popupId, setPopupId] = useState(uuidv4())
|
const [popupId, setPopupId] = useState(uuidv4())
|
||||||
const { addPopup, closePopup, closeAll } = usePopup()
|
const { addPopup, closePopup, closeAll } = usePopup()
|
||||||
const currentObject = useRecoilValue(currentObjectState)
|
const currentObject = useRecoilValue(currentObjectState)
|
||||||
const { setMenuNumber } = useCanvasMenu()
|
const { setSelectedMenu } = useCanvasMenu()
|
||||||
const setMenuType = useSetRecoilState(menuTypeState)
|
|
||||||
const roofMaterials = useRecoilValue(roofMaterialsSelector)
|
const roofMaterials = useRecoilValue(roofMaterialsSelector)
|
||||||
const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector)
|
const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector)
|
||||||
const [basicSetting, setBasicSetting] = useRecoilState(basicSettingState)
|
const [basicSetting, setBasicSetting] = useRecoilState(basicSettingState)
|
||||||
@ -387,8 +385,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
})
|
})
|
||||||
setEditingLines([])
|
setEditingLines([])
|
||||||
closeAll()
|
closeAll()
|
||||||
setMenuNumber(3)
|
setSelectedMenu('surface')
|
||||||
setMenuType('surface')
|
|
||||||
|
|
||||||
modifyModuleSelectionData()
|
modifyModuleSelectionData()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ import { roofDisplaySelector } from '@/store/settingAtom'
|
|||||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||||
import PlacementSurfaceLineProperty from '@/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty'
|
import PlacementSurfaceLineProperty from '@/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty'
|
||||||
|
|
||||||
// 면형상 배치
|
// 배치면 그리기
|
||||||
export function usePlacementShapeDrawing(id) {
|
export function usePlacementShapeDrawing(id) {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
||||||
@ -93,6 +93,12 @@ export function usePlacementShapeDrawing(id) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setPoints([])
|
setPoints([])
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const placementShapeDrawingStartPoint = canvas.getObjects().find((obj) => obj.name === 'placementShapeDrawingStartPoint')
|
||||||
|
|
||||||
|
canvas.remove(placementShapeDrawingStartPoint)
|
||||||
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -58,32 +58,3 @@ export async function login() {
|
|||||||
redirect('/')
|
redirect('/')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const customSetMenuNumber = async ({ objectNo, pid, menuNum, callback = () => {} }) => {
|
|
||||||
let db = null
|
|
||||||
|
|
||||||
if (!db) {
|
|
||||||
db = await open({
|
|
||||||
filename: 'qcast3.global.sqlite',
|
|
||||||
driver: sqlite3.Database,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const chkSql = `SELECT menu_num FROM current_menu WHERE object_no = ? AND pid = ?`
|
|
||||||
const prevMenuNum = await getInstance().get(chkSql, objectNo, pid)
|
|
||||||
|
|
||||||
if (prevMenuNum) {
|
|
||||||
if (prevMenuNum > menuNum) {
|
|
||||||
callback()
|
|
||||||
} else {
|
|
||||||
const sql = `UPDATE current_menu SET menu_num = ? WHERE object_no = ? AND pid = ?`
|
|
||||||
await getInstance().run(sql, menuNum, objectNo, pid)
|
|
||||||
|
|
||||||
setMenuNumber(menuNum)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const sql = `INSERT INTO current_menu (object_no, pid, menu_num) VALUES (?, ?, ?)`
|
|
||||||
await getInstance().run(sql, objectNo, pid, menuNum)
|
|
||||||
setMenuNumber(menuNum)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -896,7 +896,7 @@
|
|||||||
"estimate.detail.dragFileGuide": "(※北面設置の場合、ファイル添付が必須です.)",
|
"estimate.detail.dragFileGuide": "(※北面設置の場合、ファイル添付が必須です.)",
|
||||||
"estimate.detail.header.fileList1": "ファイル添付",
|
"estimate.detail.header.fileList1": "ファイル添付",
|
||||||
"estimate.detail.fileList.btn": "ファイル選択",
|
"estimate.detail.fileList.btn": "ファイル選択",
|
||||||
"estimate.detail.fileList.extCheck": "画像ファイルのみ添付可能です。",
|
"estimate.detail.fileList.extCheck": "画像、PDF、Excelファイルのみ添付可能.",
|
||||||
"estimate.detail.header.fileList2": "添付ファイル一覧",
|
"estimate.detail.header.fileList2": "添付ファイル一覧",
|
||||||
"estimate.detail.fileList2.btn.return": "復元",
|
"estimate.detail.fileList2.btn.return": "復元",
|
||||||
"estimate.detail.header.specialEstimate": "見積もりの特定",
|
"estimate.detail.header.specialEstimate": "見積もりの特定",
|
||||||
|
|||||||
@ -897,7 +897,7 @@
|
|||||||
"estimate.detail.dragFileGuide": "(※ 북면설치인 경우, 파일 첨부가 필수입니다.)",
|
"estimate.detail.dragFileGuide": "(※ 북면설치인 경우, 파일 첨부가 필수입니다.)",
|
||||||
"estimate.detail.header.fileList1": "파일첨부",
|
"estimate.detail.header.fileList1": "파일첨부",
|
||||||
"estimate.detail.fileList.btn": "파일선택",
|
"estimate.detail.fileList.btn": "파일선택",
|
||||||
"estimate.detail.fileList.extCheck": "이미지 파일만 첨부 가능합니다.",
|
"estimate.detail.fileList.extCheck": "이미지, PDF, 엑셀 파일만 첨부 가능합니다.",
|
||||||
"estimate.detail.header.fileList2": "첨부파일 목록",
|
"estimate.detail.header.fileList2": "첨부파일 목록",
|
||||||
"estimate.detail.fileList2.btn.return": "복원",
|
"estimate.detail.fileList2.btn.return": "복원",
|
||||||
"estimate.detail.header.specialEstimate": "견적특이사항",
|
"estimate.detail.header.specialEstimate": "견적특이사항",
|
||||||
|
|||||||
@ -6,32 +6,33 @@ export const menuNumberState = atom({
|
|||||||
default: null,
|
default: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const menuTypeState = atom({
|
export const selectedMenuState = atom({
|
||||||
key: 'menuTypeState',
|
key: 'selectedMenuState',
|
||||||
default: null,
|
default: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const menusState = atom({
|
export const menusState = atom({
|
||||||
key: 'menusState',
|
key: 'menusState',
|
||||||
default: [
|
default: [
|
||||||
{ index: 0, name: 'plan.menu.plan.drawing', icon: 'con00', title: MENU.PLAN_DRAWING },
|
{ type: 'drawing', name: 'plan.menu.plan.drawing', icon: 'con00', title: MENU.PLAN_DRAWING }, //. 도면 작성
|
||||||
{
|
{
|
||||||
index: 1,
|
type: 'placement', // 배치면 초기설정
|
||||||
name: 'plan.menu.placement.surface.initial.setting',
|
name: 'plan.menu.placement.surface.initial.setting',
|
||||||
icon: 'con01',
|
icon: 'con01',
|
||||||
title: MENU.INITIAL_CANVAS_SETTING,
|
title: MENU.INITIAL_CANVAS_SETTING,
|
||||||
},
|
},
|
||||||
{ index: 2, name: 'plan.menu.roof.cover', icon: 'con02', title: MENU.ROOF_COVERING.DEFAULT },
|
{ type: 'outline', name: 'plan.menu.roof.cover', icon: 'con02', title: MENU.ROOF_COVERING.DEFAULT },
|
||||||
{ index: 3, name: 'plan.menu.placement.surface', icon: 'con03', title: MENU.BATCH_CANVAS.DEFAULT },
|
{ type: 'surface', name: 'plan.menu.placement.surface', icon: 'con03', title: MENU.BATCH_CANVAS.DEFAULT },
|
||||||
{ index: 4, name: 'plan.menu.module.circuit.setting', icon: 'con04', title: MENU.MODULE_CIRCUIT_SETTING.DEFAULT },
|
{ type: 'module', name: 'plan.menu.module.circuit.setting', icon: 'con04', title: MENU.MODULE_CIRCUIT_SETTING.DEFAULT },
|
||||||
{ index: 5, name: 'plan.menu.estimate', icon: 'con06', title: MENU.ESTIMATE.DEFAULT },
|
{ type: 'estimate', name: 'plan.menu.estimate', icon: 'con06', title: MENU.ESTIMATE.DEFAULT },
|
||||||
{ index: 6, name: 'plan.menu.simulation', icon: 'con05', title: MENU.POWER_GENERATION_SIMULATION.DEFAULT },
|
{ type: 'simulation', name: 'plan.menu.simulation', icon: 'con05', title: MENU.POWER_GENERATION_SIMULATION.DEFAULT },
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
export const subMenusState = atom({
|
export const subMenusState = atom({
|
||||||
key: 'subMenusState',
|
key: 'subMenusState',
|
||||||
default: {
|
default: {
|
||||||
|
placement: [], // 배치면 초기 설정
|
||||||
outline: [
|
outline: [
|
||||||
// 지붕덮개
|
// 지붕덮개
|
||||||
{ id: 0, name: 'plan.menu.roof.cover.outline.drawing', menu: MENU.ROOF_COVERING.EXTERIOR_WALL_LINE },
|
{ id: 0, name: 'plan.menu.roof.cover.outline.drawing', menu: MENU.ROOF_COVERING.EXTERIOR_WALL_LINE },
|
||||||
|
|||||||
@ -995,6 +995,26 @@ $alert-color: #101010;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&:disabled{
|
||||||
|
color: $pop-color;
|
||||||
|
border: 1px solid #646464;
|
||||||
|
background-color: transparent;
|
||||||
|
opacity: 0.5;
|
||||||
|
&.act,
|
||||||
|
&:hover{
|
||||||
|
color: $pop-color;
|
||||||
|
border: 1px solid #646464;
|
||||||
|
background-color: transparent;
|
||||||
|
i{
|
||||||
|
&.allocation01{
|
||||||
|
background-image: url(../../public/static/images/canvas/allocation_icon01_white.svg);
|
||||||
|
}
|
||||||
|
&.allocation02{
|
||||||
|
background-image: url(../../public/static/images/canvas/allocation_icon02_white.svg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user