From eeb2ba6c17b753bc976c4ad8739fddd29f102723 Mon Sep 17 00:00:00 2001 From: minsik Date: Tue, 3 Dec 2024 13:05:41 +0900 Subject: [PATCH 1/9] =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EB=B6=88=EB=9F=AC?= =?UTF-8?q?=EC=98=A4=EA=B8=B0=20=EB=8B=A4=EA=B5=AD=EC=96=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/locales/ja.json | 5 +++++ src/locales/ko.json | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/locales/ja.json b/src/locales/ja.json index 23903120..0409bee0 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -341,6 +341,7 @@ "modal.panel.column.insert.info": "挿入する方向を選択してください。", "modal.panel.column.insert.type.left": "左挿入", "modal.panel.column.insert.type.right": "右挿入", + "modal.image.load.size.rotate": "サイズ調整と回転", "contextmenu.column.insert": "列の挿入", "contextmenu.row.move": "단 이동(JA)", "contextmenu.row.copy": "단 복사(JA)", @@ -483,9 +484,13 @@ "common.message.writeToConfirm": "作成解除を実行しますか?", "common.message.password.init.success": "パスワード [{0}] に初期化されました。", "common.message.no.edit.save": "この文書は変更できません。", + "common.load": "ファイルの追加", "common.input.file": "ファイルを読み込む", "common.input.file.load": "ファイルの追加", + "common.input.image.load": "이미지 불러오기", + "common.input.address.load": "アドレスを読み込む", "common.require": "必須", + "common.finish": "完了", "common.ok": "確認", "commons.west": "立つ", "commons.east": "ドン", diff --git a/src/locales/ko.json b/src/locales/ko.json index 0cf7217b..2adcdb28 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -348,6 +348,7 @@ "modal.panel.column.insert.info": "삽입할 방향을 선택해주세요.", "modal.panel.column.insert.type.left": "왼쪽 삽입", "modal.panel.column.insert.type.right": "오른쪽 삽입", + "modal.image.load.size.rotate": "크기 조절 및 회전", "contextmenu.row.move": "단 이동", "contextmenu.row.copy": "단 복사", "contextmenu.row.remove": "단 삭제", @@ -492,9 +493,13 @@ "common.message.writeToConfirm": "작성 해제를 실행하시겠습니까?", "common.message.password.init.success": "비밀번호 [{0}]로 초기화 되었습니다.", "common.message.no.edit.save": "This document cannot be changed.", + "common.load": "불러오기", "common.input.file": "파일 불러오기", "common.input.file.load": "불러오기", + "common.input.image.load": "이미지 불러오기", + "common.input.address.load": "주소 불러오기", "common.require": "필수", + "common.finish": "완료", "common.ok": "확인", "commons.west": "서", "commons.east": "동", From 57ce17a9323985bb9f15de5b294f865c1b96fa23 Mon Sep 17 00:00:00 2001 From: minsik Date: Tue, 3 Dec 2024 13:08:29 +0900 Subject: [PATCH 2/9] =?UTF-8?q?-=20=ED=8C=8C=EC=9D=BC=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=20=EA=B3=B5=ED=86=B5=20=EC=BD=94=EB=93=9C=20=EC=A0=81=EC=9A=A9?= =?UTF-8?q?=20-=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80=20-=20=EB=8B=A4=EA=B5=AD?= =?UTF-8?q?=EC=96=B4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/api/html2canvas/route.js | 10 +-- src/app/api/image-upload/route.js | 20 ++--- src/components/floor-plan/modal/ImgLoad.jsx | 31 ++++---- src/hooks/common/useRefFiles.js | 81 ++++++++++++++++++--- src/hooks/usePlan.js | 9 +++ src/lib/fileAction.js | 62 ++++++++++++---- 6 files changed, 155 insertions(+), 58 deletions(-) diff --git a/src/app/api/html2canvas/route.js b/src/app/api/html2canvas/route.js index ada6c54a..21f93c82 100644 --- a/src/app/api/html2canvas/route.js +++ b/src/app/api/html2canvas/route.js @@ -3,6 +3,7 @@ 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' @@ -15,14 +16,7 @@ export async function GET(req) { 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) - } + await writeImage(fileNm, buffer) return NextResponse.json({ fileNm: `${fileNm}.png` }) } diff --git a/src/app/api/image-upload/route.js b/src/app/api/image-upload/route.js index e817bd3b..92cf7da4 100644 --- a/src/app/api/image-upload/route.js +++ b/src/app/api/image-upload/route.js @@ -3,23 +3,25 @@ import fs from 'fs/promises' import { NextResponse } from 'next/server' +import { writeImage } from '@/lib/fileAction' export async function POST(req) { const path = 'public/plan-bg-images' 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) // const buffer = new Uint8Array(arrayBuffer) + await writeImage(fileName, buffer) + // try { + // await fs.readdir(path) + // } catch { + // await fs.mkdir(path) + // } finally { + // await fs.writeFile(`${path}/${fileName}`, buffer) + // } - try { - await fs.readdir(path) - } catch { - await fs.mkdir(path) - } finally { - await fs.writeFile(`${path}/${file.name}`, buffer) - } - - return NextResponse.json({ fileNm: `${file.name}` }) + return NextResponse.json({ fileNm: `${fileName}` }) } diff --git a/src/components/floor-plan/modal/ImgLoad.jsx b/src/components/floor-plan/modal/ImgLoad.jsx index c95d62a9..d5724972 100644 --- a/src/components/floor-plan/modal/ImgLoad.jsx +++ b/src/components/floor-plan/modal/ImgLoad.jsx @@ -22,18 +22,20 @@ export default function ImgLoad() { setMapPositionAddress, handleFileDelete, handleMapImageDown, + handleAddressDelete, } = useRefFiles() const { currentCanvasPlan } = usePlan() const { getMessage } = useMessage() const { floorPlanState, setFloorPlanState } = useContext(FloorPlanContext) const handleModal = () => { + console.log(floorPlanState) setFloorPlanState({ ...floorPlanState, refFileModalOpen: false }) } useEffect(() => { - console.log('🚀 ~ ImgLoad ~ floorPlanState.refFileModalOpen:', floorPlanState.refFileModalOpen) - console.log('🚀 ~ ImgLoad ~ currentCanvasPlan:', currentCanvasPlan) + // console.log('🚀 ~ ImgLoad ~ floorPlanState.refFileModalOpen:', floorPlanState.refFileModalOpen) + // console.log('🚀 ~ ImgLoad ~ currentCanvasPlan:', currentCanvasPlan) }, [floorPlanState.refFileModalOpen]) useEffect(() => { @@ -50,7 +52,7 @@ export default function ImgLoad() {
- サイズ調整と回転 + {getMessage('modal.image.load.size.rotate')}
diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 05f60afe..5997b399 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -5,7 +5,7 @@ import { v4 as uuidv4 } from 'uuid' import { useSwal } from '@/hooks/useSwal' import { useAxios } from '../useAxios' import { currentCanvasPlanState } from '@/store/canvasAtom' -import { convertDwgToPng, writeImageBuffer } from '@/lib/fileAction' +import { convertDwgToPng, removeImage, writeImageBuffer } from '@/lib/fileAction' export function useRefFiles() { const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL @@ -19,17 +19,51 @@ export function useRefFiles() { const { get, promisePut, promisePost } = useAxios() // const { currentCanvasPlan, setCurrentCanvasPlan } = usePlan() + useEffect(() => { + console.log('refImage', refImage) + }, [refImage]) + + useEffect(() => { + if (refFileMethod === '1') { + // 파일 불러오기 + setMapPositionAddress('') + } else { + setRefImage(null) + } + }, [refFileMethod]) /** * 파일 불러오기 버튼 컨트롤 * @param {*} file */ const handleRefFile = (file) => { - setRefImage(file) + console.log('handleRefFile', file) + console.log('refImage', refImage) + if (file && ['image/png', 'image/jpg', 'image/jpeg', 'image/bmp', 'image/gif'].includes(file.type)) { + // setRefImage(file) + file.name.split('.').pop() === 'dwg' ? handleUploadConvertRefFile(file) : handleUploadImageRefFile(file) + } else { + swalFire({ + text: '이미지가 아닙니다.', + type: 'alert', + icon: 'error', + }) + } + if (refImage) { + swalFire({ + text: '파일을 변경하시겠습니까?', + type: 'confirm', + confirmFn: () => { + setRefImage(file) + file.name.split('.').pop() === 'dwg' ? handleUploadConvertRefFile(file) : handleUploadImageRefFile(file) + }, + }) + } + /** * 파일 확장자가 dwg일 경우 변환하여 이미지로 저장 * 파일 확장자가 이미지일 경우 이미지 저장 */ - file.name.split('.').pop() === 'dwg' ? handleUploadConvertRefFile(file) : handleUploadImageRefFile(file) + // handleUploadRefFile(file) } @@ -37,15 +71,34 @@ export function useRefFiles() { * 파일 삭제 */ const handleFileDelete = () => { - setRefImage(null) - setCurrentCanvasPlan((prev) => ({ ...prev, bgFileName: null })) + swalFire({ + text: '삭제하시겠습니까?', + type: 'confirm', + confirmFn: () => { + setRefImage(null) + setCurrentCanvasPlan((prev) => ({ ...prev, bgFileName: null })) + removeImage(currentCanvasPlan.id).then((res) => { + console.log(res) + }) + }, + }) } /** * 주소 삭제 */ const handleAddressDelete = () => { - setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) + swalFire({ + text: '삭제하시겠습니까?', + type: 'confirm', + confirmFn: () => { + setMapPositionAddress('') + setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) + removeImage(currentCanvasPlan.id).then((res) => { + console.log(res) + }) + }, + }) } /** @@ -56,9 +109,10 @@ export function useRefFiles() { return } - const res = await get({ url: `http://localhost:3000/api/html2canvas?q=${queryRef.current.value}&fileNm=${uuidv4()}&zoom=20` }) - console.log('🚀 ~ handleMapImageDown ~ res:', res) - setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: res.fileNm, mapPositionAddress: queryRef.current.value })) + const res = await get({ url: `http://localhost:3000/api/html2canvas?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20` }) + // console.log('🚀 ~ handleMapImageDown ~ res:', res) + console.log('currentCanvasPlan', currentCanvasPlan) + setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: currentCanvasPlan.id, mapPositionAddress: queryRef.current.value })) } /** @@ -66,9 +120,10 @@ export function useRefFiles() { * @param {*} file */ const handleUploadImageRefFile = async (file) => { - console.log('🚀 ~ handleUploadImageRefFile ~ file:', file) + // console.log('🚀 ~ handleUploadImageRefFile ~ file:', file) const formData = new FormData() formData.append('file', file) + formData.append('fileName', currentCanvasPlan.id) const response = await fetch('http://localhost:3000/api/image-upload', { method: 'POST', @@ -76,7 +131,8 @@ export function useRefFiles() { }) const result = await response.json() - console.log('🚀 ~ handleUploadImageRefFile ~ res:', result) + setRefImage(file) + // console.log('🚀 ~ handleUploadImageRefFile ~ res:', result) // writeImageBuffer(file) } @@ -92,6 +148,7 @@ export function useRefFiles() { .then((res) => { convertDwgToPng(res.data.Files[0].FileName, res.data.Files[0].FileData) swalFire({ text: '파일 변환 성공' }) + setRefImage(res.data.Files[0].FileData) }) .catch((err) => { swalFire({ text: '파일 변환 실패', icon: 'error' }) @@ -110,7 +167,7 @@ export function useRefFiles() { * 현재 플랜이 변경되면 플랜 상태 저장 */ useEffect(() => { - console.log('🚀 ~ useRefFiles ~ currentCanvasPlan:', currentCanvasPlan) + // console.log('🚀 ~ useRefFiles ~ currentCanvasPlan:', currentCanvasPlan) // const handleCurrentPlan = async () => { // await promisePut({ url: '/api/canvas-management/canvas-statuses', data: currentCanvasPlan }).then((res) => { // console.log('🚀 ~ awaitpromisePut ~ res:', res) diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index 6b1336a5..3f3ad1a0 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -6,6 +6,7 @@ import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' import { useSwal } from '@/hooks/useSwal' import { SAVE_KEY } from '@/common/common' +import { readImage } from '@/lib/fileAction' export function usePlan() { const [planNum, setPlanNum] = useState(0) @@ -204,6 +205,7 @@ export function usePlan() { userId: userId, imageName: 'image_name', // api 필수항목이여서 임시로 넣음, 이후 삭제 필요 objectNo: currentCanvasPlan.objectNo, + mapPositionAddress: currentCanvasPlan.mapPositionAddress, canvasStatus: canvasToDbFormat(canvasStatus), } await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData }) @@ -233,6 +235,7 @@ export function usePlan() { const putCanvasStatus = async (canvasStatus) => { const planData = { id: currentCanvasPlan.id, + mapPositionAddress: currentCanvasPlan.mapPositionAddress, canvasStatus: canvasToDbFormat(canvasStatus), } await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData }) @@ -285,6 +288,7 @@ export function usePlan() { updateCurrentPlan(newCurrentId) } } + const updateCurrentPlan = (newCurrentId) => { setPlans((plans) => plans.map((plan) => { @@ -295,8 +299,13 @@ export function usePlan() { useEffect(() => { setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null) setSelectedPlan(plans.find((plan) => plan.isCurrent)) + // setBgImage() }, [plans]) + const setBgImage = () => { + readImage(selectedPlan?.id) + } + /** * 새로운 plan 생성 * 현재 plan의 데이터가 있을 경우 복제 여부를 확인 diff --git a/src/lib/fileAction.js b/src/lib/fileAction.js index d09473a8..6f88758a 100644 --- a/src/lib/fileAction.js +++ b/src/lib/fileAction.js @@ -4,6 +4,7 @@ import fs from 'fs/promises' const CAD_FILE_PATH = 'public/cad-images' const IMAGE_FILE_PATH = 'public/plan-bg-images' +const FILE_PATH = 'public/plan-images' /** * 파일 변환 & 저장 @@ -39,25 +40,54 @@ const writeImageBase64 = async (title, data) => { return fs.writeFile(`${IMAGE_FILE_PATH}/${title}.png`, data, 'base64') } -/** - * 이미지 저장 - * Buffer 형식으로 저장 - * @param {*} title - * @param {*} data - * @returns - */ -const writeImageBuffer = async (file) => { - // 해당 경로에 Directory 가 없다면 생성 +// /** +// * 이미지 저장 +// * Buffer 형식으로 저장 +// * @param {*} title +// * @param {*} data +// * @returns +// */ +// const writeImageBuffer = async (file) => { +// // 해당 경로에 Directory 가 없다면 생성 +// try { +// await fs.readdir(IMAGE_FILE_PATH) +// } catch { +// await fs.mkdir(IMAGE_FILE_PATH) +// } +// +// const arrayBuffer = await fileURLToPath.arrayBuffer() +// const buffer = new Uint8Array(arrayBuffer) +// +// return fs.writeFile(`${IMAGE_FILE_PATH}/${file.fileName}`, buffer) +// } + +const writeImage = async (fileName, file) => { try { - await fs.readdir(IMAGE_FILE_PATH) + await fs.readdir(FILE_PATH) } catch { - await fs.mkdir(IMAGE_FILE_PATH) + await fs.mkdir(FILE_PATH) } - const arrayBuffer = await fileURLToPath.arrayBuffer() - const buffer = new Uint8Array(arrayBuffer) - - return fs.writeFile(`${IMAGE_FILE_PATH}/${file.fileName}`, buffer) + return fs.writeFile(`${FILE_PATH}/${fileName}.png`, file) } -export { convertDwgToPng, writeImageBase64, writeImageBuffer } +const readImage = async (fileName) => { + await fs + .readFile(`${FILE_PATH}/${fileName}.png`) + .then((res) => { + console.log('readImage-then', res) + }) + .catch((e) => { + console.log('readImage-catch', e) + }) +} + +const removeImage = async (fileName) => { + try { + await fs.rm(`${FILE_PATH}/${fileName}.png`) + } catch (e) { + console.log(e) + } +} + +export { convertDwgToPng, writeImageBase64, writeImage, readImage, removeImage } From d0eee3cb60db3cd9640b7cd152aed60c1e4eda24 Mon Sep 17 00:00:00 2001 From: minsik Date: Tue, 3 Dec 2024 13:08:46 +0900 Subject: [PATCH 3/9] =?UTF-8?q?-=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/modal/grid/GridCopy.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/floor-plan/modal/grid/GridCopy.jsx b/src/components/floor-plan/modal/grid/GridCopy.jsx index 86f79df7..2f768406 100644 --- a/src/components/floor-plan/modal/grid/GridCopy.jsx +++ b/src/components/floor-plan/modal/grid/GridCopy.jsx @@ -17,8 +17,7 @@ export default function GridCopy(props) { const currentObject = useRecoilValue(currentObjectState) const { copy } = useGrid() const handleApply = () => { - // copy(currentObject, ) - copy(currentObject, ['↑', '←'].includes(arrow) ? Number(length) * -1 : Number(length)) + copy(currentObject, ['↑', '←'].includes(arrow) ? +length * -1 : +length) } return ( From 58c2c3cfc9127598e07762680487d0b05d02ec9e Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 3 Dec 2024 13:18:43 +0900 Subject: [PATCH 4/9] =?UTF-8?q?=F0=9F=99=80fix:=20useEvent=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=ED=98=B8=EC=B6=9C=EB=90=98=EB=8D=98=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - initEvent() 함수 중복 호출로 이벤트 바인딩 중복 되던 문제 해결 - 초기화 함수 호출 최소화 - useEffect 호출 정리 --- src/app/floor-plan/layout.js | 13 +++++-------- .../floor-plan/modal/setting01/FirstOption.jsx | 7 +++++++ .../floor-plan/modal/setting01/GridOption.jsx | 8 ++++++++ .../floor-plan/modal/setting01/SecondOption.jsx | 8 ++++++++ src/hooks/useEvent.js | 14 ++++++++++---- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/app/floor-plan/layout.js b/src/app/floor-plan/layout.js index 532a83d6..2a6fb8fd 100644 --- a/src/app/floor-plan/layout.js +++ b/src/app/floor-plan/layout.js @@ -3,20 +3,17 @@ import FloorPlanProvider from './FloorPlanProvider' import FloorPlan from '@/components/floor-plan/FloorPlan' import CanvasLayout from '@/components/floor-plan/CanvasLayout' -import EventProvider from './EventProvider' export default function FloorPlanLayout({ children }) { console.log('🚀 ~ FloorPlanLayout ~ FloorPlanLayout:') return ( <> - - - - {children} - - - + + + {children} + + ) } diff --git a/src/components/floor-plan/modal/setting01/FirstOption.jsx b/src/components/floor-plan/modal/setting01/FirstOption.jsx index 1f70f21f..566e38b5 100644 --- a/src/components/floor-plan/modal/setting01/FirstOption.jsx +++ b/src/components/floor-plan/modal/setting01/FirstOption.jsx @@ -3,11 +3,13 @@ import { useCanvasSetting } from '@/hooks/option/useCanvasSetting' import { useMessage } from '@/hooks/useMessage' import { POLYGON_TYPE } from '@/common/common' import { setSurfaceShapePattern } from '@/util/canvas-util' +import { useEvent } from '@/hooks/useEvent' export default function FirstOption() { const { getMessage } = useMessage() const { canvas, settingModalFirstOptions, setSettingModalFirstOptions } = useCanvasSetting() const { option1, option2, dimensionDisplay } = settingModalFirstOptions + const { initEvent } = useEvent() // 데이터를 최초 한 번만 조회 useEffect(() => { @@ -42,6 +44,11 @@ export default function FirstOption() { setSettingModalFirstOptions({ ...settingModalFirstOptions, option1, option2, dimensionDisplay, fontFlag: true }) } + // useEffect(() => { + // console.log('🚀 ~ useEffect ~ initEvent:') + // initEvent() + // }, [onClickOption]) + return ( <>
diff --git a/src/components/floor-plan/modal/setting01/GridOption.jsx b/src/components/floor-plan/modal/setting01/GridOption.jsx index bb6adef7..8c66534a 100644 --- a/src/components/floor-plan/modal/setting01/GridOption.jsx +++ b/src/components/floor-plan/modal/setting01/GridOption.jsx @@ -9,6 +9,7 @@ import { usePopup } from '@/hooks/usePopup' import { v4 as uuidv4 } from 'uuid' import DotLineGrid from '@/components/floor-plan/modal/grid/DotLineGrid' import { useCanvasSetting } from '@/hooks/option/useCanvasSetting' +import { useEvent } from '@/hooks/useEvent' export default function GridOption() { const [gridOptions, setGridOptions] = useRecoilState(settingModalGridOptionsState) @@ -24,6 +25,8 @@ export default function GridOption() { const { gridColor, setGridColor, color } = useCanvasSetting() + const { initEvent } = useEvent() + useEffect(() => { console.log(gridColor, color) setGridColor(color.hex) @@ -91,6 +94,11 @@ export default function GridOption() { setGridOptions(newGridOptions) } + useEffect(() => { + console.log('🚀 ~ useEffect ~ initEvent:') + initEvent() + }, [gridOptions]) + const dotLineGridProps = { id: dotLineId, setIsShow: setShowDotLineGridModal, diff --git a/src/components/floor-plan/modal/setting01/SecondOption.jsx b/src/components/floor-plan/modal/setting01/SecondOption.jsx index b5e9d98d..0b350067 100644 --- a/src/components/floor-plan/modal/setting01/SecondOption.jsx +++ b/src/components/floor-plan/modal/setting01/SecondOption.jsx @@ -8,6 +8,7 @@ import PlanSizeSetting from '@/components/floor-plan/modal/setting01/planSize/Pl import { useCanvasSetting } from '@/hooks/option/useCanvasSetting' import { useRecoilState, useRecoilValue } from 'recoil' import { fontSelector, globalFontAtom } from '@/store/fontAtom' +import { useEvent } from '@/hooks/useEvent' export default function SecondOption() { const { getMessage } = useMessage() @@ -24,6 +25,8 @@ export default function SecondOption() { const [fontId, setFontId] = useState(uuidv4()) const [planSizeId, setPlanSizeId] = useState(uuidv4()) + const { initEvent } = useEvent() + const { fetchSettings, planSizeSettingMode, @@ -189,6 +192,11 @@ export default function SecondOption() { setAdsorptionRange(50) } + useEffect(() => { + console.log('🚀 ~ useEffect ~ initEvent:') + initEvent() + }, [adsorptionPointMode]) + return ( <>
diff --git a/src/hooks/useEvent.js b/src/hooks/useEvent.js index 16d0896d..55058cf4 100644 --- a/src/hooks/useEvent.js +++ b/src/hooks/useEvent.js @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef } from 'react' +import { useRef } from 'react' import { useRecoilValue, useSetRecoilState } from 'recoil' import { canvasState, canvasZoomState, currentMenuState, textModeState } from '@/store/canvasAtom' import { fabric } from 'fabric' @@ -20,9 +20,15 @@ export function useEvent() { const textMode = useRecoilValue(textModeState) - useEffect(() => { - initEvent() - }, [currentMenu, canvas, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, dotLineGridSetting, tempGridMode]) + // 이벤트 초기화 위치 수정 -> useCanvasSetting에서 세팅값 불러오고 나서 초기화 함수 호출 + // useEffect(() => { + // initEvent() + // }, [currentMenu, canvas, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, dotLineGridSetting]) + + // 임시 그리드 모드 변경 시 이벤트 초기화 호출 위치 수정 -> GridOption 컴포넌트에서 임시 그리드 모드 변경 시 이벤트 초기화 함수 호출 + // useEffect(() => { + // initEvent() + // }, [tempGridMode]) const initEvent = () => { if (!canvas) { From 228fe576fc7b40d31c2aca8e09ca211f6d0d3539 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 3 Dec 2024 14:27:20 +0900 Subject: [PATCH 5/9] =?UTF-8?q?=F0=9F=93=8Cchore:=20Remove=20unused=20file?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../option/useCanvasSettingController.js | 127 ------------------ 1 file changed, 127 deletions(-) delete mode 100644 src/hooks/option/useCanvasSettingController.js diff --git a/src/hooks/option/useCanvasSettingController.js b/src/hooks/option/useCanvasSettingController.js deleted file mode 100644 index 48db6c08..00000000 --- a/src/hooks/option/useCanvasSettingController.js +++ /dev/null @@ -1,127 +0,0 @@ -import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom' -import { useEffect, useState } from 'react' -import { useRecoilState } from 'recoil' - -export const useCanvasSettingController = () => { - const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) - const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState) - const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요 - const { get } = useAxios() - - useEffect(() => { - fetchSettings() - }, [objectNo]) - - useEffect(() => { - fetchSettings() - }, []) - - useEffect(() => { - onClickOnlyOne() - fetchSettings() - }, [settingModalFirstOptions, settingModalSecondOptions]) - - const fetchSettings = async () => { - try { - const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` }) - const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] })) - const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] })) - const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item })) - const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] })) - const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ - ...item, - })) - // 데이터 설정 - setSettingModalFirstOptions({ - option1: optionData1, - option2: optionData2, - dimensionDisplay: optionData5, - }) - setSettingModalSecondOptions({ - option3: optionData3, - option4: optionData4, - }) - } catch (error) { - console.error('Data fetching error:', error) - } - } - - // - const onClickOption = async (option) => { - option.selected = !option.selected - - setSettingModalFirstOptions({ option1, option2, dimensionDisplay }) - setSettingModalSecondOptions({ option3, option4 }) - - try { - // 서버에 전송할 데이터 - const dataToSend = { - firstOption1: option1.map((item) => ({ - column: item.column, - selected: item.selected, - })), - firstOption2: option2.map((item) => ({ - column: item.column, - selected: item.selected, - })), - firstOption3: dimensionDisplay.map((item) => ({ - column: item.column, - selected: item.selected, - })), - // secondOption1: secondOptions[0].option1.map((item) => ({ - // name: item.id, - // name: item.name, - // // 필요한 경우 데이터 항목 추가 - // })), - secondOption2: option4.map((item) => ({ - column: item.column, - selected: item.selected, - })), - } - - const patternData = { - objectNo, - //디스플레이 설정(다중) - allocDisplay: dataToSend.firstOption1[0].selected, - outlineDisplay: dataToSend.firstOption1[1].selected, - gridDisplay: dataToSend.firstOption1[2].selected, - lineDisplay: dataToSend.firstOption1[3].selected, - wordDisplay: dataToSend.firstOption1[4].selected, - circuitNumDisplay: dataToSend.firstOption1[5].selected, - flowDisplay: dataToSend.firstOption1[6].selected, - trestleDisplay: dataToSend.firstOption1[7].selected, - totalDisplay: dataToSend.firstOption1[8].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, - } - - // HTTP POST 요청 보내기 - await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => { - swalFire({ text: getMessage(res.returnMessage) }) - }) - } catch (error) { - swalFire({ text: getMessage(res.returnMessage), icon: 'error' }) - } - } - - return { - fetchSettings, - settingModalFirstOptions, - setSettingModalFirstOptions, - settingModalSecondOptions, - setSettingModalSecondOptions, - onClickOption, - ß, - } -} From 23264bd1e08992a413ac6f060ac1543f02182d54 Mon Sep 17 00:00:00 2001 From: minsik Date: Tue, 3 Dec 2024 14:36:20 +0900 Subject: [PATCH 6/9] =?UTF-8?q?=F0=9F=9A=A8chore:=20Sync=20Sass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/static/images/canvas/ico-flx05.svg | 5 +++ public/static/images/canvas/return-btn.svg | 3 ++ src/styles/_contents.scss | 52 ++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 public/static/images/canvas/ico-flx05.svg create mode 100644 public/static/images/canvas/return-btn.svg diff --git a/public/static/images/canvas/ico-flx05.svg b/public/static/images/canvas/ico-flx05.svg new file mode 100644 index 00000000..350aee07 --- /dev/null +++ b/public/static/images/canvas/ico-flx05.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/static/images/canvas/return-btn.svg b/public/static/images/canvas/return-btn.svg new file mode 100644 index 00000000..f33f417b --- /dev/null +++ b/public/static/images/canvas/return-btn.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/styles/_contents.scss b/src/styles/_contents.scss index e72637e4..8d3b1408 100644 --- a/src/styles/_contents.scss +++ b/src/styles/_contents.scss @@ -139,6 +139,7 @@ &.ico02{background-image: url(../../public/static/images/canvas/ico-flx02.svg);} &.ico03{background-image: url(../../public/static/images/canvas/ico-flx03.svg);} &.ico04{background-image: url(../../public/static/images/canvas/ico-flx04.svg);} + &.ico05{background-image: url(../../public/static/images/canvas/ico-flx05.svg);} } .name{ font-size: 12px; @@ -827,6 +828,47 @@ &:last-child{ margin-bottom: 0; } + .file-item-wrap{ + display: flex; + align-items: center; + gap: 30px; + .return-wrap{ + display: flex; + align-items: center; + } + .return{ + padding: 0; + font-size: 13px; + color: #B0BCCD; + text-decoration: line-through; + } + .return-btn{ + flex: none; + position: relative; + top: 0; + left: 0; + transform: none; + display: flex; + align-items: center; + height: 24px; + padding: 0 9px; + margin-left: 10px; + background: none; + border: 1px solid #B0BCCD; + border-radius: 2px; + font-size: 12px; + color: #B0BCCD; + font-weight: 500; + .return-ico{ + display: block; + width: 14px; + height: 14px; + background: url(../../public/static/images/canvas/return-btn.svg)no-repeat center; + background-size: contain; + margin-right: 5px; + } + } + } } } } @@ -877,6 +919,16 @@ &.act{ background-color: #F7F9FA; } + .special-note-check-box{ + display: flex; + align-items: center; + .check-name{ + font-size: 13px; + color: #45576F; + cursor: pointer; + line-height: 1.3; + } + } } } From 0dfc2c415e6d5e3e9eaf128d96a8119f6bba7fc4 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 3 Dec 2024 14:53:08 +0900 Subject: [PATCH 7/9] =?UTF-8?q?=F0=9F=9A=A8chore:=20Remove=20unused=20file?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prisma/schema.prisma | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 prisma/schema.prisma diff --git a/prisma/schema.prisma b/prisma/schema.prisma deleted file mode 100644 index 027c8859..00000000 --- a/prisma/schema.prisma +++ /dev/null @@ -1,28 +0,0 @@ -generator client { - provider = "prisma-client-js" -} - -datasource db { - provider = "sqlserver" - url = env("DATABASE_URL") -} - -model M_USER { - USER_ID String @id(map: "M_USER_pk") @db.VarChar(50) - SALE_STORE_ID String @db.VarChar(10) - PASSWORD String @db.VarChar(10) - CATEGORY String? @db.NVarChar(20) - NAME String @db.NVarChar(20) - NAME_KANA String @db.NVarChar(20) - TEL String? @db.VarChar(15) - FAX String? @db.VarChar(15) - MAIL String? @db.NVarChar(100) - GROUP_ID String @db.VarChar(5) - MODULE_SELECT_GROUP_ID String? @db.VarChar(5) - VERSION_MANAGEMENT_ID String? @db.VarChar(20) - DISP_COST_PRICE Boolean? - DISP_SELLING_PRICE Boolean? - REGIST_DATETIME DateTime? @db.DateTime - LAST_EDIT_DATETIME DateTime? @db.DateTime - LAST_EDIT_USER String? @db.VarChar(50) -} \ No newline at end of file From 24db76fa01680cff0e61b9198a263bc6b507a2cf Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 3 Dec 2024 14:54:26 +0900 Subject: [PATCH 8/9] =?UTF-8?q?=F0=9F=93=8Cfix:=20Optimize=20imports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Reformat code - Optimize imports - Rearrange code - isGlobalLoaing 구문 추가 -> StuffSubHeader.jsx --- src/app/management/stuff/page.jsx | 4 +- src/components/management/StuffSubHeader.jsx | 173 ++++++++++--------- 2 files changed, 94 insertions(+), 83 deletions(-) diff --git a/src/app/management/stuff/page.jsx b/src/app/management/stuff/page.jsx index 414f377b..c1a3729c 100644 --- a/src/app/management/stuff/page.jsx +++ b/src/app/management/stuff/page.jsx @@ -1,7 +1,9 @@ -import StuffSearchCondition from '@/components/management/StuffSearchCondition' import Stuff from '@/components/management/Stuff' +import StuffSearchCondition from '@/components/management/StuffSearchCondition' import StuffSubHeader from '@/components/management/StuffSubHeader' + import '@/styles/grid.scss' + export default async function ManagementStuffPage() { return ( <> diff --git a/src/components/management/StuffSubHeader.jsx b/src/components/management/StuffSubHeader.jsx index 1ea2a699..ab838335 100644 --- a/src/components/management/StuffSubHeader.jsx +++ b/src/components/management/StuffSubHeader.jsx @@ -1,19 +1,26 @@ 'use client' -import { useEffect } from 'react' +import { useContext, useEffect } from 'react' + import Link from 'next/link' import Image from 'next/image' -import { useMessage } from '@/hooks/useMessage' import { useRouter, useSearchParams } from 'next/navigation' -import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' + import { useSetRecoilState } from 'recoil' + +import { QcastContext } from '@/app/QcastProvider' +import { useMessage } from '@/hooks/useMessage' +import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { queryStringFormatter } from '@/util/common-utils' + export default function StuffSubHeader({ type }) { const { getMessage } = useMessage() const router = useRouter() const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) + const { isGlobalLoading } = useContext(QcastContext) + useEffect(() => { window.scrollTo(0, 0) }, []) @@ -35,85 +42,87 @@ export default function StuffSubHeader({ type }) { } return ( - <> -
-
- {type === 'list' && ( - <> - -

{getMessage('header.menus.management')}

- -
    -
  • - - react - -
  • -
  • - {getMessage('header.menus.management')} -
  • -
  • - {getMessage('header.menus.management.stuffList')} -
  • -
- - )} - {type === 'temp' && ( - <> -
    -
  • - - {getMessage('stuff.temp.subTitle')} - -
  • -
-
    -
  • - - react - -
  • -
  • - {getMessage('header.menus.management')} -
  • -
  • - {getMessage('header.menus.management.newStuff')} -
  • -
- - )} - {type === 'detail' && ( - <> - -
    -
  • - - react - -
  • -
  • - {getMessage('header.menus.management')} -
  • -
  • - {getMessage('header.menus.management.detail')} -
  • -
- - )} + !isGlobalLoading && ( + <> +
+
+ {type === 'list' && ( + <> + +

{getMessage('header.menus.management')}

+ +
    +
  • + + react + +
  • +
  • + {getMessage('header.menus.management')} +
  • +
  • + {getMessage('header.menus.management.stuffList')} +
  • +
+ + )} + {type === 'temp' && ( + <> +
    +
  • + + {getMessage('stuff.temp.subTitle')} + +
  • +
+
    +
  • + + react + +
  • +
  • + {getMessage('header.menus.management')} +
  • +
  • + {getMessage('header.menus.management.newStuff')} +
  • +
+ + )} + {type === 'detail' && ( + <> + +
    +
  • + + react + +
  • +
  • + {getMessage('header.menus.management')} +
  • +
  • + {getMessage('header.menus.management.detail')} +
  • +
+ + )} +
-
- + + ) ) } From 9dc0c392abc0ef629b655e7c924837fe6cf00bbd Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 3 Dec 2024 15:15:16 +0900 Subject: [PATCH 9/9] =?UTF-8?q?=F0=9F=9A=A8chore:=20Reformat=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/floor-plan/EventProvider.js | 34 ------------------- src/components/floor-plan/CanvasFrame.jsx | 1 - .../floor-plan/modal/object/SizeSetting.jsx | 4 +-- src/hooks/module/useModuleBasicSetting.js | 5 +-- src/hooks/roofcover/useOuterLineWall.js | 3 +- 5 files changed, 3 insertions(+), 44 deletions(-) delete mode 100644 src/app/floor-plan/EventProvider.js diff --git a/src/app/floor-plan/EventProvider.js b/src/app/floor-plan/EventProvider.js deleted file mode 100644 index 991b19bb..00000000 --- a/src/app/floor-plan/EventProvider.js +++ /dev/null @@ -1,34 +0,0 @@ -import { useEvent } from '@/hooks/useEvent' -import { createContext, useState } from 'react' - -export const EventContext = createContext({}) - -const EventProvider = ({ children }) => { - const { - addDocumentEventListener, - addCanvasMouseEventListener, - addTargetMouseEventListener, - removeAllMouseEventListeners, - removeAllDocumentEventListeners, - removeDocumentEvent, - removeMouseEvent, - removeMouseLine, - initEvent, - } = useEvent() - - const [value, setValue] = useState({ - addDocumentEventListener, - addCanvasMouseEventListener, - addTargetMouseEventListener, - removeAllMouseEventListeners, - removeAllDocumentEventListeners, - removeDocumentEvent, - removeMouseEvent, - removeMouseLine, - initEvent, - }) - - return {children} -} - -export default EventProvider diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx index d43afc59..cd39cda0 100644 --- a/src/components/floor-plan/CanvasFrame.jsx +++ b/src/components/floor-plan/CanvasFrame.jsx @@ -15,7 +15,6 @@ import { MENU } from '@/common/common' import PanelBatchStatistics from '@/components/floor-plan/modal/panelBatch/PanelBatchStatistics' import { totalDisplaySelector } from '@/store/settingAtom' import ImgLoad from '@/components/floor-plan/modal/ImgLoad' -import { EventContext } from '@/app/floor-plan/EventProvider' export default function CanvasFrame() { const canvasRef = useRef(null) diff --git a/src/components/floor-plan/modal/object/SizeSetting.jsx b/src/components/floor-plan/modal/object/SizeSetting.jsx index bddc9f07..3466e2ed 100644 --- a/src/components/floor-plan/modal/object/SizeSetting.jsx +++ b/src/components/floor-plan/modal/object/SizeSetting.jsx @@ -5,12 +5,10 @@ import { useMessage } from '@/hooks/useMessage' import WithDraggable from '@/components/common/draggable/WithDraggable' import { usePopup } from '@/hooks/usePopup' import { contextPopupPositionState } from '@/store/popupAtom' -import { useRef, useState, useEffect, useContext } from 'react' +import { useRef, useState } from 'react' import { useObjectBatch } from '@/hooks/object/useObjectBatch' -import { useEvent } from '@/hooks/useEvent' import { BATCH_TYPE, POLYGON_TYPE } from '@/common/common' import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch' -import { EventContext } from '@/app/floor-plan/EventProvider' export default function SizeSetting(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 361347f0..133e014f 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -1,5 +1,4 @@ -import { useContext, useEffect, useState } from 'react' -import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' +import { useRecoilState, useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' import { rectToPolygon, setSurfaceShapePattern } from '@/util/canvas-util' import { roofDisplaySelector } from '@/store/settingAtom' @@ -10,9 +9,7 @@ import { moduleSetupSurfaceState, moduleIsSetupState } from '@/store/canvasAtom' import { useEvent } from '@/hooks/useEvent' import { POLYGON_TYPE, BATCH_TYPE } from '@/common/common' import * as turf from '@turf/turf' -import { EventContext } from '@/app/floor-plan/EventProvider' import { v4 as uuidv4 } from 'uuid' -import { useMainContentsController } from '../main/useMainContentsController' export function useModuleBasicSetting() { const canvas = useRecoilValue(canvasState) diff --git a/src/hooks/roofcover/useOuterLineWall.js b/src/hooks/roofcover/useOuterLineWall.js index c668dd60..74bfcbcc 100644 --- a/src/hooks/roofcover/useOuterLineWall.js +++ b/src/hooks/roofcover/useOuterLineWall.js @@ -1,4 +1,4 @@ -import { useContext, useEffect, useRef } from 'react' +import { useEffect, useRef } from 'react' import { distanceBetweenPoints } from '@/util/canvas-util' import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil' import { @@ -31,7 +31,6 @@ import { fabric } from 'fabric' import { outlineDisplaySelector } from '@/store/settingAtom' import { usePopup } from '@/hooks/usePopup' import PropertiesSetting from '@/components/floor-plan/modal/outerlinesetting/PropertiesSetting' -import { EventContext } from '@/app/floor-plan/EventProvider' //외벽선 그리기 export function useOuterLineWall(id, propertiesId) {