Merge branch 'dev' of https://git.jetbrains.space/nalpari/q-cast-iii/qcast-front into dev
This commit is contained in:
commit
d35b73d67c
@ -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>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -63,20 +63,21 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
||||
/**
|
||||
* 지붕재 초기값
|
||||
*/
|
||||
const defaultRoofSettings = {
|
||||
roofSizeSet: '1', // 기본 치수 입력 방법
|
||||
roofAngleSet: 'slope', // 기본 지붕 각도 설정
|
||||
const DEFAULT_ROOF_SETTINGS = {
|
||||
roofSizeSet: '1',
|
||||
roofAngleSet: 'slope',
|
||||
angle: 21.8,
|
||||
hajebichi: '',
|
||||
hajebichi: null,
|
||||
id: 'ROOF_ID_WA_53A',
|
||||
index: 0,
|
||||
layout: ROOF_MATERIAL_LAYOUT.PARALLEL,
|
||||
lenAuth: 'R',
|
||||
lenBase: '235.000',
|
||||
length: '235',
|
||||
length: 235,
|
||||
name: '일본기와 A',
|
||||
nameJp: '和瓦A',
|
||||
pitch: 4,
|
||||
planNo: planNo,
|
||||
raft: '',
|
||||
raftAuth: 'C',
|
||||
raftBaseCd: 'HEI_455',
|
||||
@ -89,12 +90,12 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
||||
selected: true,
|
||||
widAuth: 'R',
|
||||
widBase: '265.000',
|
||||
width: '265',
|
||||
width: 265,
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
/**
|
||||
* 메뉴에서 배치면초기설정 선택 시 조회
|
||||
* 메뉴에서 배치면초기설정 선택 시 조회 후 화면 오픈
|
||||
*/
|
||||
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) {
|
||||
const raftCodeList = findCommonCode('203800')
|
||||
setRaftCodes(raftCodeList)
|
||||
|
||||
/**
|
||||
* 데이터 설정 확인 후 데이터가 없으면 기본 데이터 설정
|
||||
*/
|
||||
if (addedRoofs.length > 0) {
|
||||
setCurrentRoof({ ...addedRoofs[0], planNo: basicSetting.planNo })
|
||||
} else {
|
||||
setCurrentRoof(defaultRoofSettings)
|
||||
}
|
||||
setCurrentRoof({ ...addedRoofs[0], planNo: planNo, roofSizeSet: String(basicSetting.roofSizeSet), roofAngleSet: basicSetting.roofAngleSet })
|
||||
} else {
|
||||
/** 데이터 설정 확인 후 데이터가 없으면 기본 데이터 설정 */
|
||||
setCurrentRoof({ ...DEFAULT_ROOF_SETTINGS })
|
||||
}
|
||||
}, [addedRoofs])
|
||||
|
||||
/**
|
||||
* 배치면초기설정 정보 변경 시 basicSettings 설정
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!currentRoof) return
|
||||
setBasicSettings({
|
||||
@ -256,7 +255,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
||||
id={item.id}
|
||||
name={item.name}
|
||||
value={item.value}
|
||||
checked={currentRoof?.roofSizeSet === item.value}
|
||||
checked={String(currentRoof?.roofSizeSet) === item.value}
|
||||
onChange={(e) => setCurrentRoof({ ...currentRoof, roofSizeSet: e.target.value })}
|
||||
/>
|
||||
<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}
|
||||
name={item.name}
|
||||
value={item.value}
|
||||
checked={currentRoof?.roofAngleSet === item.value}
|
||||
checked={String(currentRoof?.roofAngleSet) === item.value}
|
||||
onChange={(e) => setCurrentRoof({ ...currentRoof, roofAngleSet: e.target.value })}
|
||||
/>
|
||||
<label htmlFor={item.id}>{getMessage(item.message)}</label>
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
.test {
|
||||
@apply bg-red-500;
|
||||
@apply text-2xl;
|
||||
}
|
||||
@ -2,10 +2,6 @@ import { useAxios } from '@/hooks/useAxios'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
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'
|
||||
|
||||
/**
|
||||
* 마스터 컨트롤러 훅
|
||||
|
||||
@ -43,21 +43,19 @@ import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
const defaultDotLineGridSetting = {
|
||||
INTERVAL: {
|
||||
type: 2, // 1: 가로,세로 간격 수동, 2: 비율 간격
|
||||
type: 2 /* 1: 가로,세로 간격 수동, 2: 비율 간격 */,
|
||||
ratioInterval: 910,
|
||||
verticalInterval: 910,
|
||||
horizontalInterval: 910,
|
||||
dimension: 1, // 치수
|
||||
dimension: 1 /* 치수 */,
|
||||
},
|
||||
DOT: false,
|
||||
LINE: false,
|
||||
}
|
||||
|
||||
// let previousRoofMaterialsYn = 'N' // 지붕재 select 정보 비교 후 변경된 것이 없으면 1회만 실행
|
||||
|
||||
export function useCanvasSetting() {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
/* canvas가 null이 아닐 때에만 getObjects 호출 */
|
||||
/** canvas가 null이 아닐 때에만 getObjects 호출 */
|
||||
const canvasObjects = canvas ? canvas.getObjects() : []
|
||||
const [correntObjectNo, setCorrentObjectNo] = useRecoilState(correntObjectNoState)
|
||||
|
||||
@ -119,14 +117,14 @@ export function useCanvasSetting() {
|
||||
const [type, setType] = useRecoilState(menuTypeState)
|
||||
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
||||
|
||||
const resetModuleSelectionData = useResetRecoilState(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
|
||||
const resetSelectedModules = useResetRecoilState(selectedModuleState) //선택된 모듈
|
||||
const resetModuleSelectionData = useResetRecoilState(moduleSelectionDataState) /* 다음으로 넘어가는 최종 데이터 */
|
||||
const resetSelectedModules = useResetRecoilState(selectedModuleState) /* 선택된 모듈 */
|
||||
|
||||
const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
|
||||
|
||||
const [raftCodes, setRaftCodes] = useState([]) // 서까래 정보
|
||||
const [raftCodes, setRaftCodes] = useState([]) /* 서까래 정보 */
|
||||
const { findCommonCode } = useCommonCode()
|
||||
const [currentRoof, setCurrentRoof] = useState(null) // 현재 선택된 지붕재 정보
|
||||
const [currentRoof, setCurrentRoof] = useState(null) /* 현재 선택된 지붕재 정보 */
|
||||
const { addPopup } = usePopup()
|
||||
const [popupId, setPopupId] = useState(uuidv4())
|
||||
|
||||
@ -144,7 +142,7 @@ export function useCanvasSetting() {
|
||||
useEffect(() => {
|
||||
const tempFetchRoofMaterials = !fetchRoofMaterials
|
||||
|
||||
/* 초 1회만 실행하도록 처리 */
|
||||
/** 초 1회만 실행하도록 처리 */
|
||||
setFetchRoofMaterials(tempFetchRoofMaterials)
|
||||
if (tempFetchRoofMaterials) {
|
||||
addRoofMaterials()
|
||||
@ -176,7 +174,23 @@ export function useCanvasSetting() {
|
||||
angle: item.angle ? parseInt(item.angle) : 21.8,
|
||||
}))
|
||||
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) {
|
||||
const newAddedRoofs = []
|
||||
@ -184,19 +198,7 @@ export function useCanvasSetting() {
|
||||
setAddedRoofs(newAddedRoofs)
|
||||
}
|
||||
setBasicSettings({ ...basicSetting, selectedRoofMaterial: selectedRoofMaterial })
|
||||
}
|
||||
|
||||
/**
|
||||
* 배치면 초기설정 화면이 열리지 않아도 데이터 set 하기 위해서 추가
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (addedRoofs.length > 0) {
|
||||
const raftCodeList = findCommonCode('203800')
|
||||
setRaftCodes(raftCodeList)
|
||||
|
||||
setCurrentRoof({ ...addedRoofs[0] })
|
||||
}
|
||||
}, [addedRoofs])
|
||||
}, [roofMaterials])
|
||||
|
||||
useEffect(() => {
|
||||
if (!canvas) {
|
||||
@ -339,7 +341,7 @@ export function useCanvasSetting() {
|
||||
}
|
||||
})
|
||||
|
||||
/* 데이터 존재 시 화면 닫기(메뉴/저장 클릭 시 제외) */
|
||||
/** 데이터 존재 시 화면 닫기(메뉴/저장 클릭 시 제외) */
|
||||
if (openPoint !== 'canvasMenus' && openPoint !== 'basicSettingSave') {
|
||||
//closePopup(popupId)
|
||||
closeAll()
|
||||
@ -369,9 +371,9 @@ export function useCanvasSetting() {
|
||||
},
|
||||
]
|
||||
|
||||
/* 메뉴에서 배치면 초기설정 클릭 시 실행하지 않음 */
|
||||
/** 메뉴에서 배치면 초기설정 클릭 시 실행하지 않음 */
|
||||
if (openPoint === null) {
|
||||
/* 배치면 초기설정 미저장 상태이면 화면 열기 */
|
||||
/** 배치면 초기설정 미저장 상태이면 화면 열기 */
|
||||
const placementInitialProps = {
|
||||
id: popupId,
|
||||
pos: {
|
||||
@ -385,7 +387,7 @@ export function useCanvasSetting() {
|
||||
}
|
||||
}
|
||||
|
||||
/* 데이터 설정 */
|
||||
/** 데이터 설정 */
|
||||
const addRoofs = []
|
||||
for (let i = 0; i < roofsArray.length; i++) {
|
||||
roofMaterials?.map((material) => {
|
||||
@ -440,6 +442,21 @@ export function useCanvasSetting() {
|
||||
// setCanvasSetting({ ...basicSetting })
|
||||
}
|
||||
|
||||
/**
|
||||
* 저장/복사저장 시 지붕 크기에 따른 메뉴 설정
|
||||
*/
|
||||
const setMenuByRoofSize = (roofSizeSet) => {
|
||||
if (['2', '3'].includes(String(roofSizeSet))) {
|
||||
setMenuNumber(3)
|
||||
setType('surface')
|
||||
setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
|
||||
} else {
|
||||
setMenuNumber(2)
|
||||
setType('outline')
|
||||
setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 기본설정(PlacementShapeSetting) 저장
|
||||
*/
|
||||
@ -471,31 +488,23 @@ export function useCanvasSetting() {
|
||||
|
||||
await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => {
|
||||
swalFire({ text: getMessage(res.returnMessage) })
|
||||
/* BasicSettings Recoil 설정 */
|
||||
/** BasicSettings Recoil 설정 */
|
||||
setBasicSettings({ ...params })
|
||||
})
|
||||
|
||||
/* CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */
|
||||
/** CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */
|
||||
setCanvasSetting({
|
||||
...basicSetting,
|
||||
roofSizeSet: String(params.roofSizeSet),
|
||||
})
|
||||
|
||||
/* 메뉴 설정 */
|
||||
if (['2', '3'].includes(params.roofSizeSet)) {
|
||||
setMenuNumber(3)
|
||||
setType('surface')
|
||||
setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
|
||||
} else {
|
||||
setMenuNumber(2)
|
||||
setType('outline')
|
||||
setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
||||
}
|
||||
/** 메뉴 설정 */
|
||||
setMenuByRoofSize(params.roofSizeSet)
|
||||
|
||||
/* 배치면초기설정 조회 */
|
||||
/** 배치면초기설정 조회 */
|
||||
fetchBasicSettings(params.planNo, 'basicSettingSave')
|
||||
|
||||
/* 모듈 선택 데이터 초기화 */
|
||||
/** 모듈 선택 데이터 초기화 */
|
||||
resetModuleSelectionData()
|
||||
moduleSelectedDataTrigger({ common: {}, module: {}, roofConstructions: [] })
|
||||
const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||
@ -536,27 +545,19 @@ export function useCanvasSetting() {
|
||||
swalFire({ text: getMessage(res.returnMessage) })
|
||||
})
|
||||
|
||||
/* CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */
|
||||
/** CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */
|
||||
setCanvasSetting({
|
||||
...basicSetting,
|
||||
roofSizeSet: String(params.roofSizeSet),
|
||||
})
|
||||
|
||||
/* 메뉴 설정 */
|
||||
if (['2', '3'].includes(params?.roofSizeSet)) {
|
||||
setMenuNumber(3)
|
||||
setType('surface')
|
||||
setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
|
||||
} else {
|
||||
setMenuNumber(2)
|
||||
setType('outline')
|
||||
setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
||||
}
|
||||
/** 메뉴 설정 */
|
||||
setMenuByRoofSize(params.roofSizeSet)
|
||||
|
||||
/* 배치면초기설정 조회 */
|
||||
/** 배치면초기설정 조회 */
|
||||
fetchBasicSettings(Number(params.planNo), 'basicSettingSave')
|
||||
|
||||
/* 모듈 선택 데이터 초기화 */
|
||||
/** 모듈 선택 데이터 초기화 */
|
||||
resetModuleSelectionData()
|
||||
moduleSelectedDataTrigger({ common: {}, module: {}, roofConstructions: [] })
|
||||
const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||
@ -582,24 +583,16 @@ export function useCanvasSetting() {
|
||||
const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
|
||||
const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item }))
|
||||
|
||||
/**
|
||||
* 흡착점 ON/OFF
|
||||
*/
|
||||
/** 흡착점 ON/OFF */
|
||||
setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: res.adsorpPoint })
|
||||
|
||||
/**
|
||||
* 치수선 설정
|
||||
*/
|
||||
/** 치수선 설정 */
|
||||
setDimensionLineSettings({ ...dimensionLineSettings, pixel: res.originPixel, color: res.originColor })
|
||||
|
||||
/**
|
||||
* 도면크기 설정
|
||||
*/
|
||||
/** 도면크기 설정 */
|
||||
setPlanSizeSettingMode({ ...planSizeSettingMode, originHorizon: res.originHorizon, originVertical: res.originVertical })
|
||||
|
||||
/**
|
||||
* 데이터 설정
|
||||
*/
|
||||
/** 데이터 설정 */
|
||||
setSettingModalFirstOptions({
|
||||
...settingModalFirstOptions,
|
||||
option1: optionData1,
|
||||
@ -614,45 +607,35 @@ export function useCanvasSetting() {
|
||||
|
||||
const fontPatternData = {
|
||||
commonText: {
|
||||
/**
|
||||
* 문자 글꼴 조회 데이터
|
||||
*/
|
||||
/** 문자 글꼴 조회 데이터 */
|
||||
fontFamily: getFonts(res.wordFont),
|
||||
fontWeight: getFontStyles(res.wordFontStyle),
|
||||
fontSize: getFontSizes(res.wordFontSize),
|
||||
fontColor: getFontColors(res.wordFontColor),
|
||||
},
|
||||
flowText: {
|
||||
/**
|
||||
* 흐름방향 글꼴 조회 데이터
|
||||
*/
|
||||
/** 흐름방향 글꼴 조회 데이터 */
|
||||
fontFamily: getFonts(res.flowFont),
|
||||
fontWeight: getFontStyles(res.flowFontStyle),
|
||||
fontSize: getFontSizes(res.flowFontSize),
|
||||
fontColor: getFontColors(res.flowFontColor),
|
||||
},
|
||||
dimensionLineText: {
|
||||
/**
|
||||
* 치수 글꼴 조회 데이터
|
||||
*/
|
||||
/** 치수 글꼴 조회 데이터 */
|
||||
fontFamily: getFonts(res.dimensioFont),
|
||||
fontWeight: getFontStyles(res.dimensioFontStyle),
|
||||
fontSize: getFontSizes(res.dimensioFontSize),
|
||||
fontColor: getFontColors(res.dimensioFontColor),
|
||||
},
|
||||
circuitNumberText: {
|
||||
/**
|
||||
* 회로번호 글꼴 조회 데이터
|
||||
*/
|
||||
/** 회로번호 글꼴 조회 데이터 */
|
||||
fontFamily: getFonts(res.circuitNumFont),
|
||||
fontWeight: getFontStyles(res.circuitNumFontStyle),
|
||||
fontSize: getFontSizes(res.circuitNumFontSize),
|
||||
fontColor: getFontColors(res.circuitNumFontColor),
|
||||
},
|
||||
lengthText: {
|
||||
/**
|
||||
* 치수선 글꼴 조회 데이터
|
||||
*/
|
||||
/** 치수선 글꼴 조회 데이터 */
|
||||
fontFamily: getFonts(res.lengthFont),
|
||||
fontWeight: getFontStyles(res.lengthFontStyle),
|
||||
fontSize: getFontSizes(res.lengthFontSize),
|
||||
@ -660,14 +643,10 @@ export function useCanvasSetting() {
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* 조회된 글꼴 데이터 set
|
||||
*/
|
||||
/** 조회된 글꼴 데이터 set */
|
||||
setGlobalFont(fontPatternData)
|
||||
|
||||
/**
|
||||
* 점/선 그리드
|
||||
*/
|
||||
/** 점/선 그리드 */
|
||||
const patternData = {
|
||||
INTERVAL: {
|
||||
type: res.gridType,
|
||||
@ -682,47 +661,31 @@ export function useCanvasSetting() {
|
||||
|
||||
setDotLineGridSettingState(patternData)
|
||||
|
||||
/**
|
||||
* 그리드 색 설정
|
||||
*/
|
||||
/** 그리드 색 설정 */
|
||||
setGridColor(res.gridColor)
|
||||
} else {
|
||||
//조회된 글꼴 데이터가 없는 경우 (데이터 초기화)
|
||||
/** 조회된 글꼴 데이터가 없는 경우 (데이터 초기화) */
|
||||
|
||||
/**
|
||||
* 흡착점 ON/OFF
|
||||
*/
|
||||
/** 흡착점 ON/OFF */
|
||||
setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: false })
|
||||
|
||||
/**
|
||||
* 치수선 설정
|
||||
*/
|
||||
/** 치수선 설정 */
|
||||
resetDimensionLineSettings()
|
||||
|
||||
/**
|
||||
* 도면크기 설정
|
||||
*/
|
||||
/** 도면크기 설정 */
|
||||
resetPlanSizeSettingMode()
|
||||
|
||||
/**
|
||||
* 데이터 설정
|
||||
*/
|
||||
/** 데이터 설정 */
|
||||
resetSettingModalFirstOptions()
|
||||
resetSettingModalSecondOptions()
|
||||
|
||||
/**
|
||||
* 데이터 초기화
|
||||
*/
|
||||
/** 데이터 초기화 */
|
||||
resetGlobalFont()
|
||||
|
||||
/**
|
||||
* 점/선 그리드
|
||||
*/
|
||||
/** 점/선 그리드 */
|
||||
setDotLineGridSettingState({ ...defaultDotLineGridSetting })
|
||||
|
||||
/**
|
||||
* 그리드 색 설정
|
||||
*/
|
||||
/** 그리드 색 설정 */
|
||||
setGridColor('#FF0000')
|
||||
}
|
||||
|
||||
@ -736,9 +699,7 @@ export function useCanvasSetting() {
|
||||
* CanvasSetting 옵션 클릭 후 저장
|
||||
*/
|
||||
const onClickOption2 = async () => {
|
||||
/**
|
||||
* 서버에 전송할 데이터
|
||||
*/
|
||||
/** 서버에 전송할 데이터 */
|
||||
const dataToSend = {
|
||||
firstOption1: option1.map((item) => ({
|
||||
column: item.column,
|
||||
@ -759,13 +720,9 @@ export function useCanvasSetting() {
|
||||
})),
|
||||
}
|
||||
const patternData = {
|
||||
/**
|
||||
* 견적서 번호
|
||||
*/
|
||||
/** 견적서 번호 */
|
||||
objectNo: correntObjectNo,
|
||||
/**
|
||||
* 디스플레이 설정(다중)
|
||||
*/
|
||||
/** 디스플레이 설정(다중) */
|
||||
allocDisplay: dataToSend.firstOption1[0].selected,
|
||||
outlineDisplay: dataToSend.firstOption1[1].selected,
|
||||
gridDisplay: dataToSend.firstOption1[2].selected,
|
||||
@ -776,85 +733,62 @@ export function useCanvasSetting() {
|
||||
trestleDisplay: dataToSend.firstOption1[7].selected,
|
||||
imageDisplay: dataToSend.firstOption1[8].selected,
|
||||
totalDisplay: dataToSend.firstOption1[9].selected,
|
||||
/**
|
||||
* 차수 표시(단 건)
|
||||
*/
|
||||
/** 차수 표시(단 건) */
|
||||
corridorDimension: dataToSend.firstOption3[0].selected,
|
||||
realDimension: dataToSend.firstOption3[1].selected,
|
||||
noneDimension: dataToSend.firstOption3[2].selected,
|
||||
/**
|
||||
* 화면 표시(단 건)
|
||||
*/
|
||||
/** 화면 표시(단 건) */
|
||||
onlyBorder: dataToSend.firstOption2[0].selected,
|
||||
lineHatch: dataToSend.firstOption2[1].selected,
|
||||
allPainted: dataToSend.firstOption2[2].selected,
|
||||
/**
|
||||
* 흡착범위 설정(단 건)
|
||||
*/
|
||||
/** 흡착범위 설정(단 건) */
|
||||
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
|
||||
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
|
||||
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
|
||||
adsorpRangeLarge: dataToSend.secondOption2[3].selected,
|
||||
|
||||
/**
|
||||
* 흡착점 ON/OFF
|
||||
*/
|
||||
/** 흡착점 ON/OFF */
|
||||
adsorpPoint: adsorptionPointMode.adsorptionPoint,
|
||||
//??: adsorptionRange, 사용여부 확인 필요
|
||||
|
||||
/**
|
||||
* 글꼴 설정
|
||||
*/
|
||||
//문자 글꼴
|
||||
/** 문자 글꼴 설정 */
|
||||
wordFont: globalFont.commonText.fontFamily?.value ?? 'MS PGothic',
|
||||
wordFontStyle: globalFont.commonText.fontWeight?.value ?? 'normal',
|
||||
wordFontSize: globalFont.commonText.fontSize?.value ?? 16,
|
||||
wordFontColor: globalFont.commonText.fontColor?.value ?? 'black',
|
||||
|
||||
/**
|
||||
* 흐름방향 글꼴
|
||||
*/
|
||||
/** 흐름방향 글꼴 설정 */
|
||||
flowFont: globalFont.flowText.fontFamily?.value ?? 'MS PGothic',
|
||||
flowFontStyle: globalFont.flowText.fontWeight?.value ?? 'normal',
|
||||
flowFontSize: globalFont.flowText.fontSize?.value ?? 16,
|
||||
flowFontColor: globalFont.flowText.fontColor?.value ?? 'black',
|
||||
|
||||
/**
|
||||
* 치수 글꼴
|
||||
*/
|
||||
/** 치수 글꼴 설정 */
|
||||
dimensioFont: globalFont.dimensionLineText.fontFamily?.value ?? 'MS PGothic',
|
||||
dimensioFontStyle: globalFont.dimensionLineText.fontWeight?.value ?? 'normal',
|
||||
dimensioFontSize: globalFont.dimensionLineText.fontSize?.value ?? 16,
|
||||
dimensioFontColor: globalFont.dimensionLineText.fontColor?.value ?? 'black',
|
||||
|
||||
/**
|
||||
* 회로번호 글꼴
|
||||
*/
|
||||
/** 회로번호 글꼴 설정 */
|
||||
circuitNumFont: globalFont.circuitNumberText.fontFamily?.value ?? 'MS PGothic',
|
||||
circuitNumFontStyle: globalFont.circuitNumberText.fontWeight?.value ?? 'normal',
|
||||
circuitNumFontSize: globalFont.circuitNumberText.fontSize?.value ?? 16,
|
||||
circuitNumFontColor: globalFont.circuitNumberText.fontColor?.value ?? 'black',
|
||||
|
||||
/**
|
||||
* 치수선 글꼴
|
||||
*/
|
||||
/** 치수선 글꼴 설정 */
|
||||
lengthFont: globalFont.lengthText.fontFamily?.value ?? 'MS PGothic',
|
||||
lengthFontStyle: globalFont.lengthText.fontWeight?.value ?? 'normal',
|
||||
lengthFontSize: globalFont.lengthText.fontSize?.value ?? 16,
|
||||
lengthFontColor: globalFont.lengthText.fontColor?.value ?? 'black',
|
||||
|
||||
/**
|
||||
* 치수선 설정
|
||||
*/
|
||||
/** 치수선 설정 */
|
||||
originPixel: dimensionLineSettings.pixel,
|
||||
originColor: dimensionLineSettings.color,
|
||||
|
||||
/**
|
||||
* 도면크기 설정
|
||||
*/
|
||||
/** 도면크기 설정 */
|
||||
originHorizon: planSizeSettingMode.originHorizon,
|
||||
originVertical: planSizeSettingMode.originVertical,
|
||||
|
||||
/** 점/선 그리드 */
|
||||
dotGridDisplay: dotLineGridSetting.DOT,
|
||||
lineGridDisplay: dotLineGridSetting.LINE,
|
||||
gridType: dotLineGridSetting.INTERVAL.type,
|
||||
@ -863,6 +797,7 @@ export function useCanvasSetting() {
|
||||
gridRatio: dotLineGridSetting.INTERVAL.ratioInterval / 10,
|
||||
gridDimen: dotLineGridSetting.INTERVAL.dimension,
|
||||
|
||||
/** 그리드 색 설정 */
|
||||
gridColor: gridColor,
|
||||
}
|
||||
|
||||
@ -875,13 +810,10 @@ export function useCanvasSetting() {
|
||||
.then((res) => {
|
||||
//swalFire({ text: getMessage(res.returnMessage) })
|
||||
|
||||
/**
|
||||
* Canvas 디스플레이 설정 시 해당 옵션 적용
|
||||
*/
|
||||
/** Canvas 디스플레이 설정 시 해당 옵션 적용 */
|
||||
frontSettings()
|
||||
/**
|
||||
* 저장 후 재조회
|
||||
*/
|
||||
|
||||
/** 저장 후 재조회 */
|
||||
fetchSettings()
|
||||
})
|
||||
.catch((error) => {
|
||||
@ -912,8 +844,8 @@ export function useCanvasSetting() {
|
||||
*/
|
||||
|
||||
/**
|
||||
* 옵션명
|
||||
* 옵션상태
|
||||
* 옵션명 optionName
|
||||
* 옵션상태 optionSelected
|
||||
*/
|
||||
let optionName
|
||||
let optionSelected
|
||||
@ -948,15 +880,11 @@ export function useCanvasSetting() {
|
||||
optionName = ['backGroundImage']
|
||||
break
|
||||
case 'totalDisplay':
|
||||
/**
|
||||
* 작업할 필요 없음
|
||||
*/
|
||||
/** 작업할 필요 없음 */
|
||||
optionName = []
|
||||
break
|
||||
}
|
||||
/**
|
||||
* 표시 선택 상태(true/false)
|
||||
*/
|
||||
/** 표시 선택 상태(true/false)*/
|
||||
optionSelected = option1[i].selected
|
||||
|
||||
canvasObjects
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user