From aee7d6aa1323de858842c0155c58a487ecdc062a Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 25 Nov 2024 17:00:08 +0900 Subject: [PATCH 01/10] =?UTF-8?q?'=EB=B0=A9=ED=96=A5=20=EC=84=A0=ED=83=9D'?= =?UTF-8?q?=20=EB=8B=A4=EA=B5=AD=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/components/floor-plan/modal/object/type/PentagonDormer.jsx | 2 +- src/components/floor-plan/modal/object/type/TriangleDormer.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/floor-plan/modal/object/type/PentagonDormer.jsx b/src/components/floor-plan/modal/object/type/PentagonDormer.jsx index c67a08fc..0bca7527 100644 --- a/src/components/floor-plan/modal/object/type/PentagonDormer.jsx +++ b/src/components/floor-plan/modal/object/type/PentagonDormer.jsx @@ -82,7 +82,7 @@ const PentagonDormer = forwardRef((props, refs) => {
-
方向の選択
+
{getMessage('modal.object.setting.direction.select')}
{getMessage('commons.north')} diff --git a/src/components/floor-plan/modal/object/type/TriangleDormer.jsx b/src/components/floor-plan/modal/object/type/TriangleDormer.jsx index 34a87e44..229043c8 100644 --- a/src/components/floor-plan/modal/object/type/TriangleDormer.jsx +++ b/src/components/floor-plan/modal/object/type/TriangleDormer.jsx @@ -60,7 +60,7 @@ const TriangleDormer = forwardRef((props, refs) => {
-
方向の選択
+
{getMessage('modal.object.setting.direction.select')}
{getMessage('commons.north')} From 09a709ff163e6a70a790ac249364de3d33f61440 Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 25 Nov 2024 17:02:17 +0900 Subject: [PATCH 02/10] =?UTF-8?q?=EB=B3=B4=EC=A1=B0=EC=84=A0=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modal/auxiliary/AuxiliaryDrawing.jsx | 4 ++ .../modal/auxiliary/AuxiliaryEdit.jsx | 8 ++- .../modal/auxiliary/AuxiliarySize.jsx | 8 ++- src/hooks/roofcover/useAuxiliaryDrawing.js | 65 ++++++++++--------- src/hooks/useContextMenu.js | 28 ++++++-- 5 files changed, 71 insertions(+), 42 deletions(-) diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx index 84e7ab91..609ff975 100644 --- a/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx +++ b/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx @@ -49,6 +49,7 @@ export default function AuxiliaryDrawing({ id, pos = { x: 50, y: 230 } }) { handleFix, buttonAct, setButtonAct, + cutAuxiliary, } = useAuxiliaryDrawing(id) const outerLineProps = { @@ -151,6 +152,9 @@ export default function AuxiliaryDrawing({ id, pos = { x: 50, y: 230 } }) { + diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx index da00ac06..07fc9e46 100644 --- a/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx +++ b/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx @@ -5,8 +5,8 @@ import { useRecoilValue } from 'recoil' import { contextPopupPositionState } from '@/store/popupAtom' import { useState } from 'react' import { currentObjectState } from '@/store/canvasAtom' -import { useLine } from '@/hooks/useLine' import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing' +import { useSwal } from '@/hooks/useSwal' export default function AuxiliaryEdit(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) @@ -18,9 +18,13 @@ export default function AuxiliaryEdit(props) { const [horizonSize, setHorizonSize] = useState('0') const [arrow1, setArrow1] = useState(null) const [arrow2, setArrow2] = useState(null) - const { addLine, removeLine } = useLine() const currentObject = useRecoilValue(currentObjectState) + const { swalFire } = useSwal() const handleSave = () => { + if (!horizonSize || !verticalSize || !arrow1 || !arrow2) { + swalFire({ title: '길이와 방향을 입력하세요.', type: 'alert' }) + return + } if (type === 'copy') { if (currentObject) { copy( diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx index 70245626..e984be57 100644 --- a/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx +++ b/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx @@ -3,12 +3,14 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' import { usePopup } from '@/hooks/usePopup' import { useRecoilValue } from 'recoil' import { contextPopupPositionState } from '@/store/popupAtom' +import { useCanvas } from '@/hooks/useCanvas' export default function AuxiliarySize(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) const { id, pos = contextPopupPosition } = props const { getMessage } = useMessage() const { closePopup } = usePopup() + const { currentObject } = useCanvas() return (
@@ -26,7 +28,7 @@ export default function AuxiliarySize(props) {
- +
mm
@@ -45,14 +47,14 @@ export default function AuxiliarySize(props) {
- +
mm
{getMessage('length')}
- +
mm
diff --git a/src/hooks/roofcover/useAuxiliaryDrawing.js b/src/hooks/roofcover/useAuxiliaryDrawing.js index 30e3982e..0d23fd44 100644 --- a/src/hooks/roofcover/useAuxiliaryDrawing.js +++ b/src/hooks/roofcover/useAuxiliaryDrawing.js @@ -92,7 +92,7 @@ export function useAuxiliaryDrawing(id) { addCanvasMouseEventListener('mouse:move', mouseMove) addCanvasMouseEventListener('mouse:down', mouseDown) - addDocumentEventListener('contextmenu', document, cutAuxiliary) + // addDocumentEventListener('contextmenu', document, cutAuxiliary) addDocumentEventListener('keydown', document, keydown[type]) return () => { @@ -135,23 +135,6 @@ export function useAuxiliaryDrawing(id) { }) } - const addBisectorLine = (target) => { - const slope = (target.y2 - target.y1) / (target.x2 - target.x1) - const bisectorSlope = -1 / slope - const length = target.length - const dx = length / Math.sqrt(1 + bisectorSlope * bisectorSlope) - const dy = bisectorSlope * dx - const endX = (target.x1 + target.x2) / 2 - const endY = (target.y1 + target.y2) / 2 - - addLine([dx, dy, endX, endY], { - stroke: 'red', - strokeWidth: 1, - selectable: true, - name: 'auxiliaryLine', - }) - } - const keydown = { outerLine: (e) => { if (mousePointerArr.current.length === 0) { @@ -565,8 +548,24 @@ export function useAuxiliaryDrawing(id) { otherAdsorptionPoints.push(intersectionPoint) }) }) + let innerLinePoints = [] + canvas + .getObjects() + .filter((obj) => obj.innerLines) + .forEach((polygon) => { + polygon.innerLines.forEach((line) => { + innerLinePoints.push({ x: line.x1, y: line.y1 }) + innerLinePoints.push({ x: line.x2, y: line.y2 }) + }) + }) - const adsorptionPoints = [...getAdsorptionPoints(), ...roofAdsorptionPoints.current, ...otherAdsorptionPoints, ...intersectionPoints.current] + const adsorptionPoints = [ + ...getAdsorptionPoints(), + ...roofAdsorptionPoints.current, + ...otherAdsorptionPoints, + ...intersectionPoints.current, + ...innerLinePoints, + ] let arrivalPoint = { x: pointer.x, y: pointer.y } @@ -825,7 +824,6 @@ export function useAuxiliaryDrawing(id) { //lineHistory.current에 있는 선들 중 startPoint와 endPoint가 겹치는 line은 제거 // 겹치는 선 하나는 canvas에서 제거한다. - const tempLines = [...lineHistory.current] lineHistory.current = [] tempLines.forEach((line) => { @@ -849,27 +847,30 @@ export function useAuxiliaryDrawing(id) { const tempPolygonPoints = [...roofBase.points].map((obj) => { return { x: Math.round(obj.x), y: Math.round(obj.y) } }) - const roofInnerLines = innerLines.filter((line) => { + const roofInnerLines = [...roofBase.innerLines, ...innerLines].filter((line) => { const inPolygon1 = - tempPolygonPoints.some((point) => point.x === line.x1 && point.y === line.y1) || - roofBase.inPolygon({ x: line.x1, y: line.y1 }) || - roofBase.lines.some((line) => isPointOnLine(line, { x: line.x1, y: line.y1 })) + tempPolygonPoints.some((point) => Math.round(point.x) === Math.round(line.x1) && Math.round(point.y) === Math.round(line.y1)) || + roofBase.inPolygon({ x: Math.round(line.x1), y: Math.round(line.y1) }) || + roofBase.lines.some((line) => isPointOnLine(line, { x: Math.round(line.x1), y: Math.round(line.y1) })) const inPolygon2 = - tempPolygonPoints.some((point) => point.x === line.x2 && point.y === line.y2) || - roofBase.inPolygon({ x: line.x2, y: line.y2 }) || - roofBase.lines.some((line) => isPointOnLine(line, { x: line.x2, y: line.y2 })) + tempPolygonPoints.some((point) => Math.round(point.x) === Math.round(line.x2) && Math.round(point.y) === Math.round(line.y2)) || + roofBase.inPolygon({ x: Math.round(line.x2), y: Math.round(line.y2) }) || + roofBase.lines.some((line) => isPointOnLine(line, { x: Math.round(line.x2), y: Math.round(line.y2) })) if (inPolygon1 && inPolygon2) { - line.attributes = { ...line.attributes, roofId: roofBase.id, actualSize: 0, planeSize: line.getLength() } + line.attributes = { + ...line.attributes, + roofId: roofBase.id, + actualSize: line.attributes?.actualSize ?? 0, + planeSize: line.getLength(), + } return true } }) - roofBase.innerLines = [...roofInnerLines] - + roofBase.innerLines = lineHistory.current.length !== 0 ? [...roofInnerLines] : roofBase.innerLines canvas.renderAll() }) - closePopup(id) } @@ -903,6 +904,6 @@ export function useAuxiliaryDrawing(id) { setButtonAct, move, copy, - addBisectorLine, + cutAuxiliary, } } diff --git a/src/hooks/useContextMenu.js b/src/hooks/useContextMenu.js index 1f5f59cb..331259e3 100644 --- a/src/hooks/useContextMenu.js +++ b/src/hooks/useContextMenu.js @@ -34,6 +34,7 @@ import { useObjectBatch } from '@/hooks/object/useObjectBatch' import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch' import { fontSelector, globalFontAtom } from '@/store/fontAtom' import { useLine } from '@/hooks/useLine' +import { useSwal } from '@/hooks/useSwal' export function useContextMenu() { const canvas = useRecoilValue(canvasState) @@ -56,6 +57,7 @@ export function useContextMenu() { const [globalFont, setGlobalFont] = useRecoilState(globalFontAtom) const { addLine, removeLine } = useLine() const commonTextFont = useRecoilValue(fontSelector('commonText')) + const { swalFire } = useSwal() const currentMenuSetting = () => { switch (currentMenu) { @@ -145,6 +147,9 @@ export function useContextMenu() { shortcut: ['d', 'D'], name: `${getMessage('contextmenu.auxiliary.remove')}(D)`, fn: () => { + const roof = canvas.getObjects().filter((obj) => obj.id === currentObject.attributes.roofId)[0] + const innerLines = roof.innerLines?.filter((line) => currentObject.id !== line.id) + roof.innerLines = [...innerLines] canvas.remove(currentObject) canvas.discardActiveObject() }, @@ -176,21 +181,34 @@ export function useContextMenu() { endY = (currentObject.y1 + currentObject.y2) / 2 - dy } - addLine([startX, startY, endX, endY], { + const line = addLine([startX, startY, endX, endY], { stroke: 'red', strokeWidth: 1, selectable: true, name: 'auxiliaryLine', + attributes: { ...currentObject.attributes }, }) + canvas + .getObjects() + .filter((obj) => obj.id === currentObject.attributes.roofId)[0] + .innerLines.push(line) }, }, - { - id: 'auxiliaryCut', - name: getMessage('contextmenu.auxiliary.cut'), - }, { id: 'auxiliaryRemoveAll', name: getMessage('contextmenu.auxiliary.remove.all'), + fn: () => { + if (!currentObject) { + swalFire({ text: '지붕을 선택해주세요.' }) + return + } + const innerLines = canvas.getObjects().filter((obj) => obj.id === currentObject.attributes.roofId)[0].innerLines + innerLines.forEach((line) => { + canvas.remove(line) + }) + innerLines.length = 0 + canvas.renderAll() + }, }, ], ]) From 0aaa54de733b0622592f5f66294841da53af0aaf Mon Sep 17 00:00:00 2001 From: basssy Date: Mon, 25 Nov 2024 17:10:57 +0900 Subject: [PATCH 03/10] =?UTF-8?q?=EA=B2=AC=EC=A0=81=EC=84=9C=20=EC=83=81?= =?UTF-8?q?=EC=84=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/estimate/Estimate.jsx | 172 +++++++++++++++++++-------- src/util/common-utils.js | 7 ++ 2 files changed, 128 insertions(+), 51 deletions(-) diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index 4f578b5e..c165c55e 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -15,7 +15,7 @@ import { useCommonCode } from '@/hooks/common/useCommonCode' import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController' import { SessionContext } from '@/app/SessionProvider' import Select, { components } from 'react-select' -import { convertNumberToPriceDecimal } from '@/util/common-utils' +import { convertNumberToPriceDecimal, convertNumberToPriceDecimalToFixed } from '@/util/common-utils' import ProductFeaturesPop from './popup/ProductFeaturesPop' import { v4 as uuidv4 } from 'uuid' @@ -129,17 +129,21 @@ export default function Estimate({ params }) { }) }, [estimateContextState?.estimateOption]) + //API데이터로 견적일 셋팅 + let begin = 1 + useEffect(() => { + if (begin === 1) { + setStartDate(estimateContextState?.estimateDate) + begin++ + } + }, [estimateContextState?.estimateDate]) + //견적일 set useEffect(() => { let estimateDate = dayjs(startDate).format('YYYY-MM-DD') setEstimateContextState({ estimateDate: estimateDate }) }, [startDate]) - //API데이터로 견적일 셋팅 - useEffect(() => { - setStartDate(estimateContextState?.estimateDate) - }, [estimateContextState?.estimateDate]) - useEffect(() => { //선택된 견적특이사항 setEstimateContextState if (isNotEmptyArray(specialNoteList)) { @@ -296,9 +300,8 @@ export default function Estimate({ params }) { //기존itemList랑 프라이싱결과랑 비교해서 단가만 업뎃 서로 갯수가 안맞을 수 있음 없는 itemId면 unitPrice 0으로 //itemId로 비교해서 salePrice만 업데이트 if (data.result.code === 200) { - console.log('data::확인해서 넣기:::::::::', data.data.pkgUnitPrice) setEstimateContextState({ - pkgAsp: data.data.pkgUnitPrice, + pkgAsp: data?.data?.pkgUnitPrice, }) //주택PKG단가 체인지 이벤트 발생시키기 onChangePkgAsp(data.data.pkgUnitPrice) @@ -333,6 +336,24 @@ export default function Estimate({ params }) { }) } + const getAbledItems = (items) => { + return items.filter((items) => items.paDispOrder === null) + } + + const onChangeSelectAll = (e) => { + if (e.target.checked) { + const allCheckedSelection = new Set(getAbledItems(estimateContextState.itemList).map((item) => item.dispOrder)) + + setSelection(allCheckedSelection) + } else { + setSelection(new Set()) + } + } + + const isSelectedAll = () => { + return selection.size === getAbledItems(estimateContextState.itemList).length + } + //row 체크박스 컨트롤 const onChangeSelect = (dispOrder) => { const newSelection = new Set(selection) @@ -358,13 +379,12 @@ export default function Estimate({ params }) { let totVolKw = estimateContextState.totVolKw * 1000 let pkgTotPrice = pkgAsp.replaceAll(',', '') * totVolKw - setEstimateContextState({ pkgAsp: pkgAsp, pkgTotPrice: pkgTotPrice.toFixed(3), }) //아이템들 중 조건에 맞는애들 뽑아서 상단 공급가액 부가세 총액 수정 - // setItemChangeYn(true) + setItemChangeYn(true) } } @@ -392,7 +412,6 @@ export default function Estimate({ params }) { return item } }) - setEstimateContextState({ itemList: updateList, }) @@ -429,7 +448,7 @@ export default function Estimate({ params }) { setItemChangeYn(true) } - // 아이템 자동완성 검색시 아이템 변경 + // 아이템 자동완성 검색시 아이템 추가/변경시 const onChangeDisplayItem = (itemId, dispOrder, index) => { const param = { itemId: itemId, @@ -438,7 +457,7 @@ export default function Estimate({ params }) { let updateList = [] let updates = {} get({ url: apiUrl }).then((res) => { - // console.log('아이템상세정보:::::::', res) + console.log('아이템디테일::::::::', res) updates.objectNo = objectNo updates.planNo = planNo updates.itemId = res.itemId @@ -460,6 +479,12 @@ export default function Estimate({ params }) { updates.delFlg = '0' // 삭제플래그 0 updates.saleTotPrice = (res.salePrice * estimateContextState.itemList[index].amount).toString() + if (estimateContextState.estimateType === 'YJSS') { + if (res.pkgMaterialFlg === '0') { + updates.showSalePrice = '0' + updates.showSaleTotPrice = '0' + } + } //104671 let bomList = res.itemBomList @@ -467,7 +492,8 @@ export default function Estimate({ params }) { if (item.dispOrder === dispOrder) { return { ...item, ...updates } } else if (item.paDispOrder === dispOrder) { - return { ...item, delFlg: '1' } + return { ...item, delFlg: '0' } + // return { ...item, delFlg: '1' } } else { return item } @@ -476,7 +502,14 @@ export default function Estimate({ params }) { if (bomList) { bomList.map((bomItem, index) => { let newItemDispOrder = Math.max(...estimateContextState.itemList.map((item) => item.dispOrder)) - bomItem.dispOrder = index + 1 + newItemDispOrder + if (newItemDispOrder == dispOrder) { + bomItem.dispOrder = (index + 1 + newItemDispOrder).toString() + bomItem.paDispOrder = dispOrder + } else { + bomItem.dispOrder = (index + 1 + Number(dispOrder)).toString() + bomItem.paDispOrder = dispOrder + } + bomItem.delFlg = '0' bomItem.objectNo = objectNo bomItem.planNo = planNo @@ -539,20 +572,26 @@ export default function Estimate({ params }) { useEffect(() => { if (itemChangeYn) { - console.log(' 토탈만들어주기::::::::::', estimateContextState.itemList) - let totAmount = 0 let totVolKw = 0 let supplyPrice = 0 let vatPrice = 0 let totPrice = 0 - let addPkgPrice = 0 + let addSupplyPrice = 0 if (estimateContextState.estimateType === 'YJOD') { - estimateContextState.itemList.map((item) => { - if (item.delFlg === '0') { - const amount = Number(item.amount.replace(/[^0-9]/g, '').replaceAll(',', '')) + console.log('YJOD 토탈만들어주기::::::::::', estimateContextState.itemList) - const price = Number(item.saleTotPrice.replaceAll(',', '')) + estimateContextState.itemList.sort((a, b) => { + return a.dispOrder - b.dispOrder + }) + + estimateContextState.itemList.map((item) => { + delete item.showSalePrice + delete item.showSaleTotPrice + if (item.delFlg === '0') { + const amount = Number(item?.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) + + const price = Number(item?.saleTotPrice?.replaceAll(',', '')) if (item.moduleFlg === '1') { //용량(Kw)은 모듈플래그 1만 합산 @@ -567,7 +606,6 @@ export default function Estimate({ params }) { vatPrice = supplyPrice * 0.1 totPrice = supplyPrice + vatPrice - setEstimateContextState({ totAmount: totAmount, totVolKw: totVolKw.toFixed(3), @@ -577,11 +615,15 @@ export default function Estimate({ params }) { }) } else { //YJSS + console.log('YJSS 토탈만들어주기::::::::::', estimateContextState.itemList) + estimateContextState.itemList.sort((a, b) => { + return a.dispOrder - b.dispOrder + }) estimateContextState.itemList.map((item) => { if (item.delFlg === '0') { - const amount = Number(item.amount.replace(/[^0-9]/g, '').replaceAll(',', '')) - const price = Number(item.saleTotPrice.replaceAll(',', '')) - const salePrice = Number(item.salePrice.replaceAll(',', '')) + const amount = Number(item.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) + const price = Number(item.saleTotPrice?.replaceAll(',', '')) + const salePrice = Number(item.salePrice?.replaceAll(',', '')) if (item.moduleFlg === '1') { //용량(Kw)은 모듈플래그 1만 합산 @@ -590,19 +632,27 @@ export default function Estimate({ params }) { } if (item.pkgMaterialFlg === '1') { const pkgPrice = amount * salePrice - //YJSS는 PKG제외상품들만 모아서 수량 * 단가를 공급가액에 추가로 더해줌 - addPkgPrice += pkgPrice + //YJSS는 PKG제외상품들만(1) 모아서 수량 * 단가를 공급가액(supplyPrice)에 추가로 더해줌 + addSupplyPrice += pkgPrice + supplyPrice += price } // const price totAmount += amount - supplyPrice += price + + if (!item.paDispOrder) { + //paDispOrder + if (item.pkgMaterialFlg === '0') { + item.showSalePrice = '0' + item.showSaleTotPrice = '0' + } + } } }) + supplyPrice += addSupplyPrice vatPrice = supplyPrice * 0.1 totPrice = supplyPrice + vatPrice - setEstimateContextState({ totAmount: totAmount, totVolKw: totVolKw.toFixed(3), @@ -845,6 +895,23 @@ export default function Estimate({ params }) { setEstimateContextState({ fileFlg: e.target.checked ? '1' : '0', }) + if (e.target.checked) { + if (specialNoteList.length > 0) { + specialNoteList.map((item) => { + if (item.code === 'ATTR019') { + item.check = true + } + }) + } + } else { + if (specialNoteList.length > 0) { + specialNoteList.map((item) => { + if (item.code === 'ATTR019') { + item.check = false + } + }) + } + } }} />
@@ -1036,9 +1102,9 @@ export default function Estimate({ params }) {
{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgWeight')} - {convertNumberToPriceDecimal(estimateContextState?.totVolKw)} + {convertNumberToPriceDecimalToFixed(estimateContextState?.totVolKw, 2)} {getMessage('estimate.detail.sepcialEstimateProductInfo.pkgPrice')} - {convertNumberToPriceDecimal(estimateContextState?.pkgTotPrice)} + {convertNumberToPriceDecimalToFixed(estimateContextState?.pkgTotPrice, 2)} @@ -1096,13 +1162,11 @@ export default function Estimate({ params }) {
- {/*