Merge branch 'dev' of https://git.jetbrains.space/nalpari/q-cast-iii/qcast-front into dev
This commit is contained in:
commit
dee5f23f1c
@ -25,6 +25,7 @@
|
|||||||
"react-colorful": "^5.6.1",
|
"react-colorful": "^5.6.1",
|
||||||
"react-datepicker": "^7.3.0",
|
"react-datepicker": "^7.3.0",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
|
"react-icons": "^5.3.0",
|
||||||
"react-responsive-modal": "^6.4.2",
|
"react-responsive-modal": "^6.4.2",
|
||||||
"react-toastify": "^10.0.5",
|
"react-toastify": "^10.0.5",
|
||||||
"recoil": "^0.7.7",
|
"recoil": "^0.7.7",
|
||||||
|
|||||||
5
src/app/[locale]/floor-plan/page.jsx
Normal file
5
src/app/[locale]/floor-plan/page.jsx
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import FloorPlan from '@/components/floor-plan/FloorPlan'
|
||||||
|
|
||||||
|
export default function floorPlanPage() {
|
||||||
|
return <FloorPlan />
|
||||||
|
}
|
||||||
29
src/app/api/html2canvas/route.js
Normal file
29
src/app/api/html2canvas/route.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use server'
|
||||||
|
|
||||||
|
import fs from 'fs/promises'
|
||||||
|
|
||||||
|
import { NextResponse } from 'next/server'
|
||||||
|
|
||||||
|
export async function GET(req) {
|
||||||
|
const path = 'public/mapImages'
|
||||||
|
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)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.readdir(path)
|
||||||
|
} catch {
|
||||||
|
await fs.mkdir(path)
|
||||||
|
} finally {
|
||||||
|
await fs.writeFile(`${path}/${fileNm}.png`, buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ fileNm: `${fileNm}.png` })
|
||||||
|
}
|
||||||
@ -1,25 +1,32 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useRef, useState } from 'react'
|
import { useRef, useState } from 'react'
|
||||||
import { Button } from '@nextui-org/react'
|
import { useRecoilState } from 'recoil'
|
||||||
import ColorPicker from './common/color-picker/ColorPicker'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
import { FaAnglesUp } from 'react-icons/fa6'
|
||||||
|
import { FaAnglesDown } from 'react-icons/fa6'
|
||||||
|
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { convertDwgToPng } from '@/lib/cadAction'
|
import { convertDwgToPng } from '@/lib/cadAction'
|
||||||
// import { get } from '@/lib/Axios'
|
import { cadFileNameState, googleMapFileNameState, useCadFileState, useGoogleMapFileState } from '@/store/canvasAtom'
|
||||||
|
|
||||||
import QSelect from '@/components/ui/QSelect'
|
import QSelect from '@/components/ui/QSelect'
|
||||||
|
import { Button } from '@nextui-org/react'
|
||||||
|
import ColorPicker from './common/color-picker/ColorPicker'
|
||||||
|
import { toastUp } from '@/hooks/useToast'
|
||||||
|
|
||||||
import styles from './playground.module.css'
|
import styles from './playground.module.css'
|
||||||
import { useRecoilState } from 'recoil'
|
import Image from 'next/image'
|
||||||
import { cadFileNameState, useCadFileState } from '@/store/canvasAtom'
|
|
||||||
import { toastUp } from '@/hooks/useToast'
|
|
||||||
|
|
||||||
export default function Playground() {
|
export default function Playground() {
|
||||||
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
|
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
|
||||||
const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState)
|
const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState)
|
||||||
|
const [useGoogleMapFile, setUseGoogleMapFile] = useRecoilState(useGoogleMapFileState)
|
||||||
|
const [googleMapFileName, setGoogleMapFileName] = useRecoilState(googleMapFileNameState)
|
||||||
const fileRef = useRef(null)
|
const fileRef = useRef(null)
|
||||||
|
const queryRef = useRef(null)
|
||||||
|
const [zoom, setZoom] = useState(20)
|
||||||
const { get, promisePost } = useAxios()
|
const { get, promisePost } = useAxios()
|
||||||
const testVar = process.env.NEXT_PUBLIC_TEST
|
const testVar = process.env.NEXT_PUBLIC_TEST
|
||||||
const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL
|
const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL
|
||||||
@ -56,6 +63,26 @@ export default function Playground() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
toastUp({ message: '이미지 저장 완료', type: 'success' })
|
||||||
|
setUseGoogleMapFile(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleZoom = async (type) => {
|
||||||
|
if (type === 'up') {
|
||||||
|
setZoom((prevState) => prevState + 1)
|
||||||
|
} else {
|
||||||
|
setZoom((prevState) => prevState - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
await handleDownImage()
|
||||||
|
}
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@ -99,11 +126,31 @@ export default function Playground() {
|
|||||||
<div className="p-4">{color}</div>
|
<div className="p-4">{color}</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
<h1 className="text-2xl">캐드 파일 이미지 사용</h1>
|
||||||
<input type="file" name="file" ref={fileRef} />
|
<input type="file" name="file" ref={fileRef} />
|
||||||
<div>
|
<div>
|
||||||
<Button onClick={handleConvert}>Convert</Button>
|
<Button onClick={handleConvert}>Convert</Button>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -16,11 +16,13 @@ import {
|
|||||||
currentObjectState,
|
currentObjectState,
|
||||||
fontSizeState,
|
fontSizeState,
|
||||||
globalCompassState,
|
globalCompassState,
|
||||||
|
googleMapFileNameState,
|
||||||
roofMaterialState,
|
roofMaterialState,
|
||||||
roofState,
|
roofState,
|
||||||
sortedPolygonArray,
|
sortedPolygonArray,
|
||||||
templateTypeState,
|
templateTypeState,
|
||||||
useCadFileState,
|
useCadFileState,
|
||||||
|
useGoogleMapFileState,
|
||||||
wallState,
|
wallState,
|
||||||
} from '@/store/canvasAtom'
|
} from '@/store/canvasAtom'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
@ -50,7 +52,7 @@ export default function Roof2(props) {
|
|||||||
setCanvasBackgroundWithDots,
|
setCanvasBackgroundWithDots,
|
||||||
saveImage,
|
saveImage,
|
||||||
addCanvas,
|
addCanvas,
|
||||||
handleCadImageLoad,
|
handleBackImageLoadToCanvas,
|
||||||
handleCadImageInit,
|
handleCadImageInit,
|
||||||
backImg,
|
backImg,
|
||||||
setBackImg,
|
setBackImg,
|
||||||
@ -100,13 +102,18 @@ export default function Roof2(props) {
|
|||||||
canvas,
|
canvas,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let imgPath
|
||||||
// cad 파일 업로드
|
// cad 파일 업로드
|
||||||
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
|
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
|
||||||
const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState)
|
const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState)
|
||||||
const [cadFileComplete, setCadFileComplete] = useRecoilState(cadFileCompleteState)
|
const [cadFileComplete, setCadFileComplete] = useRecoilState(cadFileCompleteState)
|
||||||
let imgPath
|
|
||||||
useCadFile && (imgPath = `/cadImages/${cadFileName}`)
|
useCadFile && (imgPath = `/cadImages/${cadFileName}`)
|
||||||
|
|
||||||
|
// 구글맵 이미지 업로드
|
||||||
|
const [useGoogleMapFile, setUseGoogleMapFile] = useRecoilState(useGoogleMapFileState)
|
||||||
|
const [googleMapFileName, setGoogleMapFileName] = useRecoilState(googleMapFileNameState)
|
||||||
|
useGoogleMapFile && (imgPath = `/mapImages/${googleMapFileName}`)
|
||||||
|
|
||||||
const [globalCampass, setGlobalCampass] = useRecoilState(globalCompassState)
|
const [globalCampass, setGlobalCampass] = useRecoilState(globalCompassState)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -158,7 +165,11 @@ export default function Roof2(props) {
|
|||||||
|
|
||||||
if (!cadFileComplete && useCadFile) {
|
if (!cadFileComplete && useCadFile) {
|
||||||
// cad 파일 로드
|
// cad 파일 로드
|
||||||
useCadFile && handleCadImageLoad(imgPath, canvas)
|
useCadFile && handleBackImageLoadToCanvas(imgPath, canvas)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useGoogleMapFile) {
|
||||||
|
handleBackImageLoadToCanvas(imgPath, canvas)
|
||||||
}
|
}
|
||||||
}, [canvas, mode])
|
}, [canvas, mode])
|
||||||
|
|
||||||
@ -822,6 +833,7 @@ export default function Roof2(props) {
|
|||||||
backImg
|
backImg
|
||||||
.set({
|
.set({
|
||||||
selectable: false,
|
selectable: false,
|
||||||
|
opacity: 0.7,
|
||||||
})
|
})
|
||||||
.sendToBack()
|
.sendToBack()
|
||||||
canvas.clear()
|
canvas.clear()
|
||||||
@ -831,7 +843,7 @@ export default function Roof2(props) {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
cad 파일 조정 완료
|
배경 이미지 조정 완료
|
||||||
</Button>
|
</Button>
|
||||||
<Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}>
|
<Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}>
|
||||||
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
|
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
|
||||||
|
|||||||
@ -12,9 +12,11 @@ export default function QContextMenu(props) {
|
|||||||
let contextType = ''
|
let contextType = ''
|
||||||
|
|
||||||
if (activeObject) {
|
if (activeObject) {
|
||||||
//이건 바뀔 가능성이 있음
|
if (activeObject.initOptions) {
|
||||||
if (activeObject.initOptions.name.indexOf('guide') > -1) {
|
//이건 바뀔 가능성이 있음
|
||||||
contextType = 'surface' //면형상
|
if (activeObject.initOptions.name.indexOf('guide') > -1) {
|
||||||
|
contextType = 'surface' //면형상
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
7
src/components/floor-plan/FloorPlan.jsx
Normal file
7
src/components/floor-plan/FloorPlan.jsx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export default function FloorPlan() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>도면 작성 페이지</h1>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -449,7 +449,7 @@ export function useCanvas(id) {
|
|||||||
/**
|
/**
|
||||||
* cad 파일 사용시 이미지 로딩 함수
|
* cad 파일 사용시 이미지 로딩 함수
|
||||||
*/
|
*/
|
||||||
const handleCadImageLoad = (url) => {
|
const handleBackImageLoadToCanvas = (url) => {
|
||||||
console.log('image load url: ', url)
|
console.log('image load url: ', url)
|
||||||
|
|
||||||
fabric.Image.fromURL(url, function (img) {
|
fabric.Image.fromURL(url, function (img) {
|
||||||
@ -485,7 +485,7 @@ export function useCanvas(id) {
|
|||||||
setCanvasBackgroundWithDots,
|
setCanvasBackgroundWithDots,
|
||||||
addCanvas,
|
addCanvas,
|
||||||
removeMouseLines,
|
removeMouseLines,
|
||||||
handleCadImageLoad,
|
handleBackImageLoadToCanvas,
|
||||||
handleCadImageInit,
|
handleCadImageInit,
|
||||||
backImg,
|
backImg,
|
||||||
setBackImg,
|
setBackImg,
|
||||||
|
|||||||
@ -145,6 +145,17 @@ export const cadFileCompleteState = atom({
|
|||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const useGoogleMapFileState = atom({
|
||||||
|
key: 'useGoogleMapFile',
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 구글맵 저장 이미지 파일 이름
|
||||||
|
export const googleMapFileNameState = atom({
|
||||||
|
key: 'googleMapFileName',
|
||||||
|
default: '',
|
||||||
|
})
|
||||||
|
|
||||||
export const globalCompassState = atom({
|
export const globalCompassState = atom({
|
||||||
key: 'globalCompass',
|
key: 'globalCompass',
|
||||||
default: 0,
|
default: 0,
|
||||||
|
|||||||
@ -5515,6 +5515,11 @@ react-dom@^18:
|
|||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
scheduler "^0.23.2"
|
scheduler "^0.23.2"
|
||||||
|
|
||||||
|
react-icons@^5.3.0:
|
||||||
|
version "5.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-5.3.0.tgz#ccad07a30aebd40a89f8cfa7d82e466019203f1c"
|
||||||
|
integrity sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==
|
||||||
|
|
||||||
react-is@^16.13.1:
|
react-is@^16.13.1:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user