From f185912c293661a0838d12f39f71d024809f3adb Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Fri, 13 Sep 2024 14:15:44 +0900 Subject: [PATCH 001/152] =?UTF-8?q?=EC=A7=80=EB=B6=95=20=EA=B7=B8=EB=A6=AC?= =?UTF-8?q?=EA=B8=B0=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 11 +- src/hooks/useMode.js | 466 ++++++++++++++++----------------------- 2 files changed, 206 insertions(+), 271 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index d8b4c25e..e9da0e7a 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -405,6 +405,15 @@ export default function Roof2(props) { { x: 600, y: 100 }, ] + const type1C = [ + { x: 100, y: 100 }, + { x: 850, y: 100 }, + { x: 850, y: 800 }, + { x: 550, y: 800 }, + { x: 500, y: 400 }, + { x: 100, y: 400 }, + ] + const types = [type1, type2, type3, type4, type1A, type1B, eightPoint, eightPoint2, eightPoint3, eightPoint4, twelvePoint] const newP = [ { x: 450, y: 450 }, @@ -413,7 +422,7 @@ export default function Roof2(props) { { x: 450, y: 850 }, ] - const polygon = new QPolygon(twelvePoint, { + const polygon = new QPolygon(type1C, { fill: 'transparent', stroke: 'green', strokeWidth: 1, diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index d427b548..bc650216 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -1263,7 +1263,8 @@ export function useMode() { historyPoints.current = [] const wall = makePolygon(null, sort) - wall.set({ name: 'wall' }) + wall.name = 'wall' + // wall.set({ name: 'wall' }) return wall } @@ -1471,7 +1472,8 @@ export function useMode() { *벽 지붕 외곽선 생성 polygon을 입력받아 만들기 */ const handleOuterlinesTest2 = (polygon, offset = 50) => { - const offsetPoints = offsetPolygon(polygon.points, offset) + drawRoofPolygon(polygon, offset) + /*const offsetPoints = offsetPolygon(polygon.points, offset) const roof = makePolygon( offsetPoints.map((point) => { @@ -1484,287 +1486,211 @@ export function useMode() { setWall(polygon) roof.drawHelpLine() - roof.divideLine() + roof.divideLine()*/ } const drawRoofPolygon = (wall, offset = 50) => { - console.log(wall) - let points = wall.points, - expandedPoints = [] - - let minX = points[0].x, - minY = points[0].y, - maxX = points[0].x, - maxY = points[0].y - - points.forEach((point) => { - if (point.x < minX) minX = point.x - if (point.y < minY) minY = point.y - if (point.x > maxX) maxX = point.x - if (point.y > maxY) maxY = point.y - }) - - console.log(points) - points.forEach((point, index) => { - const prevIndex = index === 0 ? points.length - 1 : index - 1 - const nextIndex = index === points.length - 1 ? 0 : index + 1 - point.direction = getDirectionByPoint(point, points[nextIndex]) - point.length = Math.abs(point.x - points[nextIndex].x) === 0 ? Math.abs(point.y - points[nextIndex].y) : Math.abs(point.x - points[nextIndex].x) - // point.degree = Math.round(getDegreeBetweenTwoLines(points[prevIndex], point, points[nextIndex])) - }) - console.log('points : ', points) - - points.forEach((currentWall, index) => { - let prevWall = points[index === 0 ? points.length - 1 : index - 1] - let nextWall = points[index === points.length - 1 ? 0 : index + 1] - let isStartPointIn = minX < currentWall.x && currentWall.x < maxX && minY < currentWall.y && currentWall.y < maxY - // let isEndPointIn = minX < currentWall.x2 && currentWall.x2 < maxX && minY < currentWall.y2 && currentWall.y2 < maxY - - if (prevWall.direction !== nextWall.direction) { - if (currentWall.direction === 'top') { - console.log('prevWall degree : ', 45) - if (prevWall.direction === 'right') { - let addLength = getLineOffsetPoint(prevWall, currentWall, nextWall, offset) - expandedPoints.push({ - x: currentWall.x + addLength, - y: currentWall.y + addLength, - }) - } - if (prevWall.direction === 'left') { - console.log('prevWall degree : ', 225) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y + offset, - }) - } - } - if (currentWall.direction === 'bottom') { - if (prevWall.direction === 'right') { - console.log('prevWall degree : ', 45) - let addLength = getLineOffsetPoint(prevWall, currentWall, nextWall, offset) - console.log(currentWall.x, '-', offset, '+', addLength) - console.log('addLength : ', addLength) - expandedPoints.push({ - x: currentWall.x + addLength, - y: currentWall.y - addLength, - }) - } - if (prevWall.direction === 'left') { - console.log('prevWall degree : ', 315) - let addLength = getLineOffsetPoint(prevWall, currentWall, nextWall, offset) - console.log(currentWall.x, '-', offset, '+', addLength) - console.log('addLength : ', addLength) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y - offset, - }) - } - } - if (currentWall.direction === 'right') { - if (prevWall.direction === 'top') { - if (isStartPointIn) { - console.log('prevWall degree : ', 135) - expandedPoints.push({ - x: currentWall.x + offset, - y: currentWall.y + offset, - }) - } else { - console.log('prevWall degree : ', 315) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y - offset, - }) - } - } - if (prevWall.direction === 'bottom') { - if (isStartPointIn) { - console.log('prevWall degree : ', 45) - - expandedPoints.push({ - x: currentWall.x + offset, - y: currentWall.y - offset, - }) - } else { - console.log('prevWall degree : ', 225) - let addLength = getLineOffsetPoint(prevWall, currentWall, nextWall, offset) - console.log('addLength : ', addLength) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y + offset, - }) - } - } - } - if (currentWall.direction === 'left') { - if (prevWall.direction === 'top') { - if (isStartPointIn) { - console.log('prevWall degree : ', 225) - let addLength = getLineOffsetPoint(prevWall, currentWall, nextWall, offset) - console.log('addLength : ', addLength) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y + offset, - }) - } else { - console.log('prevWall degree : ', 45) - - let addLength = getLineOffsetPoint(prevWall, currentWall, nextWall, offset) - - expandedPoints.push({ - x: currentWall.x + offset, - y: currentWall.y - offset, - }) - } - } - if (prevWall.direction === 'bottom') { - if (isStartPointIn) { - console.log('prevWall degree : ', 315) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y - offset, - }) - } else { - console.log('prevWall degree : ', 135) - expandedPoints.push({ - x: currentWall.x + offset, - y: currentWall.y + offset, - }) - } - } + let walls = wall.lines + walls.forEach((wall, index) => { + if (index === 0) { + wall.attributes = { + type: 'gable', + width: 30, } } else { - console.log('else :::: ') - if (currentWall.direction === 'top') { - if (prevWall.direction === 'right') { - if (isStartPointIn) { - console.log('prevWall degree : ', 315) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y - offset, - }) - } else { - console.log('prevWall degree : ', 135) - expandedPoints.push({ - x: currentWall.x + offset, - y: currentWall.y + offset, - }) - } - } - if (prevWall.direction === 'left') { - if (isStartPointIn) { - console.log('prevWall degree : ', 45) - expandedPoints.push({ - x: currentWall.x + offset, - y: currentWall.y - offset, - }) - } else { - console.log('prevWall degree : ', 225) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y + offset, - }) - } - } - } - if (currentWall.direction === 'bottom') { - if (prevWall.direction === 'right') { - if (isStartPointIn) { - console.log('prevWall degree : ', 225) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y + offset, - }) - } else { - console.log('prevWall degree : ', 45) - expandedPoints.push({ - x: currentWall.x + offset, - y: currentWall.y - offset, - }) - } - } - } - if (currentWall.direction === 'right') { - if (prevWall.direction === 'top') { - if (isStartPointIn) { - console.log('prevWall degree : ', 135) - expandedPoints.push({ - x: currentWall.x + offset, - y: currentWall.y + offset, - }) - } else { - console.log('prevWall degree : ', 315) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y - offset, - }) - } - } - if (prevWall.direction === 'bottom') { - if (isStartPointIn) { - console.log('prevWall degree : ', 225) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y + offset, - }) - } else { - console.log('prevWall degree : ', 45) - expandedPoints.push({ - x: currentWall.x + offset, - y: currentWall.y - offset, - }) - } - } - } - if (currentWall.direction === 'left') { - if (prevWall.direction === 'top') { - if (isStartPointIn) { - console.log('prevWall degree : ', 225) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y + offset, - }) - } else { - console.log('prevWall degree : ', 45) - expandedPoints.push({ - x: currentWall.x + offset, - y: currentWall.y - offset, - }) - } - } - if (prevWall.direction === 'bottom') { - if (isStartPointIn) { - console.log('prevWall degree : ', 135) - expandedPoints.push({ - x: currentWall.x + offset, - y: currentWall.y + offset, - }) - } else { - console.log('prevWall degree : ', 315) - expandedPoints.push({ - x: currentWall.x - offset, - y: currentWall.y - offset, - }) - } - } + wall.attributes = { + type: 'hip', + width: 50, } } }) - console.log('expandedPoints : ', expandedPoints) + console.log('walls', walls) - /*const roof = new fabric.Polygon(expandedPoints, { - fill: 'transparent', - stroke: 'red', - strokeWidth: 1, - selectable: true, - fontSize: fontSize, - name: 'QPolygon1', + walls.forEach((currentWall, index) => { + let prevWall, nextWall + if (index === 0) { + prevWall = walls[walls.length - 1] + nextWall = walls[index + 1] + } else if (index === walls.length - 1) { + prevWall = walls[index - 1] + nextWall = walls[0] + } else { + prevWall = walls[index - 1] + nextWall = walls[index + 1] + } + + let p1 = [ + { x: currentWall.x1, y: currentWall.y1 }, + { x: currentWall.x2, y: currentWall.y2 }, + { x: prevWall.x1, y: prevWall.y1 }, + { x: prevWall.x2, y: prevWall.y2 }, + ], + p2 = [ + { x: currentWall.x1, y: currentWall.y1 }, + { x: currentWall.x2, y: currentWall.y2 }, + { x: nextWall.x1, y: nextWall.y1 }, + { x: nextWall.x2, y: nextWall.y2 }, + ] + + p1 = Array.from(new Set(p1.map((point) => JSON.stringify(point)))).map((point) => JSON.parse(point)) + p2 = Array.from(new Set(p2.map((point) => JSON.stringify(point)))).map((point) => JSON.parse(point)) + + let p1Lengths = [] + p1.forEach((point1, index) => { + let point2 + if (p1.length - 1 === index) { + point2 = p1[0] + } else { + point2 = p1[index + 1] + } + const dx = Math.abs(point2.x - point1.x) + const dy = Math.abs(point2.y - point1.y) + p1Lengths.push({ + length: Math.round(Math.sqrt(dx ** 2 + dy ** 2)), + coords: [ + { x: point1.x, y: point1.y }, + { x: point2.x, y: point2.y }, + ], + }) + }) + + let p2Lengths = [] + p2.forEach((point1, index) => { + let point2 + if (p2.length - 1 === index) { + point2 = p2[0] + } else { + point2 = p2[index + 1] + } + const dx = Math.abs(point2.x - point1.x) + const dy = Math.abs(point2.y - point1.y) + p2Lengths.push({ + length: Math.round(Math.sqrt(dx ** 2 + dy ** 2)), + coords: [ + { x: point1.x, y: point1.y }, + { x: point2.x, y: point2.y }, + ], + }) + }) + + let x1 = 0, + y1 = 0, + x2 = 0, + y2 = 0, + offsetX1 = 0, + offsetY1 = 0, + offsetX2 = 0, + offsetY2 = 0 + + let alfa = Math.round(Math.sqrt(Math.abs(currentWall.x1 - currentWall.x2) ** 2 + Math.abs(currentWall.y1 - currentWall.y2) ** 2)), + bravo = Math.round(Math.sqrt(Math.abs(prevWall.x1 - prevWall.x2) ** 2 + Math.abs(prevWall.y1 - prevWall.y2) ** 2)), + charlie = p1Lengths.filter((length) => length.length !== alfa && length.length !== bravo)[0], + alpha = Math.round(Math.acos((alfa ** 2 + charlie.length ** 2 - bravo ** 2) / (2 * alfa * charlie.length)) * (180 / Math.PI) * 100) / 100, + beta = Math.round(Math.acos((bravo ** 2 + charlie.length ** 2 - alfa ** 2) / (2 * bravo * charlie.length)) * (180 / Math.PI) * 100) / 100, + gamma = Math.round(Math.acos((alfa ** 2 + bravo ** 2 - charlie.length ** 2) / (2 * alfa * bravo)) * (180 / Math.PI) * 100) / 100, + isValley = checkValley(wall, currentWall, prevWall) + console.log('현재 라인 : ', alfa) + gamma = isValley ? Math.round(((360 - gamma) / 2) * 100) / 100 : Math.round((gamma / 2) * 100) / 100 + + console.log('이전 라인과의 각도', gamma) + + if (currentWall.x1 === currentWall.x2) { + offsetY1 = currentWall.attributes.width + offsetX1 = prevWall.attributes.width + x1 = Math.min(currentWall.x1, currentWall.x2) + offsetX1 + y1 = currentWall.y1 + offsetY1 + } else if (currentWall.y1 === currentWall.y2) { + offsetX1 = currentWall.attributes.width + offsetY1 = prevWall.attributes.width + x1 = currentWall.x1 + offsetX1 + y1 = Math.min(currentWall.y1, currentWall.y2) + offsetY1 + } else { + } + + bravo = Math.round(Math.sqrt(Math.abs(nextWall.x1 - nextWall.x2) ** 2 + Math.abs(nextWall.y1 - nextWall.y2) ** 2)) + charlie = p2Lengths.filter((length) => length.length !== alfa && length.length !== bravo)[0] + + // alpha = Math.round(Math.acos((alfa ** 2 + charlie ** 2 - bravo ** 2) / (2 * alfa * charlie)) * (180 / Math.PI)) + // betta = Math.round(Math.acos((bravo ** 2 + charlie ** 2 - alfa ** 2) / (2 * bravo * charlie)) * (180 / Math.PI)) + gamma = Math.round(Math.acos((alfa ** 2 + bravo ** 2 - charlie.length ** 2) / (2 * alfa * bravo)) * (180 / Math.PI) * 100) / 100 + isValley = checkValley(wall, currentWall, nextWall) + gamma = isValley ? Math.round(((360 - gamma) / 2) * 100) / 100 : Math.round((gamma / 2) * 100) / 100 + + console.log('다음 라인과의 각도', gamma) + + /*let offsetX = 0, + offsetY = 0 + let x1 = 0, + y1 = 0, + x2 = 0, + y2 = 0 + if (prevWall.direction !== nextWall.direction) { + if (currentWall.x1 === currentWall.x2) { + offsetX = prevWall.x1 < currentWall.x1 ? currentWall.attributes.width : -currentWall.attributes.width + x1 = currentWall.x1 + x2 = currentWall.x2 + y1 = Math.min(currentWall.y1, currentWall.y2) - Math.min(prevWall.attributes.width, nextWall.attributes.width) + y2 = Math.max(currentWall.y1, currentWall.y2) + Math.max(prevWall.attributes.width, nextWall.attributes.width) + } else { + offsetY = prevWall.y1 < currentWall.y1 ? currentWall.attributes.width : -currentWall.attributes.width + x1 = Math.min(currentWall.x1, currentWall.x2) - Math.min(prevWall.attributes.width, nextWall.attributes.width) + x2 = Math.max(currentWall.x1, currentWall.x2) + Math.max(prevWall.attributes.width, nextWall.attributes.width) + y1 = currentWall.y1 + y2 = currentWall.y2 + } + } else { + } + + x1 = x1 + offsetX + x2 = x2 + offsetX + y1 = y1 + offsetY + y2 = y2 + offsetY + + const roof = new QLine([x1, y1, x2, y2], { + fontSize: fontSize, + stroke: 'black', + strokeWidth: 1, + name: 'roofLine', + }) + canvas?.add(roof) + canvas?.renderAll()*/ }) + } - roof.wall = wall - canvas?.add(roof)*/ + /** + * 라인 사이가 지붕골 인지 확인. + * @param polygon + * @param line1 + * @param line2 + * @returns {boolean} + */ + const checkValley = (polygon, line1, line2) => { + let points = [ + { x: line1.x1, y: line1.y1 }, + { x: line1.x2, y: line1.y2 }, + { x: line2.x1, y: line2.y1 }, + { x: line2.x2, y: line2.y2 }, + ] + points = Array.from(new Set(points.map((point) => JSON.stringify(point)))).map((point) => JSON.parse(point)) + const centroidX = points.reduce((acc, point) => acc + point.x, 0) / points.length + const centroidY = points.reduce((acc, point) => acc + point.y, 0) / points.length - // roof.drawHelpLine() + let isValley = true + const pPoints = polygon.points + pPoints.forEach((point, index) => { + if (index < pPoints.length - 1) { + let j = index + 1 + let xi = pPoints[index].x + polygon.left, + yi = pPoints[index].y + polygon.top + let xj = pPoints[j].x + polygon.left, + yj = pPoints[j].y + polygon.top + + let intersect = yi > centroidY !== yj > centroidY && centroidX < ((xj - xi) * (centroidY - yi)) / (yj - yi) + xi + if (intersect) isValley = !isValley + } + }) + return isValley } /** From d6d295867efee445c653048e6a9d9f4a2ba80b16 Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Fri, 20 Sep 2024 09:44:36 +0900 Subject: [PATCH 002/152] =?UTF-8?q?=EC=A7=80=EB=B6=95=20=EB=9D=BC=EC=9D=B8?= =?UTF-8?q?=EB=B3=84=20offset=20=EC=A0=81=EC=9A=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 4 +- src/hooks/useMode.js | 414 ++++++++++++++++++------------------- src/util/qpolygon-utils.js | 4 - 3 files changed, 198 insertions(+), 224 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index e9da0e7a..f57f62ae 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -140,10 +140,10 @@ export default function Roof2(props) { useEffect(() => { get({ url: `/api/canvas-management/canvas-statuses/by-object/test123240822001` }).then((res) => { - console.log(res) + // console.log(res) const arrangeData = res.map((item) => { - console.log(item.canvasStatus.replace(/##/g, '"').replace(/\\/g, '')) + // console.log(item.canvasStatus.replace(/##/g, '"').replace(/\\/g, '')) const test = item.canvasStatus.replace(/##/g, '"').replace(/\\/g, '') const test2 = test.substring(1, test.length - 1) return { diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index bc650216..0ea0c065 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -1472,11 +1472,203 @@ export function useMode() { *벽 지붕 외곽선 생성 polygon을 입력받아 만들기 */ const handleOuterlinesTest2 = (polygon, offset = 50) => { - drawRoofPolygon(polygon, offset) - /*const offsetPoints = offsetPolygon(polygon.points, offset) + const roof = drawRoofPolygon(polygon) + roof.drawHelpLine() + roof.divideLine() + } + + function inwardEdgeNormal(vertex1, vertex2) { + // Assuming that polygon vertices are in clockwise order + const dx = vertex2.x - vertex1.x + const dy = vertex2.y - vertex1.y + const edgeLength = Math.sqrt(dx * dx + dy * dy) + + return { + x: -dy / edgeLength, + y: dx / edgeLength, + } + } + + function outwardEdgeNormal(vertex1, vertex2) { + const n = inwardEdgeNormal(vertex1, vertex2) + + return { + x: -n.x, + y: -n.y, + } + } + + function createRoofPolygon(vertices) { + const edges = [] + let minX = vertices.length > 0 ? vertices[0].x : undefined + let minY = vertices.length > 0 ? vertices[0].y : undefined + let maxX = minX + let maxY = minY + + for (let i = 0; i < vertices.length; i++) { + const vertex1 = vertices[i] + const vertex2 = vertices[(i + 1) % vertices.length] + + const outwardNormal = outwardEdgeNormal(vertex1, vertex2) + + const inwardNormal = inwardEdgeNormal(vertex1, vertex2) + + const edge = { + vertex1, + vertex2, + index: i, + outwardNormal, + inwardNormal, + } + + edges.push(edge) + + const x = vertices[i].x + const y = vertices[i].y + minX = Math.min(x, minX) + minY = Math.min(y, minY) + maxX = Math.max(x, maxX) + maxY = Math.max(y, maxY) + } + + return { + vertices, + edges, + minX, + minY, + maxX, + maxY, + } + } + + function createOffsetEdge(edge, dx, dy) { + return { + vertex1: { + x: edge.vertex1.x + dx, + y: edge.vertex1.y + dy, + }, + vertex2: { + x: edge.vertex2.x + dx, + y: edge.vertex2.y + dy, + }, + } + } + + function edgesIntersection(edgeA, edgeB) { + const den = + (edgeB.vertex2.y - edgeB.vertex1.y) * (edgeA.vertex2.x - edgeA.vertex1.x) - + (edgeB.vertex2.x - edgeB.vertex1.x) * (edgeA.vertex2.y - edgeA.vertex1.y) + + if (den === 0) { + return null // lines are parallel or coincident + } + + const ua = + ((edgeB.vertex2.x - edgeB.vertex1.x) * (edgeA.vertex1.y - edgeB.vertex1.y) - + (edgeB.vertex2.y - edgeB.vertex1.y) * (edgeA.vertex1.x - edgeB.vertex1.x)) / + den + + const ub = + ((edgeA.vertex2.x - edgeA.vertex1.x) * (edgeA.vertex1.y - edgeB.vertex1.y) - + (edgeA.vertex2.y - edgeA.vertex1.y) * (edgeA.vertex1.x - edgeB.vertex1.x)) / + den + + // Edges are not intersecting but the lines defined by them are + const isIntersectionOutside = ua < 0 || ub < 0 || ua > 1 || ub > 1 + + return { + x: edgeA.vertex1.x + ua * (edgeA.vertex2.x - edgeA.vertex1.x), + y: edgeA.vertex1.y + ua * (edgeA.vertex2.y - edgeA.vertex1.y), + isIntersectionOutside, + } + } + + function createMarginPolygon(polygon, lines, arcSegments = 0) { + const offsetEdges = [] + + polygon.edges.forEach((edge, i) => { + const offset = lines[i % lines.length].attributes.offset + const dx = edge.outwardNormal.x * offset + const dy = edge.outwardNormal.y * offset + offsetEdges.push(createOffsetEdge(edge, dx, dy)) + }) + + const vertices = [] + + offsetEdges.forEach((thisEdge, i) => { + const prevEdge = offsetEdges[(i + offsetEdges.length - 1) % offsetEdges.length] + const vertex = edgesIntersection(prevEdge, thisEdge) + if (vertex && (!vertex.isIntersectionOutside || arcSegments < 1)) { + vertices.push({ + x: vertex.x, + y: vertex.y, + }) + } + }) + + const marginPolygon = createRoofPolygon(vertices) + marginPolygon.offsetEdges = offsetEdges + return marginPolygon + } + + function createPaddingPolygon(polygon, lines, arcSegments = 0) { + const offsetEdges = [] + + polygon.edges.forEach((edge, i) => { + const offset = lines[i % lines.length].attributes.offset + const dx = edge.inwardNormal.x * offset + const dy = edge.inwardNormal.y * offset + offsetEdges.push(createOffsetEdge(edge, dx, dy)) + }) + + const vertices = [] + + offsetEdges.forEach((thisEdge, i) => { + const prevEdge = offsetEdges[(i + offsetEdges.length - 1) % offsetEdges.length] + const vertex = edgesIntersection(prevEdge, thisEdge) + if (vertex && (!vertex.isIntersectionOutside || arcSegments < 1)) { + vertices.push({ + x: vertex.x, + y: vertex.y, + }) + } + }) + + const paddingPolygon = createRoofPolygon(vertices) + paddingPolygon.offsetEdges = offsetEdges + return paddingPolygon + } + + const drawRoofPolygon = (wall) => { + let walls = wall.lines + walls.forEach((wall, index) => { + if (index === walls.length - 1 || index === 3) { + wall.attributes = { + type: 'gable', + offset: 30, + } + } else { + wall.attributes = { + type: 'hip', + offset: 50, + } + } + }) + const polygon = createRoofPolygon(wall.points) + const originPolygon = new QPolygon(wall.points, { fontSize: 0 }) + let offsetPolygon + + let result = createMarginPolygon(polygon, wall.lines).vertices + const allPointsOutside = result.every((point) => !originPolygon.inPolygon(point)) + + if (allPointsOutside) { + offsetPolygon = createMarginPolygon(polygon, wall.lines).vertices + } else { + offsetPolygon = createPaddingPolygon(polygon, wall.lines).vertices + } const roof = makePolygon( - offsetPoints.map((point) => { + offsetPolygon.map((point) => { return { x1: point.x, y1: point.y } }), ) @@ -1485,177 +1677,7 @@ export function useMode() { setRoof(roof) setWall(polygon) - roof.drawHelpLine() - roof.divideLine()*/ - } - - const drawRoofPolygon = (wall, offset = 50) => { - let walls = wall.lines - walls.forEach((wall, index) => { - if (index === 0) { - wall.attributes = { - type: 'gable', - width: 30, - } - } else { - wall.attributes = { - type: 'hip', - width: 50, - } - } - }) - - console.log('walls', walls) - - walls.forEach((currentWall, index) => { - let prevWall, nextWall - if (index === 0) { - prevWall = walls[walls.length - 1] - nextWall = walls[index + 1] - } else if (index === walls.length - 1) { - prevWall = walls[index - 1] - nextWall = walls[0] - } else { - prevWall = walls[index - 1] - nextWall = walls[index + 1] - } - - let p1 = [ - { x: currentWall.x1, y: currentWall.y1 }, - { x: currentWall.x2, y: currentWall.y2 }, - { x: prevWall.x1, y: prevWall.y1 }, - { x: prevWall.x2, y: prevWall.y2 }, - ], - p2 = [ - { x: currentWall.x1, y: currentWall.y1 }, - { x: currentWall.x2, y: currentWall.y2 }, - { x: nextWall.x1, y: nextWall.y1 }, - { x: nextWall.x2, y: nextWall.y2 }, - ] - - p1 = Array.from(new Set(p1.map((point) => JSON.stringify(point)))).map((point) => JSON.parse(point)) - p2 = Array.from(new Set(p2.map((point) => JSON.stringify(point)))).map((point) => JSON.parse(point)) - - let p1Lengths = [] - p1.forEach((point1, index) => { - let point2 - if (p1.length - 1 === index) { - point2 = p1[0] - } else { - point2 = p1[index + 1] - } - const dx = Math.abs(point2.x - point1.x) - const dy = Math.abs(point2.y - point1.y) - p1Lengths.push({ - length: Math.round(Math.sqrt(dx ** 2 + dy ** 2)), - coords: [ - { x: point1.x, y: point1.y }, - { x: point2.x, y: point2.y }, - ], - }) - }) - - let p2Lengths = [] - p2.forEach((point1, index) => { - let point2 - if (p2.length - 1 === index) { - point2 = p2[0] - } else { - point2 = p2[index + 1] - } - const dx = Math.abs(point2.x - point1.x) - const dy = Math.abs(point2.y - point1.y) - p2Lengths.push({ - length: Math.round(Math.sqrt(dx ** 2 + dy ** 2)), - coords: [ - { x: point1.x, y: point1.y }, - { x: point2.x, y: point2.y }, - ], - }) - }) - - let x1 = 0, - y1 = 0, - x2 = 0, - y2 = 0, - offsetX1 = 0, - offsetY1 = 0, - offsetX2 = 0, - offsetY2 = 0 - - let alfa = Math.round(Math.sqrt(Math.abs(currentWall.x1 - currentWall.x2) ** 2 + Math.abs(currentWall.y1 - currentWall.y2) ** 2)), - bravo = Math.round(Math.sqrt(Math.abs(prevWall.x1 - prevWall.x2) ** 2 + Math.abs(prevWall.y1 - prevWall.y2) ** 2)), - charlie = p1Lengths.filter((length) => length.length !== alfa && length.length !== bravo)[0], - alpha = Math.round(Math.acos((alfa ** 2 + charlie.length ** 2 - bravo ** 2) / (2 * alfa * charlie.length)) * (180 / Math.PI) * 100) / 100, - beta = Math.round(Math.acos((bravo ** 2 + charlie.length ** 2 - alfa ** 2) / (2 * bravo * charlie.length)) * (180 / Math.PI) * 100) / 100, - gamma = Math.round(Math.acos((alfa ** 2 + bravo ** 2 - charlie.length ** 2) / (2 * alfa * bravo)) * (180 / Math.PI) * 100) / 100, - isValley = checkValley(wall, currentWall, prevWall) - console.log('현재 라인 : ', alfa) - gamma = isValley ? Math.round(((360 - gamma) / 2) * 100) / 100 : Math.round((gamma / 2) * 100) / 100 - - console.log('이전 라인과의 각도', gamma) - - if (currentWall.x1 === currentWall.x2) { - offsetY1 = currentWall.attributes.width - offsetX1 = prevWall.attributes.width - x1 = Math.min(currentWall.x1, currentWall.x2) + offsetX1 - y1 = currentWall.y1 + offsetY1 - } else if (currentWall.y1 === currentWall.y2) { - offsetX1 = currentWall.attributes.width - offsetY1 = prevWall.attributes.width - x1 = currentWall.x1 + offsetX1 - y1 = Math.min(currentWall.y1, currentWall.y2) + offsetY1 - } else { - } - - bravo = Math.round(Math.sqrt(Math.abs(nextWall.x1 - nextWall.x2) ** 2 + Math.abs(nextWall.y1 - nextWall.y2) ** 2)) - charlie = p2Lengths.filter((length) => length.length !== alfa && length.length !== bravo)[0] - - // alpha = Math.round(Math.acos((alfa ** 2 + charlie ** 2 - bravo ** 2) / (2 * alfa * charlie)) * (180 / Math.PI)) - // betta = Math.round(Math.acos((bravo ** 2 + charlie ** 2 - alfa ** 2) / (2 * bravo * charlie)) * (180 / Math.PI)) - gamma = Math.round(Math.acos((alfa ** 2 + bravo ** 2 - charlie.length ** 2) / (2 * alfa * bravo)) * (180 / Math.PI) * 100) / 100 - isValley = checkValley(wall, currentWall, nextWall) - gamma = isValley ? Math.round(((360 - gamma) / 2) * 100) / 100 : Math.round((gamma / 2) * 100) / 100 - - console.log('다음 라인과의 각도', gamma) - - /*let offsetX = 0, - offsetY = 0 - let x1 = 0, - y1 = 0, - x2 = 0, - y2 = 0 - if (prevWall.direction !== nextWall.direction) { - if (currentWall.x1 === currentWall.x2) { - offsetX = prevWall.x1 < currentWall.x1 ? currentWall.attributes.width : -currentWall.attributes.width - x1 = currentWall.x1 - x2 = currentWall.x2 - y1 = Math.min(currentWall.y1, currentWall.y2) - Math.min(prevWall.attributes.width, nextWall.attributes.width) - y2 = Math.max(currentWall.y1, currentWall.y2) + Math.max(prevWall.attributes.width, nextWall.attributes.width) - } else { - offsetY = prevWall.y1 < currentWall.y1 ? currentWall.attributes.width : -currentWall.attributes.width - x1 = Math.min(currentWall.x1, currentWall.x2) - Math.min(prevWall.attributes.width, nextWall.attributes.width) - x2 = Math.max(currentWall.x1, currentWall.x2) + Math.max(prevWall.attributes.width, nextWall.attributes.width) - y1 = currentWall.y1 - y2 = currentWall.y2 - } - } else { - } - - x1 = x1 + offsetX - x2 = x2 + offsetX - y1 = y1 + offsetY - y2 = y2 + offsetY - - const roof = new QLine([x1, y1, x2, y2], { - fontSize: fontSize, - stroke: 'black', - strokeWidth: 1, - name: 'roofLine', - }) - canvas?.add(roof) - canvas?.renderAll()*/ - }) + return roof } /** @@ -1693,50 +1715,6 @@ export function useMode() { return isValley } - /** - * 구하려는 라인의 x1,y1좌표가 기준 - * @param line1 이전 라인 - * @param line2 현재 라인 - * @param line3 다음 라인 - * @param offset - * @returns {number} - */ - const getLineOffsetPoint = (line1, line2, line3, offset) => { - //밑변 - let a = Math.abs(line1.x - line2.x) - //빗변 - let c = Math.sqrt(Math.abs(line1.x - line2.x) ** 2 + Math.abs(line1.y - line2.y) ** 2) - - console.log(a, c) - //밑변과 빗변사이의 각도 - let alphaDegree = getDegreeBetweenTwoLines(line1, line2, line3) - alphaDegree = alphaDegree <= 90 ? alphaDegree : 180 - alphaDegree - alphaDegree = 90 - alphaDegree - console.log('alphaDegree : ', alphaDegree) - - // console.log('Math.tan(alphaDegree * (Math.PI / 180)) : ', Math.tan(alphaDegree * (Math.PI / 180))) - console.log(Math.round(offset * Math.tan(alphaDegree * (Math.PI / 180)))) - - const angle = getDegreeBetweenTwoLines(line1, line2, line3) - const side1 = line1.length - const side2 = line2.length - const side3 = Math.sqrt(side1 ** 2 + side2 ** 2 - 2 * side1 * side2 * Math.cos(angle * (Math.PI / 180))) - const beta = Math.round(Math.asin((side2 * Math.sin(angle * (Math.PI / 180))) / side3) * (180 / Math.PI) * 10) / 10 - const alpha = 180 - angle - beta - - console.log('angle : ', angle, 'alpha : ', alpha, 'beta : ', beta) - - const h = side2 * Math.sin(alpha * (Math.PI / 180)) - const h_new = h + offset - console.log('빗변까지 길이 : ', h, 'offset 적용된 빗변까지 길이 : ', h_new) - const newAdjacent = h_new / Math.sin(angle * (Math.PI / 180)) - console.log('offset 적용된 밑변 : ', newAdjacent) - - // offset = Math.sqrt(diffAdjacent ** 2 + diffAdjacent ** 2) / 2 - console.log('offset : ', offset) - return offset - } - /** * 구하려는 라인의 x1,y1좌표가 기준 * @param line1 이전 라인 diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 1599905d..032ad5be 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1206,10 +1206,6 @@ export const drawHippedRoof = (polygon, chon) => { } const drawRoofRidge = (polygon, chon) => { - const points = [] - polygon.wall.points.forEach((point) => points.push({ x: point.x, y: point.y })) - console.log('points : ', points) - const walls = polygon.wall.lines // 외벽의 라인 const roofs = polygon.lines // 지붕의 라인 let ridgeWall = [] From 112ebea1c1a71b5281aec8492c6ded3f0c22ff6b Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Fri, 27 Sep 2024 16:23:04 +0900 Subject: [PATCH 003/152] =?UTF-8?q?=EB=B3=80=EB=B3=84=20=EC=86=8D=EC=84=B1?= =?UTF-8?q?=20=EC=9E=91=EC=97=85=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 11 +- src/hooks/useMode.js | 24 ++- src/util/qpolygon-utils.js | 406 ++++++++++++++++++------------------- 3 files changed, 222 insertions(+), 219 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 8e326c7f..3cfff65c 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -39,7 +39,7 @@ import QEmptyContextMenu from '@/components/common/context-menu/QEmptyContextMen import InitSettingsModal from './InitSettingsModal' import GridSettingsModal from './GridSettingsModal' import { SurfaceShapeModal } from '@/components/ui/SurfaceShape' -import { changeAllGableRoof, drawDirectionStringToArrow } from '@/util/qpolygon-utils' +import { changeAllHipAndGableRoof, drawDirectionStringToArrow } from '@/util/qpolygon-utils' import ThumbnailList from '@/components/ui/ThumbnailLIst' import ObjectPlacement from '@/components/ui/ObjectPlacement' import { globalLocaleStore } from '@/store/localeAtom' @@ -425,7 +425,7 @@ export default function Roof2(props) { { x: 450, y: 850 }, ] - const polygon = new QPolygon(type1C, { + const polygon = new QPolygon(twelvePoint, { fill: 'transparent', stroke: 'green', strokeWidth: 1, @@ -640,13 +640,14 @@ export default function Roof2(props) { drawDirectionStringToArrow(canvas, globalCampass) } - const setAllGableRoof = () => { + // 팔작지붕, 합각지붕 + const setAllHipAndGableRoof = () => { let offset = Number(prompt('gable roof offset', '50')) if (!isNaN(offset) && offset > 0) { const polygon = canvas?.getObjects() console.log('gable roof offset : ', offset) console.log('polygon : ', polygon) - changeAllGableRoof(polygon, offset, canvas) + changeAllHipAndGableRoof(polygon, offset, canvas) } else { alert('offset 은 0 보다 커야 함') } @@ -777,7 +778,7 @@ export default function Roof2(props) { )} - + +
+
{getMessage('modal.canvas.setting.wallline.properties.setting.info')}
+
+
{getMessage('setting')}
+
+ + +
+
+
+ + +
+
+ + + ) +} diff --git a/src/locales/ja.json b/src/locales/ja.json index 8e62d630..06429bc6 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -32,6 +32,7 @@ "modal.cover.outline.arrow": "方向 (矢印)", "modal.cover.outline.fix": "外壁線確定", "modal.cover.outline.rollback": "一変戦に戻る", + "modal.cover.outline.finish": "設定完了", "modal.cover.outline.remove": "外壁の削除", "modal.cover.outline.select.move": "外壁の選択、移動", "plan.menu.roof.cover.roof.setting": "屋根形状設定", @@ -115,6 +116,11 @@ "modal.canvas.setting.first.option.border": "ボーダーのみ", "modal.canvas.setting.first.option.line": "ラインハッチ", "modal.canvas.setting.first.option.all": "All painted", + "modal.canvas.setting.wallline.properties.setting": "外壁のプロパティの設定", + "modal.canvas.setting.wallline.properties.setting.info": "※属性を変更する外壁線を選択し、軒で設定またはケラバで設定 ボタンをクリックして設定値を適用します。", + "modal.canvas.setting.wallline.properties.setting.eaves": "軒で設定", + "modal.canvas.setting.wallline.properties.setting.edge": "ケラバに設定", + "setting": "設定", "common.message.no.data": "No data", "common.message.no.dataDown": "ダウンロードするデータがありません", "common.message.noData": "表示するデータがありません", diff --git a/src/locales/ko.json b/src/locales/ko.json index 9bf624d6..b3e2decd 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -36,6 +36,7 @@ "modal.cover.outline.arrow": "방향(화살표)", "modal.cover.outline.fix": "외벽선 확정", "modal.cover.outline.rollback": "일변전으로 돌아가기", + "modal.cover.outline.finish": "설정완료", "modal.cover.outline.remove": "외벽 제거", "modal.cover.outline.select.move": "외벽 선택, 이동", "plan.menu.placement.surface": "배치면", @@ -116,6 +117,11 @@ "modal.canvas.setting.first.option.border": "테두리만", "modal.canvas.setting.first.option.line": "라인해치", "modal.canvas.setting.first.option.all": "All painted", + "modal.canvas.setting.wallline.properties.setting": "외벽선 속성 설정", + "modal.canvas.setting.wallline.properties.setting.info": "※ 속성을 변경할 외벽선을 선택하고, 처마로 설정 또는 케라바로 설정\n 버튼을 클릭하여 설정값을 적용하십시오.\n", + "modal.canvas.setting.wallline.properties.setting.eaves": "처마로 설정", + "modal.canvas.setting.wallline.properties.setting.edge": "케라바로 설정", + "setting": "설정", "common.message.no.data": "No data", "common.message.no.dataDown": "No data to download", "common.message.noData": "No data to display", diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss index 6309f50e..0ad517a3 100644 --- a/src/styles/_modal.scss +++ b/src/styles/_modal.scss @@ -4,466 +4,617 @@ $pop-bold-weight: 500; $pop-normal-size: 12px; $alert-color: #101010; -@keyframes mountpop{ - from{opacity: 0; scale: 0.95;} - to{opacity: 1; scale: 1;} -} -@keyframes unmountpop{ - from{opacity: 1; scale: 1;} - to{opacity: 0; scale: 0.95;} +@keyframes mountpop { + from { + opacity: 0; + scale: 0.95; + } + to { + opacity: 1; + scale: 1; + } } -.modal-pop-wrap{ - position: fixed; - top: 200px; - right: 100px; - width: 100%; - min-width: 300px; - height: -webkit-fit-content; - height: -moz-fit-content; - height: fit-content; - border: 1px solid #000; - border-radius: 4px; - background-color: #272727; - z-index: 9999999; - overflow: hidden; - &.r{ - width: 400px; - } - &.sm{ - width: 580px; - } - &.ssm{ - width: 380px; - } - &.xm{ - width: 300px; - } - &.l{ - width: 800px; - } - &.mount{ - animation: mountpop .17s ease-in-out forwards; - } - &.unmount{ - animation: unmountpop .17s ease-in-out forwards; - } - &.alert{ - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background-color: transparent; - border: none; - .modal-head{ - background-color: transparent; - padding: 0 0 8px; - .modal-close{ - width: 20px; - height: 20px; - background: url(../../public/static/images/canvas/alert_close.svg)no-repeat center; - } - } - .modal-body{ - background-color: #fff; - padding: 22px; - border-radius: 4px; - border: 1px solid #101010; - color: $alert-color; - .alert-title{ - font-size: 13px; - font-weight: 700; - color: $alert-color; - margin-bottom: 15px; - } - } - } +@keyframes unmountpop { + from { + opacity: 1; + scale: 1; + } + to { + opacity: 0; + scale: 0.95; + } } -.modal-head{ - display: flex; - align-items: center; - padding: 10px 24px; - background-color: #000; - h1.title{ + +.modal-pop-wrap { + position: fixed; + top: 200px; + right: 100px; + width: 100%; + min-width: 300px; + height: -webkit-fit-content; + height: -moz-fit-content; + height: fit-content; + border: 1px solid #000; + border-radius: 4px; + background-color: #272727; + z-index: 9999999; + overflow: hidden; + + &.r { + width: 400px; + } + + &.sm { + width: 580px; + } + + &.ssm { + width: 380px; + } + + &.xm { + width: 300px; + } + + &.l { + width: 800px; + } + + &.mount { + animation: mountpop .17s ease-in-out forwards; + } + + &.unmount { + animation: unmountpop .17s ease-in-out forwards; + } + + &.alert { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: transparent; + border: none; + + .modal-head { + background-color: transparent; + padding: 0 0 8px; + + .modal-close { + width: 20px; + height: 20px; + background: url(../../public/static/images/canvas/alert_close.svg) no-repeat center; + } + } + + .modal-body { + background-color: #fff; + padding: 22px; + border-radius: 4px; + border: 1px solid #101010; + color: $alert-color; + + .alert-title { font-size: 13px; - color: $pop-color; font-weight: 700; - } - .modal-close{ - margin-left: auto; - color: $pop-color; - text-indent: -999999999px; - width: 10px; - height: 10px; - background: url(../../public/static/images/canvas/modal_close.svg)no-repeat center; - } -} -.modal-body{ - padding: 24px; - .modal-btn-wrap{ - display: flex; - align-items: center; - gap: 5px; - button{ - flex: 1; - } - } - .modal-check-btn-wrap{ - margin-top: 15px; - .check-wrap-title{ - font-size: $pop-normal-size; - color: $pop-color; - font-weight: 600; - &.light{ - font-weight: $pop-normal-weight; - } - } - .flex-check-box{ - display: flex; - flex-wrap: wrap; - gap: 10px; - margin-top: 15px; - &.for2{ - justify-content: flex-end; - button{ - width: calc(50% - 5px); - } - &.btn{ - gap: 5px; - button{ - width: calc(50% - 2.5px); - } - } - } - &.for-line{ - button{ - flex: 1; - } - } - } - } - .outer-line-wrap{ - border-top: 1px solid #3C3C3C; - margin-top: 10px; - padding-top: 15px; - margin-bottom: 15px; - > div{ - margin-bottom: 15px; - &:last-child{ - margin-bottom: 0; - } - } - } - .modal-guide{ - display: block; - font-size: $pop-normal-size; color: $alert-color; - font-weight: $pop-normal-weight; + margin-bottom: 15px; + } } + } } -.adsorption-point{ +.modal-head { + display: flex; + align-items: center; + padding: 10px 24px; + background-color: #000; + + h1.title { + font-size: 13px; + color: $pop-color; + font-weight: 700; + } + + .modal-close { + margin-left: auto; + color: $pop-color; + text-indent: -999999999px; + width: 10px; + height: 10px; + background: url(../../public/static/images/canvas/modal_close.svg) no-repeat center; + } +} + +.modal-body { + padding: 24px; + + .modal-btn-wrap { display: flex; align-items: center; - background-color: #3A3A3A; - border-radius: 3px; - padding-left: 11px; - overflow: hidden; - transition: all 0.17s ease-in-out; - span{ - font-size: $pop-normal-size; - color: #898989; + gap: 5px; + + button { + flex: 1; } - i{ - display: flex; - align-items: center; - padding: 0 7px; - margin-left: auto; - height: 100%; - font-size: 13px; - color: #898989; + } + + .modal-check-btn-wrap { + margin-top: 15px; + + .check-wrap-title { + font-size: $pop-normal-size; + color: $pop-color; + font-weight: 600; + + &.light { + font-weight: $pop-normal-weight; + } } - &.act{ - i{ - color: $pop-color; - background-color: #1083E3; + + .flex-check-box { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin-top: 15px; + + &.for2 { + justify-content: flex-end; + + button { + width: calc(50% - 5px); } + + &.btn { + gap: 5px; + + button { + width: calc(50% - 2.5px); + } + } + } + + &.for-line { + button { + flex: 1; + } + } } + } + + .outer-line-wrap { + border-top: 1px solid #3C3C3C; + margin-top: 10px; + padding-top: 15px; + margin-bottom: 15px; + + > div { + margin-bottom: 15px; + + &:last-child { + margin-bottom: 0; + } + } + } + + .modal-guide { + display: block; + font-size: $pop-normal-size; + color: $alert-color; + font-weight: $pop-normal-weight; + } +} + +.adsorption-point { + display: flex; + align-items: center; + background-color: #3A3A3A; + border-radius: 3px; + padding-left: 11px; + overflow: hidden; + transition: all 0.17s ease-in-out; + + span { + font-size: $pop-normal-size; + color: #898989; + } + + i { + display: flex; + align-items: center; + padding: 0 7px; + margin-left: auto; + height: 100%; + font-size: 13px; + color: #898989; + } + + &.act { + i { + color: $pop-color; + background-color: #1083E3; + } + } } // grid-option -.grid-check-form{ +.grid-check-form { + display: flex; + align-items: center; + gap: 15px; + padding-bottom: 15px; + border-bottom: 1px solid #3C3C3C; +} + +.grid-option-wrap { + padding: 15px 0; + border-bottom: 1px solid #3C3C3C; + + .grid-option-box { display: flex; align-items: center; - gap: 15px; - padding-bottom: 15px; - border-bottom: 1px solid #3C3C3C; -} -.grid-option-wrap{ - padding: 15px 0; - border-bottom: 1px solid #3C3C3C; - .grid-option-box{ - display: flex; - align-items: center; - background-color: #3D3D3D; - border-radius: 2px; - padding: 10px; - gap: 20px; - margin-bottom: 5px; - .grid-input-form{ - display: flex; - align-items: center; - span{ - flex: none; - font-size: $pop-normal-size; - color: $pop-color; - font-weight: $pop-bold-weight; - } - .input-grid{ - width: 54px; - input{ - width: 100%; - } - } - } - &:last-child{ - margin-bottom: 0; + background-color: #3D3D3D; + border-radius: 2px; + padding: 10px; + gap: 20px; + margin-bottom: 5px; + + .grid-input-form { + display: flex; + align-items: center; + + span { + flex: none; + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-bold-weight; + } + + .input-grid { + width: 54px; + + input { + width: 100%; } + } } + + &:last-child { + margin-bottom: 0; + } + } } -.grid-select{ - flex: 1; - .sort-select{ - width: 100%; - background-color: #313131; - } + +.grid-select { + flex: 1; + + .sort-select { + width: 100%; + background-color: #313131; + } } -.grid-btn-wrap{ - padding-top: 15px; - text-align: right; - button{ - padding: 0 20px; - } + +.grid-btn-wrap { + padding-top: 15px; + text-align: right; + + button { + padding: 0 20px; + } } // grid copy -.grid-option-tit{ - font-size: $pop-normal-size; - color: $pop-color; - font-weight: $pop-normal-weight; - padding-bottom: 15px; - border-bottom: 1px solid #3C3C3C; +.grid-option-tit { + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-normal-weight; + padding-bottom: 15px; + border-bottom: 1px solid #3C3C3C; } -.grid-direction{ - display: flex; - align-items: center; - gap: 5px; - flex: 1; + +.grid-direction { + display: flex; + align-items: center; + gap: 5px; + flex: 1; } -.direction{ - width: 22px; - height: 22px; - background-color: #757575; - background-image: url(../../public/static/images/canvas/grid_option_arr.svg); - background-repeat: no-repeat; - background-position: center; - background-size: 16px 15px; - border-radius: 50%; - transition: all .15s ease-in-out; - opacity: 0.6; - &.down{transform: rotate(180deg);} - &.left{transform: rotate(-90deg);} - &.right{transform: rotate(90deg);} - &:hover, - &.act{ - opacity: 1; - } + +.direction { + width: 22px; + height: 22px; + background-color: #757575; + background-image: url(../../public/static/images/canvas/grid_option_arr.svg); + background-repeat: no-repeat; + background-position: center; + background-size: 16px 15px; + border-radius: 50%; + transition: all .15s ease-in-out; + opacity: 0.6; + + &.down { + transform: rotate(180deg); + } + + &.left { + transform: rotate(-90deg); + } + + &.right { + transform: rotate(90deg); + } + + &:hover, + &.act { + opacity: 1; + } } // grid-move -.move-form{ - p{ - font-size: $pop-normal-size; - color: $pop-color; - font-weight: $pop-bold-weight; - } +.move-form { + p { + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-bold-weight; + } } -.input-move-wrap{ - display: flex; - align-items: center; - gap: 5px; - span{ - color: $pop-color; - font-size: $pop-normal-size; - } - .input-move{ - width: 130px; - input{ - width: 100%; - } + +.input-move-wrap { + display: flex; + align-items: center; + gap: 5px; + + span { + color: $pop-color; + font-size: $pop-normal-size; + } + + .input-move { + width: 130px; + + input { + width: 100%; } + } } -.direction-move-wrap{ - flex: none; - display: grid; - grid-template-columns: 1fr 1fr; - gap: 10px; + +.direction-move-wrap { + flex: none; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; } // 배치면 초기 설정 -.placement-table{ - table{ - table-layout: fixed; - tr{ - th{ - display: flex; - align-items: center; - font-size: $pop-normal-size; - color: $pop-color; - font-weight: $pop-bold-weight; - padding: 18px 0; - border-bottom: 1px solid #424242; - } - td{ - font-size: $pop-normal-size; - color: $pop-color; - border-bottom: 1px solid #424242; - padding-left: 20px; - } - &:first-child{ - td, - th{ - padding-top: 0; - } - } - } - } - .tooltip{ - position: relative; - display: block; - width: 15px; - height: 15px; - margin-left: 5px; - background: url(../../public/static/images/canvas/pop_tip.svg)no-repeat center; - background-size: cover; - } - &.light{ - padding: 0; - th,td{ - color: $alert-color; - border-bottom: none; - border-top: 1px solid #EFEFEF; - } - th{ - padding: 14px 0; - } - tr{ - &:first-child{ - td, - th{ - padding-top: 14px; - } - } - &:last-child{ - td, - th{ - padding-bottom: 0px; - } - } - } - } -} +.placement-table { + table { + table-layout: fixed; -.pop-form-radio{ - display: flex; - align-items: center; - gap: 10px; -} -.placement-option{ - display: flex; - align-items: center; - gap: 20px; -} -.select-wrap{ - div{ - width: 100%; - } -} -.flex-ment{ - display: flex; - align-items: center; - gap: 5px; - span{ + tr { + th { + display: flex; + align-items: center; font-size: $pop-normal-size; color: $pop-color; - font-weight: $pop-normal-weight; + font-weight: $pop-bold-weight; + padding: 18px 0; + border-bottom: 1px solid #424242; + } + + td { + font-size: $pop-normal-size; + color: $pop-color; + border-bottom: 1px solid #424242; + padding-left: 20px; + } + + &:first-child { + td, + th { + padding-top: 0; + } + } } + } + + .tooltip { + position: relative; + display: block; + width: 15px; + height: 15px; + margin-left: 5px; + background: url(../../public/static/images/canvas/pop_tip.svg) no-repeat center; + background-size: cover; + } + + &.light { + padding: 0; + + th, td { + color: $alert-color; + border-bottom: none; + border-top: 1px solid #EFEFEF; + } + + th { + padding: 14px 0; + } + + tr { + &:first-child { + td, + th { + padding-top: 14px; + } + } + + &:last-child { + td, + th { + padding-bottom: 0px; + } + } + } + } +} + +.pop-form-radio { + display: flex; + align-items: center; + gap: 10px; +} + +.placement-option { + display: flex; + align-items: center; + gap: 20px; +} + +.select-wrap { + div { + width: 100%; + } +} + +.flex-ment { + display: flex; + align-items: center; + gap: 5px; + + span { + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-normal-weight; + } } // 외벽선 그리기 -.outline-wrap{ - padding: 24px 0; - border-bottom: 1px solid #424242; - .outline-inner{ - display: flex; - align-items: center; - margin-bottom: 14px; - &:last-child{ - margin-bottom: 0; - } - } -} -.outline-form{ - width: 50%; +.outline-wrap { + padding: 24px 0; + border-bottom: 1px solid #424242; + + .outline-inner { display: flex; align-items: center; - margin-right: 15px; - span{ - width: 60px; - flex: none; - font-size: $pop-normal-size; - font-weight: $pop-bold-weight; - color: $pop-color; - margin-right: 10px; - } - .reset-btn{ - flex: none; - width: 30px; - height: 30px; - background: transparent; - border: 1px solid #484848; - border-radius: 2px; - margin-left: 5px; - background-image: url(../../public/static/images/canvas/reset_ico.svg); - background-repeat: no-repeat; - background-size: 12px 12px; - background-position: center; - } - &:last-child{ - margin-right: 0; + margin-bottom: 14px; + + &:last-child { + margin-bottom: 0; } + } } -.cul-wrap{ +.outline-form { + width: 50%; + display: flex; + align-items: center; + margin-right: 15px; + + span { + width: 60px; + flex: none; + font-size: $pop-normal-size; + font-weight: $pop-bold-weight; + color: $pop-color; + margin-right: 10px; + } + + .reset-btn { + flex: none; + width: 30px; + height: 30px; + background: transparent; + border: 1px solid #484848; + border-radius: 2px; + margin-left: 5px; + background-image: url(../../public/static/images/canvas/reset_ico.svg); + background-repeat: no-repeat; + background-size: 12px 12px; + background-position: center; + } + + &:last-child { + margin-right: 0; + } +} + +.cul-wrap { + display: flex; + + .outline-box { + width: 50%; + margin-right: 15px; + + .outline-form { + width: 100%; + margin-bottom: 14px; + margin-right: 0; + + &:last-child { + margin-bottom: 0; + } + } + } + + .cul-box { display: flex; - .outline-box{ - width: 50%; - margin-right: 15px; - .outline-form{ - width: 100%; - margin-bottom: 14px; - margin-right: 0; - &:last-child{ - margin-bottom: 0; - } + align-items: center; + justify-content: center; + width: 50%; + background-color: #3D3D3D; + border-radius: 2px; + } +} + +.properties-guide { + font-size: $pop-normal-size; + color: #AAA; + font-weight: $pop-normal-weight; + margin-bottom: 14px; +} + +.properties-setting-wrap { + .setting-tit { + font-size: 13px; + color: $pop-color; + font-weight: $pop-bold-weight; + margin-bottom: 10px; + } + + .setting-btn-wrap { + display: flex; + align-items: center; + padding: 14px 0; + border-top: 1px solid #424242; + border-bottom: 1px solid #424242; + + .setting-btn { + display: block; + width: 100%; + height: 40px; + font-size: 13px; + color: #fff; + font-weight: 700; + border-radius: 2px; + transition: all .15s ease-in-out; + + &.green { + background-color: #305941; + border: 1px solid #45CD7D; + + &:hover { + background-color: #3a6b4e; } + } + + &.blue { + background-color: #2E5360; + border: 1px solid #3FBAE6; + + &:hover { + background-color: #365f6e; + } + } } - .cul-box{ - display: flex; - align-items: center; - justify-content: center; - width: 50%; - background-color: #3D3D3D; - border-radius: 2px ; - } + } } \ No newline at end of file From 1d8d46eb4a0e72104e0a1d5911000ad20129b49e Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 30 Sep 2024 13:29:22 +0900 Subject: [PATCH 006/152] =?UTF-8?q?=F0=9F=9A=A8chore:=20Sync=20Sass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/styles/_modal.scss | 84 ++- src/styles/_reset.scss | 1262 ++++++++++++++++++++++------------------ 2 files changed, 777 insertions(+), 569 deletions(-) diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss index 0ad517a3..28456176 100644 --- a/src/styles/_modal.scss +++ b/src/styles/_modal.scss @@ -45,6 +45,10 @@ $alert-color: #101010; width: 400px; } + &.lr { + width: 440px; + } + &.sm { width: 580px; } @@ -138,6 +142,13 @@ $alert-color: #101010; button { flex: 1; } + + &.sub { + button { + flex: 1 1 auto; + padding: 0; + } + } } .modal-check-btn-wrap { @@ -491,6 +502,7 @@ $alert-color: #101010; // 외벽선 그리기 .outline-wrap { padding: 24px 0; + border-top: 1px solid #424242; border-bottom: 1px solid #424242; .outline-inner { @@ -501,11 +513,14 @@ $alert-color: #101010; &:last-child { margin-bottom: 0; } + + .outline-form { + width: 50%; + } } } .outline-form { - width: 50%; display: flex; align-items: center; margin-right: 15px; @@ -517,6 +532,10 @@ $alert-color: #101010; font-weight: $pop-bold-weight; color: $pop-color; margin-right: 10px; + + &.thin { + font-weight: & $pop-normal-weight; + } } .reset-btn { @@ -566,6 +585,7 @@ $alert-color: #101010; } } +// 외벽선 속성 설정 .properties-guide { font-size: $pop-normal-size; color: #AAA; @@ -574,6 +594,10 @@ $alert-color: #101010; } .properties-setting-wrap { + &.outer { + margin-top: 24px; + } + .setting-tit { font-size: 13px; color: $pop-color; @@ -617,4 +641,62 @@ $alert-color: #101010; } } } +} + +// 지붕형상 설정 +.roof-shape-menu { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-rows: 1fr 1fr; + gap: 24px 10px; + margin-bottom: 24px; + + .shape-box { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + padding: 13px; + background-color: #3D3D3D; + transition: background .15s ease-in-out; + + img { + max-width: 100%; + } + } + + .shape-title { + font-size: $pop-normal-size; + font-weight: $pop-bold-weight; + color: $pop-color; + margin-top: 10px; + text-align: center; + transition: color .15s ease-in-out; + } + + .shape-menu-box { + &.act, + &:hover { + .shape-box { + background-color: #008BFF; + } + + .shape-title { + color: #008BFF; + } + } + } +} + +.setting-box { + padding: 14px 0; + border-top: 1px solid #424242; + border-bottom: 1px solid #424242; +} + +.discrimination-box { + padding: 16px 12px; + border: 1px solid #3D3D3D; + border-radius: 2px; + margin-top: 14px; } \ No newline at end of file diff --git a/src/styles/_reset.scss b/src/styles/_reset.scss index 2c5b1e22..dcf0c0d2 100644 --- a/src/styles/_reset.scss +++ b/src/styles/_reset.scss @@ -1,18 +1,21 @@ * { - -webkit-text-size-adjust:none; - -moz-text-size-adjust:none; - -ms-text-size-adjust:none; - text-size-adjust: none; - box-sizing: content-box + -webkit-text-size-adjust: none; + -moz-text-size-adjust: none; + -ms-text-size-adjust: none; + text-size-adjust: none; + box-sizing: content-box } + *, ::after, ::before { - box-sizing: border-box; + box-sizing: border-box; } -html, body{ - width: 100%; - height: 100%; - font-size: 16px; + +html, body { + width: 100%; + height: 100%; + font-size: 16px; } + html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, @@ -22,654 +25,777 @@ b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, canvas, details, embed, -figure, figcaption, footer, header, hgroup, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font: inherit; - vertical-align: baseline; - font-family: 'Noto Sans JP', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-smooth: never; + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; + font-family: 'Noto Sans JP', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-smooth: never; } + /* HTML5 display-role reset for older browsers */ -article, aside, details, figcaption, figure, +article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { - display: block; + display: block; } + body { - line-height: 1.4; + line-height: 1.4; +} + +body:first-of-type caption { + display: none; } -body:first-of-type caption { display:none;} ol, ul { - list-style: none; -} -blockquote, q { - quotes: none; -} -blockquote:before, blockquote:after, -q:before, q:after { - content: ''; - content: none; -} -table { - width: 100%; - border-collapse: separate; - border-spacing:0; - border:0 none; -} -caption, th, td { - text-align:left; - font-weight: normal; - border:0; + list-style: none; } -a { - cursor:pointer; - color:#000; +blockquote, q { + quotes: none; } + +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} + +table { + width: 100%; + border-collapse: separate; + border-spacing: 0; + border: 0 none; +} + +caption, th, td { + text-align: left; + font-weight: normal; + border: 0; +} + +a { + cursor: pointer; + color: #000; +} + a, a:hover, a:active { - text-decoration:none; - -webkit-tap-highlight-color: transparent; + text-decoration: none; + -webkit-tap-highlight-color: transparent; } + /*form_style*/ input, select, textarea, button, a, label { - -webkit-tap-highlight-color:rgba(0,0,0,0); + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } -button,input[type=text], input[type=button] { - -webkit-appearance: none; - -webkit-border-radius: 0; - -webkit-appearance:none; - appearance: none; - border-radius: 0 + +button, input[type=text], input[type=button] { + -webkit-appearance: none; + -webkit-border-radius: 0; + -webkit-appearance: none; + appearance: none; + border-radius: 0 } + input[type=checkbox], input[type=radio] { - box-sizing: border-box; - padding: 0; + box-sizing: border-box; + padding: 0; } + input, select, button { - border:0 none; - outline:none; - margin:0; + border: 0 none; + outline: none; + margin: 0; } + select { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } + select::-ms-expand { - display: none; + display: none; } + ::-webkit-input-placeholder { - line-height:1; - font-weight:300; - font-size:0.938rem; - letter-spacing:-0.6px; - color:#8b8b8b; + line-height: 1; + font-weight: 300; + font-size: 0.938rem; + letter-spacing: -0.6px; + color: #8b8b8b; } -.log-box ::-webkit-input-placeholder{ - color:#8b8b8b; + +.log-box ::-webkit-input-placeholder { + color: #8b8b8b; } -button{ - background: transparent; - font-family: 'Noto Sans JP', sans-serif; - border: none; - padding: 0; - margin: 0; - line-height: 1.4; - color: inherit; - outline: none; - cursor: pointer; + +button { + background: transparent; + font-family: 'Noto Sans JP', sans-serif; + border: none; + padding: 0; + margin: 0; + line-height: 1.4; + color: inherit; + outline: none; + cursor: pointer; } -.pre{ - font-family: 'Pretendard', sans-serif !important; + +.pre { + font-family: 'Pretendard', sans-serif !important; } // margin -.mt5{margin-top: 5px !important;} -.mt10{margin-top: 10px !important;} -.mb5{margin-bottom: 5px !important;} -.mb10{margin-bottom: 10px !important;} -.mr5{margin-right: 5px !important;} -.mr10{margin-right: 10px !important;} -.ml5{margin-left: 5px !important;} -.ml10{margin-left: 10px !important;} - -// button -.btn-frame{ - display: inline-block; - padding: 0 7px; - height: 34px; - line-height: 34px; - border-radius: 2px; - color: #fff; - font-size: 12px; - font-weight: 400; - border: 1px solid #000; - text-align: center; - font-family: 'Pretendard', sans-serif; - transition: all .17s ease-in-out; - cursor: pointer; - &.block{ - width: 100%; - } - &.small{ - font-family: 'Noto Sans JP', sans-serif; - height: 30px; - line-height: 30px; - font-size: 13px; - } - - &.deepgray{ - background-color: #2C2C2C; - border: 1px solid #484848; - } - &.gray{ - background-color: #3C3C3C; - border: 1px solid #545454; - } - &.dark{ - background-color: #1C1C1C; - border: 1px solid #484848; - } - &.modal{ - font-family: 'Noto Sans JP', sans-serif; - background-color: #272727; - border: 1px solid #484848; - color: #aaa; - &:hover{ - background-color: #1083E3; - border: 1px solid #1083E3; - color: #fff; - font-weight: 500; - } - } - &:hover, - &.act{ - background-color: #1083E3; - border: 1px solid #1083E3; - color: #fff; - font-weight: 500; - } - &.block{ - display: block; - width: 100%; - } - &.ico-flx{ - display: flex; - align-items: center; - .ico{ - margin-right: 10px; - } - &:hover, - &.act{ - font-weight: 400; - } - } +.mt5 { + margin-top: 5px !important; } -.btn-origin{ - display: inline-block; +.mt10 { + margin-top: 10px !important; +} + +.mb5 { + margin-bottom: 5px !important; +} + +.mb10 { + margin-bottom: 10px !important; +} + +.mr5 { + margin-right: 5px !important; +} + +.mr10 { + margin-right: 10px !important; +} + +.ml5 { + margin-left: 5px !important; +} + +.ml10 { + margin-left: 10px !important; +} + +// button +.btn-frame { + display: inline-block; + padding: 0 7px; + height: 34px; + line-height: 34px; + border-radius: 2px; + color: #fff; + font-size: 12px; + font-weight: 400; + border: 1px solid #000; + text-align: center; + font-family: 'Pretendard', sans-serif; + transition: all .17s ease-in-out; + cursor: pointer; + + &.block { + width: 100%; + } + + &.small { + font-family: 'Noto Sans JP', sans-serif; height: 30px; - padding: 0 14px; - border-radius: 2px; - background-color: #101010; - color: #fff; + line-height: 30px; font-size: 13px; - font-weight: 400; - transition: all .15s ease-in-out; - &.navy{ - background-color: #304961; - &:hover{ - background-color: #1083E3; - } + } + + &.deepgray { + background-color: #2C2C2C; + border: 1px solid #484848; + } + + &.gray { + background-color: #3C3C3C; + border: 1px solid #545454; + } + + &.dark { + background-color: #1C1C1C; + border: 1px solid #484848; + } + + &.modal { + font-family: 'Noto Sans JP', sans-serif; + background-color: #272727; + border: 1px solid #484848; + color: #aaa; + + &:hover { + background-color: #1083E3; + border: 1px solid #1083E3; + color: #fff; + font-weight: 500; } - &.grey{ - background-color: #94A0AD; - &:hover{ - background-color: #607F9A; - } + } + + &.sub-tab { + height: 30px; + padding: 0 10px; + line-height: 28px; + font-family: 'Noto Sans JP', sans-serif; + background-color: #2D2D2D; + border: 1px solid #393939; + color: #aaa; + + &.act, + &:hover { + background-color: #414E6C; + border: 1px solid #414E6C; + color: #fff; + font-weight: 500; } + } + + &:hover, + &.act { + background-color: #1083E3; + border: 1px solid #1083E3; + color: #fff; + font-weight: 500; + } + + &.block { + display: block; + width: 100%; + } + + &.ico-flx { + display: flex; + align-items: center; + + .ico { + margin-right: 10px; + } + + &:hover, + &.act { + font-weight: 400; + } + } +} + +.btn-origin { + display: inline-block; + height: 30px; + padding: 0 14px; + border-radius: 2px; + background-color: #101010; + color: #fff; + font-size: 13px; + font-weight: 400; + transition: all .15s ease-in-out; + + &.navy { + background-color: #304961; + + &:hover { + background-color: #1083E3; + } + } + + &.grey { + background-color: #94A0AD; + + &:hover { + background-color: #607F9A; + } + } } // select -.sort-select{ - position: relative; - display: inline-block; - min-width: 100px; - height: 30px; - line-height: 30px; - padding: 0 10px; +.sort-select { + position: relative; + display: inline-block; + min-width: 100px; + height: 30px; + line-height: 30px; + padding: 0 10px; + background-color: #373737; + border: 1px solid #3F3F3F; + border-radius: 2px; + border-top-left-radius: 2px; + color: #fff; + cursor: pointer; + + p { + font-size: 13px; + color: #fff; + height: 100%; + } + + .select-item-wrap { + position: absolute; + top: 100%; + left: -1px; + clip-path: inset(0 0 100% 0); + width: calc(100% + 2px); + padding: 8px 0; background-color: #373737; border: 1px solid #3F3F3F; border-radius: 2px; - border-top-left-radius: 2px; - color: #fff; - cursor: pointer; - p{ - font-size: 13px; + transition: all 0.17s ease-in-out; + visibility: hidden; + + .select-item { + display: flex; + align-items: center; + padding: 8px 20px; + line-height: 1.4; + transition: all .17s ease-in-out; + + button { + font-size: 12px; color: #fff; - height: 100%; + line-height: 1.4; + } + + &:hover { + background-color: #2C2C2C; + } } - .select-item-wrap{ - position: absolute; - top: 100%; - left: -1px; - clip-path:inset(0 0 100% 0); - width: calc(100% + 2px); - padding: 8px 0; - background-color: #373737; - border: 1px solid #3F3F3F; - border-radius: 2px; - transition: all 0.17s ease-in-out; - visibility: hidden; - .select-item{ - display: flex; - align-items: center; - padding: 8px 20px; - line-height: 1.4; - transition: all .17s ease-in-out; - button{ - font-size: 12px; - color: #fff; - line-height: 1.4; - } - &:hover{ - background-color: #2C2C2C; - } - } + } + + &::after { + content: ''; + position: absolute; + top: 50%; + right: 7px; + transform: translateY(-50%); + width: 10px; + height: 6px; + background: url(/static/images/common/select-arr.svg) no-repeat center; + background-size: cover; + transition: all .17s ease-in-out; + } + + &.active { + .select-item-wrap { + clip-path: inset(0 0 0 0); + visibility: visible; } - &::after{ - content: ''; - position: absolute; - top: 50%; - right: 7px; - transform: translateY(-50%); - width: 10px; - height: 6px; - background: url(/static/images/common/select-arr.svg) no-repeat center; - background-size: cover; - transition: all .17s ease-in-out; - } - &.active{ - .select-item-wrap{ - clip-path: inset(0 0 0 0); - visibility: visible; - } - &:after{ - transform: translateY(-50%) rotate(-180deg); - } + + &:after { + transform: translateY(-50%) rotate(-180deg); } + } } -.select-light{ - position: relative; - display: block; - width: 100%; - height: 30px; - background: #FFF url(../../public/static/images/common/select_light_arr.svg) calc(100% - 11px) center no-repeat; - background-size: 10px 6px; - border: 1px solid #eee; - padding: 0 30px 0 10px; - font-size: 13px; - color: #45576F; - font-family: 'Noto Sans JP', sans-serif; - cursor: pointer; - &:disabled{ - opacity: 1; - background-color: #FAFAFA; - color: #999; - cursor: default; - } - &.black{ - color: #101010; - } - &.dark{ - background: #323234 url(../../public/static/images/common/select_dark_arr.svg) calc(100% - 11px) center no-repeat; - color: #898989; - font-size: 12px; - border-radius: 2px; - border: none; - } +.select-light { + position: relative; + display: block; + width: 100%; + height: 30px; + background: #FFF url(../../public/static/images/common/select_light_arr.svg) calc(100% - 11px) center no-repeat; + background-size: 10px 6px; + border: 1px solid #eee; + padding: 0 30px 0 10px; + font-size: 13px; + color: #45576F; + font-family: 'Noto Sans JP', sans-serif; + cursor: pointer; + + &:disabled { + opacity: 1; + background-color: #FAFAFA; + color: #999; + cursor: default; + } + + &.black { + color: #101010; + } + + &.dark { + background: #323234 url(../../public/static/images/common/select_dark_arr.svg) calc(100% - 11px) center no-repeat; + color: #898989; + font-size: 12px; + border-radius: 2px; + border: none; + } } // input -.form-input{ - label{ - display: block; - color: #aaa; - font-size: 12px; - font-weight: 500; - margin-bottom: 10px; - } -} -input[type=number], -input[type=text]{ - &.input-origin{ - display: inline-block; - height: 30px; - line-height: 30px; - border-radius: 2px; - background-color: #323234; - color: #fff; - font-size: 12px; - font-weight: 500; - font-family: 'Pretendard', sans-serif; - padding: 0 10px; - letter-spacing: 0px; - text-align: right; - &::placeholder{ - opacity: 1; - font-size: 12px; - letter-spacing: 0px; - } - &.block{ - width: 100%; - } - } - &.input-light{ - display: block; - width: 100%; - height: 30px; - padding: 0 10px; - border: 1px solid #eee; - border-radius: 2px; - background-color: #fff; - font-family: 'Noto Sans JP', sans-serif; - font-size: 13px; - color: #45576F; - font-weight: normal; - transition: border-color .17s ease-in-out; - text-align: left; - &:read-only{ - background-color: #FAFAFA; - color: #999999; - } - } +.form-input { + label { + display: block; + color: #aaa; + font-size: 12px; + font-weight: 500; + margin-bottom: 10px; + } } +input[type=number], +input[type=text] { + &.input-origin { + display: inline-block; + height: 30px; + line-height: 30px; + border-radius: 2px; + background-color: #323234; + color: #fff; + font-size: 12px; + font-weight: 500; + font-family: 'Pretendard', sans-serif; + padding: 0 10px; + letter-spacing: 0px; + text-align: right; + + &::placeholder { + opacity: 1; + font-size: 12px; + letter-spacing: 0px; + } + + &.block { + width: 100%; + } + } + + &.input-light { + display: block; + width: 100%; + height: 30px; + padding: 0 10px; + border: 1px solid #eee; + border-radius: 2px; + background-color: #fff; + font-family: 'Noto Sans JP', sans-serif; + font-size: 13px; + color: #45576F; + font-weight: normal; + transition: border-color .17s ease-in-out; + text-align: left; + + &:read-only { + background-color: #FAFAFA; + color: #999999; + } + } +} // check-btn -.check-btn{ - display: flex; - align-items: center; - height: 30px; - background-color: #3A3A3A; - border-radius: 3px; - transition: all .17s ease-in-out; - .check-area{ - flex: none; - width: 30px; - height: 100%; - border-right: 1px solid #272727; - background: url(../../public/static/images/canvas/check-grey.svg)no-repeat center; - background-size: 11px 9px; +.check-btn { + display: flex; + align-items: center; + height: 30px; + background-color: #3A3A3A; + border-radius: 3px; + transition: all .17s ease-in-out; + + .check-area { + flex: none; + width: 30px; + height: 100%; + border-right: 1px solid #272727; + background: url(../../public/static/images/canvas/check-grey.svg) no-repeat center; + background-size: 11px 9px; + } + + .title-area { + padding: 0 10px; + font-size: 12px; + color: #898989; + font-weight: 400; + } + + &.block { + width: 100%; + } + + &:hover, + &.act { + background-color: #fff; + + .check-area { + border-right: 1px solid #101010; + background: url(../../public/static/images/canvas/check-black.svg) no-repeat center; } - .title-area{ - padding: 0 10px; - font-size: 12px; - color: #898989; - font-weight: 400; - } - &.block{ - width: 100%; - } - &:hover, - &.act{ - background-color: #fff; - .check-area{ - border-right: 1px solid #101010; - background: url(../../public/static/images/canvas/check-black.svg)no-repeat center; - } - .title-area{ - color: #101010; - font-weight: 600; - } + + .title-area { + color: #101010; + font-weight: 600; } + } } // arr-btn -.arr-btn{ - display: block; - height: 30px; - border-radius: 3px; - background-color: #3A3A3A; - padding: 0 11px; - text-align: left; - transition: all .17s ease-in-out; - span{ - position: relative; - font-size: 12px; - color: #898989; - font-weight: 400; - padding-right: 15px; - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 5px; - height: 8px; - background: url(../../public/static/images/canvas/arr_btn_ico.svg)no-repeat center; - } +.arr-btn { + display: block; + height: 30px; + border-radius: 3px; + background-color: #3A3A3A; + padding: 0 11px; + text-align: left; + transition: all .17s ease-in-out; + + span { + position: relative; + font-size: 12px; + color: #898989; + font-weight: 400; + padding-right: 15px; + + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 5px; + height: 8px; + background: url(../../public/static/images/canvas/arr_btn_ico.svg) no-repeat center; } + } + + &:hover, + &.act { + background-color: #fff; + + span { + color: #101010; + font-weight: 500; + + &:after { + background: url(../../public/static/images/canvas/arr_btn_ico_black.svg) no-repeat center; + } + } + } + + &.dark { + text-align: center; + background-color: #272727; + border: 1px solid #484848; + + span { + color: #Fff; + + &:after { + background: url(../../public/static/images/canvas/arr_btn_ico_white.svg) no-repeat center; + } + } + &:hover, - &.act{ - background-color: #fff; - span{ - color: #101010; - font-weight: 500; - &:after{ - background: url(../../public/static/images/canvas/arr_btn_ico_black.svg)no-repeat center; - } - } - } - &.dark{ - text-align: center; - background-color: #272727; - border: 1px solid #484848; - span{ - color: #Fff; - &:after{ - background: url(../../public/static/images/canvas/arr_btn_ico_white.svg)no-repeat center; - } - } - &:hover, - &.act{ - background-color: #1083E3; - border: 1px solid #1083E3; - } + &.act { + background-color: #1083E3; + border: 1px solid #1083E3; } + } } // radio .d-check-radio, -.d-check-box{ - line-height: 1.1; +.d-check-box { + line-height: 1.1; + cursor: pointer; + + input[type=checkbox], + input[type=radio] { + position: static; + margin-left: 0; cursor: pointer; - input[type=checkbox], - input[type=radio]{ - position: static; - margin-left: 0; - cursor: pointer; - opacity: 0; - z-index: 1; - flex: 0 0 auto; + opacity: 0; + z-index: 1; + flex: 0 0 auto; + } + + label { + position: relative; + padding-left: 10px; + margin-bottom: 0; + word-break: break-all; + line-height: 1.2; + display: inline; + vertical-align: top; + color: #fff; + font-size: 13px; + font-weight: 400; + cursor: pointer; + } + + &.light { + label { + color: #45576F; } - label{ - position: relative; - padding-left: 10px; - margin-bottom: 0; - word-break: break-all; - line-height: 1.2; - display: inline; - vertical-align: top; - color: #fff; - font-size: 13px; - font-weight: 400; - cursor: pointer; - } - &.light{ - label{ - color: #45576F; - } - } - &.no-text{ - label{ - padding-left: 0; - } + } + + &.no-text { + label { + padding-left: 0; } + } } .d-check-radio { - label{ - &::before{ - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 17px; - height: 17px; - top:2px; - left: 0; - margin-left: -12px; - border: 1px solid #999999; - border-radius: 100%; - background-color: transparent; - text-align:center; - font-size:13px; - line-height:1.4; - transition: border 0.15s ease-in-out, color 0.15s ease-in-out; - } - &::after{ - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 9px; - height: 9px; - top:6px; - left: 4px; - margin-left: -12px; - border: none; - border-radius: 100%; - background-color: #fff; - text-align:center; - font-size:13px; - line-height:1.4; - opacity: 0; - visibility: hidden; - transition: opacity 0.15s ease-in-out, color 0.15s ease-in-out; - } + label { + &::before { + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 17px; + height: 17px; + top: 2px; + left: 0; + margin-left: -12px; + border: 1px solid #999999; + border-radius: 100%; + background-color: transparent; + text-align: center; + font-size: 13px; + line-height: 1.4; + transition: border 0.15s ease-in-out, color 0.15s ease-in-out; } - &.light{ - label{ - &:before{ - border-color: #D6D6D7; - } - &:after{ - background-color: #697C8F; - } - } + + &::after { + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 9px; + height: 9px; + top: 6px; + left: 4px; + margin-left: -12px; + border: none; + border-radius: 100%; + background-color: #fff; + text-align: center; + font-size: 13px; + line-height: 1.4; + opacity: 0; + visibility: hidden; + transition: opacity 0.15s ease-in-out, color 0.15s ease-in-out; } - input[type=radio]:checked + label::after{ - opacity: 1; - visibility: visible; + } + + &.light { + label { + &:before { + border-color: #D6D6D7; + } + + &:after { + background-color: #697C8F; + } } - &.pop{ - label{ - &:before{ - width: 16px; - height: 16px; - border-color: #fff; - } - &:after{ - width: 8px; - height: 8px; - background-color: #fff; - } - } + } + + input[type=radio]:checked + label::after { + opacity: 1; + visibility: visible; + } + + &.pop { + label { + &:before { + width: 16px; + height: 16px; + border-color: #fff; + } + + &:after { + width: 8px; + height: 8px; + background-color: #fff; + } } + } } // check-box -.d-check-box{ - label{ - &::before{ - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 17px; - height: 17px; - top: 2px; - left: 0; - margin-left: -12px; - border: 1px solid #D6D6D7; - background-color: transparent; - transition: border 0.15s ease-in-out, color 0.15s ease-in-out; - } - &:after{ - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 16px; - height: 16px; - top:0; - left: 0; - margin-left: -.8rem; - transition: border 0.05s ease-in-out, color 0.05s ease-in-out; - } +.d-check-box { + label { + &::before { + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 17px; + height: 17px; + top: 2px; + left: 0; + margin-left: -12px; + border: 1px solid #D6D6D7; + background-color: transparent; + transition: border 0.15s ease-in-out, color 0.15s ease-in-out; } - input[type=checkbox]:checked + label::after{ - content: ""; - display: inline-block; - position: absolute; - top: 1px; - left: -1px; - width: 5px; - height: 8px; - border: 2px solid #697C8F; - border-left: none; - border-top: none; - transform: translate(7.75px,4.5px) rotate(45deg); - -ms-transform: translate(7.75px,4.5px) rotate(45deg); + + &:after { + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 16px; + height: 16px; + top: 0; + left: 0; + margin-left: -.8rem; + transition: border 0.05s ease-in-out, color 0.05s ease-in-out; } - &.pop{ - input[type=checkbox]:checked + label::after{ - border-color: #fff; - } + } + + input[type=checkbox]:checked + label::after { + content: ""; + display: inline-block; + position: absolute; + top: 1px; + left: -1px; + width: 5px; + height: 8px; + border: 2px solid #697C8F; + border-left: none; + border-top: none; + transform: translate(7.75px, 4.5px) rotate(45deg); + -ms-transform: translate(7.75px, 4.5px) rotate(45deg); + } + + &.pop { + input[type=checkbox]:checked + label::after { + border-color: #fff; } + } } // date-picker -.date-picker{ - svg{display: none;} - .react-datepicker-wrapper{ - width: 100%; - } - input[type=text]{ - display: block; - width: 100%; - height: 30px; - padding: 0 34px 0 10px; - border-radius: 2px; - border: 1px solid #eee; - font-size: 13px; - color: #45576F; - font-weight: normal; - font-family: 'Noto Sans JP', sans-serif; - background: #fff url(../../public/static/images/common/datepicker.svg) calc(100% - 11px) center no-repeat; - background-size: 14px 15px; - cursor: pointer; - } +.date-picker { + svg { + display: none; + } + + .react-datepicker-wrapper { + width: 100%; + } + + input[type=text] { + display: block; + width: 100%; + height: 30px; + padding: 0 34px 0 10px; + border-radius: 2px; + border: 1px solid #eee; + font-size: 13px; + color: #45576F; + font-weight: normal; + font-family: 'Noto Sans JP', sans-serif; + background: #fff url(../../public/static/images/common/datepicker.svg) calc(100% - 11px) center no-repeat; + background-size: 14px 15px; + cursor: pointer; + } } \ No newline at end of file From c28f798038810cd06935562c749719ce4db07dc2 Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 30 Sep 2024 13:30:13 +0900 Subject: [PATCH 007/152] =?UTF-8?q?title=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outerlinesetting/WallLineSetting.jsx | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx index cff90c61..0cba88c2 100644 --- a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx @@ -55,19 +55,22 @@ export default function WallLineSetting(props) { {getMessage('modal.cover.outline.diagonal')} - {type === OUTER_LINE_TYPE.OUTER_LINE ? ( - - ) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? ( - - ) : type === OUTER_LINE_TYPE.DOUBLE_PITCH ? ( - - ) : type === OUTER_LINE_TYPE.ANGLE ? ( - - ) : type === OUTER_LINE_TYPE.DIAGONAL_LINE ? ( - - ) : ( - <> - )} +
+
{getMessage('modal.cover.outline.setting')}
+ {type === OUTER_LINE_TYPE.OUTER_LINE ? ( + + ) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? ( + + ) : type === OUTER_LINE_TYPE.DOUBLE_PITCH ? ( + + ) : type === OUTER_LINE_TYPE.ANGLE ? ( + + ) : type === OUTER_LINE_TYPE.DIAGONAL_LINE ? ( + + ) : ( + <> + )} +
diff --git a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.js b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.js index 1ff975a7..c4950666 100644 --- a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.js +++ b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.js @@ -1,14 +1,18 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' import { useMessage } from '@/hooks/useMessage' -export default function PropertiesSetting() { +export default function PropertiesSetting(props) { const { getMessage } = useMessage() + const { setShowPropertiesSettingModal } = props + return (

{getMessage('modal.canvas.setting.wallline.properties.setting')}

- +
{getMessage('modal.canvas.setting.wallline.properties.setting.info')}
From 8f3f74b60856d8847b84746e6882bc2e0e12dbdb Mon Sep 17 00:00:00 2001 From: Daseul Kim Date: Mon, 30 Sep 2024 14:26:36 +0900 Subject: [PATCH 009/152] =?UTF-8?q?refactor:=20canvas=20status=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=ED=95=A8=EC=88=98=EC=97=90=20userId=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/CanvasLayout.jsx | 4 +++- src/hooks/usePlan.js | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx index 5d3817a2..e71c01f5 100644 --- a/src/components/floor-plan/CanvasLayout.jsx +++ b/src/components/floor-plan/CanvasLayout.jsx @@ -6,6 +6,7 @@ import CanvasFrame from './CanvasFrame' import { usePlan } from '@/hooks/usePlan' import { globalLocaleStore } from '@/store/localeAtom' import { currentCanvasPlanState, initCanvasPlansState } from '@/store/canvasAtom' +import { sessionStore } from '@/store/commonAtom' export default function CanvasLayout() { const [objectNo, setObjectNo] = useState('test123240822001') // 이후 삭제 필요 @@ -14,6 +15,7 @@ export default function CanvasLayout() { const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) const globalLocaleState = useRecoilValue(globalLocaleStore) + const sessionState = useRecoilValue(sessionStore) const { getCanvasByObjectNo } = usePlan() @@ -63,7 +65,7 @@ export default function CanvasLayout() { } useEffect(() => { - getCanvasByObjectNo(objectNo).then((res) => { + getCanvasByObjectNo(sessionState.userId, objectNo).then((res) => { console.log('canvas 목록 ', res) if (res.length > 0) { setInitCanvasPlans(res) diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index 55854cb7..cf566b3f 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -12,8 +12,6 @@ export function usePlan() { const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) const { getMessage } = useMessage() const { get, promisePost, promisePut } = useAxios() - const [sessionState, setSessionState] = useRecoilState(sessionStore) - const [userId, setUserId] = useState(sessionState.userId) /** * 마우스 포인터의 가이드라인을 제거합니다. @@ -137,7 +135,7 @@ export function usePlan() { /** * objectNo에 해당하는 canvas 목록을 조회하는 함수 */ - const getCanvasByObjectNo = async (objectNo) => { + const getCanvasByObjectNo = async (userId, objectNo) => { return get({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}/${userId}` }).then((res) => res.map((item) => ({ id: item.id, From 0bf1fbfe5683d1faf6a833c1d7404f7a48e1643f Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Mon, 30 Sep 2024 14:48:02 +0900 Subject: [PATCH 010/152] =?UTF-8?q?=EC=99=B8=EB=B2=BD=EC=84=A0=20=EA=B7=B8?= =?UTF-8?q?=EB=A6=AC=EA=B8=B0=20=3D>=20=EC=99=B8=EB=B2=BD=EC=84=A0=20?= =?UTF-8?q?=EC=86=8D=EC=84=B1=20=EC=84=A4=EC=A0=95=20=EC=9E=91=EC=97=85?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/common.js | 3 +- src/components/floor-plan/FloorPlan.jsx | 1 + .../modal/outerlinesetting/Angle.jsx | 39 +- .../modal/outerlinesetting/Diagonal.jsx | 128 +++++- .../modal/outerlinesetting/DoublePitch.jsx | 173 +++++++- .../modal/outerlinesetting/OuterLineWall.jsx | 40 +- ...ertiesSetting.js => PropertiesSetting.jsx} | 21 +- .../modal/outerlinesetting/RightAngle.jsx | 101 ++++- .../outerlinesetting/WallLineSetting.jsx | 115 +++++- src/hooks/roofcover/useOuterLineWall.js | 371 ++++++++++++++---- src/hooks/roofcover/usePropertiesSetting.js | 89 +++++ src/hooks/useAdsorptionPoint.js | 2 +- src/hooks/useCanvas.js | 9 +- src/hooks/useDotLineGrid.js | 1 + src/hooks/useEvent.js | 44 ++- src/hooks/useLine.js | 1 + 16 files changed, 974 insertions(+), 164 deletions(-) rename src/components/floor-plan/modal/outerlinesetting/{PropertiesSetting.js => PropertiesSetting.jsx} (56%) create mode 100644 src/hooks/roofcover/usePropertiesSetting.js diff --git a/src/common/common.js b/src/common/common.js index 84cf60a3..f9ca6fff 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -53,8 +53,9 @@ export const Mode = { export const LINE_TYPE = { WALLLINE: { /** - * 처마 / 캐라바 / 벽 / 팔작지붕 / 반절처 / 한쪽흐름 + * 없음 / 처마 / 캐라바 / 벽 / 팔작지붕 / 반절처 / 한쪽흐름 */ + DEFAULT: 'default', EAVES: 'eaves', GABLE: 'gable', WALL: 'wall', diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx index 9f7c6641..55b700c1 100644 --- a/src/components/floor-plan/FloorPlan.jsx +++ b/src/components/floor-plan/FloorPlan.jsx @@ -34,6 +34,7 @@ export default function FloorPlan() { const outlineProps = { setShowOutlineModal, + setShowPropertiesSettingModal, } const modalProps = { diff --git a/src/components/floor-plan/modal/outerlinesetting/Angle.jsx b/src/components/floor-plan/modal/outerlinesetting/Angle.jsx index ca3ea288..83985016 100644 --- a/src/components/floor-plan/modal/outerlinesetting/Angle.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/Angle.jsx @@ -1,8 +1,11 @@ import Image from 'next/image' import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' -export default function Angle() { +export default function Angle({ props }) { const { getMessage } = useMessage() + const { angle1, setAngle1, angle1Ref, length1, setLength1, length1Ref } = props + return ( <>
@@ -11,16 +14,40 @@ export default function Angle() {
{getMessage('modal.cover.outline.angle')}
- + onlyNumberWithDotInputChange(e, setAngle1)} + placeholder="45" + />
- +
- {getMessage('modal.cover.outline.arrow')} + {getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength1)} + placeholder="3000" + />
- +
diff --git a/src/components/floor-plan/modal/outerlinesetting/Diagonal.jsx b/src/components/floor-plan/modal/outerlinesetting/Diagonal.jsx index 9ae9f02e..84c25329 100644 --- a/src/components/floor-plan/modal/outerlinesetting/Diagonal.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/Diagonal.jsx @@ -1,7 +1,24 @@ import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange } from '@/util/input-utils' -export default function Diagonal() { +export default function Diagonal({ props }) { const { getMessage } = useMessage() + + const { + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + outerLineDiagonalLength, + setOuterLineDiagonalLength, + outerLineDiagonalLengthRef, + arrow1, + setArrow1, + arrow2, + setArrow2, + } = props return ( <>
@@ -13,26 +30,77 @@ export default function Diagonal() { {getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setOuterLineDiagonalLength)} + placeholder="3000" + />
- +
{getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength1)} + placeholder="3000" + />
- +
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
@@ -40,16 +108,48 @@ export default function Diagonal() {
{getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength2)} + readOnly={true} + placeholder="3000" + />
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
diff --git a/src/components/floor-plan/modal/outerlinesetting/DoublePitch.jsx b/src/components/floor-plan/modal/outerlinesetting/DoublePitch.jsx index ea386d4b..5bfa5950 100644 --- a/src/components/floor-plan/modal/outerlinesetting/DoublePitch.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/DoublePitch.jsx @@ -1,7 +1,48 @@ import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' +import { getDegreeByChon } from '@/util/canvas-util' -export default function DoublePitch() { +export default function DoublePitch({ props }) { const { getMessage } = useMessage() + const { + angle1, + setAngle1, + angle1Ref, + angle2, + setAngle2, + angle2Ref, + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + arrow1Ref, + arrow2Ref, + } = props + + const getLength2 = () => { + const angle1Value = angle1Ref.current.value + const angle2Value = angle2Ref.current.value + const length1Value = length1Ref.current.value + + const arrow1Value = arrow1Ref.current + const arrow2Value = arrow2Ref.current + + if (angle1Value !== 0 && length1Value !== 0 && angle2Value !== 0 && arrow1Value !== '') { + const radian1 = (getDegreeByChon(angle1Value) * Math.PI) / 180 + + const radian2 = (getDegreeByChon(angle2Value) * Math.PI) / 180 + return Math.floor((Math.tan(radian1) * length1Value) / Math.tan(radian2)) + } + + return 0 + } + return ( <>
@@ -9,26 +50,70 @@ export default function DoublePitch() {
{getMessage('modal.cover.outline.angle')}
- + onlyNumberWithDotInputChange(e, setAngle1)} + placeholder="45" + />
- +
{getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength1)} + placeholder="3000" + />
- +
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
@@ -38,26 +123,80 @@ export default function DoublePitch() {
{getMessage('modal.cover.outline.angle')}
- + { + onlyNumberWithDotInputChange(e, setAngle2) + console.log(getLength2()) + setLength2(getLength2()) + }} + placeholder="45" + />
- +
{getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength2)} + readOnly={true} + placeholder="3000" + />
- +
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
diff --git a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx index 9dfa85c8..a3493f17 100644 --- a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx @@ -1,12 +1,12 @@ 'use client' import { useMessage } from '@/hooks/useMessage' -import { useOuterLineWall } from '@/hooks/roofcover/useOuterLineWall' import { onlyNumberInputChange } from '@/util/input-utils' -export default function OuterLineWall(props) { +export default function OuterLineWall({ props }) { const { getMessage } = useMessage() - const { length1, setLength1, length1Ref, arrow1, setArrow1 } = useOuterLineWall() + + const { length1, setLength1, length1Ref, arrow1, setArrow1 } = props return (
@@ -22,15 +22,39 @@ export default function OuterLineWall(props) { placeholder="3000" />
- +
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
diff --git a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.js b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx similarity index 56% rename from src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.js rename to src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx index c4950666..0120f6a4 100644 --- a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.js +++ b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx @@ -1,10 +1,13 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' import { useMessage } from '@/hooks/useMessage' +import { usePropertiesSetting } from '@/hooks/roofcover/usePropertiesSetting' export default function PropertiesSetting(props) { const { getMessage } = useMessage() const { setShowPropertiesSettingModal } = props - + + const { handleSetEaves, handleSetGable, handleRollback, handleFix } = usePropertiesSetting() + return (
@@ -19,13 +22,21 @@ export default function PropertiesSetting(props) {
{getMessage('setting')}
- - + +
- - + +
diff --git a/src/components/floor-plan/modal/outerlinesetting/RightAngle.jsx b/src/components/floor-plan/modal/outerlinesetting/RightAngle.jsx index 815ab087..306a09f0 100644 --- a/src/components/floor-plan/modal/outerlinesetting/RightAngle.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/RightAngle.jsx @@ -1,24 +1,63 @@ import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange } from '@/util/input-utils' -export default function RightAngle() { +export default function RightAngle({ props }) { const { getMessage } = useMessage() + const { length1, setLength1, length1Ref, length2, setLength2, length2Ref, arrow1, setArrow1, arrow2, setArrow2 } = props return (
{getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength1)} + placeholder="3000" + />
- +
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
@@ -26,17 +65,53 @@ export default function RightAngle() {
{getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength2)} + placeholder="3000" + />
- +
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
diff --git a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx index 0cba88c2..8a9c1979 100644 --- a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx @@ -11,9 +11,102 @@ import DoublePitch from '@/components/floor-plan/modal/outerlinesetting/DoublePi import Diagonal from '@/components/floor-plan/modal/outerlinesetting/Diagonal' export default function WallLineSetting(props) { - const { setShowOutlineModal } = props + const { setShowOutlineModal, setShowPropertiesSettingModal } = props const { getMessage } = useMessage() - const { type, setType, handleFix, handleRollback } = useOuterLineWall() + const { + length1, + setLength1, + length2, + setLength2, + length1Ref, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + angle1, + setAngle1, + angle1Ref, + angle2, + setAngle2, + angle2Ref, + type, + setType, + arrow1Ref, + arrow2Ref, + outerLineDiagonalLength, + setOuterLineDiagonalLength, + outerLineDiagonalLengthRef, + handleRollback, + handleFix, + } = useOuterLineWall() + + const outerLineProps = { + length1, + setLength1, + length1Ref, + arrow1, + setArrow1, + } + + const rightAngleProps = { + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + } + + const doublePitchProps = { + angle1, + setAngle1, + angle1Ref, + angle2, + setAngle2, + angle2Ref, + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + arrow1Ref, + arrow2Ref, + } + + const angleProps = { + angle1, + setAngle1, + angle1Ref, + length1, + setLength1, + length1Ref, + } + + const diagonalLineProps = { + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + outerLineDiagonalLength, + setOuterLineDiagonalLength, + outerLineDiagonalLengthRef, + arrow1, + setArrow1, + arrow2, + setArrow2, + } return ( @@ -58,15 +151,15 @@ export default function WallLineSetting(props) {
{getMessage('modal.cover.outline.setting')}
{type === OUTER_LINE_TYPE.OUTER_LINE ? ( - + ) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? ( - + ) : type === OUTER_LINE_TYPE.DOUBLE_PITCH ? ( - + ) : type === OUTER_LINE_TYPE.ANGLE ? ( - + ) : type === OUTER_LINE_TYPE.DIAGONAL_LINE ? ( - + ) : ( <> )} @@ -75,7 +168,13 @@ export default function WallLineSetting(props) { -
diff --git a/src/hooks/roofcover/useOuterLineWall.js b/src/hooks/roofcover/useOuterLineWall.js index 355eca16..0f1e4f41 100644 --- a/src/hooks/roofcover/useOuterLineWall.js +++ b/src/hooks/roofcover/useOuterLineWall.js @@ -1,5 +1,5 @@ import { useEffect, useRef } from 'react' -import { distanceBetweenPoints } from '@/util/canvas-util' +import { distanceBetweenPoints, getDegreeByChon } from '@/util/canvas-util' import { useRecoilState, useRecoilValue } from 'recoil' import { adsorptionPointAddModeState, @@ -16,14 +16,17 @@ import { useTempGrid } from '@/hooks/useTempGrid' import { usePolygon } from '@/hooks/usePolygon' import { outerLineAngle1State, + outerLineAngle2State, outerLineArrow1State, outerLineArrow2State, + outerLineDiagonalState, outerLineLength1State, outerLineLength2State, outerLinePointsState, outerLineTypeState, } from '@/store/outerLineAtom' import { calculateAngle } from '@/util/qpolygon-utils' +import { fabric } from 'fabric' export function useOuterLineWall() { const canvas = useRecoilValue(canvasState) @@ -33,6 +36,7 @@ export function useOuterLineWall() { const { addLine, removeLine } = useLine() const { tempGridMode } = useTempGrid() const { addPolygonByLines } = usePolygon() + const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState) const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState) const adsorptionPointMode = useRecoilValue(adsorptionPointModeState) @@ -42,28 +46,31 @@ export function useOuterLineWall() { const length1Ref = useRef(null) const length2Ref = useRef(null) const angle1Ref = useRef(null) + const angle2Ref = useRef(null) const [length1, setLength1] = useRecoilState(outerLineLength1State) const [length2, setLength2] = useRecoilState(outerLineLength2State) const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State) const [arrow2, setArrow2] = useRecoilState(outerLineArrow2State) const [points, setPoints] = useRecoilState(outerLinePointsState) const [type, setType] = useRecoilState(outerLineTypeState) + const [angle1, setAngle1] = useRecoilState(outerLineAngle1State) + const [angle2, setAngle2] = useRecoilState(outerLineAngle2State) + const [outerLineDiagonalLength, setOuterLineDiagonalLength] = useRecoilState(outerLineDiagonalState) const arrow1Ref = useRef(arrow1) const arrow2Ref = useRef(arrow2) + const outerLineDiagonalLengthRef = useRef(null) + const isFix = useRef(false) - const [angle1, setAngle1] = useRecoilState(outerLineAngle1State) + const closeModalFn = useRef(null) + useEffect(() => { if (adsorptionPointAddMode || tempGridMode) { return } - removeMouseEvent('mouse:down', mouseDown) addCanvasMouseEventListener('mouse:down', mouseDown) clear() - return () => { - removeAllMouseEventListeners() - } }, [verticalHorizontalMode, points, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, interval, tempGridMode]) useEffect(() => { @@ -75,9 +82,8 @@ export function useOuterLineWall() { }, [arrow2]) useEffect(() => { - removeAllDocumentEventListeners() - addDocumentEventListener('keydown', document, keydown[type]) clear() + addDocumentEventListener('keydown', document, keydown[type]) }, [type]) const clear = () => { @@ -88,6 +94,9 @@ export function useOuterLineWall() { setArrow2('') setAngle1(0) + setAngle2(0) + + setOuterLineDiagonalLength(0) } const mouseDown = (e) => { @@ -143,14 +152,13 @@ export function useOuterLineWall() { canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'startPoint')) - // point가 변경 될때마다 이벤트 리스너를 제거하고 다시 등록 - removeAllDocumentEventListeners() - addDocumentEventListener('keydown', document, keydown[type]) - if (points.length === 0) { + removeAllDocumentEventListeners() return } + addDocumentEventListener('keydown', document, keydown[type]) + if (points.length === 1) { const point = new fabric.Circle({ radius: 5, @@ -174,6 +182,13 @@ export function useOuterLineWall() { const lastPoint = points[points.length - 1] const firstPoint = points[0] + if (isFix.current) { + canvas?.renderAll() + closeModalFn.current(false) + removeAllMouseEventListeners() + removeAllDocumentEventListeners() + } + if (points.length < 3) { return } @@ -241,7 +256,7 @@ export function useOuterLineWall() { stroke: 'black', strokeWidth: 3, idx: idx, - selectable: false, + selectable: true, name: 'outerLine', }) } @@ -261,7 +276,26 @@ export function useOuterLineWall() { } // 직각 완료될 경우 확인 - const checkRightAngle = () => { + const checkRightAngle = (direction) => { + const activeElem = document.activeElement + + const canDirection = + direction === '↓' || direction === '↑' + ? arrow1Ref.current === '←' || arrow1Ref.current === '→' + : arrow1Ref.current === '↓' || arrow1Ref.current === '↑' + + if (activeElem === length1Ref.current || activeElem === angle1Ref.current) { + setArrow1(direction) + arrow1Ref.current = direction + length2Ref.current.focus() + } else if (activeElem === length2Ref.current || activeElem === angle2Ref.current) { + if (!canDirection) { + return + } + setArrow2(direction) + arrow2Ref.current = direction + } + const length1Num = Number(length1Ref.current.value) / 10 const length2Num = Number(length2Ref.current.value) / 10 @@ -332,6 +366,191 @@ export function useOuterLineWall() { } } + //이구배 완료될 경우 확인 ↓, ↑, ←, → + const checkDoublePitch = (direction) => { + const activeElem = document.activeElement + + const canDirection = + direction === '↓' || direction === '↑' + ? arrow1Ref.current === '←' || arrow1Ref.current === '→' + : arrow1Ref.current === '↓' || arrow1Ref.current === '↑' + + if (activeElem === length1Ref.current || activeElem === angle1Ref.current) { + setArrow1(direction) + arrow1Ref.current = direction + angle2Ref.current.focus() + } else if (activeElem === length2Ref.current || activeElem === angle2Ref.current) { + if (!canDirection) { + return + } + setArrow2(direction) + arrow2Ref.current = direction + } + + const angle1Value = angle1Ref.current.value + const angle2Value = angle2Ref.current.value + const length1Value = length1Ref.current.value + const length2Value = length2Ref.current.value + + const arrow1Value = arrow1Ref.current + const arrow2Value = arrow2Ref.current + + if (angle1Value !== 0 && length1Value !== 0 && angle2Value !== 0 && arrow1Value !== '' && arrow2Value !== '') { + if (arrow1Value === '↓' && arrow2Value === '→') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length1Value / 10, y: prev[prev.length - 1].y + length2Value / 10 }] + }) + } else if (arrow1Value === '↓' && arrow2Value === '←') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x - length1Value / 10, y: prev[prev.length - 1].y + length2Value / 10 }] + }) + } else if (arrow1Value === '↑' && arrow2Value === '→') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length1Value / 10, y: prev[prev.length - 1].y - length2Value / 10 }] + }) + } else if (arrow1Value === '↑' && arrow2Value === '←') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x - length1Value / 10, y: prev[prev.length - 1].y - length2Value / 10 }] + }) + } else if (arrow1Value === '→' && arrow2Value === '↓') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length2Value / 10, y: prev[prev.length - 1].y + length1Value / 10 }] + }) + } else if (arrow1Value === '→' && arrow2Value === '↑') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length2Value / 10, y: prev[prev.length - 1].y - length1Value / 10 }] + }) + } else if (arrow1Value === '←' && arrow2Value === '↓') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x - length2Value / 10, y: prev[prev.length - 1].y + length1Value / 10 }] + }) + } else if (arrow1Value === '←' && arrow2Value === '↑') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x - length2Value / 10, y: prev[prev.length - 1].y - length1Value / 10 }] + }) + } + + angle1Ref.current.focus() + } + } + + //대각선 완료될 경우 확인 + const checkDiagonal = (direction) => { + const activeElem = document.activeElement + + const canDirection = + direction === '↓' || direction === '↑' + ? arrow1Ref.current === '←' || arrow1Ref.current === '→' + : arrow1Ref.current === '↓' || arrow1Ref.current === '↑' + + if (activeElem === length1Ref.current) { + setArrow1(direction) + arrow1Ref.current = direction + } else if (activeElem === length2Ref.current || activeElem === angle2Ref.current) { + if (!canDirection) { + return + } + setArrow2(direction) + arrow2Ref.current = direction + } + + const diagonalLength = outerLineDiagonalLengthRef.current.value // 대각선 길이 + + const length1Value = length1Ref.current.value + + const arrow1Value = arrow1Ref.current + const arrow2Value = arrow2Ref.current + + const getLength2 = () => { + return Math.floor(Math.sqrt(diagonalLength ** 2 - length1Value ** 2)) + } + + const length2Value = getLength2() + + console.log(length2Value) + + if (diagonalLength !== 0 && length1Value !== 0 && arrow1Value !== '') { + setLength2(getLength2()) + length2Ref.current.focus() + } + + if (length1Value !== 0 && length2Value !== 0 && arrow1Value !== '' && arrow2Value !== '') { + if (arrow1Value === '↓' && arrow2Value === '→') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length2Value / 10, y: prev[prev.length - 1].y + length1Value / 10 }] + }) + } else if (arrow1Value === '↓' && arrow2Value === '←') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x - length2Value / 10, y: prev[prev.length - 1].y + length1Value / 10 }] + }) + } else if (arrow1Value === '↑' && arrow2Value === '→') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length2Value / 10, y: prev[prev.length - 1].y - length1Value / 10 }] + }) + } else if (arrow1Value === '↑' && arrow2Value === '←') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x - length2Value / 10, y: prev[prev.length - 1].y - length1Value / 10 }] + }) + } else if (arrow1Value === '→' && arrow2Value === '↓') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length1Value / 10, y: prev[prev.length - 1].y + length2Value / 10 }] + }) + } else if (arrow1Value === '→' && arrow2Value === '↑') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [ + ...prev, + { + x: prev[prev.length - 1].x + length1Value / 10, + y: prev[prev.length - 1].y - length2Value / 10, + }, + ] + }) + } + } + } + const keydown = { outerLine: (e) => { if (points.length === 0) { @@ -411,75 +630,52 @@ export function useOuterLineWall() { switch (key) { case 'Down': // IE/Edge에서 사용되는 값 case 'ArrowDown': { - if (activeElem === length1Ref.current) { - setArrow1('↓') - arrow1Ref.current = '↓' - length2Ref.current.focus() - } else if (activeElem === length2Ref.current) { - if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') { - break - } - setArrow2('↓') - arrow2Ref.current = '↓' - checkRightAngle() - } - + checkRightAngle('↓') break } case 'Up': // IE/Edge에서 사용되는 값 case 'ArrowUp': - if (activeElem === length1Ref.current) { - setArrow1('↑') - arrow1Ref.current = '↑' - length2Ref.current.focus() - } else if (activeElem === length2Ref.current) { - if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') { - break - } - setArrow2('↑') - arrow2Ref.current = '↑' - checkRightAngle() - } - + checkRightAngle('↑') break case 'Left': // IE/Edge에서 사용되는 값 case 'ArrowLeft': - if (activeElem === length1Ref.current) { - setArrow1('←') - arrow1Ref.current = '←' - length2Ref.current.focus() - } else if (activeElem === length2Ref.current) { - if (arrow1Ref.current === '←' || arrow1Ref.current === '→') { - break - } - setArrow2('←') - arrow2Ref.current = '←' - checkRightAngle() - } - + checkRightAngle('←') break case 'Right': // IE/Edge에서 사용되는 값 case 'ArrowRight': - if (activeElem === length1Ref.current) { - setArrow1('→') - arrow1Ref.current = '→' - length2Ref.current.focus() - } else if (activeElem === length2Ref.current) { - if (arrow1Ref.current === '←' || arrow1Ref.current === '→') { - break - } - setArrow2('→') - arrow2Ref.current = '→' - checkRightAngle() - } - + checkRightAngle('→') break } }, - leeGubae: (e) => { - console.log('leegubae') + doublePitch: (e) => { + if (points.length === 0) { + return + } + const key = e.key + switch (key) { + case 'Down': // IE/Edge에서 사용되는 값 + case 'ArrowDown': { + checkDoublePitch('↓') + break + } + case 'Up': // IE/Edge에서 사용되는 값 + case 'ArrowUp': + checkDoublePitch('↑') + break + case 'Left': // IE/Edge에서 사용되는 값 + case 'ArrowLeft': + checkDoublePitch('←') + break + case 'Right': // IE/Edge에서 사용되는 값 + case 'ArrowRight': + checkDoublePitch('→') + break + } }, angle: (e) => { + if (points.length === 0) { + return + } const key = e.key switch (key) { case 'Enter': { @@ -501,7 +697,30 @@ export function useOuterLineWall() { } }, diagonalLine: (e) => { - console.log('diagonalLine') + if (points.length === 0) { + return + } + + const key = e.key + switch (key) { + case 'Down': // IE/Edge에서 사용되는 값 + case 'ArrowDown': { + checkDiagonal('↓') + break + } + case 'Up': // IE/Edge에서 사용되는 값 + case 'ArrowUp': + checkDiagonal('↑') + break + case 'Left': // IE/Edge에서 사용되는 값 + case 'ArrowLeft': + checkDiagonal('←') + break + case 'Right': // IE/Edge에서 사용되는 값 + case 'ArrowRight': + checkDiagonal('→') + break + } }, } @@ -513,7 +732,7 @@ export function useOuterLineWall() { setPoints((prev) => prev.slice(0, prev.length - 1)) } - const handleFix = () => { + const handleFix = (fn) => { if (points.length < 3) { return } @@ -541,6 +760,9 @@ export function useOuterLineWall() { setPoints((prev) => { return [...prev, { x: prev[0].x, y: prev[0].y }] }) + + isFix.current = true + closeModalFn.current = fn } return { @@ -558,6 +780,15 @@ export function useOuterLineWall() { setArrow2, arrow1Ref, arrow2Ref, + angle1, + setAngle1, + angle1Ref, + angle2, + setAngle2, + angle2Ref, + outerLineDiagonalLength, + setOuterLineDiagonalLength, + outerLineDiagonalLengthRef, type, setType, handleFix, diff --git a/src/hooks/roofcover/usePropertiesSetting.js b/src/hooks/roofcover/usePropertiesSetting.js new file mode 100644 index 00000000..95800dfd --- /dev/null +++ b/src/hooks/roofcover/usePropertiesSetting.js @@ -0,0 +1,89 @@ +import { useEffect, useRef } from 'react' +import { useRecoilValue } from 'recoil' +import { canvasState } from '@/store/canvasAtom' +import { LINE_TYPE } from '@/common/common' + +export function usePropertiesSetting() { + const currentLine = useRef(null) + const canvas = useRecoilValue(canvasState) + + useEffect(() => { + initLineSetting() + }, []) + + useEffect(() => { + const lines = canvas?.getObjects().filter((obj) => obj.name === 'outerLine') + lines.forEach((line) => { + line.set({ + type: line.type, + stroke: line.type === LINE_TYPE.WALLLINE.EAVES ? '#45CD7D' : line.type === LINE_TYPE.WALLLINE.GABLE ? '#3FBAE6' : '#000000', + strokeWidth: 4, + }) + }) + }, [currentLine.current]) + + const handleSetEaves = () => { + currentLine.current.set({ + stroke: '#45CD7D', + strokeWidth: 4, + attributes: { + offset: 500, + type: LINE_TYPE.WALLLINE.EAVES, + pitch: 4, + }, + }) + + nextLineSetting() + } + + const handleSetGable = () => { + currentLine.current.set({ + type: LINE_TYPE.WALLLINE.GABLE, + stroke: '#3FBAE6', + strokeWidth: 4, + attributes: { + offset: 300, + type: LINE_TYPE.WALLLINE.GABLE, + }, + }) + + nextLineSetting() + } + + const initLineSetting = () => { + currentLine.current = canvas?.getObjects().filter((obj) => obj.name === 'outerLine')[0] + + currentLine.current.set({ + stroke: '#EA10AC', + strokeWidth: 4, + }) + + canvas?.renderAll() + } + + const nextLineSetting = () => { + // currentLine.current의 값은 currentLine.current의 idx 다음 값, 없을 경우는 null + currentLine.current = canvas?.getObjects().find((obj) => obj.idx === currentLine.current.idx + 1) + + if (!currentLine.current) { + canvas?.renderAll() + handleFix() + return + } + + currentLine.current = currentLine.current.set({ + stroke: '#EA10AC', + strokeWidth: 4, + }) + + canvas?.renderAll() + } + + const currentLineSetting = () => {} + + const handleRollback = () => {} + + const handleFix = () => {} + + return { handleSetEaves, handleSetGable, handleRollback, handleFix } +} diff --git a/src/hooks/useAdsorptionPoint.js b/src/hooks/useAdsorptionPoint.js index 44e2495b..49d49714 100644 --- a/src/hooks/useAdsorptionPoint.js +++ b/src/hooks/useAdsorptionPoint.js @@ -26,7 +26,7 @@ export function useAdsorptionPoint() { top: pointer.y - 3, x: pointer.x, y: pointer.y, - selectable: false, + selectable: true, name: 'adsorptionPoint', }) diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index 37ffdc5f..0f506fd3 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -36,6 +36,7 @@ export function useCanvas(id) { setCanvas(c) setCanvasForEvent(c) + attachDefaultEventOnCanvas() return () => { // c.dispose() @@ -45,7 +46,6 @@ export function useCanvas(id) { useEffect(() => { // canvas 사이즈가 변경되면 다시 - attachDefaultEventOnCanvas() }, [canvasSize]) useEffect(() => { @@ -91,6 +91,13 @@ export function useCanvas(id) { // settings for all canvas in the app fabric.Object.prototype.transparentCorners = false fabric.Object.prototype.id = uuidv4() + fabric.Object.prototype.selectable = true + fabric.Object.prototype.lockMovementX = true + fabric.Object.prototype.lockMovementY = true + fabric.Object.prototype.lockRotation = true + fabric.Object.prototype.lockScalingX = true + fabric.Object.prototype.lockScalingY = true + fabric.Object.prototype.cornerColor = '#2BEBC8' fabric.Object.prototype.cornerStyle = 'rect' fabric.Object.prototype.cornerStrokeColor = '#2BEBC8' diff --git a/src/hooks/useDotLineGrid.js b/src/hooks/useDotLineGrid.js index 34d82fa7..0c21c030 100644 --- a/src/hooks/useDotLineGrid.js +++ b/src/hooks/useDotLineGrid.js @@ -6,6 +6,7 @@ import { gridColorState } from '@/store/gridAtom' export function useDotLineGrid() { const canvas = useRecoilValue(canvasState) + const gridColor = useRecoilValue(gridColorState) const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState) const interval = useRecoilValue(dotLineIntervalSelector) // 가로 세로 간격 diff --git a/src/hooks/useEvent.js b/src/hooks/useEvent.js index 31a2cd8a..67ff8c44 100644 --- a/src/hooks/useEvent.js +++ b/src/hooks/useEvent.js @@ -1,24 +1,16 @@ import { useEffect, useRef } from 'react' import { useRecoilState, useRecoilValue } from 'recoil' -import { - adsorptionPointAddModeState, - adsorptionPointModeState, - adsorptionRangeState, - canvasState, - canvasZoomState, - currentMenuState, -} from '@/store/canvasAtom' +import { canvasState, canvasZoomState, currentMenuState } from '@/store/canvasAtom' import { fabric } from 'fabric' -import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util' +import { calculateDistance, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util' import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint' -import { useMouse } from '@/hooks/useMouse' import { useDotLineGrid } from '@/hooks/useDotLineGrid' import { useTempGrid } from '@/hooks/useTempGrid' export function useEvent() { const canvas = useRecoilValue(canvasState) const currentMenu = useRecoilValue(currentMenuState) - const keyboardEventListeners = useRef([]) + const documentEventListeners = useRef([]) const mouseEventListeners = useRef([]) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) @@ -30,9 +22,8 @@ export function useEvent() { if (!canvas) { return } - removeAllMouseEventListeners() removeAllDocumentEventListeners() - + removeAllMouseEventListeners() /** * wheelEvent */ @@ -193,13 +184,14 @@ export function useEvent() { } const addCanvasMouseEventListener = (eventType, handler) => { + canvas.off(eventType) canvas.on(eventType, handler) mouseEventListeners.current.push({ eventType, handler }) } const removeAllMouseEventListeners = () => { mouseEventListeners.current.forEach(({ eventType, handler }) => { - canvas.off(eventType, handler) + canvas.off(eventType) }) mouseEventListeners.current.length = 0 // 배열 초기화 } @@ -211,24 +203,36 @@ export function useEvent() { * @param handler */ const addDocumentEventListener = (eventType, element, handler) => { + removeDocumentEvent(eventType) element.addEventListener(eventType, handler) - keyboardEventListeners.current.push({ eventType, element, handler }) + documentEventListeners.current.push({ eventType, element, handler }) } /** * document에 등록되는 event 제거 */ const removeAllDocumentEventListeners = () => { - keyboardEventListeners.current.forEach(({ eventType, element, handler }) => { + documentEventListeners.current.forEach(({ eventType, element, handler }) => { element.removeEventListener(eventType, handler) }) - keyboardEventListeners.current.length = 0 // 배열 초기화 + documentEventListeners.current.length = 0 // 배열 초기화 } - const removeMouseEvent = (type, handler) => { + const removeMouseEvent = (type) => { mouseEventListeners.current = mouseEventListeners.current.filter((event) => { - if (event.type === type && event.handler === handler) { - canvas.off(type, handler) + if (event.eventType === type) { + canvas.off(type, event.handler) + return false + } + return true + }) + } + + const removeDocumentEvent = (type) => { + documentEventListeners.current = documentEventListeners.current.filter((event) => { + if (event.eventType === type) { + console.log(type) + event.element.removeEventListener(type, event.handler) return false } return true diff --git a/src/hooks/useLine.js b/src/hooks/useLine.js index e701a2ff..d42af418 100644 --- a/src/hooks/useLine.js +++ b/src/hooks/useLine.js @@ -38,6 +38,7 @@ export const useLine = () => { const removeLine = (line) => { removeLineText(line) canvas?.remove(line) + canvas?.renderAll() } const removeLineText = (line) => { From 05d2db69c376360736e920554baa8d098ab30d0c Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Mon, 30 Sep 2024 16:22:00 +0900 Subject: [PATCH 011/152] =?UTF-8?q?=EC=99=B8=EB=B2=BD=EC=84=A0=20=EC=86=8D?= =?UTF-8?q?=EC=84=B1=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outerlinesetting/PropertiesSetting.jsx | 17 ++- src/hooks/roofcover/usePropertiesSetting.js | 116 ++++++++++++------ 2 files changed, 92 insertions(+), 41 deletions(-) diff --git a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx index 0120f6a4..cd2973e7 100644 --- a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx @@ -6,14 +6,19 @@ export default function PropertiesSetting(props) { const { getMessage } = useMessage() const { setShowPropertiesSettingModal } = props - const { handleSetEaves, handleSetGable, handleRollback, handleFix } = usePropertiesSetting() + const { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } = usePropertiesSetting() return (

{getMessage('modal.canvas.setting.wallline.properties.setting')}

-
@@ -34,7 +39,13 @@ export default function PropertiesSetting(props) { -
diff --git a/src/hooks/roofcover/usePropertiesSetting.js b/src/hooks/roofcover/usePropertiesSetting.js index 95800dfd..9df385ed 100644 --- a/src/hooks/roofcover/usePropertiesSetting.js +++ b/src/hooks/roofcover/usePropertiesSetting.js @@ -1,27 +1,17 @@ import { useEffect, useRef } from 'react' +import { LINE_TYPE } from '@/common/common' import { useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' -import { LINE_TYPE } from '@/common/common' export function usePropertiesSetting() { const currentLine = useRef(null) + const currentIdx = useRef(-1) const canvas = useRecoilValue(canvasState) useEffect(() => { - initLineSetting() + selectNextLine() }, []) - useEffect(() => { - const lines = canvas?.getObjects().filter((obj) => obj.name === 'outerLine') - lines.forEach((line) => { - line.set({ - type: line.type, - stroke: line.type === LINE_TYPE.WALLLINE.EAVES ? '#45CD7D' : line.type === LINE_TYPE.WALLLINE.GABLE ? '#3FBAE6' : '#000000', - strokeWidth: 4, - }) - }) - }, [currentLine.current]) - const handleSetEaves = () => { currentLine.current.set({ stroke: '#45CD7D', @@ -32,13 +22,12 @@ export function usePropertiesSetting() { pitch: 4, }, }) - - nextLineSetting() + canvas.renderAll() + selectNextLine() } const handleSetGable = () => { currentLine.current.set({ - type: LINE_TYPE.WALLLINE.GABLE, stroke: '#3FBAE6', strokeWidth: 4, attributes: { @@ -46,44 +35,95 @@ export function usePropertiesSetting() { type: LINE_TYPE.WALLLINE.GABLE, }, }) - - nextLineSetting() + canvas.renderAll() + selectNextLine() } - const initLineSetting = () => { - currentLine.current = canvas?.getObjects().filter((obj) => obj.name === 'outerLine')[0] + const selectNextLine = () => { + const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + currentIdx.current++ + + if (currentIdx.current >= lines.length) { + currentIdx.current = lines.length + currentLine.current = lines[currentIdx.current - 1] + return + } + + currentLine.current = lines[currentIdx.current] currentLine.current.set({ stroke: '#EA10AC', strokeWidth: 4, }) - canvas?.renderAll() + canvas.renderAll() } - const nextLineSetting = () => { - // currentLine.current의 값은 currentLine.current의 idx 다음 값, 없을 경우는 null - currentLine.current = canvas?.getObjects().find((obj) => obj.idx === currentLine.current.idx + 1) + const selectPrevLine = () => { + const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') - if (!currentLine.current) { - canvas?.renderAll() - handleFix() + currentIdx.current-- + + if (currentIdx.current <= -1) { + currentIdx.current = -1 + selectNextLine() + return + } else { + lines.forEach((line, index) => { + if (index >= currentIdx.current) { + delete line.attributes + line.set({ + stroke: '#000000', + strokeWidth: 4, + }) + } + currentIdx.current-- + canvas.renderAll() + selectNextLine() + }) + } + } + + const handleRollback = () => { + selectPrevLine() + } + + const handleFix = () => { + if (!confirm('외벽선 속성 설정을 완료하시겠습니까?')) { + return + } + const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + lines.forEach((line) => { + line.set({ + attributes: line.attributes ? line.attributes : { offset: 0, type: LINE_TYPE.WALLLINE.WALL }, + stroke: '#000000', + strokeWidth: 4, + }) + }) + + canvas.renderAll() + } + + const closeModal = (fn) => { + if (!confirm('외벽선 속성 설정을 종료 하시겠습니까?')) { return } - currentLine.current = currentLine.current.set({ - stroke: '#EA10AC', - strokeWidth: 4, + const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + lines.forEach((line) => { + line.set({ + attributes: { offset: 0, type: LINE_TYPE.WALLLINE.WALL }, + stroke: '#000000', + strokeWidth: 4, + }) }) - canvas?.renderAll() + canvas.renderAll() + + fn(false) } - const currentLineSetting = () => {} - - const handleRollback = () => {} - - const handleFix = () => {} - - return { handleSetEaves, handleSetGable, handleRollback, handleFix } + return { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } } From 4ee102f1b9b1bc777396efd4d6302da6127ec928 Mon Sep 17 00:00:00 2001 From: Daseul Kim Date: Mon, 30 Sep 2024 16:36:10 +0900 Subject: [PATCH 012/152] =?UTF-8?q?feat:=20canvas=20plan=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/CanvasLayout.jsx | 55 +++++++++++++++------- src/hooks/useAxios.js | 6 ++- src/hooks/usePlan.js | 17 ++++++- 3 files changed, 60 insertions(+), 18 deletions(-) diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx index e71c01f5..3abebd85 100644 --- a/src/components/floor-plan/CanvasLayout.jsx +++ b/src/components/floor-plan/CanvasLayout.jsx @@ -3,6 +3,8 @@ import { useEffect, useState } from 'react' import { useRecoilState, useRecoilValue } from 'recoil' import CanvasFrame from './CanvasFrame' +import { useMessage } from '@/hooks/useMessage' +import { useSwal } from '@/hooks/useSwal' import { usePlan } from '@/hooks/usePlan' import { globalLocaleStore } from '@/store/localeAtom' import { currentCanvasPlanState, initCanvasPlansState } from '@/store/canvasAtom' @@ -17,7 +19,9 @@ export default function CanvasLayout() { const globalLocaleState = useRecoilValue(globalLocaleStore) const sessionState = useRecoilValue(sessionStore) - const { getCanvasByObjectNo } = usePlan() + const { getMessage } = useMessage() + const { swalFire } = useSwal() + const { getCanvasByObjectNo, delCanvasById } = usePlan() const handleCurrentPlan = (newCurrentId) => { if (!currentCanvasPlan?.id || currentCanvasPlan.id !== newCurrentId) { @@ -40,21 +44,29 @@ export default function CanvasLayout() { const handleDeletePlan = (e, id) => { e.stopPropagation() // 이벤트 버블링 방지 - // 삭제할 아이디와 다른 아이템만 남김 - const filterInitPlans = initCanvasPlans.filter((plan) => plan.id !== id) - setInitCanvasPlans(filterInitPlans) - const filterAddPlans = addCanvasPlans.filter((plan) => plan.id !== id) - setAddCanvasPlans(filterAddPlans) - - const combinedPlans = [...filterInitPlans, ...filterAddPlans] - if (combinedPlans.length === 0) { - // 모든 데이터가 삭제된 경우 - setPlanNum(0) + if (initCanvasPlans.some((plan) => plan.id === id)) { + delCanvasById(id) + .then((res) => { + swalFire({ text: getMessage('common.message.delete') }) + console.log('[DELETE] canvas-statuses res :::::::: %o', res) + setInitCanvasPlans((initCanvasPlans) => initCanvasPlans.filter((plan) => plan.id !== id)) + }) + .catch((error) => { + swalFire({ text: error.message, icon: 'error' }) + console.error('[DELETE] canvas-statuses res error :::::::: %o', error) + }) } else { - const lastPlanId = combinedPlans.at(-1).id - if (id !== lastPlanId) { - handleCurrentPlan(lastPlanId) - } + setAddCanvasPlans(addCanvasPlans.filter((plan) => plan.id !== id)) + swalFire({ text: getMessage('common.message.delete') }) + } + + // 삭제 후 last 데이터에 포커싱 + const lastPlan = [...initCanvasPlans, ...addCanvasPlans].filter((plan) => plan.id !== id).at(-1) + if (!lastPlan) { + setPlanNum(0) + setCurrentCanvasPlan(null) + } else if (id !== lastPlan.id) { + handleCurrentPlan(lastPlan.id) } } @@ -84,7 +96,18 @@ export default function CanvasLayout() { {[...initCanvasPlans, ...addCanvasPlans].map((plan) => ( ))} diff --git a/src/hooks/useAxios.js b/src/hooks/useAxios.js index a1ecda2a..1a7cd03e 100644 --- a/src/hooks/useAxios.js +++ b/src/hooks/useAxios.js @@ -79,5 +79,9 @@ export function useAxios(lang = '') { .catch(console.error) } - return { get, promiseGet, post, promisePost, put, promisePut, patch, del } + const promiseDel = async ({ url }) => { + return await getInstances(url).delete(url) + } + + return { get, promiseGet, post, promisePost, put, promisePut, patch, del, promiseDel } } diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index cf566b3f..0d28d94d 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -11,7 +11,7 @@ export function usePlan() { const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) const { getMessage } = useMessage() - const { get, promisePost, promisePut } = useAxios() + const { get, promisePost, promisePut, promiseDel } = useAxios() /** * 마우스 포인터의 가이드라인을 제거합니다. @@ -147,11 +147,26 @@ export function usePlan() { ) } + /** + * id에 해당하는 canvas 데이터를 삭제하는 함수 + */ + const delCanvasById = (id) => { + return promiseDel({ url: `/api/canvas-management/canvas-statuses/by-id/${id}` }) + } + + /** + * objectNo에 해당하는 canvas 데이터들을 삭제하는 함수 + */ + const delCanvasByObjectNo = (objectNo) => { + return promiseDel({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}` }) + } + return { canvas, removeMouseLines, saveCanvas, addCanvas, getCanvasByObjectNo, + delCanvasById, } } From 82e751f2ca447fb2af0c8711b5a270cd874a9d3c Mon Sep 17 00:00:00 2001 From: Daseul Kim Date: Mon, 30 Sep 2024 17:08:40 +0900 Subject: [PATCH 013/152] =?UTF-8?q?refactor:=20canvas=20plan=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EC=8B=9C=20swalFire(confirm)=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/CanvasMenu.jsx | 13 +++++++++++-- src/hooks/usePlan.js | 13 ++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index 99b3e048..07b248cb 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -9,7 +9,8 @@ import QSelectBox from '@/components/common/select/QSelectBox' import { useMessage } from '@/hooks/useMessage' import { usePlan } from '@/hooks/usePlan' -import { canvasState, canvasZoomState, currentMenuState, verticalHorizontalModeState } from '@/store/canvasAtom' +import { useSwal } from '@/hooks/useSwal' +import { canvasState, canvasZoomState, currentMenuState, currentCanvasPlanState, verticalHorizontalModeState } from '@/store/canvasAtom' import { sessionStore } from '@/store/commonAtom' import { outerLinePointsState } from '@/store/outerLineAtom' import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' @@ -40,6 +41,7 @@ export default function CanvasMenu(props) { const setCurrentMenu = useSetRecoilState(currentMenuState) const setPoints = useSetRecoilState(outerLinePointsState) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) + const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const globalLocale = useRecoilValue(globalLocaleStore) const canvas = useRecoilValue(canvasState) @@ -47,6 +49,7 @@ export default function CanvasMenu(props) { const { getMessage } = useMessage() const { saveCanvas } = usePlan() + const { swalFire } = useSwal() const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }] const onClickNav = (menu) => { @@ -78,7 +81,13 @@ export default function CanvasMenu(props) { // 저장버튼(btn08) 클릭 시 호출되는 함수 const handleSaveCanvas = () => { - saveCanvas(sessionState.userId) + swalFire({ + html: getMessage('common.message.confirm.save') + `
${currentCanvasPlan.name}`, + type: 'confirm', + confirmFn: () => { + saveCanvas(sessionState.userId) + }, + }) } const handleClear = () => { diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index 0d28d94d..fedbb3be 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -2,14 +2,13 @@ import { useRecoilState } from 'recoil' import { canvasState, currentCanvasPlanState, initCanvasPlansState } from '@/store/canvasAtom' import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' -import { toastUp } from '@/hooks/useToast' -import { sessionStore } from '@/store/commonAtom' -import { useState } from 'react' +import { useSwal } from '@/hooks/useSwal' export function usePlan() { const [canvas, setCanvas] = useRecoilState(canvasState) const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) + const { swalFire } = useSwal() const { getMessage } = useMessage() const { get, promisePost, promisePut, promiseDel } = useAxios() @@ -101,14 +100,14 @@ export function usePlan() { await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData }) .then((res) => { - toastUp({ message: getMessage('common.message.save'), type: 'success' }) // 성공 시 메세지 없음 + swalFire({ text: getMessage('common.message.save') }) console.log('[PUT] canvas-statuses res :::::::: %o', res) setInitCanvasPlans((initCanvasPlans) => initCanvasPlans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)), ) }) .catch((error) => { - toastUp({ message: error.message, type: 'error' }) + swalFire({ text: error.message, icon: 'error' }) console.error('[PUT] canvas-statuses error :::::::: %o', error) }) } else { @@ -122,11 +121,11 @@ export function usePlan() { await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData }) .then((res) => { - toastUp({ message: getMessage('common.message.save'), type: 'success' }) // 성공 시 메세지 없음 + swalFire({ text: getMessage('common.message.save') }) console.log('[POST] canvas-statuses response :::::::: %o', res) }) .catch((error) => { - toastUp({ message: error.message, type: 'error' }) + swalFire({ text: error.message, icon: 'error' }) console.error('[POST] canvas-statuses res error :::::::: %o', error) }) } From 71e3d78c9b70b6a2c839ff4edebc542dc5fc6484 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 30 Sep 2024 17:09:31 +0900 Subject: [PATCH 014/152] =?UTF-8?q?=EB=AA=A8=EB=93=88=20=ED=9D=A1=EC=B0=A9?= =?UTF-8?q?=EC=A0=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMode.js | 195 +++++++++++++++++++++++++++---------------- 1 file changed, 121 insertions(+), 74 deletions(-) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index c2b29121..91444740 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -39,6 +39,7 @@ import * as turf from '@turf/turf' import { INPUT_TYPE, Mode } from '@/common/common' import { m } from 'framer-motion' import { set } from 'react-hook-form' +import { FaWineGlassEmpty } from 'react-icons/fa6' export function useMode() { const [mode, setMode] = useRecoilState(modeState) @@ -4941,6 +4942,12 @@ export function useMode() { ) } + const coordToTurfPolygon = (points) => { + const coordinates = points.map((point) => [point.x, point.y]) + coordinates.push(coordinates[0]) + return turf.polygon([coordinates]) + } + /** * trestle에서 영역을 가져와 mouse:move 이벤트로 해당 영역에 진입했을때 booleanPointInPolygon 로 진입여부를 확인 * 확인 후 셀을 이동시킴 @@ -4949,58 +4956,125 @@ export function useMode() { const trestlePolygons = canvas?.getObjects().filter((obj) => obj.name === 'trestle') //가대를 가져옴 if (trestlePolygons.length !== 0) { - let lastPointPosition = { x: 0, y: 0 } let fabricPolygon = null let inside = false let turfPolygon - let manualDrawCells = drewRoofCells // - + let manualDrawCells = drewRoofCells // 앞에서 자동으로 했을때 추가됨 + let direction canvas.on('mouse:move', (e) => { //마우스 이벤트 삭제 후 재추가 const mousePoint = canvas.getPointer(e.e) - const turfPoint = turf.point([mousePoint.x, mousePoint.y]) - for (let i = 0; i < trestlePolygons.length; i++) { turfPolygon = polygonToTurfPolygon(trestlePolygons[i]) - if (turf.booleanPointInPolygon(turfPoint, turfPolygon)) { + direction = trestlePolygons[i].direction //도형의 방향 + let width = direction === 'south' || direction === 'north' ? 172 : 113 + let height = direction === 'south' || direction === 'north' ? 113 : 172 + + const points = [ + { x: mousePoint.x - width / 2, y: mousePoint.y - height / 2 }, + { x: mousePoint.x + width / 2, y: mousePoint.y - height / 2 }, + { x: mousePoint.x + width / 2, y: mousePoint.y + height / 2 }, + { x: mousePoint.x - width / 2, y: mousePoint.y + height / 2 }, + ] + + const turfPoints = coordToTurfPolygon(points) + + if (turf.booleanWithin(turfPoints, turfPolygon)) { //turf에 보면 폴리곤안에 포인트가 있는지 함수가 있다 - const direction = trestlePolygons[i].direction //도형의 방향 - let width = direction === 'south' || direction === 'north' ? 172.2 : 113.4 - let height = direction === 'south' || direction === 'north' ? 113.4 : 172.2 - if (Math.abs(mousePoint.x - lastPointPosition.x) >= 5 || Math.abs(mousePoint.y - lastPointPosition.y) >= 5) { - let isDrawing = false - if (isDrawing) return - canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tmpCell')) //움직일때 일단 지워가면서 움직임 + // if (Math.abs(mousePoint.x - lastPointPosition.x) >= 5 || Math.abs(mousePoint.y - lastPointPosition.y) >= 5) { + let isDrawing = false - const points = [ - { x: mousePoint.x - width / 2, y: mousePoint.y - height / 2 }, - { x: mousePoint.x + width / 2, y: mousePoint.y - height / 2 }, - { x: mousePoint.x + width / 2, y: mousePoint.y + height / 2 }, - { x: mousePoint.x - width / 2, y: mousePoint.y + height / 2 }, - ] + if (isDrawing) return + canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tmpCell')) //움직일때 일단 지워가면서 움직임 - fabricPolygon = new QPolygon(points, { - fill: '#BFFD9F', - stroke: 'black', - selectable: false, // 선택 가능하게 설정 - lockMovementX: true, // X 축 이동 잠금 - lockMovementY: true, // Y 축 이동 잠금 - lockRotation: true, // 회전 잠금 - lockScalingX: true, // X 축 크기 조정 잠금 - lockScalingY: true, // Y 축 크기 조정 잠금 - opacity: 0.8, - parentId: trestlePolygons[i].parentId, - name: 'tmpCell', - }) + fabricPolygon = new QPolygon(points, { + fill: '#BFFD9F', + // stroke: 'black', + // strokeWidth: 1, + selectable: false, // 선택 가능하게 설정 + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + lockScalingX: true, // X 축 크기 조정 잠금 + lockScalingY: true, // Y 축 크기 조정 잠금 + opacity: 0.8, + parentId: trestlePolygons[i].parentId, + name: 'tmpCell', + }) - canvas?.add(fabricPolygon) //움직여가면서 추가됨 - lastPointPosition = { x: mousePoint.x, y: mousePoint.y } + canvas?.add(fabricPolygon) //움직여가면서 추가됨 + + /** + * 스냅기능 + */ + let snapDistance = 20 + + const bigLeft = trestlePolygons[i].left + const bigTop = trestlePolygons[i].top + const bigRight = bigLeft + trestlePolygons[i].width * trestlePolygons[i].scaleX + const bigBottom = bigTop + trestlePolygons[i].height * trestlePolygons[i].scaleY + const bigCenter = (bigTop + bigTop + trestlePolygons[i].height) / 2 + + // 작은 폴리곤의 경계 좌표 계산 + const smallLeft = fabricPolygon.left + const smallTop = fabricPolygon.top + const smallRight = smallLeft + fabricPolygon.width * fabricPolygon.scaleX + const smallBottom = smallTop + fabricPolygon.height * fabricPolygon.scaleY + const smallCenter = smallLeft + (fabricPolygon.width * fabricPolygon.scaleX) / 2 + + // 위쪽 변에 스냅 + if (Math.abs(smallTop - bigTop) < snapDistance) { + fabricPolygon.top = bigTop } + // 아래쪽 변에 스냅 + if (Math.abs(smallTop + fabricPolygon.height * fabricPolygon.scaleY - (bigTop + trestlePolygons[i].height)) < snapDistance) { + fabricPolygon.top = bigTop + trestlePolygons[i].height - fabricPolygon.height * fabricPolygon.scaleY + } + + // 왼쪽변에 스냅 + if (Math.abs(smallLeft - bigLeft) < snapDistance) { + fabricPolygon.left = bigLeft + } + //오른쪽 변에 스냅 + if (Math.abs(smallRight - bigRight) < snapDistance) { + fabricPolygon.left = bigRight - fabricPolygon.width * fabricPolygon.scaleX + } + + if (direction === 'south' || direction === 'north') { + // 모듈왼쪽이 세로중앙선에 붙게 스냅 + if (Math.abs(smallLeft - (bigLeft + trestlePolygons[i].width / 2)) < snapDistance) { + fabricPolygon.left = bigLeft + trestlePolygons[i].width / 2 + } + + // 모듈이 가운데가 세로중앙선에 붙게 스냅 + if (Math.abs(smallCenter - (bigLeft + trestlePolygons[i].width / 2)) < snapDistance) { + fabricPolygon.left = bigLeft + trestlePolygons[i].width / 2 - (fabricPolygon.width * fabricPolygon.scaleX) / 2 + } + + // 모듈오른쪽이 세로중앙선에 붙게 스냅 + if (Math.abs(smallRight - (bigLeft + trestlePolygons[i].width / 2)) < snapDistance) { + fabricPolygon.left = bigLeft + trestlePolygons[i].width / 2 - fabricPolygon.width * fabricPolygon.scaleX + } + } else { + // 모듈이 가로중앙선에 스냅 + if (Math.abs(smallTop + fabricPolygon.height / 2 - bigCenter) < snapDistance) { + fabricPolygon.top = bigCenter - fabricPolygon.height / 2 + } + + if (Math.abs(smallTop - (bigTop + trestlePolygons[i].height / 2)) < snapDistance) { + fabricPolygon.top = bigTop + trestlePolygons[i].height / 2 + } + // 모듈 밑면이 가로중앙선에 스냅 + if (Math.abs(smallBottom - (bigTop + trestlePolygons[i].height / 2)) < snapDistance) { + fabricPolygon.top = bigTop + trestlePolygons[i].height / 2 - fabricPolygon.height * fabricPolygon.scaleY + } + } + + fabricPolygon.setCoords() canvas?.renderAll() inside = true - break } else { inside = false } @@ -5016,20 +5090,26 @@ export function useMode() { if (!inside) return if (fabricPolygon) { const turfCellPolygon = polygonToTurfPolygon(fabricPolygon) - + fabricPolygon.setCoords() //좌표 재정렬 if (turf.booleanWithin(turfCellPolygon, turfPolygon)) { //마우스 클릭시 set으로 해당 위치에 셀을 넣음 + + manualDrawCells.forEach((cell) => { + console.log('cells', cell.points) + }) + console.log('turfCellPolygon', turfCellPolygon.geometry.coordinates) + const isOverlap = manualDrawCells.some((cell) => turf.booleanOverlap(turfCellPolygon, polygonToTurfPolygon(cell))) if (!isOverlap) { //안겹치면 넣는다 - fabricPolygon.set({ name: 'cell' }) fabricPolygon.setCoords() + fabricPolygon.set({ name: 'cell' }) manualDrawCells.push(fabricPolygon) } else { alert('셀끼리 겹치면 안되죠?') } - } else { - alert('나갔으요!!') + // } else { + // alert('나갔으요!!') } setDrewRoofCells(manualDrawCells) } @@ -5106,27 +5186,6 @@ export function useMode() { // console.log('bbox', bbox) - const boxes = [] - const installedCellsArray = [] - - for (let x = bbox[0]; x < bbox[2]; x += width) { - for (let y = bbox[1]; y < bbox[3]; y += height) { - const box = turf.polygon([ - [ - [x, y], - [x + width, y], - [x + width, y + height], - [x, y + height], - [x, y], - ], - ]) - - if (turf.booleanWithin(box, turfTrestlePolygon)) { - boxes.push(box) - } - } - } - for (let col = 0; col <= cols; col++) { for (let row = 0; row <= rows; row++) { let x = 0, @@ -5176,20 +5235,6 @@ export function useMode() { const squarePolygon = turf.polygon([square]) - // console.log('turfTrestlePolygon', turfTrestlePolygon) - // console.log('squarePolygon', squarePolygon) - - const areaSize = turf.area(turfTrestlePolygon) - - // console.log('areaSize', areaSize) - const objSize = turf.area(squarePolygon) - - // console.log('objSize', objSize) - - const maxObject = Math.floor(areaSize / objSize) - - // console.log('maxObjectSize', maxObject) - const disjointFromTrestle = turf.booleanContains(turfTrestlePolygon, squarePolygon) || turf.booleanWithin(squarePolygon, turfTrestlePolygon) if (disjointFromTrestle) { @@ -5230,6 +5275,8 @@ export function useMode() { lockScalingY: true, // Y 축 크기 조정 잠금 opacity: 0.8, parentId: trestle.parentId, + lineCol: col, + lineRow: row, }) canvas?.add(fabricPolygon) drawCellsArray.push(fabricPolygon) From 533b39f0ecdcbc4612baa78bf7b4c94fec017b06 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 2 Oct 2024 11:33:49 +0900 Subject: [PATCH 015/152] refactor: Add modal handle --- src/components/common/draggable/WithDraggable.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/common/draggable/WithDraggable.jsx b/src/components/common/draggable/WithDraggable.jsx index 23195fbe..0e19704c 100644 --- a/src/components/common/draggable/WithDraggable.jsx +++ b/src/components/common/draggable/WithDraggable.jsx @@ -17,7 +17,7 @@ export default function WithDraggable({ isShow, children, pos }) { return ( <> {isShow && ( - handleOnDrag(e, data)}> + handleOnDrag(e, data)} handle=".modal-head"> {children} )} From d6641369098ea714b8a12b7379c62d9f03422c27 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 2 Oct 2024 13:18:04 +0900 Subject: [PATCH 016/152] fix: Control modal handle props --- src/components/common/draggable/WithDraggable.jsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/common/draggable/WithDraggable.jsx b/src/components/common/draggable/WithDraggable.jsx index 0e19704c..29952981 100644 --- a/src/components/common/draggable/WithDraggable.jsx +++ b/src/components/common/draggable/WithDraggable.jsx @@ -3,7 +3,7 @@ import { useEffect, useState } from 'react' import Draggable from 'react-draggable' -export default function WithDraggable({ isShow, children, pos }) { +export default function WithDraggable({ isShow, children, pos, handle = '' }) { const [position, setPosition] = useState({ x: 0, y: 0 }) const handleOnDrag = (e, data) => { @@ -17,7 +17,11 @@ export default function WithDraggable({ isShow, children, pos }) { return ( <> {isShow && ( - handleOnDrag(e, data)} handle=".modal-head"> + handleOnDrag(e, data)} + handle={handle === '' ? '.modal-head' : handle} + > {children} )} From f7310b53d5276f0622d7204c51889bb28020d33e Mon Sep 17 00:00:00 2001 From: minsik Date: Wed, 2 Oct 2024 13:51:31 +0900 Subject: [PATCH 017/152] =?UTF-8?q?-=20=EB=B0=B0=EC=B9=98=EB=A9=B4=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=20=EC=84=A4=EC=A0=95=20modal=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/components/floor-plan/CanvasMenu.jsx | 16 ++- src/components/floor-plan/FloorPlan.jsx | 5 +- src/components/floor-plan/MenuDepth01.jsx | 3 +- .../outerlinesetting/WallLineSetting.jsx | 2 +- .../modal/placementShape/MaterialGuide.jsx | 17 +++ .../placementShape/PlacementShapeSetting.js | 120 ++++++++++++++++++ .../modal/placementShape/SizeGuide.jsx | 39 ++++++ .../modal/setting01/SettingModal01.jsx | 2 +- src/locales/ja.json | 17 +++ src/locales/ko.json | 17 +++ src/styles/_modal.scss | 2 - 11 files changed, 233 insertions(+), 7 deletions(-) create mode 100644 src/components/floor-plan/modal/placementShape/MaterialGuide.jsx create mode 100644 src/components/floor-plan/modal/placementShape/PlacementShapeSetting.js create mode 100644 src/components/floor-plan/modal/placementShape/SizeGuide.jsx diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index 99b3e048..bda5a3ca 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -30,7 +30,7 @@ const canvasMenus = [ ] export default function CanvasMenu(props) { - const { setShowCanvasSettingModal, showOutlineModal, setShowOutlineModal } = props + const { setShowCanvasSettingModal, showOutlineModal, setShowOutlineModal, setShowPlaceShapeModal } = props const [menuNumber, setMenuNumber] = useState(null) const [type, setType] = useState('') @@ -54,6 +54,10 @@ export default function CanvasMenu(props) { setCurrentMenu(menu.title) switch (menu.index) { + case 1: + setType('placementShape') + onClickPlacementInitialMenu() + break case 2: setType('outline') break @@ -67,12 +71,16 @@ export default function CanvasMenu(props) { } const menuProps = { setShowOutlineModal, + setShowPlaceShapeModal, type, } const settingsModalOptions = useRecoilState(settingModalFirstOptionsState) useEffect(() => { + if (menuNumber === 1) { + onClickPlacementInitialMenu() + } if (menuNumber !== 2 && showOutlineModal) setShowOutlineModal(false) }, [menuNumber, type]) @@ -81,6 +89,12 @@ export default function CanvasMenu(props) { saveCanvas(sessionState.userId) } + const onClickPlacementInitialMenu = () => { + setShowOutlineModal(false) + setShowCanvasSettingModal(false) + setShowPlaceShapeModal(true) + } + const handleClear = () => { setPoints([]) canvas?.clear() diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx index 9f7c6641..50ed672e 100644 --- a/src/components/floor-plan/FloorPlan.jsx +++ b/src/components/floor-plan/FloorPlan.jsx @@ -12,10 +12,12 @@ import CanvasLayout from '@/components/floor-plan/CanvasLayout' import DotLineGrid from '@/components/floor-plan/modal/grid/DotLineGrid' import WallLineSetting from '@/components/floor-plan/modal/outerlinesetting/WallLineSetting' import PropertiesSetting from '@/components/floor-plan/modal/outerlinesetting/PropertiesSetting' +import PlacementShapeSetting from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting' export default function FloorPlan() { const [showCanvasSettingModal, setShowCanvasSettingModal] = useState(false) const [showOutlineModal, setShowOutlineModal] = useState(false) + const [showPlaceShapeModal, setShowPlaceShapeModal] = useState(false) const [showPropertiesSettingModal, setShowPropertiesSettingModal] = useState(false) const globalLocaleState = useRecoilValue(globalLocaleStore) const { get } = useAxios(globalLocaleState) @@ -40,6 +42,7 @@ export default function FloorPlan() { setShowCanvasSettingModal, showOutlineModal, setShowOutlineModal, + setShowPlaceShapeModal, } useEffect(() => { @@ -90,10 +93,10 @@ export default function FloorPlan() {
{showCanvasSettingModal && } - {/*{showOutlineModal && }*/} {showOutlineModal && } {showDotLineGridModal && } {showPropertiesSettingModal && } + {showPlaceShapeModal && }
diff --git a/src/components/floor-plan/MenuDepth01.jsx b/src/components/floor-plan/MenuDepth01.jsx index a6b12877..925978e6 100644 --- a/src/components/floor-plan/MenuDepth01.jsx +++ b/src/components/floor-plan/MenuDepth01.jsx @@ -7,7 +7,7 @@ import { currentMenuState } from '@/store/canvasAtom' import { useSetRecoilState } from 'recoil' export default function MenuDepth01(props) { - const { setShowOutlineModal, type } = props + const { setShowOutlineModal, type, setShowPlaceShapeModal } = props const { getMessage } = useMessage() const [activeMenu, setActiveMenu] = useState() const setCurrentMenu = useSetRecoilState(currentMenuState) @@ -16,6 +16,7 @@ export default function MenuDepth01(props) { setShowOutlineModal(menu === MENU.ROOF_COVERING.EXTERIOR_WALL_LINE) setCurrentMenu(menu) if (type === 'outline') { + setShowPlaceShapeModal(false) setShowOutlineModal(id === 0) } } diff --git a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx index 0cba88c2..d4b05967 100644 --- a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx @@ -16,7 +16,7 @@ export default function WallLineSetting(props) { const { type, setType, handleFix, handleRollback } = useOuterLineWall() return ( - +

{getMessage('modal.cover.outline.drawing')}

diff --git a/src/components/floor-plan/modal/placementShape/MaterialGuide.jsx b/src/components/floor-plan/modal/placementShape/MaterialGuide.jsx new file mode 100644 index 00000000..eff09305 --- /dev/null +++ b/src/components/floor-plan/modal/placementShape/MaterialGuide.jsx @@ -0,0 +1,17 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function MaterialGuide({ setShowMaterialGuidModal }) { + const { getMessage } = useMessage() + return ( +
+
+ +
+
+
{getMessage('modal.placement.initial.setting.roof.material.info')}
+
+
+ ) +} diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.js b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.js new file mode 100644 index 00000000..606f932d --- /dev/null +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.js @@ -0,0 +1,120 @@ +import SizeGuide from '@/components/floor-plan/modal/placementShape/SizeGuide' +import MaterialGuide from '@/components/floor-plan/modal/placementShape/MaterialGuide' +import WithDraggable from '@/components/common/draggable/WithDraggable' +import { useState } from 'react' +import { useMessage } from '@/hooks/useMessage' + +export default function PlacementShapeSetting({ setShowPlaceShapeModal }) { + const [showSizeGuideModal, setShowSizeGuidModal] = useState(false) + const [showMaterialGuideModal, setShowMaterialGuidModal] = useState(false) + const { getMessage } = useMessage() + return ( + +
+
+

{getMessage('plan.menu.placement.surface.initial.setting')}

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
{getMessage('modal.placement.initial.setting.plan.drawing')}{getMessage('modal.placement.initial.setting.plan.drawing.size.stuff')}
+ {getMessage('modal.placement.initial.setting.size')} + + +
+
+ + +
+
+ + +
+
+ + +
+
+
{getMessage('modal.placement.initial.setting.roof.angle.setting')} +
+
+ + +
+
+ + +
+
+
+ {getMessage('modal.placement.initial.setting.roof.material')} + + +
+
+ +
+
+ W +
+ +
+
+
+ L +
+ +
+
+
+ {getMessage('modal.placement.initial.setting.rafter')} +
+ +
+
+
+
+
+
+ +
+
+ {showSizeGuideModal && } + {showMaterialGuideModal && } +
+
+ ) +} diff --git a/src/components/floor-plan/modal/placementShape/SizeGuide.jsx b/src/components/floor-plan/modal/placementShape/SizeGuide.jsx new file mode 100644 index 00000000..1f9d2770 --- /dev/null +++ b/src/components/floor-plan/modal/placementShape/SizeGuide.jsx @@ -0,0 +1,39 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function SizeGuide({ setShowSizeGuidModal }) { + const { getMessage } = useMessage() + return ( +
+
+ +
+
+
{getMessage('modal.placement.initial.setting.size.info')}
+
+ + + + + + + + + + + + + + + + + + + +
{getMessage('modal.placement.initial.setting.size.roof')}{getMessage('modal.placement.initial.setting.size.roof.info')}
{getMessage('modal.placement.initial.setting.size.actual')}{getMessage('modal.placement.initial.setting.size.actual.info')}
{getMessage('modal.placement.initial.setting.size.none.pitch')}{getMessage('modal.placement.initial.setting.size.none.pitch.info')}
+
+
+
+ ) +} diff --git a/src/components/floor-plan/modal/setting01/SettingModal01.jsx b/src/components/floor-plan/modal/setting01/SettingModal01.jsx index 263fc924..9207bd76 100644 --- a/src/components/floor-plan/modal/setting01/SettingModal01.jsx +++ b/src/components/floor-plan/modal/setting01/SettingModal01.jsx @@ -13,7 +13,7 @@ export default function SettingModal01(props) { const { getMessage } = useMessage() return ( - +

{getMessage('modal.canvas.setting')}

diff --git a/src/locales/ja.json b/src/locales/ja.json index 06429bc6..a1285410 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -15,6 +15,22 @@ "header.stem": "ステム", "plan.menu.plan.drawing": "도면작성", "plan.menu.placement.surface.initial.setting": "配置面 初期設定", + "modal.placement.initial.setting.plan.drawing.size.stuff": "寸法入力による物品作成", + "modal.placement.initial.setting.plan.": "図面の作成方法", + "modal.placement.initial.setting.size": "寸法入力方法", + "modal.placement.initial.setting.size.info": "寸法入力方法案内", + "modal.placement.initial.setting.size.roof": "複視図入力", + "modal.placement.initial.setting.size.roof.info": "平面の外壁線と立面の屋根勾配に基づいて作画する場合に選択", + "modal.placement.initial.setting.size.actual": "実測値入力", + "modal.placement.initial.setting.size.actual.info": "現地屋根の外周寸法を入力して作画する場合選択", + "modal.placement.initial.setting.size.none.pitch": "陸上屋根", + "modal.placement.initial.setting.size.none.pitch.info": "傾斜のない平面形状の屋根にパネルを配置する場合に選択", + "modal.placement.initial.setting.roof.angle.setting": "屋根角度設定", + "modal.placement.initial.setting.roof.pitch": "傾斜", + "modal.placement.initial.setting.roof.angle": "角度", + "modal.placement.initial.setting.roof.material": "屋根材の選択(単位:mm)", + "modal.placement.initial.setting.roof.material.info": "対応可能な屋根材や足場は限定されますので、必ず事前マニュアルをご確認ください。", + "modal.placement.initial.setting.rafter": "垂木の間隔", "plan.menu.roof.cover": "지붕덮개", "plan.menu.roof.cover.outline.drawing": "外壁線を描", "plan.menu.roof.cover.roof.shape.setting": "屋根形状設定", @@ -84,6 +100,7 @@ "modal.grid.copy.info": "間隔を設定し、コピー方向を選択します", "modal.grid.copy.length": "長さ", "modal.grid.copy.save": "保存", + "modal.common.save": "保存", "modal.canvas.setting.font.plan.edit": "フォントとサイズの変更", "modal.canvas.setting.font.plan.edit.word": "文字フォントの変更", "modal.canvas.setting.font.plan.edit.flow": "フロー方向フォントの変更", diff --git a/src/locales/ko.json b/src/locales/ko.json index b3e2decd..cc84b9d7 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -15,6 +15,22 @@ "header.stem": "Stem", "plan.menu.plan.drawing": "도면작성", "plan.menu.placement.surface.initial.setting": "배치면 초기 설정", + "modal.placement.initial.setting.plan.drawing": "도면 작성방법", + "modal.placement.initial.setting.plan.drawing.size.stuff": "치수 입력에 의한 물건 작성", + "modal.placement.initial.setting.size": "치수 입력방법", + "modal.placement.initial.setting.size.info": "치수 입력방법 안내", + "modal.placement.initial.setting.size.roof": "복시도 입력", + "modal.placement.initial.setting.size.roof.info": "평면의 외벽선과 입면의 지붕 구배를 바탕으로 작화할 경우 선택", + "modal.placement.initial.setting.size.actual": "실측값 입력", + "modal.placement.initial.setting.size.actual.info": "현지 지붕의 외주 치수를 입력하여 작화하는 경우 선택", + "modal.placement.initial.setting.size.none.pitch": "육지붕", + "modal.placement.initial.setting.size.none.pitch.info": "경사가 없는 평면 형태의 지붕에 패널을 배치할 경우 선택", + "modal.placement.initial.setting.roof.angle.setting": "지붕각도 설정", + "modal.placement.initial.setting.roof.pitch": "경사", + "modal.placement.initial.setting.roof.angle": "각도", + "modal.placement.initial.setting.roof.material": "지붕재 선택(단위: mm)", + "modal.placement.initial.setting.roof.material.info": "대응 가능한 지붕재 및 발판은 한정되므로 반드시 사전 매뉴얼을 확인하십시오.", + "modal.placement.initial.setting.rafter": "서까래", "plan.menu.roof.cover": "지붕덮개", "plan.menu.roof.cover.outline.drawing": "외벽선 그리기", "plan.menu.roof.cover.roof.shape.setting": "지붕형상 설정", @@ -85,6 +101,7 @@ "modal.grid.copy.info": "간격을 설정하고 복사 방향을 선택하십시오", "modal.grid.copy.length": "길이", "modal.grid.copy.save": "저장", + "modal.common.save": "저장", "modal.canvas.setting.font.plan.edit": "글꼴 및 크기 변경", "modal.canvas.setting.font.plan.edit.word": "문자 글꼴 변경", "modal.canvas.setting.font.plan.edit.flow": "흐름 방향 글꼴 변경", diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss index 28456176..88b63229 100644 --- a/src/styles/_modal.scss +++ b/src/styles/_modal.scss @@ -28,8 +28,6 @@ $alert-color: #101010; .modal-pop-wrap { position: fixed; - top: 200px; - right: 100px; width: 100%; min-width: 300px; height: -webkit-fit-content; From fcfdd6547c2aa318f444a8e4ae63eb516854627f Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 2 Oct 2024 14:05:33 +0900 Subject: [PATCH 018/152] feat: Add grid color setting modal --- src/components/floor-plan/FloorPlan.jsx | 8 ++++++ .../modal/grid/GridColorSetting.jsx | 27 +++++++++++++++++++ .../floor-plan/modal/setting01/GridOption.jsx | 6 +++-- .../modal/setting01/SettingModal01.jsx | 4 +-- 4 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 src/components/floor-plan/modal/grid/GridColorSetting.jsx diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx index 55b700c1..19dfe66a 100644 --- a/src/components/floor-plan/FloorPlan.jsx +++ b/src/components/floor-plan/FloorPlan.jsx @@ -12,6 +12,7 @@ import CanvasLayout from '@/components/floor-plan/CanvasLayout' import DotLineGrid from '@/components/floor-plan/modal/grid/DotLineGrid' import WallLineSetting from '@/components/floor-plan/modal/outerlinesetting/WallLineSetting' import PropertiesSetting from '@/components/floor-plan/modal/outerlinesetting/PropertiesSetting' +import GridColorSetting from './modal/grid/GridColorSetting' export default function FloorPlan() { const [showCanvasSettingModal, setShowCanvasSettingModal] = useState(false) @@ -27,9 +28,11 @@ export default function FloorPlan() { const [showDotLineGridModal, setShowDotLineGridModal] = useState(false) const [showGridCopyModal, setShowGridCopyModal] = useState(false) const [showGridMoveModal, setShowGridMoveModal] = useState(false) + const [showColorPickerModal, setShowColorPickerModal] = useState(false) const canvasSettingProps = { setShowCanvasSettingModal, setShowDotLineGridModal, + setShowColorPickerModal, } const outlineProps = { @@ -78,6 +81,10 @@ export default function FloorPlan() { setShowDotLineGridModal, } + const gridColorProps = { + setShowColorPickerModal, + } + const propertiesSettingProps = { setShowPropertiesSettingModal, } @@ -94,6 +101,7 @@ export default function FloorPlan() { {/*{showOutlineModal && }*/} {showOutlineModal && } {showDotLineGridModal && } + {showColorPickerModal && } {showPropertiesSettingModal && }
diff --git a/src/components/floor-plan/modal/grid/GridColorSetting.jsx b/src/components/floor-plan/modal/grid/GridColorSetting.jsx new file mode 100644 index 00000000..21d2a210 --- /dev/null +++ b/src/components/floor-plan/modal/grid/GridColorSetting.jsx @@ -0,0 +1,27 @@ +import WithDraggable from '@/components/common/draggable/WithDraggable' +import ColorPicker from '@/components/common/color-picker/ColorPicker' +import { useRecoilState } from 'recoil' +import { gridColorState } from '@/store/gridAtom' +import { useMessage } from '@/hooks/useMessage' + +export default function GridColorSetting(props) { + const { setShowColorPickerModal } = props + const [color, setColor] = useRecoilState(gridColorState) + const { getMessage } = useMessage() + + return ( + +
+
+

{getMessage('modal.canvas.setting.grid.color.setting')}

+ +
+
+ +
+
+
+ ) +} diff --git a/src/components/floor-plan/modal/setting01/GridOption.jsx b/src/components/floor-plan/modal/setting01/GridOption.jsx index edf1e802..1b157b75 100644 --- a/src/components/floor-plan/modal/setting01/GridOption.jsx +++ b/src/components/floor-plan/modal/setting01/GridOption.jsx @@ -8,7 +8,7 @@ import { gridColorState } from '@/store/gridAtom' import { useColor } from 'react-color-palette' export default function GridOption(props) { - const { setShowDotLineGridModal } = props + const { setShowDotLineGridModal, setShowColorPickerModal } = props const [gridOptions, setGridOptions] = useRecoilState(settingModalGridOptionsState) const [gridColor, setGridColor] = useRecoilState(gridColorState) const [adsorptionPointAddMode, setAdsorptionPointAddMode] = useRecoilState(adsorptionPointAddModeState) @@ -55,7 +55,9 @@ export default function GridOption(props) { if (option.id === 4) { // 그리드 색 설정 if (option.selected) { - setColorPickerShow(true) + setShowColorPickerModal(true) + } else { + setShowColorPickerModal(false) } } diff --git a/src/components/floor-plan/modal/setting01/SettingModal01.jsx b/src/components/floor-plan/modal/setting01/SettingModal01.jsx index 263fc924..356b90c7 100644 --- a/src/components/floor-plan/modal/setting01/SettingModal01.jsx +++ b/src/components/floor-plan/modal/setting01/SettingModal01.jsx @@ -8,7 +8,7 @@ import { useMessage } from '@/hooks/useMessage' import GridOption from '@/components/floor-plan/modal/setting01/GridOption' export default function SettingModal01(props) { - const { setShowCanvasSettingModal, setShowDotLineGridModal } = props + const { setShowCanvasSettingModal, setShowDotLineGridModal, setShowColorPickerModal } = props const [buttonAct, setButtonAct] = useState(1) const { getMessage } = useMessage() @@ -36,7 +36,7 @@ export default function SettingModal01(props) {
{buttonAct === 1 && } {buttonAct === 2 && } - {buttonAct === 3 && } + {buttonAct === 3 && }
From 2e52a05f3ed7af27a9f898195fa51015da98c15c Mon Sep 17 00:00:00 2001 From: yjnoh Date: Wed, 2 Oct 2024 14:07:40 +0900 Subject: [PATCH 019/152] =?UTF-8?q?=EC=88=98=EB=8F=99=20=EC=85=80=20?= =?UTF-8?q?=EC=9E=91=EC=97=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMode.js | 174 ++++++++++++++++++++++++++++++------------- 1 file changed, 122 insertions(+), 52 deletions(-) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 6778bdba..ee110a5e 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -4871,9 +4871,11 @@ export function useMode() { let turfPolygon let manualDrawCells = drewRoofCells // 앞에서 자동으로 했을때 추가됨 let direction + canvas.on('mouse:move', (e) => { //마우스 이벤트 삭제 후 재추가 const mousePoint = canvas.getPointer(e.e) + for (let i = 0; i < trestlePolygons.length; i++) { turfPolygon = polygonToTurfPolygon(trestlePolygons[i]) direction = trestlePolygons[i].direction //도형의 방향 @@ -4890,27 +4892,28 @@ export function useMode() { const turfPoints = coordToTurfPolygon(points) if (turf.booleanWithin(turfPoints, turfPolygon)) { - //turf에 보면 폴리곤안에 포인트가 있는지 함수가 있다 - - // if (Math.abs(mousePoint.x - lastPointPosition.x) >= 5 || Math.abs(mousePoint.y - lastPointPosition.y) >= 5) { let isDrawing = false if (isDrawing) return canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tmpCell')) //움직일때 일단 지워가면서 움직임 - fabricPolygon = new QPolygon(points, { - fill: '#BFFD9F', - // stroke: 'black', - // strokeWidth: 1, - selectable: false, // 선택 가능하게 설정 - lockMovementX: true, // X 축 이동 잠금 - lockMovementY: true, // Y 축 이동 잠금 - lockRotation: true, // 회전 잠금 - lockScalingX: true, // X 축 크기 조정 잠금 - lockScalingY: true, // Y 축 크기 조정 잠금 + fabricPolygon = new fabric.Rect({ + fill: 'white', + stroke: 'black', + strokeWidth: 1, + width: width, + height: height, + left: mousePoint.x - width / 2, + top: mousePoint.y - height / 2, + selectable: false, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, opacity: 0.8, - parentId: trestlePolygons[i].parentId, name: 'tmpCell', + parentId: trestlePolygons[i].parentId, }) canvas?.add(fabricPolygon) //움직여가면서 추가됨 @@ -4918,67 +4921,127 @@ export function useMode() { /** * 스냅기능 */ - let snapDistance = 20 + let snapDistance = 10 + let cellSnapDistance = 20 - const bigLeft = trestlePolygons[i].left - const bigTop = trestlePolygons[i].top - const bigRight = bigLeft + trestlePolygons[i].width * trestlePolygons[i].scaleX - const bigBottom = bigTop + trestlePolygons[i].height * trestlePolygons[i].scaleY - const bigCenter = (bigTop + bigTop + trestlePolygons[i].height) / 2 + const trestleLeft = trestlePolygons[i].left + const trestleTop = trestlePolygons[i].top + const trestleRight = trestleLeft + trestlePolygons[i].width * trestlePolygons[i].scaleX + const trestleBottom = trestleTop + trestlePolygons[i].height * trestlePolygons[i].scaleY + const bigCenterY = (trestleTop + trestleTop + trestlePolygons[i].height) / 2 // 작은 폴리곤의 경계 좌표 계산 const smallLeft = fabricPolygon.left const smallTop = fabricPolygon.top const smallRight = smallLeft + fabricPolygon.width * fabricPolygon.scaleX const smallBottom = smallTop + fabricPolygon.height * fabricPolygon.scaleY - const smallCenter = smallLeft + (fabricPolygon.width * fabricPolygon.scaleX) / 2 + const smallCenterX = smallLeft + (fabricPolygon.width * fabricPolygon.scaleX) / 2 + const smallCenterY = smallTop + (fabricPolygon.height * fabricPolygon.scaleX) / 2 + + /** + * 미리 깔아놓은 셀이 있을때 셀에 흡착됨 + */ + if (manualDrawCells) { + manualDrawCells.forEach((cell) => { + const holdCellLeft = cell.left + const holdCellTop = cell.top + const holdCellRight = holdCellLeft + cell.width * cell.scaleX + const holdCellBottom = holdCellTop + cell.height * cell.scaleY + const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2 + const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2 + + //설치된 셀에 좌측에 스냅 + if (Math.abs(smallRight - holdCellLeft) < snapDistance) { + fabricPolygon.left = holdCellLeft - width - 0.5 + } + + //설치된 셀에 우측에 스냅 + if (Math.abs(smallLeft - holdCellRight) < snapDistance) { + fabricPolygon.left = holdCellRight + 0.5 + } + + //설치된 셀에 위쪽에 스냅 + if (Math.abs(smallBottom - holdCellTop) < snapDistance) { + fabricPolygon.top = holdCellTop - height - 0.5 + } + + //설치된 셀에 밑쪽에 스냅 + if (Math.abs(smallTop - holdCellBottom) < snapDistance) { + fabricPolygon.top = holdCellBottom + 0.5 + } + //가운데 -> 가운데 + if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) { + fabricPolygon.left = holdCellCenterX - width / 2 + } + //왼쪽 -> 가운데 + if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) { + fabricPolygon.left = holdCellCenterX + } + // 오른쪽 -> 가운데 + if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) { + fabricPolygon.left = holdCellCenterX - width + } + //세로 가운데 -> 가운데 + if (Math.abs(smallCenterY - holdCellCenterY) < cellSnapDistance) { + fabricPolygon.top = holdCellCenterY - height / 2 + } + //위쪽 -> 가운데 + if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { + fabricPolygon.top = holdCellCenterY + } + //아랫쪽 -> 가운데 + if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { + fabricPolygon.top = holdCellCenterY - height + } + }) + } // 위쪽 변에 스냅 - if (Math.abs(smallTop - bigTop) < snapDistance) { - fabricPolygon.top = bigTop + if (Math.abs(smallTop - trestleTop) < snapDistance) { + fabricPolygon.top = trestleTop } // 아래쪽 변에 스냅 - if (Math.abs(smallTop + fabricPolygon.height * fabricPolygon.scaleY - (bigTop + trestlePolygons[i].height)) < snapDistance) { - fabricPolygon.top = bigTop + trestlePolygons[i].height - fabricPolygon.height * fabricPolygon.scaleY + if (Math.abs(smallTop + fabricPolygon.height * fabricPolygon.scaleY - (trestleTop + trestlePolygons[i].height)) < snapDistance) { + fabricPolygon.top = trestleTop + trestlePolygons[i].height - fabricPolygon.height * fabricPolygon.scaleY } // 왼쪽변에 스냅 - if (Math.abs(smallLeft - bigLeft) < snapDistance) { - fabricPolygon.left = bigLeft + if (Math.abs(smallLeft - trestleLeft) < snapDistance) { + fabricPolygon.left = trestleLeft } //오른쪽 변에 스냅 - if (Math.abs(smallRight - bigRight) < snapDistance) { - fabricPolygon.left = bigRight - fabricPolygon.width * fabricPolygon.scaleX + if (Math.abs(smallRight - trestleRight) < snapDistance) { + fabricPolygon.left = trestleRight - fabricPolygon.width * fabricPolygon.scaleX } if (direction === 'south' || direction === 'north') { // 모듈왼쪽이 세로중앙선에 붙게 스냅 - if (Math.abs(smallLeft - (bigLeft + trestlePolygons[i].width / 2)) < snapDistance) { - fabricPolygon.left = bigLeft + trestlePolygons[i].width / 2 + if (Math.abs(smallLeft - (trestleLeft + trestlePolygons[i].width / 2)) < snapDistance) { + fabricPolygon.left = trestleLeft + trestlePolygons[i].width / 2 } // 모듈이 가운데가 세로중앙선에 붙게 스냅 - if (Math.abs(smallCenter - (bigLeft + trestlePolygons[i].width / 2)) < snapDistance) { - fabricPolygon.left = bigLeft + trestlePolygons[i].width / 2 - (fabricPolygon.width * fabricPolygon.scaleX) / 2 + if (Math.abs(smallCenterX - (trestleLeft + trestlePolygons[i].width / 2)) < snapDistance) { + fabricPolygon.left = trestleLeft + trestlePolygons[i].width / 2 - (fabricPolygon.width * fabricPolygon.scaleX) / 2 } // 모듈오른쪽이 세로중앙선에 붙게 스냅 - if (Math.abs(smallRight - (bigLeft + trestlePolygons[i].width / 2)) < snapDistance) { - fabricPolygon.left = bigLeft + trestlePolygons[i].width / 2 - fabricPolygon.width * fabricPolygon.scaleX + if (Math.abs(smallRight - (trestleLeft + trestlePolygons[i].width / 2)) < snapDistance) { + fabricPolygon.left = trestleLeft + trestlePolygons[i].width / 2 - fabricPolygon.width * fabricPolygon.scaleX } } else { // 모듈이 가로중앙선에 스냅 - if (Math.abs(smallTop + fabricPolygon.height / 2 - bigCenter) < snapDistance) { - fabricPolygon.top = bigCenter - fabricPolygon.height / 2 + if (Math.abs(smallTop + fabricPolygon.height / 2 - bigCenterY) < snapDistance) { + fabricPolygon.top = bigCenterY - fabricPolygon.height / 2 } - if (Math.abs(smallTop - (bigTop + trestlePolygons[i].height / 2)) < snapDistance) { - fabricPolygon.top = bigTop + trestlePolygons[i].height / 2 + if (Math.abs(smallTop - (trestleTop + trestlePolygons[i].height / 2)) < snapDistance) { + fabricPolygon.top = trestleTop + trestlePolygons[i].height / 2 } // 모듈 밑면이 가로중앙선에 스냅 - if (Math.abs(smallBottom - (bigTop + trestlePolygons[i].height / 2)) < snapDistance) { - fabricPolygon.top = bigTop + trestlePolygons[i].height / 2 - fabricPolygon.height * fabricPolygon.scaleY + if (Math.abs(smallBottom - (trestleTop + trestlePolygons[i].height / 2)) < snapDistance) { + fabricPolygon.top = trestleTop + trestlePolygons[i].height / 2 - fabricPolygon.height * fabricPolygon.scaleY } } @@ -4999,27 +5062,34 @@ export function useMode() { canvas?.on('mouse:up', (e) => { if (!inside) return if (fabricPolygon) { - const turfCellPolygon = polygonToTurfPolygon(fabricPolygon) + const rectPoints = [ + { x: fabricPolygon.left + 0.1, y: fabricPolygon.top + 0.1 }, + { x: fabricPolygon.left + 0.1 + fabricPolygon.width * fabricPolygon.scaleX, y: fabricPolygon.top + 0.1 }, + { + x: fabricPolygon.left + fabricPolygon.width * fabricPolygon.scaleX + 0.1, + y: fabricPolygon.top + fabricPolygon.height * fabricPolygon.scaleY + 0.1, + }, + { x: fabricPolygon.left + 0.1, y: fabricPolygon.top + fabricPolygon.height * fabricPolygon.scaleY + 0.1 }, + ] + + fabricPolygon.set({ points: rectPoints }) + const tempTurfModule = polygonToTurfPolygon(fabricPolygon) + fabricPolygon.setCoords() //좌표 재정렬 - if (turf.booleanWithin(turfCellPolygon, turfPolygon)) { + if (turf.booleanWithin(tempTurfModule, turfPolygon)) { //마우스 클릭시 set으로 해당 위치에 셀을 넣음 - manualDrawCells.forEach((cell) => { - console.log('cells', cell.points) - }) - console.log('turfCellPolygon', turfCellPolygon.geometry.coordinates) - - const isOverlap = manualDrawCells.some((cell) => turf.booleanOverlap(turfCellPolygon, polygonToTurfPolygon(cell))) + const isOverlap = manualDrawCells.some((cell) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(cell))) if (!isOverlap) { //안겹치면 넣는다 fabricPolygon.setCoords() - fabricPolygon.set({ name: 'cell' }) + fabricPolygon.set({ name: 'cell', fill: '#BFFD9F' }) manualDrawCells.push(fabricPolygon) } else { alert('셀끼리 겹치면 안되죠?') } - // } else { - // alert('나갔으요!!') + } else { + alert('나갔으요!!') } setDrewRoofCells(manualDrawCells) } From 1bf8bff0aabb26a7273770b7e4d6e815a6d4a246 Mon Sep 17 00:00:00 2001 From: minsik Date: Wed, 2 Oct 2024 15:00:19 +0900 Subject: [PATCH 020/152] =?UTF-8?q?-=20dot.line=20=EB=AA=A8=EB=8B=AC=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95=20-=20grid=20color=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=AC=20=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/modal/grid/DotLineGrid.jsx | 2 +- src/components/floor-plan/modal/grid/GridColorSetting.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/floor-plan/modal/grid/DotLineGrid.jsx b/src/components/floor-plan/modal/grid/DotLineGrid.jsx index 1609f5a0..86584959 100644 --- a/src/components/floor-plan/modal/grid/DotLineGrid.jsx +++ b/src/components/floor-plan/modal/grid/DotLineGrid.jsx @@ -220,7 +220,7 @@ export default function DotLineGrid(props) { } return ( - +

{getMessage('modal.canvas.setting.grid.dot.line.setting')}

diff --git a/src/components/floor-plan/modal/grid/GridColorSetting.jsx b/src/components/floor-plan/modal/grid/GridColorSetting.jsx index 21d2a210..ed213250 100644 --- a/src/components/floor-plan/modal/grid/GridColorSetting.jsx +++ b/src/components/floor-plan/modal/grid/GridColorSetting.jsx @@ -10,7 +10,7 @@ export default function GridColorSetting(props) { const { getMessage } = useMessage() return ( - +

{getMessage('modal.canvas.setting.grid.color.setting')}

From 4857c31d5a5c95b112a227e4ca6b4dfb32fafc61 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Wed, 2 Oct 2024 15:07:13 +0900 Subject: [PATCH 021/152] =?UTF-8?q?=EC=85=80=20=EB=8F=84=EB=A8=B8=EC=98=81?= =?UTF-8?q?=EC=97=AD=20=EC=A0=9C=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMode.js | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index ee110a5e..dbe3753b 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -4865,6 +4865,8 @@ export function useMode() { const drawCellManualInTrestle = () => { const trestlePolygons = canvas?.getObjects().filter((obj) => obj.name === 'trestle') //가대를 가져옴 + const dormerTrestlePolygons = canvas?.getObjects().filter((obj) => obj.name === 'dormerTrestle') //도머 객체 + if (trestlePolygons.length !== 0) { let fabricPolygon = null let inside = false @@ -5060,22 +5062,39 @@ export function useMode() { }) canvas?.on('mouse:up', (e) => { + let isIntersection = true if (!inside) return if (fabricPolygon) { const rectPoints = [ - { x: fabricPolygon.left + 0.1, y: fabricPolygon.top + 0.1 }, - { x: fabricPolygon.left + 0.1 + fabricPolygon.width * fabricPolygon.scaleX, y: fabricPolygon.top + 0.1 }, + { x: fabricPolygon.left + 0.5, y: fabricPolygon.top + 0.5 }, + { x: fabricPolygon.left + 0.5 + fabricPolygon.width * fabricPolygon.scaleX, y: fabricPolygon.top + 0.5 }, { - x: fabricPolygon.left + fabricPolygon.width * fabricPolygon.scaleX + 0.1, - y: fabricPolygon.top + fabricPolygon.height * fabricPolygon.scaleY + 0.1, + x: fabricPolygon.left + fabricPolygon.width * fabricPolygon.scaleX + 0.5, + y: fabricPolygon.top + fabricPolygon.height * fabricPolygon.scaleY + 0.5, }, - { x: fabricPolygon.left + 0.1, y: fabricPolygon.top + fabricPolygon.height * fabricPolygon.scaleY + 0.1 }, + { x: fabricPolygon.left + 0.5, y: fabricPolygon.top + fabricPolygon.height * fabricPolygon.scaleY + 0.5 }, ] fabricPolygon.set({ points: rectPoints }) const tempTurfModule = polygonToTurfPolygon(fabricPolygon) + if (dormerTrestlePolygons) { + dormerTrestlePolygons.forEach((dormerTrestle) => { + const dormerTurfPolygon = polygonToTurfPolygon(dormerTrestle) + + const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) + + if (intersection) { + alert('도머위에 모듈을 올릴 수 없습니다.') + isIntersection = false + } + }) + } + + if (!isIntersection) return + fabricPolygon.setCoords() //좌표 재정렬 + if (turf.booleanWithin(tempTurfModule, turfPolygon)) { //마우스 클릭시 set으로 해당 위치에 셀을 넣음 @@ -5164,8 +5183,6 @@ export function useMode() { const cols = Math.floor((bbox[2] - bbox[0]) / width) const rows = Math.floor((bbox[3] - bbox[1]) / height) - // console.log('bbox', bbox) - for (let col = 0; col <= cols; col++) { for (let row = 0; row <= rows; row++) { let x = 0, From 0eaf9735176bb9dc8e4926194e901aaeda5113a9 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Wed, 2 Oct 2024 15:41:22 +0900 Subject: [PATCH 022/152] =?UTF-8?q?=EC=99=B8=EB=B2=BD=EC=84=A0=20=EA=B7=B8?= =?UTF-8?q?=EB=A6=AC=EA=B8=B0=20=EC=99=84=EB=A3=8C=20=ED=9B=84=20offset=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/GridSettingsModal.jsx | 7 +- src/components/fabric/QLine.js | 4 +- src/components/fabric/QPolygon.js | 9 +- src/components/floor-plan/CanvasMenu.jsx | 2 +- .../floor-plan/modal/grid/DotLineGrid.jsx | 19 ++- .../modal/grid/GridColorSetting.jsx | 14 +- .../modal/outerlinesetting/OuterLineWall.jsx | 1 + .../outerlinesetting/PropertiesSetting.jsx | 2 +- .../floor-plan/modal/setting01/GridOption.jsx | 1 - .../modal/setting01/SettingModal01.jsx | 19 ++- src/hooks/roofcover/useOuterLineWall.js | 20 ++- src/hooks/roofcover/usePropertiesSetting.js | 135 +++++++++++------- src/hooks/useEvent.js | 9 +- src/hooks/useLine.js | 7 +- src/hooks/useMode.js | 4 +- src/hooks/usePolygon.js | 15 +- src/store/canvasAtom.js | 16 +++ src/store/gridAtom.js | 2 +- src/store/outerLineAtom.js | 5 + src/store/settingAtom.js | 2 +- 20 files changed, 204 insertions(+), 89 deletions(-) diff --git a/src/components/GridSettingsModal.jsx b/src/components/GridSettingsModal.jsx index 35bb1793..92b2e618 100644 --- a/src/components/GridSettingsModal.jsx +++ b/src/components/GridSettingsModal.jsx @@ -6,6 +6,7 @@ import { guideLineState, horiGuideLinesState, vertGuideLinesState } from '@/stor 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 @@ -23,7 +24,7 @@ export default function GridSettingsModal(props) { const gridSettingArray = [] - const [guideColor, setGuideColor] = useColor('rgb(200, 15, 15)') + const gridColor = useRecoilValue(gridColorState) const [colorPickerShow, setColorPickerShow] = useState(false) const boxStyle = { @@ -67,7 +68,7 @@ export default function GridSettingsModal(props) { const horizontalLine = new fabric.Line( [0, i * moduleVertLength - moduleVertLength / 2, canvasProps.width, i * moduleVertLength - moduleVertLength / 2], { - stroke: guideColor.hex, + stroke: gridColor, strokeWidth: 1, selectable: true, lockMovementX: true, @@ -89,7 +90,7 @@ export default function GridSettingsModal(props) { const verticalLine = new fabric.Line( [i * moduleHoriLength - moduleHoriLength / 2, 0, i * moduleHoriLength - moduleHoriLength / 2, canvasProps.height], { - stroke: guideColor.hex, + stroke: gridColor, strokeWidth: 1, selectable: true, lockMovementX: true, diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index da141287..c73e442f 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -13,7 +13,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { area: 0, children: [], initialize: function (points, options, canvas) { - this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? false }) + this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? true }) if (options.id) { this.id = options.id } else { @@ -75,7 +75,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { const y2 = this.top + this.height * scaleY const dx = x2 - x1 const dy = y2 - y1 - this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0)) + this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) * 10 }, addLengthText() { diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 84e57974..fec9e227 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -27,6 +27,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { point.x = Math.round(point.x) point.y = Math.round(point.y) }) + options.selectable = options.selectable ?? true options.sort = options.sort ?? true options.parentId = options.parentId ?? null @@ -51,6 +52,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { } this.callSuper('initialize', points, options) + if (options.id) { this.id = options.id } else { @@ -164,6 +166,9 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { stroke: this.stroke, strokeWidth: this.strokeWidth, fontSize: this.fontSize, + attributes: { + offset: 0, + }, direction: getDirectionByPoint(point, nextPoint), idx: i, }) @@ -193,14 +198,14 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { const end = points[(i + 1) % points.length] const dx = end.x - start.x const dy = end.y - start.y - const length = Math.sqrt(dx * dx + dy * dy) + const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) * 10 const midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2) const degree = (Math.atan2(dy, dx) * 180) / Math.PI // Create new text object if it doesn't exist - const text = new fabric.IText(length.toFixed(0), { + const text = new fabric.Text(length.toFixed(0), { left: midPoint.x, top: midPoint.y, fontSize: this.fontSize, diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index 7276805a..975c944b 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -149,7 +149,7 @@ export default function CanvasMenu(props) {
}
- +
diff --git a/src/components/floor-plan/modal/grid/DotLineGrid.jsx b/src/components/floor-plan/modal/grid/DotLineGrid.jsx index 86584959..54780ab5 100644 --- a/src/components/floor-plan/modal/grid/DotLineGrid.jsx +++ b/src/components/floor-plan/modal/grid/DotLineGrid.jsx @@ -1,12 +1,13 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' import QSelectBox from '@/components/common/select/QSelectBox' -import { useState } from 'react' +import { useEffect, useState } from 'react' import { useMessage } from '@/hooks/useMessage' import { canvasState, dotLineGridSettingState, dotLineIntervalSelector } from '@/store/canvasAtom' -import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' +import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil' import { onlyNumberInputChange } from '@/util/input-utils' import { fabric } from 'fabric' import { gridColorState } from '@/store/gridAtom' +import { settingModalGridOptionsState } from '@/store/settingAtom' const TYPE = { DOT: 'DOT', @@ -17,6 +18,7 @@ export default function DotLineGrid(props) { // const [modalOption, setModalOption] = useRecoilState(modalState); //modal 열림닫힘 state const [close, setClose] = useState(false) const { setShowDotLineGridModal } = props + const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState) const gridColor = useRecoilValue(gridColorState) const canvas = useRecoilValue(canvasState) @@ -25,6 +27,17 @@ export default function DotLineGrid(props) { const interval = useRecoilValue(dotLineIntervalSelector) const { getMessage } = useMessage() + + useEffect(() => { + return () => { + setSettingModalGridOptions((prev) => { + const newSettingOptions = [...prev] + newSettingOptions[1].selected = false + return [...newSettingOptions] + }) + } + }, []) + const SelectOption = [ { id: 1, name: getMessage('modal.canvas.setting.grid.dot.line.setting.line.origin'), value: 1 }, { id: 2, name: '1/2', value: 1 / 2 }, @@ -144,7 +157,7 @@ export default function DotLineGrid(props) { const verticalLine = new fabric.Line( [i * horizontalInterval - horizontalInterval / 2, 0, i * horizontalInterval - horizontalInterval / 2, canvas.height], { - stroke: 'black', + stroke: gridColor, strokeWidth: 1, selectable: true, lockMovementX: true, diff --git a/src/components/floor-plan/modal/grid/GridColorSetting.jsx b/src/components/floor-plan/modal/grid/GridColorSetting.jsx index ed213250..5b7b2ff6 100644 --- a/src/components/floor-plan/modal/grid/GridColorSetting.jsx +++ b/src/components/floor-plan/modal/grid/GridColorSetting.jsx @@ -1,14 +1,26 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' import ColorPicker from '@/components/common/color-picker/ColorPicker' -import { useRecoilState } from 'recoil' +import { useRecoilState, useSetRecoilState } from 'recoil' import { gridColorState } from '@/store/gridAtom' import { useMessage } from '@/hooks/useMessage' +import { useEffect } from 'react' +import { settingModalGridOptionsState } from '@/store/settingAtom' export default function GridColorSetting(props) { const { setShowColorPickerModal } = props const [color, setColor] = useRecoilState(gridColorState) + const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState) const { getMessage } = useMessage() + useEffect(() => { + return () => { + setSettingModalGridOptions((prev) => { + const newSettingOptions = [...prev] + newSettingOptions[3].selected = false + return [...newSettingOptions] + }) + } + }, []) return (
diff --git a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx index a3493f17..ffa5e0e7 100644 --- a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx @@ -2,6 +2,7 @@ import { useMessage } from '@/hooks/useMessage' import { onlyNumberInputChange } from '@/util/input-utils' +import GridMove from '@/components/floor-plan/modal/grid/GridMove' export default function OuterLineWall({ props }) { const { getMessage } = useMessage() diff --git a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx index cd2973e7..248567e3 100644 --- a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx @@ -9,7 +9,7 @@ export default function PropertiesSetting(props) { const { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } = usePropertiesSetting() return ( - +

{getMessage('modal.canvas.setting.wallline.properties.setting')}

diff --git a/src/components/floor-plan/modal/setting01/GridOption.jsx b/src/components/floor-plan/modal/setting01/GridOption.jsx index 1b157b75..d9301afc 100644 --- a/src/components/floor-plan/modal/setting01/GridOption.jsx +++ b/src/components/floor-plan/modal/setting01/GridOption.jsx @@ -18,7 +18,6 @@ export default function GridOption(props) { const [color, setColor] = useColor(gridColor) useEffect(() => { - console.log(color) setGridColor(color.hex) }, [color]) diff --git a/src/components/floor-plan/modal/setting01/SettingModal01.jsx b/src/components/floor-plan/modal/setting01/SettingModal01.jsx index b08a2578..78511548 100644 --- a/src/components/floor-plan/modal/setting01/SettingModal01.jsx +++ b/src/components/floor-plan/modal/setting01/SettingModal01.jsx @@ -6,11 +6,18 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' import SecondOption from '@/components/floor-plan/modal/setting01/SecondOption' import { useMessage } from '@/hooks/useMessage' import GridOption from '@/components/floor-plan/modal/setting01/GridOption' +import { canGridOptionSeletor } from '@/store/canvasAtom' +import { useRecoilValue } from 'recoil' export default function SettingModal01(props) { const { setShowCanvasSettingModal, setShowDotLineGridModal, setShowColorPickerModal } = props const [buttonAct, setButtonAct] = useState(1) const { getMessage } = useMessage() + const canGridOptionSeletorValue = useRecoilValue(canGridOptionSeletor) + + const handleBtnClick = (num) => { + setButtonAct(num) + } return ( @@ -23,16 +30,18 @@ export default function SettingModal01(props) {
- - - + {canGridOptionSeletorValue && ( + + )}
{buttonAct === 1 && } {buttonAct === 2 && } diff --git a/src/hooks/roofcover/useOuterLineWall.js b/src/hooks/roofcover/useOuterLineWall.js index 0f1e4f41..130593a0 100644 --- a/src/hooks/roofcover/useOuterLineWall.js +++ b/src/hooks/roofcover/useOuterLineWall.js @@ -1,6 +1,6 @@ import { useEffect, useRef } from 'react' import { distanceBetweenPoints, getDegreeByChon } from '@/util/canvas-util' -import { useRecoilState, useRecoilValue } from 'recoil' +import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { adsorptionPointAddModeState, adsorptionPointModeState, @@ -20,6 +20,7 @@ import { outerLineArrow1State, outerLineArrow2State, outerLineDiagonalState, + outerLineFixState, outerLineLength1State, outerLineLength2State, outerLinePointsState, @@ -59,6 +60,8 @@ export function useOuterLineWall() { const arrow1Ref = useRef(arrow1) const arrow2Ref = useRef(arrow2) + const setOuterLineFix = useSetRecoilState(outerLineFixState) + const outerLineDiagonalLengthRef = useRef(null) const isFix = useRef(false) @@ -69,6 +72,15 @@ export function useOuterLineWall() { if (adsorptionPointAddMode || tempGridMode) { return } + + if (points.length === 0) { + // 만약 포인트가 없다면 모든 라인과 텍스트를 삭제 후 outerLines에서 point를 뽑아 points에 넣어준다. + const lengthTxts = canvas?.getObjects().filter((obj) => obj.name === 'lengthTxt') + lengthTxts.forEach((txt) => { + canvas?.remove(txt) + }) + } + addCanvasMouseEventListener('mouse:down', mouseDown) clear() }, [verticalHorizontalMode, points, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, interval, tempGridMode]) @@ -153,6 +165,7 @@ export function useOuterLineWall() { canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'startPoint')) if (points.length === 0) { + setOuterLineFix(true) removeAllDocumentEventListeners() return } @@ -172,6 +185,7 @@ export function useOuterLineWall() { canvas?.add(point) } else { + setOuterLineFix(false) points.forEach((point, idx) => { if (idx === 0) { return @@ -183,10 +197,10 @@ export function useOuterLineWall() { const firstPoint = points[0] if (isFix.current) { - canvas?.renderAll() - closeModalFn.current(false) removeAllMouseEventListeners() removeAllDocumentEventListeners() + canvas?.renderAll() + closeModalFn.current(false) } if (points.length < 3) { diff --git a/src/hooks/roofcover/usePropertiesSetting.js b/src/hooks/roofcover/usePropertiesSetting.js index 9df385ed..d478a1bc 100644 --- a/src/hooks/roofcover/usePropertiesSetting.js +++ b/src/hooks/roofcover/usePropertiesSetting.js @@ -1,91 +1,116 @@ import { useEffect, useRef } from 'react' import { LINE_TYPE } from '@/common/common' import { useRecoilValue } from 'recoil' -import { canvasState } from '@/store/canvasAtom' +import { canvasState, currentObjectState } from '@/store/canvasAtom' +import { useMode } from '@/hooks/useMode' +import { usePolygon } from '@/hooks/usePolygon' +import { useLine } from '@/hooks/useLine' export function usePropertiesSetting() { - const currentLine = useRef(null) - const currentIdx = useRef(-1) const canvas = useRecoilValue(canvasState) + const currentObject = useRecoilValue(currentObjectState) + + const { drawRoofPolygon } = useMode() + + const { addPolygonByLines } = usePolygon() + const { removeLine } = useLine() + useEffect(() => { - selectNextLine() - }, []) + if (!currentObject) { + return + } + if (currentObject.name !== 'outerLine') { + return + } + + const type = currentObject.attributes?.type + + const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + lines.forEach((line) => { + const lineType = line.attributes?.type + if (!lineType) { + line.set({ + stroke: '#000000', + strokeWidth: 4, + }) + } + }) + + if (!type) { + currentObject.set({ + stroke: '#EA10AC', + strokeWidth: 4, + }) + } + }, [currentObject]) + + const history = useRef([]) const handleSetEaves = () => { - currentLine.current.set({ + const selectedLine = canvas?.getActiveObject() + if (!selectedLine) { + return + } + selectedLine.set({ stroke: '#45CD7D', strokeWidth: 4, attributes: { - offset: 500, + offset: 50, type: LINE_TYPE.WALLLINE.EAVES, pitch: 4, }, }) + history.current.push(selectedLine) + nextLineFocus(selectedLine) canvas.renderAll() - selectNextLine() } const handleSetGable = () => { - currentLine.current.set({ + const selectedLine = canvas?.getActiveObject() + if (!selectedLine) { + return + } + selectedLine.set({ stroke: '#3FBAE6', strokeWidth: 4, attributes: { - offset: 300, + offset: 30, type: LINE_TYPE.WALLLINE.GABLE, }, }) - canvas.renderAll() - selectNextLine() - } - - const selectNextLine = () => { - const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') - currentIdx.current++ - - if (currentIdx.current >= lines.length) { - currentIdx.current = lines.length - currentLine.current = lines[currentIdx.current - 1] - return - } - - currentLine.current = lines[currentIdx.current] - - currentLine.current.set({ - stroke: '#EA10AC', - strokeWidth: 4, - }) - + history.current.push(selectedLine) + nextLineFocus(selectedLine) canvas.renderAll() } - const selectPrevLine = () => { + const nextLineFocus = (selectedLine) => { const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + const index = lines.findIndex((line) => line === selectedLine) - currentIdx.current-- - - if (currentIdx.current <= -1) { - currentIdx.current = -1 - selectNextLine() - return + const nextLine = lines[index + 1] || lines[0] + if (!nextLine.attributes?.type) { + canvas.setActiveObject(nextLine) } else { - lines.forEach((line, index) => { - if (index >= currentIdx.current) { - delete line.attributes - line.set({ - stroke: '#000000', - strokeWidth: 4, - }) - } - currentIdx.current-- - canvas.renderAll() - selectNextLine() - }) + //activeObject 해제 + canvas.discardActiveObject() } } const handleRollback = () => { - selectPrevLine() + if (history.current.length === 0) { + return + } + const lastLine = history.current.pop() + + lastLine.set({ + stroke: '#000000', + strokeWidth: 4, + }) + + canvas.setActiveObject(lastLine) + canvas.renderAll() } const handleFix = () => { @@ -100,8 +125,15 @@ export function usePropertiesSetting() { stroke: '#000000', strokeWidth: 4, }) + removeLine(line) }) + const wall = addPolygonByLines(lines, { name: 'WallLine', fill: 'transparent', stroke: 'black' }) + + wall.lines = [...lines] + + drawRoofPolygon(wall) + canvas.renderAll() } @@ -121,7 +153,6 @@ export function usePropertiesSetting() { }) canvas.renderAll() - fn(false) } diff --git a/src/hooks/useEvent.js b/src/hooks/useEvent.js index 67ff8c44..f9203dc1 100644 --- a/src/hooks/useEvent.js +++ b/src/hooks/useEvent.js @@ -1,6 +1,6 @@ import { useEffect, useRef } from 'react' -import { useRecoilState, useRecoilValue } from 'recoil' -import { canvasState, canvasZoomState, currentMenuState } from '@/store/canvasAtom' +import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' +import { canvasState, canvasZoomState, currentMenuState, textModeState } from '@/store/canvasAtom' import { fabric } from 'fabric' import { calculateDistance, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util' import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint' @@ -12,12 +12,14 @@ export function useEvent() { const currentMenu = useRecoilValue(currentMenuState) const documentEventListeners = useRef([]) const mouseEventListeners = useRef([]) - const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) + const setCanvasZoom = useSetRecoilState(canvasZoomState) const { adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, getAdsorptionPoints, adsorptionPointAddModeStateEvent } = useAdsorptionPoint() const { dotLineGridSetting, interval, getClosestLineGrid } = useDotLineGrid() const { tempGridModeStateLeftClickEvent, tempGridMode, tempGridRightClickEvent } = useTempGrid() + const textMode = useRecoilValue(textModeState) + useEffect(() => { if (!canvas) { return @@ -38,6 +40,7 @@ export function useEvent() { addCanvasMouseEventListener('mouse:move', defaultMouseMoveEvent) addCanvasMouseEventListener('mouse:out', defaultMouseOutEvent) addDocumentEventListener('keydown', document, defaultKeyboardEvent) + addDocumentEventListener('contextmenu', document, defaultContextMenuEvent) if (adsorptionPointAddMode) { addCanvasMouseEventListener('mouse:down', adsorptionPointAddModeStateEvent) } diff --git a/src/hooks/useLine.js b/src/hooks/useLine.js index d42af418..b6c8a532 100644 --- a/src/hooks/useLine.js +++ b/src/hooks/useLine.js @@ -1,5 +1,6 @@ import { useRecoilValue } from 'recoil' import { canvasState, fontFamilyState, fontSizeState } from '@/store/canvasAtom' +import { QLine } from '@/components/fabric/QLine' export const useLine = () => { const canvas = useRecoilValue(canvasState) @@ -7,13 +8,13 @@ export const useLine = () => { const fontFamily = useRecoilValue(fontFamilyState) const addLine = (points = [], options) => { - const line = new fabric.Line(points, { + const line = new QLine(points, { ...options, - selectable: options.selectable ?? false, + fontSize: fontSize, + fontFamily: fontFamily, }) canvas?.add(line) - addLineText(line) return line } diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index ee110a5e..0c353864 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -1678,7 +1678,7 @@ export function useMode() { const drawRoofPolygon = (wall) => { // TODO [ljyoung] : offset 입력 처리 후 제거 해야함. - wall.lines.forEach((line, index) => { + /*wall.lines.forEach((line, index) => { if (index === wall.lines.length - 1 || index === 3) { line.attributes = { type: 'gable', @@ -1690,7 +1690,7 @@ export function useMode() { offset: 50, } } - }) + })*/ const polygon = createRoofPolygon(wall.points) const originPolygon = new QPolygon(wall.points, { fontSize: 0 }) diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index b364bf86..13b12fe1 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -2,6 +2,7 @@ import { canvasState, fontFamilyState, fontSizeState } from '@/store/canvasAtom' import { useRecoilValue } from 'recoil' import { fabric } from 'fabric' import { getDirectionByPoint } from '@/util/canvas-util' +import { QPolygon } from '@/components/fabric/QPolygon' export const usePolygon = () => { const canvas = useRecoilValue(canvasState) @@ -9,19 +10,22 @@ export const usePolygon = () => { const fontFamily = useRecoilValue(fontFamilyState) const addPolygon = (points, options) => { - const polygon = new fabric.Polygon(points, { + const polygon = new QPolygon(points, { ...options, - selectable: options.selectable ?? false, + fontSize: fontSize, + fontFamily: fontFamily, + selectable: true, }) canvas?.add(polygon) - addLengthText(polygon) + + return polygon } const addPolygonByLines = (lines, options) => { const points = createPolygonPointsFromOuterLines(lines) - addPolygon(points, { + return addPolygon(points, { ...options, }) } @@ -39,10 +43,11 @@ export const usePolygon = () => { const degree = (Math.atan2(dy, dx) * 180) / Math.PI // Create new text object if it doesn't exist - const text = new fabric.IText(length.toString(), { + const text = new fabric.Text(length.toString(), { left: midPoint.x, top: midPoint.y, fontSize: fontSize, + fontFamily: fontFamily, parentId: polygon.id, minX: Math.min(start.x, end.x), maxX: Math.max(start.x, end.x), diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index aa400a46..9fb440c6 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -1,5 +1,6 @@ import { atom, selector } from 'recoil' import { MENU } from '@/common/common' +import { outerLineFixState, outerLinePointsState } from '@/store/outerLineAtom' export const canvasState = atom({ key: 'canvasState', @@ -267,3 +268,18 @@ export const tempGridModeState = atom({ key: 'tempGridModeState', default: false, }) + +export const textModeState = atom({ + key: 'textModeState', + default: false, +}) + +export const canGridOptionSeletor = selector({ + key: 'canGridOptionSeletor', + get: ({ get }) => { + const points = get(outerLinePointsState) + const currentMenu = get(currentMenuState) + const outerLineFix = get(outerLineFixState) + return points.length === 0 || outerLineFix + }, +}) diff --git a/src/store/gridAtom.js b/src/store/gridAtom.js index 9b21a9f5..a4b4b15b 100644 --- a/src/store/gridAtom.js +++ b/src/store/gridAtom.js @@ -2,5 +2,5 @@ import { atom } from 'recoil' export const gridColorState = atom({ key: 'gridColorState', - default: '#000000', + default: '#FF0000', }) diff --git a/src/store/outerLineAtom.js b/src/store/outerLineAtom.js index 2fcc5f9d..361bc526 100644 --- a/src/store/outerLineAtom.js +++ b/src/store/outerLineAtom.js @@ -63,3 +63,8 @@ export const outerLinePointsState = atom({ key: 'outerLinePointsState', default: [], }) + +export const outerLineFixState = atom({ + key: 'outerLineFixState', + default: false, +}) diff --git a/src/store/settingAtom.js b/src/store/settingAtom.js index 7c637c2f..80fa9c4c 100644 --- a/src/store/settingAtom.js +++ b/src/store/settingAtom.js @@ -1,4 +1,4 @@ -import { atom } from 'recoil' +import { atom, selector } from 'recoil' export const settingModalFirstOptionsState = atom({ key: 'settingModalFirstOptions', From 3505064c96386addbebfcbda63ba6957fe30b8d7 Mon Sep 17 00:00:00 2001 From: minsik Date: Wed, 2 Oct 2024 17:08:50 +0900 Subject: [PATCH 023/152] =?UTF-8?q?-=20=EC=A7=80=EB=B6=95=ED=98=95?= =?UTF-8?q?=EC=83=81=20=EC=84=A4=EC=A0=95=20=EB=AA=A8=EB=8B=AC=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 --- .../images/canvas/allocation_delete.svg | 4 + .../static/images/canvas/allocation_edit.svg | 4 + .../images/canvas/allocation_icon01_black.svg | 6 + .../images/canvas/allocation_icon01_white.svg | 6 + .../images/canvas/allocation_icon02_black.svg | 6 + .../images/canvas/allocation_icon02_white.svg | 6 + public/static/images/canvas/eaves_icon01.svg | 10 + public/static/images/canvas/eaves_icon02.svg | 10 + public/static/images/canvas/eaves_icon03.svg | 15 + public/static/images/canvas/eaves_icon04.svg | 9 + public/static/images/canvas/eaves_icon05.svg | 10 + public/static/images/canvas/eaves_icon06.svg | 18 + public/static/images/canvas/eaves_icon07.svg | 23 + public/static/images/canvas/eaves_icon08.svg | 15 + public/static/images/canvas/shape_menu01.svg | 34 + public/static/images/canvas/shape_menu02.svg | 31 + public/static/images/canvas/shape_menu03.svg | 31 + public/static/images/canvas/shape_menu04.svg | 30 + public/static/images/canvas/shape_menu05.svg | 29 + public/static/images/canvas/shape_menu06.svg | 29 + public/static/images/canvas/shape_menu07.svg | 29 + public/static/images/canvas/shape_menu08.svg | 29 + src/components/floor-plan/CanvasMenu.jsx | 5 +- src/components/floor-plan/FloorPlan.jsx | 4 + src/components/floor-plan/MenuDepth01.jsx | 3 +- ...peSetting.js => PlacementShapeSetting.jsx} | 0 .../modal/roofShape/RoofShapeSetting.jsx | 58 + .../modal/roofShape/type/Direction.jsx | 45 + .../modal/roofShape/type/Pattern.jsx | 36 + .../floor-plan/modal/roofShape/type/Ridge.jsx | 27 + .../floor-plan/modal/roofShape/type/Side.jsx | 46 + .../modal/roofShape/type/option/Eaves.jsx | 27 + .../modal/roofShape/type/option/Gable.jsx | 16 + .../roofShape/type/option/HipAndGable.jsx | 36 + .../roofShape/type/option/Jerkinhead.jsx | 36 + .../modal/roofShape/type/option/Shed.jsx | 16 + .../modal/roofShape/type/option/Wall.jsx | 38 + src/locales/ja.json | 29 +- src/locales/ko.json | 30 +- src/styles/_modal.scss | 312 +++- src/styles/_reset.scss | 1267 ++++++++--------- 41 files changed, 1699 insertions(+), 716 deletions(-) create mode 100644 public/static/images/canvas/allocation_delete.svg create mode 100644 public/static/images/canvas/allocation_edit.svg create mode 100644 public/static/images/canvas/allocation_icon01_black.svg create mode 100644 public/static/images/canvas/allocation_icon01_white.svg create mode 100644 public/static/images/canvas/allocation_icon02_black.svg create mode 100644 public/static/images/canvas/allocation_icon02_white.svg create mode 100644 public/static/images/canvas/eaves_icon01.svg create mode 100644 public/static/images/canvas/eaves_icon02.svg create mode 100644 public/static/images/canvas/eaves_icon03.svg create mode 100644 public/static/images/canvas/eaves_icon04.svg create mode 100644 public/static/images/canvas/eaves_icon05.svg create mode 100644 public/static/images/canvas/eaves_icon06.svg create mode 100644 public/static/images/canvas/eaves_icon07.svg create mode 100644 public/static/images/canvas/eaves_icon08.svg create mode 100644 public/static/images/canvas/shape_menu01.svg create mode 100644 public/static/images/canvas/shape_menu02.svg create mode 100644 public/static/images/canvas/shape_menu03.svg create mode 100644 public/static/images/canvas/shape_menu04.svg create mode 100644 public/static/images/canvas/shape_menu05.svg create mode 100644 public/static/images/canvas/shape_menu06.svg create mode 100644 public/static/images/canvas/shape_menu07.svg create mode 100644 public/static/images/canvas/shape_menu08.svg rename src/components/floor-plan/modal/placementShape/{PlacementShapeSetting.js => PlacementShapeSetting.jsx} (100%) create mode 100644 src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx create mode 100644 src/components/floor-plan/modal/roofShape/type/Direction.jsx create mode 100644 src/components/floor-plan/modal/roofShape/type/Pattern.jsx create mode 100644 src/components/floor-plan/modal/roofShape/type/Ridge.jsx create mode 100644 src/components/floor-plan/modal/roofShape/type/Side.jsx create mode 100644 src/components/floor-plan/modal/roofShape/type/option/Eaves.jsx create mode 100644 src/components/floor-plan/modal/roofShape/type/option/Gable.jsx create mode 100644 src/components/floor-plan/modal/roofShape/type/option/HipAndGable.jsx create mode 100644 src/components/floor-plan/modal/roofShape/type/option/Jerkinhead.jsx create mode 100644 src/components/floor-plan/modal/roofShape/type/option/Shed.jsx create mode 100644 src/components/floor-plan/modal/roofShape/type/option/Wall.jsx diff --git a/public/static/images/canvas/allocation_delete.svg b/public/static/images/canvas/allocation_delete.svg new file mode 100644 index 00000000..711a241e --- /dev/null +++ b/public/static/images/canvas/allocation_delete.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/allocation_edit.svg b/public/static/images/canvas/allocation_edit.svg new file mode 100644 index 00000000..795d10f9 --- /dev/null +++ b/public/static/images/canvas/allocation_edit.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/allocation_icon01_black.svg b/public/static/images/canvas/allocation_icon01_black.svg new file mode 100644 index 00000000..01829a32 --- /dev/null +++ b/public/static/images/canvas/allocation_icon01_black.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/static/images/canvas/allocation_icon01_white.svg b/public/static/images/canvas/allocation_icon01_white.svg new file mode 100644 index 00000000..5618848e --- /dev/null +++ b/public/static/images/canvas/allocation_icon01_white.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/static/images/canvas/allocation_icon02_black.svg b/public/static/images/canvas/allocation_icon02_black.svg new file mode 100644 index 00000000..57c6173b --- /dev/null +++ b/public/static/images/canvas/allocation_icon02_black.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/static/images/canvas/allocation_icon02_white.svg b/public/static/images/canvas/allocation_icon02_white.svg new file mode 100644 index 00000000..17211b04 --- /dev/null +++ b/public/static/images/canvas/allocation_icon02_white.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/static/images/canvas/eaves_icon01.svg b/public/static/images/canvas/eaves_icon01.svg new file mode 100644 index 00000000..da520069 --- /dev/null +++ b/public/static/images/canvas/eaves_icon01.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/static/images/canvas/eaves_icon02.svg b/public/static/images/canvas/eaves_icon02.svg new file mode 100644 index 00000000..0addbc04 --- /dev/null +++ b/public/static/images/canvas/eaves_icon02.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/static/images/canvas/eaves_icon03.svg b/public/static/images/canvas/eaves_icon03.svg new file mode 100644 index 00000000..b95b49fc --- /dev/null +++ b/public/static/images/canvas/eaves_icon03.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/eaves_icon04.svg b/public/static/images/canvas/eaves_icon04.svg new file mode 100644 index 00000000..ac08ce05 --- /dev/null +++ b/public/static/images/canvas/eaves_icon04.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/static/images/canvas/eaves_icon05.svg b/public/static/images/canvas/eaves_icon05.svg new file mode 100644 index 00000000..649a6058 --- /dev/null +++ b/public/static/images/canvas/eaves_icon05.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/static/images/canvas/eaves_icon06.svg b/public/static/images/canvas/eaves_icon06.svg new file mode 100644 index 00000000..a2f17801 --- /dev/null +++ b/public/static/images/canvas/eaves_icon06.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/eaves_icon07.svg b/public/static/images/canvas/eaves_icon07.svg new file mode 100644 index 00000000..1f101d56 --- /dev/null +++ b/public/static/images/canvas/eaves_icon07.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/eaves_icon08.svg b/public/static/images/canvas/eaves_icon08.svg new file mode 100644 index 00000000..8a2529de --- /dev/null +++ b/public/static/images/canvas/eaves_icon08.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape_menu01.svg b/public/static/images/canvas/shape_menu01.svg new file mode 100644 index 00000000..6fbe44cc --- /dev/null +++ b/public/static/images/canvas/shape_menu01.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape_menu02.svg b/public/static/images/canvas/shape_menu02.svg new file mode 100644 index 00000000..36a5eb41 --- /dev/null +++ b/public/static/images/canvas/shape_menu02.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape_menu03.svg b/public/static/images/canvas/shape_menu03.svg new file mode 100644 index 00000000..ae7701c3 --- /dev/null +++ b/public/static/images/canvas/shape_menu03.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape_menu04.svg b/public/static/images/canvas/shape_menu04.svg new file mode 100644 index 00000000..e23282c5 --- /dev/null +++ b/public/static/images/canvas/shape_menu04.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape_menu05.svg b/public/static/images/canvas/shape_menu05.svg new file mode 100644 index 00000000..500d6bc6 --- /dev/null +++ b/public/static/images/canvas/shape_menu05.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape_menu06.svg b/public/static/images/canvas/shape_menu06.svg new file mode 100644 index 00000000..a13e1b6c --- /dev/null +++ b/public/static/images/canvas/shape_menu06.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape_menu07.svg b/public/static/images/canvas/shape_menu07.svg new file mode 100644 index 00000000..08119e5e --- /dev/null +++ b/public/static/images/canvas/shape_menu07.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape_menu08.svg b/public/static/images/canvas/shape_menu08.svg new file mode 100644 index 00000000..4588b3bb --- /dev/null +++ b/public/static/images/canvas/shape_menu08.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index 7276805a..b6d2c269 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -10,7 +10,7 @@ import QSelectBox from '@/components/common/select/QSelectBox' import { useMessage } from '@/hooks/useMessage' import { usePlan } from '@/hooks/usePlan' import { useSwal } from '@/hooks/useSwal' -import { canvasState, canvasZoomState, currentMenuState, currentCanvasPlanState, verticalHorizontalModeState } from '@/store/canvasAtom' +import { canvasState, canvasZoomState, currentCanvasPlanState, currentMenuState, verticalHorizontalModeState } from '@/store/canvasAtom' import { sessionStore } from '@/store/commonAtom' import { outerLinePointsState } from '@/store/outerLineAtom' import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' @@ -31,7 +31,7 @@ const canvasMenus = [ ] export default function CanvasMenu(props) { - const { setShowCanvasSettingModal, showOutlineModal, setShowOutlineModal, setShowPlaceShapeModal } = props + const { setShowCanvasSettingModal, showOutlineModal, setShowOutlineModal, setShowPlaceShapeModal, setShowRoofShapeSettingModal } = props const [menuNumber, setMenuNumber] = useState(null) const [type, setType] = useState('') @@ -75,6 +75,7 @@ export default function CanvasMenu(props) { const menuProps = { setShowOutlineModal, setShowPlaceShapeModal, + setShowRoofShapeSettingModal, type, } diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx index ee27cbcd..38d31f9d 100644 --- a/src/components/floor-plan/FloorPlan.jsx +++ b/src/components/floor-plan/FloorPlan.jsx @@ -14,12 +14,14 @@ import WallLineSetting from '@/components/floor-plan/modal/outerlinesetting/Wall import PropertiesSetting from '@/components/floor-plan/modal/outerlinesetting/PropertiesSetting' import PlacementShapeSetting from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting' import GridColorSetting from './modal/grid/GridColorSetting' +import RoofShapeSetting from '@/components/floor-plan/modal/roofShape/RoofShapeSetting' export default function FloorPlan() { const [showCanvasSettingModal, setShowCanvasSettingModal] = useState(false) const [showOutlineModal, setShowOutlineModal] = useState(false) const [showPlaceShapeModal, setShowPlaceShapeModal] = useState(false) const [showPropertiesSettingModal, setShowPropertiesSettingModal] = useState(false) + const [showRoofShapeSettingModal, setShowRoofShapeSettingModal] = useState(false) const globalLocaleState = useRecoilValue(globalLocaleStore) const { get } = useAxios(globalLocaleState) @@ -47,6 +49,7 @@ export default function FloorPlan() { showOutlineModal, setShowOutlineModal, setShowPlaceShapeModal, + setShowRoofShapeSettingModal, } useEffect(() => { @@ -106,6 +109,7 @@ export default function FloorPlan() { {showColorPickerModal && } {showPropertiesSettingModal && } {showPlaceShapeModal && } + {showRoofShapeSettingModal && }
diff --git a/src/components/floor-plan/MenuDepth01.jsx b/src/components/floor-plan/MenuDepth01.jsx index 925978e6..43a059f0 100644 --- a/src/components/floor-plan/MenuDepth01.jsx +++ b/src/components/floor-plan/MenuDepth01.jsx @@ -7,7 +7,7 @@ import { currentMenuState } from '@/store/canvasAtom' import { useSetRecoilState } from 'recoil' export default function MenuDepth01(props) { - const { setShowOutlineModal, type, setShowPlaceShapeModal } = props + const { setShowOutlineModal, type, setShowPlaceShapeModal, setShowRoofShapeSettingModal } = props const { getMessage } = useMessage() const [activeMenu, setActiveMenu] = useState() const setCurrentMenu = useSetRecoilState(currentMenuState) @@ -18,6 +18,7 @@ export default function MenuDepth01(props) { if (type === 'outline') { setShowPlaceShapeModal(false) setShowOutlineModal(id === 0) + setShowRoofShapeSettingModal(id === 1) } } diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.js b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx similarity index 100% rename from src/components/floor-plan/modal/placementShape/PlacementShapeSetting.js rename to src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx diff --git a/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx b/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx new file mode 100644 index 00000000..517a7ba3 --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx @@ -0,0 +1,58 @@ +import { useMessage } from '@/hooks/useMessage' +import WithDraggable from '@/components/common/draggable/WithDraggable' +import Ridge from '@/components/floor-plan/modal/roofShape/type/Ridge' +import Pattern from '@/components/floor-plan/modal/roofShape/type/Pattern' +import Side from '@/components/floor-plan/modal/roofShape/type/Side' +import { useState } from 'react' +import Image from 'next/image' +import Direction from '@/components/floor-plan/modal/roofShape/type/Direction' + +export default function RoofShapeSetting({ setShowRoofShapeSettingModal }) { + const { getMessage } = useMessage() + const [shapeNum, setShapeNum] = useState(1) + const shapeMenu = [ + { id: 1, name: getMessage('modal.roof.shape.setting.ridge') }, // 용마루 + { id: 2, name: getMessage('modal.roof.shape.setting.patten.a') }, // 패턴A + { id: 3, name: getMessage('modal.roof.shape.setting.patten.b') }, // 패턴B + { id: 4, name: getMessage('modal.roof.shape.setting.side') }, // 변별로 설정 + { id: 5, name: getMessage('commons.west') }, // 서 + { id: 6, name: getMessage('commons.east') }, // 서 + { id: 7, name: getMessage('commons.south') }, // 서 + { id: 8, name: getMessage('commons.north') }, // 북 + ] + + return ( + +
+
+

{getMessage('modal.roof.shape.setting')}

+ +
+
+
+ {shapeMenu.map((item) => ( + + ))} +
+
+
{getMessage('setting')}
+ {shapeNum === 1 && } + {(shapeNum === 2 || shapeNum === 3) && } + {shapeNum === 4 && } + {(shapeNum === 5 || shapeNum === 6 || shapeNum === 7 || shapeNum === 8) && } +
+
+ +
+
+
+
+ ) +} diff --git a/src/components/floor-plan/modal/roofShape/type/Direction.jsx b/src/components/floor-plan/modal/roofShape/type/Direction.jsx new file mode 100644 index 00000000..a02258f9 --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/type/Direction.jsx @@ -0,0 +1,45 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function Direction() { + const { getMessage } = useMessage() + return ( +
+
+ + {getMessage('slope')} + +
+ +
+ {getMessage('size')} +
+
+ + {getMessage('eaves.offset')} + +
+ +
+ mm +
+
+ + {getMessage('gable.offset')} + +
+ +
+ mm +
+
+ + {getMessage('windage.width')} + +
+ +
+ mm +
+
+ ) +} diff --git a/src/components/floor-plan/modal/roofShape/type/Pattern.jsx b/src/components/floor-plan/modal/roofShape/type/Pattern.jsx new file mode 100644 index 00000000..606c154d --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/type/Pattern.jsx @@ -0,0 +1,36 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function Pattern() { + const { getMessage } = useMessage() + return ( +
+
+ + {getMessage('slope')} + +
+ +
+ {getMessage('size')} +
+
+ + {getMessage('eaves.offset')} + +
+ +
+ mm +
+
+ + {getMessage('gable.offset')} + +
+ +
+ mm +
+
+ ) +} diff --git a/src/components/floor-plan/modal/roofShape/type/Ridge.jsx b/src/components/floor-plan/modal/roofShape/type/Ridge.jsx new file mode 100644 index 00000000..7897046c --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/type/Ridge.jsx @@ -0,0 +1,27 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function Ridge() { + const { getMessage } = useMessage() + return ( +
+
+ + {getMessage('slope')} + +
+ +
+ {getMessage('size')} +
+
+ + {getMessage('eaves.offset')} + +
+ +
+ mm +
+
+ ) +} diff --git a/src/components/floor-plan/modal/roofShape/type/Side.jsx b/src/components/floor-plan/modal/roofShape/type/Side.jsx new file mode 100644 index 00000000..3fc1737c --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/type/Side.jsx @@ -0,0 +1,46 @@ +import { useState } from 'react' +import { useMessage } from '@/hooks/useMessage' +import Eaves from '@/components/floor-plan/modal/roofShape/type/option/Eaves' +import Gable from '@/components/floor-plan/modal/roofShape/type/option/Gable' +import HipAndGable from '@/components/floor-plan/modal/roofShape/type/option/HipAndGable' +import Wall from '@/components/floor-plan/modal/roofShape/type/option/Wall' +import Jerkinhead from '@/components/floor-plan/modal/roofShape/type/option/Jerkinhead' +import Shed from '@/components/floor-plan/modal/roofShape/type/option/Shed' + +export default function Side() { + const [buttonAct, setButtonAct] = useState(1) + const { getMessage } = useMessage() + const buttonMenu = [ + { id: 1, name: getMessage('eaves') }, + { id: 2, name: getMessage('gable') }, + { id: 3, name: getMessage('wall') }, + { id: 4, name: getMessage('hipandgable') }, + { id: 5, name: getMessage('jerkinhead') }, + { id: 6, name: getMessage('shed') }, + ] + return ( +
+
+
+ {buttonMenu.map((item) => ( + + ))} +
+
+
+ {buttonAct === 1 && } + {buttonAct === 2 && } + {buttonAct === 3 && } + {buttonAct === 4 && } + {buttonAct === 5 && } + {buttonAct === 6 && } +
+
+ + +
+
+ ) +} diff --git a/src/components/floor-plan/modal/roofShape/type/option/Eaves.jsx b/src/components/floor-plan/modal/roofShape/type/option/Eaves.jsx new file mode 100644 index 00000000..303dad55 --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/type/option/Eaves.jsx @@ -0,0 +1,27 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function Eaves() { + const { getMessage } = useMessage() + return ( + <> +
+ + {getMessage('slope')} + +
+ +
+ {getMessage('size')} +
+
+ + {getMessage('eaves.offset')} + +
+ +
+ mm +
+ + ) +} diff --git a/src/components/floor-plan/modal/roofShape/type/option/Gable.jsx b/src/components/floor-plan/modal/roofShape/type/option/Gable.jsx new file mode 100644 index 00000000..63092550 --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/type/option/Gable.jsx @@ -0,0 +1,16 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function Gable() { + const { getMessage } = useMessage() + return ( + <> +
+ {getMessage('gable.offset')} +
+ +
+ mm +
+ + ) +} diff --git a/src/components/floor-plan/modal/roofShape/type/option/HipAndGable.jsx b/src/components/floor-plan/modal/roofShape/type/option/HipAndGable.jsx new file mode 100644 index 00000000..ed2e1b60 --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/type/option/HipAndGable.jsx @@ -0,0 +1,36 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function HipAndGable() { + const { getMessage } = useMessage() + return ( + <> +
+ + {getMessage('slope')} + +
+ +
+ {getMessage('size')} +
+
+ + {getMessage('eaves.offset')} + +
+ +
+ mm +
+
+ + {getMessage('gable.offset')} + +
+ +
+ mm +
+ + ) +} diff --git a/src/components/floor-plan/modal/roofShape/type/option/Jerkinhead.jsx b/src/components/floor-plan/modal/roofShape/type/option/Jerkinhead.jsx new file mode 100644 index 00000000..d5737470 --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/type/option/Jerkinhead.jsx @@ -0,0 +1,36 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function Jerkinhead() { + const { getMessage } = useMessage() + return ( + <> +
+ + {getMessage('gable.offset')} + +
+ +
+ mm +
+
+ + {getMessage('jerkinhead.width')} + +
+ +
+ mm +
+
+ + {getMessage('jerkinhead.slope')} + +
+ +
+ {getMessage('size')} +
+ + ) +} diff --git a/src/components/floor-plan/modal/roofShape/type/option/Shed.jsx b/src/components/floor-plan/modal/roofShape/type/option/Shed.jsx new file mode 100644 index 00000000..c4fd4333 --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/type/option/Shed.jsx @@ -0,0 +1,16 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function Shed() { + const { getMessage } = useMessage() + return ( + <> +
+ {getMessage('shed.width')} +
+ +
+ mm +
+ + ) +} diff --git a/src/components/floor-plan/modal/roofShape/type/option/Wall.jsx b/src/components/floor-plan/modal/roofShape/type/option/Wall.jsx new file mode 100644 index 00000000..6b716892 --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/type/option/Wall.jsx @@ -0,0 +1,38 @@ +import { useState } from 'react' +import { useMessage } from '@/hooks/useMessage' + +export default function Wall() { + const [hasSleeve, setHasSleeve] = useState('0') + const { getMessage } = useMessage() + return ( + <> + {hasSleeve} +
+
+
+
+ setHasSleeve(e.target.value)} /> + +
+
+
+
+
+
+ setHasSleeve(e.target.value)} /> + +
+
+
+
+
+ +
+ mm +
+
+
+
+ + ) +} diff --git a/src/locales/ja.json b/src/locales/ja.json index a1285410..71c6fb8d 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -31,6 +31,11 @@ "modal.placement.initial.setting.roof.material": "屋根材の選択(単位:mm)", "modal.placement.initial.setting.roof.material.info": "対応可能な屋根材や足場は限定されますので、必ず事前マニュアルをご確認ください。", "modal.placement.initial.setting.rafter": "垂木の間隔", + "modal.roof.shape.setting": "屋根形状の設定", + "modal.roof.shape.setting.ridge": "龍丸屋根", + "modal.roof.shape.setting.patten.a": "Aパターン", + "modal.roof.shape.setting.patten.b": "Bパターン", + "modal.roof.shape.setting.side": "別に設定", "plan.menu.roof.cover": "지붕덮개", "plan.menu.roof.cover.outline.drawing": "外壁線を描", "plan.menu.roof.cover.roof.shape.setting": "屋根形状設定", @@ -49,6 +54,7 @@ "modal.cover.outline.fix": "外壁線確定", "modal.cover.outline.rollback": "一変戦に戻る", "modal.cover.outline.finish": "設定完了", + "common.setting.finish": "設定完了", "modal.cover.outline.remove": "外壁の削除", "modal.cover.outline.select.move": "外壁の選択、移動", "plan.menu.roof.cover.roof.setting": "屋根形状設定", @@ -226,6 +232,10 @@ "common.message.password.init.success": "パスワード [{0}] に初期化されました。", "common.message.no.edit.save": "この文書は変更できません。", "common.require": "필수", + "commons.west": "立つ", + "commons.east": "ドン", + "commons.south": "M", + "commons.north": "北", "site.name": "Q.CAST III", "site.sub_name": "태양광 발전 시스템 도면관리 사이트", "login": "로그인", @@ -284,5 +294,22 @@ "stuff.gridHeader.dispCompanyName": "견적처", "stuff.gridHeader.receiveUser": "담당자", "stuff.gridHeader.specDate": "사양확인", - "stuff.gridHeader.createDatetime": "등록일" + "stuff.gridHeader.createDatetime": "등록일", + "slope": "傾斜", + "eaves.offset": "軒の", + "gable.offset": "ケラバ出幅", + "size": "寸", + "eaves": "軒", + "gable": "ケラバ", + "wall": "壁", + "hipandgable": "八作屋根", + "jerkinhead": "半折", + "shed": "片側の流れ", + "apply": "適用", + "has.sleeve": "袖あり", + "has.not.sleeve": "袖なし", + "jerkinhead.width": "半折先幅", + "jerkinhead.slope": "半折先傾斜", + "shed.width": "片流幅", + "windage.width": "漂流の出幅" } diff --git a/src/locales/ko.json b/src/locales/ko.json index cc84b9d7..572c1eef 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -31,6 +31,11 @@ "modal.placement.initial.setting.roof.material": "지붕재 선택(단위: mm)", "modal.placement.initial.setting.roof.material.info": "대응 가능한 지붕재 및 발판은 한정되므로 반드시 사전 매뉴얼을 확인하십시오.", "modal.placement.initial.setting.rafter": "서까래", + "modal.roof.shape.setting": "지붕형상 설정", + "modal.roof.shape.setting.ridge": "용마루", + "modal.roof.shape.setting.patten.a": "A 패턴", + "modal.roof.shape.setting.patten.b": "A 패턴", + "modal.roof.shape.setting.side": "변별로 설정", "plan.menu.roof.cover": "지붕덮개", "plan.menu.roof.cover.outline.drawing": "외벽선 그리기", "plan.menu.roof.cover.roof.shape.setting": "지붕형상 설정", @@ -53,6 +58,8 @@ "modal.cover.outline.fix": "외벽선 확정", "modal.cover.outline.rollback": "일변전으로 돌아가기", "modal.cover.outline.finish": "설정완료", + "common.setting.finish": "설정완료", + "common.setting.rollback": "일변전으로 돌아가기", "modal.cover.outline.remove": "외벽 제거", "modal.cover.outline.select.move": "외벽 선택, 이동", "plan.menu.placement.surface": "배치면", @@ -227,6 +234,10 @@ "common.message.password.init.success": "비밀번호 [{0}]로 초기화 되었습니다.", "common.message.no.edit.save": "This document cannot be changed.", "common.require": "필수", + "commons.west": "서", + "commons.east": "동", + "commons.south": "남", + "commons.north": "북", "site.name": "Q.CAST III", "site.sub_name": "태양광 발전 시스템 도면관리 사이트", "login": "로그인", @@ -285,5 +296,22 @@ "stuff.gridHeader.dispCompanyName": "견적처", "stuff.gridHeader.receiveUser": "담당자", "stuff.gridHeader.specDate": "사양확인", - "stuff.gridHeader.createDatetime": "등록일" + "stuff.gridHeader.createDatetime": "등록일", + "slope": "경사", + "eaves.offset": "처마 출폭", + "gable.offset": "케라바 출폭", + "size": "치수", + "eaves": "처마", + "gable": "케라바", + "wall": "벽", + "hipandgable": "팔작지붕", + "jerkinhead": "반절처", + "shed": "한쪽흐름", + "apply": "적용", + "has.sleeve": "소매 있음", + "has.not.sleeve": "소매 없음", + "jerkinhead.width": "반절처 폭", + "jerkinhead.slope": "반절처 경사", + "shed.width": "한쪽흐름 폭", + "windage.width": "편류의 출폭" } diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss index 88b63229..30e19173 100644 --- a/src/styles/_modal.scss +++ b/src/styles/_modal.scss @@ -29,7 +29,6 @@ $alert-color: #101010; .modal-pop-wrap { position: fixed; width: 100%; - min-width: 300px; height: -webkit-fit-content; height: -moz-fit-content; height: fit-content; @@ -37,7 +36,26 @@ $alert-color: #101010; border-radius: 4px; background-color: #272727; z-index: 9999999; - overflow: hidden; + + &.xxxm { + width: 230px; + } + + &.xxm { + width: 270px; + } + + &.xm { + width: 300px; + } + + &.ssm { + width: 380px; + } + + &.sm { + width: 580px; + } &.r { width: 400px; @@ -47,16 +65,12 @@ $alert-color: #101010; width: 440px; } - &.sm { - width: 580px; + &.ml { + width: 530px; } - &.ssm { - width: 380px; - } - - &.xm { - width: 300px; + &.l-2 { + width: 640px; } &.l { @@ -112,7 +126,7 @@ $alert-color: #101010; align-items: center; padding: 10px 24px; background-color: #000; - + // overflow: hidden; h1.title { font-size: 13px; color: $pop-color; @@ -121,8 +135,8 @@ $alert-color: #101010; .modal-close { margin-left: auto; - color: $pop-color; - text-indent: -999999999px; + color: transparent; + font-size: 0; width: 10px; height: 10px; background: url(../../public/static/images/canvas/modal_close.svg) no-repeat center; @@ -146,6 +160,8 @@ $alert-color: #101010; flex: 1 1 auto; padding: 0; } + + margin-bottom: 14px; } } @@ -253,21 +269,18 @@ $alert-color: #101010; align-items: center; gap: 15px; padding-bottom: 15px; - border-bottom: 1px solid #3C3C3C; } .grid-option-wrap { - padding: 15px 0; - border-bottom: 1px solid #3C3C3C; - .grid-option-box { display: flex; align-items: center; - background-color: #3D3D3D; + background-color: transparent; + border: 1px solid #3D3D3D; border-radius: 2px; - padding: 10px; + padding: 15px 10px; gap: 20px; - margin-bottom: 5px; + margin-bottom: 10px; .grid-input-form { display: flex; @@ -301,6 +314,29 @@ $alert-color: #101010; .sort-select { width: 100%; background-color: #313131; + min-width: auto; + font-size: 12px; + border: none; + + p { + font-size: 12px; + } + + > ul { + border: none; + } + } + + &.right { + p { + text-align: right; + } + + ul { + li { + justify-content: flex-end; + } + } } } @@ -309,7 +345,7 @@ $alert-color: #101010; text-align: right; button { - padding: 0 20px; + padding: 0 10px; } } @@ -319,7 +355,7 @@ $alert-color: #101010; color: $pop-color; font-weight: $pop-normal-weight; padding-bottom: 15px; - border-bottom: 1px solid #3C3C3C; + } .grid-direction { @@ -501,7 +537,6 @@ $alert-color: #101010; .outline-wrap { padding: 24px 0; border-top: 1px solid #424242; - border-bottom: 1px solid #424242; .outline-inner { display: flex; @@ -513,15 +548,19 @@ $alert-color: #101010; } .outline-form { - width: 50%; + // width: 50%; + margin-right: 15px; } } + + &:last-child { + border-bottom: 1px solid #424242; + } } .outline-form { display: flex; align-items: center; - margin-right: 15px; span { width: 60px; @@ -532,7 +571,9 @@ $alert-color: #101010; margin-right: 10px; &.thin { - font-weight: & $pop-normal-weight; + width: auto; + font-weight: $pop-normal-weight; + margin-right: 0; } } @@ -591,18 +632,18 @@ $alert-color: #101010; margin-bottom: 14px; } +.setting-tit { + font-size: 13px; + color: $pop-color; + font-weight: $pop-bold-weight; + margin-bottom: 10px; +} + .properties-setting-wrap { &.outer { margin-top: 24px; } - .setting-tit { - font-size: 13px; - color: $pop-color; - font-weight: $pop-bold-weight; - margin-bottom: 10px; - } - .setting-btn-wrap { display: flex; align-items: center; @@ -692,9 +733,212 @@ $alert-color: #101010; border-bottom: 1px solid #424242; } +.padding-form { + padding-left: 23px; +} + .discrimination-box { padding: 16px 12px; border: 1px solid #3D3D3D; border-radius: 2px; - margin-top: 14px; +} + +.modal-bottom-border-bx { + margin-top: 24px; + padding-bottom: 14px; + border-bottom: 1px solid #424242; +} + +// 처마∙케라바 변경 +.eaves-keraba-table { + display: table; + border-collapse: collapse; + + .eaves-keraba-item { + display: table-row; + + .eaves-keraba-th, + .eaves-keraba-td { + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-normal-weight; + display: table-cell; + vertical-align: middle; + padding-bottom: 14px; + } + + .eaves-keraba-td { + padding-left: 15px; + } + + .eaves-keraba-ico { + display: flex; + align-items: center; + justify-content: center; + padding: 5px; + background-color: #3D3D3D; + border: 1px solid #3D3D3D; + border-radius: 2px; + + &.act { + border: 1px solid #ED0004; + } + } + + &:last-child { + .eaves-keraba-th, + .eaves-keraba-td { + padding-bottom: 0; + } + } + } +} + +.guide { + font-size: $pop-normal-size; + font-weight: $pop-normal-weight; + color: $pop-color; + margin-bottom: 24px; + + &.sm { + margin-bottom: 15px; + } +} + +// 지붕면 할당 +.allocation-select-wrap { + display: flex; + align-items: center; + padding-bottom: 14px; + border-bottom: 1px solid #424242; + margin-bottom: 14px; + + span { + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-bold-weight; + margin-right: 10px; + } + + .allocation-edit { + display: flex; + align-items: center; + height: 30px; + padding: 0 10px; + margin-left: 5px; + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-normal-weight; + border: 1px solid #484848; + background-color: #323234; + + i { + display: block; + width: 12px; + height: 12px; + margin-right: 5px; + background: url(../../public/static/images/canvas/allocation_edit.svg) no-repeat center; + background-size: cover; + } + } +} + +.block-box { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 10px; + + .flex-ment { + gap: 10px; + + .dec { + text-decoration: underline; + } + + .delete { + display: block; + width: 15px; + height: 15px; + background: url(../../public/static/images/canvas/allocation_delete.svg) no-repeat center; + background-size: cover; + } + } + + &:last-child { + margin-bottom: 0; + } +} + +.icon-btn-wrap { + flex: 1; + display: flex; + align-items: center; + gap: 5px; + + button { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 30px; + font-size: $pop-normal-size; + font-weight: $pop-normal-weight; + color: $pop-color; + border: 1px solid #646464; + border-radius: 2px; + padding: 0 10px; + transition: all .15s ease-in-out; + + i { + height: 15px; + display: block; + margin-left: 10px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; + transition: all .15s ease-in-out; + + &.allocation01 { + background-image: url(../../public/static/images/canvas/allocation_icon01_white.svg); + width: 15px; + } + + &.allocation02 { + background-image: url(../../public/static/images/canvas/allocation_icon02_white.svg); + width: 18px; + } + } + + &.act, + &:hover { + color: #101010; + border: 1px solid #101010; + background-color: #fff; + + i { + &.allocation01 { + background-image: url(../../public/static/images/canvas/allocation_icon01_black.svg); + } + + &.allocation02 { + background-image: url(../../public/static/images/canvas/allocation_icon02_black.svg); + } + } + } + } +} + +// 경사설정 +.slope-wrap { + padding-bottom: 24px; + border-bottom: 1px solid #424242; +} + +// 면형상 배치 +.roof-shape-menu { + &.plane { + grid-template-columns: 1fr 1fr 1fr 1fr 1fr; + grid-template-rows: 1fr 1fr 1fr; + } } \ No newline at end of file diff --git a/src/styles/_reset.scss b/src/styles/_reset.scss index dcf0c0d2..6d899458 100644 --- a/src/styles/_reset.scss +++ b/src/styles/_reset.scss @@ -1,21 +1,18 @@ * { - -webkit-text-size-adjust: none; - -moz-text-size-adjust: none; - -ms-text-size-adjust: none; - text-size-adjust: none; - box-sizing: content-box + -webkit-text-size-adjust:none; + -moz-text-size-adjust:none; + -ms-text-size-adjust:none; + text-size-adjust: none; + box-sizing: content-box } - *, ::after, ::before { - box-sizing: border-box; + box-sizing: border-box; } - -html, body { - width: 100%; - height: 100%; - font-size: 16px; +html, body{ + width: 100%; + height: 100%; + font-size: 16px; } - html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, @@ -25,777 +22,693 @@ b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, canvas, details, embed, -figure, figcaption, footer, header, hgroup, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font: inherit; - vertical-align: baseline; - font-family: 'Noto Sans JP', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-smooth: never; + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; + font-family: 'Noto Sans JP', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-smooth: never; } - /* HTML5 display-role reset for older browsers */ -article, aside, details, figcaption, figure, +article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { - display: block; + display: block; } - body { - line-height: 1.4; -} - -body:first-of-type caption { - display: none; + line-height: 1.4; } +body:first-of-type caption { display:none;} ol, ul { - list-style: none; + list-style: none; } - blockquote, q { - quotes: none; + quotes: none; } - blockquote:before, blockquote:after, q:before, q:after { - content: ''; - content: none; + content: ''; + content: none; } - table { - width: 100%; - border-collapse: separate; - border-spacing: 0; - border: 0 none; + width: 100%; + border-collapse: separate; + border-spacing:0; + border:0 none; } - caption, th, td { - text-align: left; - font-weight: normal; - border: 0; + text-align:left; + font-weight: normal; + border:0; } -a { - cursor: pointer; - color: #000; +a { + cursor:pointer; + color:#000; } - a, a:hover, a:active { - text-decoration: none; - -webkit-tap-highlight-color: transparent; + text-decoration:none; + -webkit-tap-highlight-color: transparent; } - /*form_style*/ input, select, textarea, button, a, label { - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + -webkit-tap-highlight-color:rgba(0,0,0,0); } - -button, input[type=text], input[type=button] { - -webkit-appearance: none; - -webkit-border-radius: 0; - -webkit-appearance: none; - appearance: none; - border-radius: 0 +button,input[type=text], input[type=button] { + -webkit-appearance: none; + -webkit-border-radius: 0; + -webkit-appearance:none; + appearance: none; + border-radius: 0 } - input[type=checkbox], input[type=radio] { - box-sizing: border-box; - padding: 0; + box-sizing: border-box; + padding: 0; } - input, select, button { - border: 0 none; - outline: none; - margin: 0; + border:0 none; + outline:none; + margin:0; } - select { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } - select::-ms-expand { - display: none; + display: none; } - ::-webkit-input-placeholder { - line-height: 1; - font-weight: 300; - font-size: 0.938rem; - letter-spacing: -0.6px; - color: #8b8b8b; + line-height:1; + font-weight:300; + font-size:0.938rem; + letter-spacing:-0.6px; + color:#8b8b8b; } - -.log-box ::-webkit-input-placeholder { - color: #8b8b8b; +.log-box ::-webkit-input-placeholder{ + color:#8b8b8b; } - -button { - background: transparent; - font-family: 'Noto Sans JP', sans-serif; - border: none; - padding: 0; - margin: 0; - line-height: 1.4; - color: inherit; - outline: none; - cursor: pointer; +button{ + background: transparent; + font-family: 'Noto Sans JP', sans-serif; + border: none; + padding: 0; + margin: 0; + line-height: 1.4; + color: inherit; + outline: none; + cursor: pointer; } - -.pre { - font-family: 'Pretendard', sans-serif !important; +.pre{ + font-family: 'Pretendard', sans-serif !important; } // margin -.mt5 { - margin-top: 5px !important; -} - -.mt10 { - margin-top: 10px !important; -} - -.mb5 { - margin-bottom: 5px !important; -} - -.mb10 { - margin-bottom: 10px !important; -} - -.mr5 { - margin-right: 5px !important; -} - -.mr10 { - margin-right: 10px !important; -} - -.ml5 { - margin-left: 5px !important; -} - -.ml10 { - margin-left: 10px !important; -} +.mt5{margin-top: 5px !important;} +.mt10{margin-top: 10px !important;} +.mt15{margin-top: 15px !important;} +.mb5{margin-bottom: 5px !important;} +.mb10{margin-bottom: 10px !important;} +.mb15{margin-bottom: 15px !important;} +.mr5{margin-right: 5px !important;} +.mr10{margin-right: 10px !important;} +.mr15{margin-right: 15px !important;} +.ml5{margin-left: 5px !important;} +.ml10{margin-left: 10px !important;} +.ml15{margin-left: 15px !important;} // button -.btn-frame { - display: inline-block; - padding: 0 7px; - height: 34px; - line-height: 34px; - border-radius: 2px; - color: #fff; - font-size: 12px; - font-weight: 400; - border: 1px solid #000; - text-align: center; - font-family: 'Pretendard', sans-serif; - transition: all .17s ease-in-out; - cursor: pointer; - - &.block { - width: 100%; - } - - &.small { - font-family: 'Noto Sans JP', sans-serif; - height: 30px; - line-height: 30px; - font-size: 13px; - } - - &.deepgray { - background-color: #2C2C2C; - border: 1px solid #484848; - } - - &.gray { - background-color: #3C3C3C; - border: 1px solid #545454; - } - - &.dark { - background-color: #1C1C1C; - border: 1px solid #484848; - } - - &.modal { - font-family: 'Noto Sans JP', sans-serif; - background-color: #272727; - border: 1px solid #484848; - color: #aaa; - - &:hover { - background-color: #1083E3; - border: 1px solid #1083E3; - color: #fff; - font-weight: 500; - } - } - - &.sub-tab { - height: 30px; - padding: 0 10px; - line-height: 28px; - font-family: 'Noto Sans JP', sans-serif; - background-color: #2D2D2D; - border: 1px solid #393939; - color: #aaa; - - &.act, - &:hover { - background-color: #414E6C; - border: 1px solid #414E6C; - color: #fff; - font-weight: 500; - } - } - - &:hover, - &.act { - background-color: #1083E3; - border: 1px solid #1083E3; +.btn-frame{ + display: inline-block; + padding: 0 7px; + height: 34px; + line-height: 34px; + border-radius: 2px; color: #fff; - font-weight: 500; - } - - &.block { - display: block; - width: 100%; - } - - &.ico-flx { - display: flex; - align-items: center; - - .ico { - margin-right: 10px; + font-size: 12px; + font-weight: 400; + border: 1px solid #000; + text-align: center; + font-family: 'Pretendard', sans-serif; + transition: all .17s ease-in-out; + cursor: pointer; + &.block{ + width: 100%; + } + &.small{ + font-family: 'Noto Sans JP', sans-serif; + height: 30px; + line-height: 30px; + font-size: 13px; } + &.deepgray{ + background-color: #2C2C2C; + border: 1px solid #484848; + } + &.gray{ + background-color: #3C3C3C; + border: 1px solid #545454; + } + &.dark{ + background-color: #1C1C1C; + border: 1px solid #484848; + } + &.modal{ + font-family: 'Noto Sans JP', sans-serif; + background-color: #272727; + border: 1px solid #484848; + color: #aaa; + &:hover{ + background-color: #1083E3; + border: 1px solid #1083E3; + color: #fff; + font-weight: 500; + } + } + &.sub-tab{ + height: 30px; + padding: 0 10px; + line-height: 28px; + font-family: 'Noto Sans JP', sans-serif; + background-color: #2D2D2D; + border: 1px solid #393939; + color: #aaa; + &.act, + &:hover{ + background-color: #414E6C; + border: 1px solid #414E6C; + color: #fff; + font-weight: 500; + } + } &:hover, - &.act { - font-weight: 400; + &.act{ + background-color: #1083E3; + border: 1px solid #1083E3; + color: #fff; + font-weight: 500; } - } + &.block{ + display: block; + width: 100%; + } + &.ico-flx{ + display: flex; + align-items: center; + .ico{ + margin-right: 10px; + } + &:hover, + &.act{ + font-weight: 400; + } + } } -.btn-origin { - display: inline-block; - height: 30px; - padding: 0 14px; - border-radius: 2px; - background-color: #101010; - color: #fff; - font-size: 13px; - font-weight: 400; - transition: all .15s ease-in-out; - - &.navy { - background-color: #304961; - - &:hover { - background-color: #1083E3; +.btn-origin{ + display: inline-block; + height: 30px; + padding: 0 14px; + border-radius: 2px; + background-color: #101010; + color: #fff; + font-size: 13px; + font-weight: 400; + transition: all .15s ease-in-out; + &.navy{ + background-color: #304961; + &:hover{ + background-color: #1083E3; + } } - } - - &.grey { - background-color: #94A0AD; - - &:hover { - background-color: #607F9A; + &.grey{ + background-color: #94A0AD; + &:hover{ + background-color: #607F9A; + } } - } } // select -.sort-select { - position: relative; - display: inline-block; - min-width: 100px; - height: 30px; - line-height: 30px; - padding: 0 10px; - background-color: #373737; - border: 1px solid #3F3F3F; - border-radius: 2px; - border-top-left-radius: 2px; - color: #fff; - cursor: pointer; - - p { - font-size: 13px; - color: #fff; - height: 100%; - } - - .select-item-wrap { - position: absolute; - top: 100%; - left: -1px; - clip-path: inset(0 0 100% 0); - width: calc(100% + 2px); - padding: 8px 0; +.sort-select{ + position: relative; + display: inline-block; + min-width: 100px; + height: 30px; + line-height: 30px; + padding: 0 25px 0 10px; background-color: #373737; border: 1px solid #3F3F3F; border-radius: 2px; - transition: all 0.17s ease-in-out; - visibility: hidden; - - .select-item { - display: flex; - align-items: center; - padding: 8px 20px; - line-height: 1.4; - transition: all .17s ease-in-out; - - button { - font-size: 12px; + border-top-left-radius: 2px; + color: #fff; + cursor: pointer; + p{ + font-size: 13px; color: #fff; - line-height: 1.4; - } - - &:hover { - background-color: #2C2C2C; - } + height: 100%; } - } - - &::after { - content: ''; - position: absolute; - top: 50%; - right: 7px; - transform: translateY(-50%); - width: 10px; - height: 6px; - background: url(/static/images/common/select-arr.svg) no-repeat center; - background-size: cover; - transition: all .17s ease-in-out; - } - - &.active { - .select-item-wrap { - clip-path: inset(0 0 0 0); - visibility: visible; + .select-item-wrap{ + position: absolute; + top: 100%; + left: -1px; + clip-path:inset(0 0 100% 0); + width: calc(100% + 2px); + padding: 8px 0; + max-height: 100px; + overflow-y: auto; + background-color: #373737; + border: 1px solid #3F3F3F; + border-radius: 2px; + transition: all 0.17s ease-in-out; + visibility: hidden; + z-index: 999; + .select-item{ + display: flex; + align-items: center; + padding: 8px 20px; + line-height: 1.4; + transition: all .17s ease-in-out; + button{ + font-size: 12px; + color: #fff; + line-height: 1.4; + } + &:hover{ + background-color: #2C2C2C; + } + } + &::-webkit-scrollbar { + width: 2px; + background-color: transparent; + + } + &::-webkit-scrollbar-thumb { + background-color: #5a5a5a; + border-radius: 10px; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } } - - &:after { - transform: translateY(-50%) rotate(-180deg); + &::after{ + content: ''; + position: absolute; + top: 50%; + right: 7px; + transform: translateY(-50%); + width: 10px; + height: 6px; + background: url(/static/images/common/select-arr.svg) no-repeat center; + background-size: cover; + transition: all .17s ease-in-out; + } + &.active{ + .select-item-wrap{ + clip-path: inset(0 0 0 0); + visibility: visible; + } + &:after{ + transform: translateY(-50%) rotate(-180deg); + } } - } } -.select-light { - position: relative; - display: block; - width: 100%; - height: 30px; - background: #FFF url(../../public/static/images/common/select_light_arr.svg) calc(100% - 11px) center no-repeat; - background-size: 10px 6px; - border: 1px solid #eee; - padding: 0 30px 0 10px; - font-size: 13px; - color: #45576F; - font-family: 'Noto Sans JP', sans-serif; - cursor: pointer; - - &:disabled { - opacity: 1; - background-color: #FAFAFA; - color: #999; - cursor: default; - } - - &.black { - color: #101010; - } - - &.dark { - background: #323234 url(../../public/static/images/common/select_dark_arr.svg) calc(100% - 11px) center no-repeat; - color: #898989; - font-size: 12px; - border-radius: 2px; - border: none; - } +.select-light{ + position: relative; + display: block; + width: 100%; + height: 30px; + background: #FFF url(../../public/static/images/common/select_light_arr.svg) calc(100% - 11px) center no-repeat; + background-size: 10px 6px; + border: 1px solid #eee; + padding: 0 30px 0 10px; + font-size: 13px; + color: #45576F; + font-family: 'Noto Sans JP', sans-serif; + cursor: pointer; + &:disabled{ + opacity: 1; + background-color: #FAFAFA; + color: #999; + cursor: default; + } + &.black{ + color: #101010; + } + &.dark{ + background: #323234 url(../../public/static/images/common/select_dark_arr.svg) calc(100% - 11px) center no-repeat; + color: #898989; + font-size: 12px; + border-radius: 2px; + border: none; + } } // input -.form-input { - label { - display: block; - color: #aaa; - font-size: 12px; - font-weight: 500; - margin-bottom: 10px; - } +.form-input{ + label{ + display: block; + color: #aaa; + font-size: 12px; + font-weight: 500; + margin-bottom: 10px; + } } - input[type=number], -input[type=text] { - &.input-origin { - display: inline-block; - height: 30px; - line-height: 30px; - border-radius: 2px; - background-color: #323234; - color: #fff; - font-size: 12px; - font-weight: 500; - font-family: 'Pretendard', sans-serif; - padding: 0 10px; - letter-spacing: 0px; - text-align: right; - - &::placeholder { - opacity: 1; - font-size: 12px; - letter-spacing: 0px; +input[type=text]{ + &.input-origin{ + display: inline-block; + height: 30px; + line-height: 30px; + border-radius: 2px; + background-color: #323234; + color: #fff; + font-size: 12px; + font-weight: 500; + font-family: 'Pretendard', sans-serif; + padding: 0 10px; + letter-spacing: 0px; + text-align: right; + &::placeholder{ + opacity: 1; + font-size: 12px; + letter-spacing: 0px; + } + &.block{ + width: 100%; + } + &:read-only{ + color: #AAA; + } } - - &.block { - width: 100%; + &.input-light{ + display: block; + width: 100%; + height: 30px; + padding: 0 10px; + border: 1px solid #eee; + border-radius: 2px; + background-color: #fff; + font-family: 'Noto Sans JP', sans-serif; + font-size: 13px; + color: #45576F; + font-weight: normal; + transition: border-color .17s ease-in-out; + text-align: left; + &:read-only{ + background-color: #FAFAFA; + color: #999999; + } } - } - - &.input-light { - display: block; - width: 100%; - height: 30px; - padding: 0 10px; - border: 1px solid #eee; - border-radius: 2px; - background-color: #fff; - font-family: 'Noto Sans JP', sans-serif; - font-size: 13px; - color: #45576F; - font-weight: normal; - transition: border-color .17s ease-in-out; - text-align: left; - - &:read-only { - background-color: #FAFAFA; - color: #999999; - } - } } + // check-btn -.check-btn { - display: flex; - align-items: center; - height: 30px; - background-color: #3A3A3A; - border-radius: 3px; - transition: all .17s ease-in-out; - - .check-area { - flex: none; - width: 30px; - height: 100%; - border-right: 1px solid #272727; - background: url(../../public/static/images/canvas/check-grey.svg) no-repeat center; - background-size: 11px 9px; - } - - .title-area { - padding: 0 10px; - font-size: 12px; - color: #898989; - font-weight: 400; - } - - &.block { - width: 100%; - } - - &:hover, - &.act { - background-color: #fff; - - .check-area { - border-right: 1px solid #101010; - background: url(../../public/static/images/canvas/check-black.svg) no-repeat center; +.check-btn{ + display: flex; + align-items: center; + height: 30px; + background-color: #3A3A3A; + border-radius: 3px; + transition: all .17s ease-in-out; + .check-area{ + flex: none; + width: 30px; + height: 100%; + border-right: 1px solid #272727; + background: url(../../public/static/images/canvas/check-grey.svg)no-repeat center; + background-size: 11px 9px; } - - .title-area { - color: #101010; - font-weight: 600; + .title-area{ + padding: 0 10px; + font-size: 12px; + color: #898989; + font-weight: 400; + } + &.block{ + width: 100%; + } + &:hover, + &.act{ + background-color: #fff; + .check-area{ + border-right: 1px solid #101010; + background: url(../../public/static/images/canvas/check-black.svg)no-repeat center; + } + .title-area{ + color: #101010; + font-weight: 600; + } } - } } // arr-btn -.arr-btn { - display: block; - height: 30px; - border-radius: 3px; - background-color: #3A3A3A; - padding: 0 11px; - text-align: left; - transition: all .17s ease-in-out; - - span { - position: relative; - font-size: 12px; - color: #898989; - font-weight: 400; - padding-right: 15px; - - &:after { - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 5px; - height: 8px; - background: url(../../public/static/images/canvas/arr_btn_ico.svg) no-repeat center; +.arr-btn{ + display: block; + height: 30px; + border-radius: 3px; + background-color: #3A3A3A; + padding: 0 11px; + text-align: left; + transition: all .17s ease-in-out; + span{ + position: relative; + font-size: 12px; + color: #898989; + font-weight: 400; + padding-right: 15px; + &:after{ + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 5px; + height: 8px; + background: url(../../public/static/images/canvas/arr_btn_ico.svg)no-repeat center; + } } - } - - &:hover, - &.act { - background-color: #fff; - - span { - color: #101010; - font-weight: 500; - - &:after { - background: url(../../public/static/images/canvas/arr_btn_ico_black.svg) no-repeat center; - } - } - } - - &.dark { - text-align: center; - background-color: #272727; - border: 1px solid #484848; - - span { - color: #Fff; - - &:after { - background: url(../../public/static/images/canvas/arr_btn_ico_white.svg) no-repeat center; - } - } - &:hover, - &.act { - background-color: #1083E3; - border: 1px solid #1083E3; + &.act{ + background-color: #fff; + span{ + color: #101010; + font-weight: 500; + &:after{ + background: url(../../public/static/images/canvas/arr_btn_ico_black.svg)no-repeat center; + } + } + } + &.dark{ + text-align: center; + background-color: #272727; + border: 1px solid #484848; + span{ + color: #Fff; + &:after{ + background: url(../../public/static/images/canvas/arr_btn_ico_white.svg)no-repeat center; + } + } + &:hover, + &.act{ + background-color: #1083E3; + border: 1px solid #1083E3; + } } - } } // radio .d-check-radio, -.d-check-box { - line-height: 1.1; - cursor: pointer; - - input[type=checkbox], - input[type=radio] { - position: static; - margin-left: 0; +.d-check-box{ + line-height: 1.1; cursor: pointer; - opacity: 0; - z-index: 1; - flex: 0 0 auto; - } - - label { - position: relative; - padding-left: 10px; - margin-bottom: 0; - word-break: break-all; - line-height: 1.2; - display: inline; - vertical-align: top; - color: #fff; - font-size: 13px; - font-weight: 400; - cursor: pointer; - } - - &.light { - label { - color: #45576F; + input[type=checkbox], + input[type=radio]{ + position: static; + margin-left: 0; + cursor: pointer; + opacity: 0; + z-index: 1; + flex: 0 0 auto; } - } - - &.no-text { - label { - padding-left: 0; + label{ + position: relative; + padding-left: 10px; + margin-bottom: 0; + word-break: break-all; + line-height: 1.2; + display: inline; + vertical-align: top; + color: #fff; + font-size: 13px; + font-weight: 400; + cursor: pointer; + } + &.light{ + label{ + color: #45576F; + } + } + &.no-text{ + label{ + padding-left: 0; + } } - } } .d-check-radio { - label { - &::before { - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 17px; - height: 17px; - top: 2px; - left: 0; - margin-left: -12px; - border: 1px solid #999999; - border-radius: 100%; - background-color: transparent; - text-align: center; - font-size: 13px; - line-height: 1.4; - transition: border 0.15s ease-in-out, color 0.15s ease-in-out; + label{ + &::before{ + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 17px; + height: 17px; + top:2px; + left: 0; + margin-left: -12px; + border: 1px solid #999999; + border-radius: 100%; + background-color: transparent; + text-align:center; + font-size:13px; + line-height:1.4; + transition: border 0.15s ease-in-out, color 0.15s ease-in-out; + } + &::after{ + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 9px; + height: 9px; + top:6px; + left: 4px; + margin-left: -12px; + border: none; + border-radius: 100%; + background-color: #fff; + text-align:center; + font-size:13px; + line-height:1.4; + opacity: 0; + visibility: hidden; + transition: opacity 0.15s ease-in-out, color 0.15s ease-in-out; + } } - - &::after { - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 9px; - height: 9px; - top: 6px; - left: 4px; - margin-left: -12px; - border: none; - border-radius: 100%; - background-color: #fff; - text-align: center; - font-size: 13px; - line-height: 1.4; - opacity: 0; - visibility: hidden; - transition: opacity 0.15s ease-in-out, color 0.15s ease-in-out; + &.light{ + label{ + &:before{ + border-color: #D6D6D7; + } + &:after{ + background-color: #697C8F; + } + } } - } - - &.light { - label { - &:before { - border-color: #D6D6D7; - } - - &:after { - background-color: #697C8F; - } + input[type=radio]:checked + label::after{ + opacity: 1; + visibility: visible; } - } - - input[type=radio]:checked + label::after { - opacity: 1; - visibility: visible; - } - - &.pop { - label { - &:before { - width: 16px; - height: 16px; - border-color: #fff; - } - - &:after { - width: 8px; - height: 8px; - background-color: #fff; - } + &.pop{ + label{ + font-size: 12px; + &:before{ + width: 16px; + height: 16px; + border-color: #fff; + } + &:after{ + width: 8px; + height: 8px; + background-color: #fff; + } + } } - } } // check-box -.d-check-box { - label { - &::before { - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 17px; - height: 17px; - top: 2px; - left: 0; - margin-left: -12px; - border: 1px solid #D6D6D7; - background-color: transparent; - transition: border 0.15s ease-in-out, color 0.15s ease-in-out; +.d-check-box{ + label{ + &::before{ + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 17px; + height: 17px; + top: 2px; + left: 0; + margin-left: -12px; + border: 1px solid #D6D6D7; + background-color: transparent; + transition: border 0.15s ease-in-out, color 0.15s ease-in-out; + } + &:after{ + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 16px; + height: 16px; + top:0; + left: 0; + margin-left: -.8rem; + transition: border 0.05s ease-in-out, color 0.05s ease-in-out; + } } - - &:after { - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 16px; - height: 16px; - top: 0; - left: 0; - margin-left: -.8rem; - transition: border 0.05s ease-in-out, color 0.05s ease-in-out; + input[type=checkbox]:checked + label::after{ + content: ""; + display: inline-block; + position: absolute; + top: 1px; + left: -1px; + width: 5px; + height: 8px; + border: 2px solid #697C8F; + border-left: none; + border-top: none; + transform: translate(7.75px,4.5px) rotate(45deg); + -ms-transform: translate(7.75px,4.5px) rotate(45deg); } - } - - input[type=checkbox]:checked + label::after { - content: ""; - display: inline-block; - position: absolute; - top: 1px; - left: -1px; - width: 5px; - height: 8px; - border: 2px solid #697C8F; - border-left: none; - border-top: none; - transform: translate(7.75px, 4.5px) rotate(45deg); - -ms-transform: translate(7.75px, 4.5px) rotate(45deg); - } - - &.pop { - input[type=checkbox]:checked + label::after { - border-color: #fff; + &.pop{ + input[type=checkbox]:checked + label::after{ + border-color: #fff; + } } - } } // date-picker -.date-picker { - svg { - display: none; - } - - .react-datepicker-wrapper { - width: 100%; - } - - input[type=text] { - display: block; - width: 100%; - height: 30px; - padding: 0 34px 0 10px; - border-radius: 2px; - border: 1px solid #eee; - font-size: 13px; - color: #45576F; - font-weight: normal; - font-family: 'Noto Sans JP', sans-serif; - background: #fff url(../../public/static/images/common/datepicker.svg) calc(100% - 11px) center no-repeat; - background-size: 14px 15px; - cursor: pointer; - } +.date-picker{ + svg{display: none;} + .react-datepicker-wrapper{ + width: 100%; + } + input[type=text]{ + display: block; + width: 100%; + height: 30px; + padding: 0 34px 0 10px; + border-radius: 2px; + border: 1px solid #eee; + font-size: 13px; + color: #45576F; + font-weight: normal; + font-family: 'Noto Sans JP', sans-serif; + background: #fff url(../../public/static/images/common/datepicker.svg) calc(100% - 11px) center no-repeat; + background-size: 14px 15px; + cursor: pointer; + } } \ No newline at end of file From d40b196f3dfeb48210b30d5a21ac152838d0125f Mon Sep 17 00:00:00 2001 From: changkyu choi Date: Wed, 2 Oct 2024 18:49:59 +0900 Subject: [PATCH 024/152] =?UTF-8?q?Canvas=20=EA=B7=B8=EB=A6=AC=EB=93=9C=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=A1=B0=ED=9A=8C/=EB=93=B1=EB=A1=9D=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/grid/DotLineGrid.jsx | 289 +++++++++++------- .../modal/setting01/FirstOption.jsx | 24 +- .../floor-plan/modal/setting01/GridOption.jsx | 6 +- 3 files changed, 203 insertions(+), 116 deletions(-) diff --git a/src/components/floor-plan/modal/grid/DotLineGrid.jsx b/src/components/floor-plan/modal/grid/DotLineGrid.jsx index db700207..e9d32a3a 100644 --- a/src/components/floor-plan/modal/grid/DotLineGrid.jsx +++ b/src/components/floor-plan/modal/grid/DotLineGrid.jsx @@ -1,12 +1,15 @@ import WithDraggable from '@/components/common/draggable/withDraggable' import QSelectBox from '@/components/common/select/QSelectBox' -import { useState } from 'react' +import { useEffect, useState } from 'react' import { useMessage } from '@/hooks/useMessage' import { canvasState, dotLineGridSettingState, dotLineIntervalSelector } from '@/store/canvasAtom' import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' import { onlyNumberInputChange } from '@/util/input-utils' import { fabric } from 'fabric' +import { useAxios } from '@/hooks/useAxios' +import { useSwal } from '@/hooks/useSwal' import { gridColorState } from '@/store/gridAtom' +import { settingModalGridOptionsState } from '@/store/settingAtom' const TYPE = { DOT: 'DOT', @@ -15,6 +18,7 @@ const TYPE = { export default function DotLineGrid(props) { // const [modalOption, setModalOption] = useRecoilState(modalState); //modal 열림닫힘 state + const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요 const [close, setClose] = useState(false) const { setShowDotLineGridModal } = props const gridColor = useRecoilValue(gridColorState) @@ -25,6 +29,11 @@ export default function DotLineGrid(props) { const interval = useRecoilValue(dotLineIntervalSelector) const { getMessage } = useMessage() + const { get, post } = useAxios() + const { swalFire } = useSwal() + + const [gridOptions, setGridOptions] = useRecoilState(settingModalGridOptionsState) + const SelectOption = [ { id: 1, name: getMessage('modal.canvas.setting.grid.dot.line.setting.line.origin'), value: 1 }, { id: 2, name: '1/2', value: 1 / 2 }, @@ -34,13 +43,23 @@ export default function DotLineGrid(props) { const [selectOption, setSelectOption] = useState(SelectOption[0]) const HandleClickClose = () => { - // setClose(true) - // setTimeout(() => { - // setModalOption({ ...modalOption, gridoption: false }) - // setClose(false) - // }, 180) + setShowDotLineGridModal(false) // 모달 닫기 처리 + + const newGridOptions = [...gridOptions] // 모달 닫으면서 점선그리드 버튼 비활성화 + newGridOptions.map((item) => { + if (item.id === 2) { + item.selected = false + } + }) + setGridOptions(newGridOptions) } + // 데이터를 최초 한 번만 조회 + useEffect(() => { + console.log('DotLineGrid useEffect 실행') + fetchGridSettings() + }, [objectNo]) + const handleCheckBoxChange = (e) => { const { value, checked } = e.target setDotLineGridSettingState((prev) => { @@ -51,118 +70,174 @@ export default function DotLineGrid(props) { }) } - const handleSave = () => { - // 1. 점.선 그리드 설정으로 만들어진 기존 오브젝트 제거 - canvas - ?.getObjects() - .filter((obj) => obj.name === 'lineGrid') - .forEach((obj) => canvas?.remove(obj)) - canvas - ?.getObjects() - .filter((obj) => obj.name === 'dotGrid') - .forEach((obj) => canvas?.remove(obj)) + // Canvas Grid Setting 조회 및 초기화 + const fetchGridSettings = async () => { + try { + const res = await get({ url: `/api/canvas-management/canvas-grid-settings/by-object/${objectNo}` }) - const horizontalInterval = interval.horizontalInterval - const verticalInterval = interval.verticalInterval - - if (dotLineGridSetting.DOT) { - const circle = new fabric.Circle({ - radius: 2, - fill: 'red', - 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: horizontalInterval, - height: verticalInterval, - }) - - 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: canvas.width, y: 0 }, - { x: canvas.width, y: canvas.height }, - { x: 0, y: canvas.height }, - ], - { - fill: pattern, - selectable: false, - name: 'dotGrid', + const patternData = { + INTERVAL: { + type: res.gridType, + horizontalInterval: res.gridHorizon, + verticalInterval: res.gridVertical, + ratioInterval: res.gridRatio, }, - ) + dimension: res.gridDimen, + DOT: res.dotGridDisplay, + LINE: res.lineGridDisplay, + } - canvas.add(backgroundPolygon) - backgroundPolygon.sendToBack() - canvas.renderAll() + const matchedOption = SelectOption.find((option) => option.value == res.gridDimen) + + // dimension 값에 맞는 옵션을 선택 + setSelectOption(matchedOption) + + // 서버에서 받은 데이터로 상태 업데이트 + setDotLineGridSettingState(patternData) + } catch (error) { + console.error('Data fetching error:', error) } + } - if (dotLineGridSetting.LINE) { - for (let i = 0; i < canvas.height / verticalInterval + 1; i++) { - const horizontalLine = new fabric.Line( - [0, i * verticalInterval - verticalInterval / 2, canvas.width, i * verticalInterval - verticalInterval / 2], - { - stroke: gridColor, - strokeWidth: 1, - selectable: true, + // 저장 버튼 클릭 시 + const handleSave = async () => { + try { + const patternData = { + objectNo, + dotGridDisplay: dotLineGridSetting.DOT, + lineGridDisplay: dotLineGridSetting.LINE, + gridType: dotLineGridSetting.INTERVAL.type, + gridHorizon: dotLineGridSetting.INTERVAL.horizontalInterval, + gridVertical: dotLineGridSetting.INTERVAL.verticalInterval, + gridRatio: dotLineGridSetting.INTERVAL.ratioInterval, + gridDimen: dotLineGridSetting.INTERVAL.dimension, + } + + // HTTP POST 요청 보내기 + await post({ url: `/api/canvas-management/canvas-grid-settings`, data: patternData }).then((res) => { + swalFire({ text: getMessage(res.returnMessage) }) + + // 1. 점.선 그리드 설정으로 만들어진 기존 오브젝트 제거 + canvas + ?.getObjects() + .filter((obj) => obj.name === 'lineGrid') + .forEach((obj) => canvas?.remove(obj)) + canvas + ?.getObjects() + .filter((obj) => obj.name === 'dotGrid') + .forEach((obj) => canvas?.remove(obj)) + + if (patternData.dotGridDisplay) { + const circle = new fabric.Circle({ + radius: 2, + fill: 'red', + strokeWidth: 0.7, + originX: 'center', + originY: 'center', + selectable: false, lockMovementX: true, lockMovementY: true, lockRotation: true, lockScalingX: true, lockScalingY: true, - name: 'lineGrid', - strokeDashArray: [5, 2], - opacity: 0.3, - direction: 'horizontal', - }, - ) - canvas.add(horizontalLine) - } + }) - for (let i = 0; i < canvas.width / horizontalInterval + 1; i++) { - const verticalLine = new fabric.Line( - [i * horizontalInterval - horizontalInterval / 2, 0, i * horizontalInterval - horizontalInterval / 2, canvas.height], - { - stroke: 'black', - strokeWidth: 1, - selectable: true, - lockMovementX: true, - lockMovementY: true, - lockRotation: true, - lockScalingX: true, - lockScalingY: true, - name: 'lineGrid', - strokeDashArray: [5, 2], - opacity: 0.3, - direction: 'vertical', - }, - ) - canvas.add(verticalLine) - } + const patternSourceCanvas = new fabric.StaticCanvas(null, { + width: patternData.gridHorizon, + height: patternData.gridVertical, + }) + + 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: canvas.width, y: 0 }, + { x: canvas.width, y: canvas.height }, + { x: 0, y: canvas.height }, + ], + { + fill: pattern, + selectable: false, + name: 'dotGrid', + }, + ) + + canvas.add(backgroundPolygon) + backgroundPolygon.sendToBack() + canvas.renderAll() + } + + if (patternData.lineGridDisplay) { + for (let i = 0; i < canvas.height / patternData.gridVertical + 1; i++) { + const horizontalLine = new fabric.Line( + [ + 0, + i * patternData.gridVertical - patternData.gridVertical / 2, + canvas.width, + i * patternData.gridVertical - patternData.gridVertical / 2, + ], + { + stroke: gridColor, + strokeWidth: 1, + selectable: true, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + name: 'lineGrid', + strokeDashArray: [5, 2], + opacity: 0.3, + direction: 'horizontal', + }, + ) + canvas.add(horizontalLine) + } + + for (let i = 0; i < canvas.width / patternData.gridHorizon + 1; i++) { + const verticalLine = new fabric.Line( + [ + i * patternData.gridHorizon - patternData.gridHorizon / 2, + 0, + i * patternData.gridHorizon - patternData.gridHorizon / 2, + canvas.height, + ], + { + stroke: 'black', + strokeWidth: 1, + selectable: true, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + name: 'lineGrid', + strokeDashArray: [5, 2], + opacity: 0.3, + direction: 'vertical', + }, + ) + canvas.add(verticalLine) + } + } + canvas.renderAll() + }) + } catch (error) { + swalFire({ text: getMessage(res.returnMessage), icon: 'error' }) } - - canvas.renderAll() } const handleRadioChange = (e) => { @@ -224,7 +299,7 @@ export default function DotLineGrid(props) {

{getMessage('modal.canvas.setting.grid.dot.line.setting')}

-
diff --git a/src/components/floor-plan/modal/setting01/FirstOption.jsx b/src/components/floor-plan/modal/setting01/FirstOption.jsx index ac8f08d6..c4e75ea4 100644 --- a/src/components/floor-plan/modal/setting01/FirstOption.jsx +++ b/src/components/floor-plan/modal/setting01/FirstOption.jsx @@ -116,11 +116,21 @@ export default function FirstOption() { } } - const onClickDimension = async (item) => { - const options = settingModalFirstOptions?.dimensionDisplay.map((option) => { - option.selected = option.id === item.id - return option - }) + const onClickOnlyOne = async (item) => { + //화면 표시 + if (item.column === 'onlyBorder' || item.column === 'lineHatch' || item.column === 'allPainted') { + const options2 = settingModalFirstOptions?.option2.map((option2) => { + option2.selected = option2.id === item.id + return option2 + }) + + //치수 표시 + } else { + const options = settingModalFirstOptions?.dimensionDisplay.map((option) => { + option.selected = option.id === item.id + return option + }) + } setSettingModalFirstOptions({ option1, option2, dimensionDisplay }) @@ -205,7 +215,7 @@ export default function FirstOption() {
{settingModalFirstOptions && settingModalFirstOptions.dimensionDisplay.map((item) => ( - @@ -217,7 +227,7 @@ export default function FirstOption() {
{settingModalFirstOptions && settingModalFirstOptions.option2.map((item) => ( - diff --git a/src/components/floor-plan/modal/setting01/GridOption.jsx b/src/components/floor-plan/modal/setting01/GridOption.jsx index edf1e802..c5502d6f 100644 --- a/src/components/floor-plan/modal/setting01/GridOption.jsx +++ b/src/components/floor-plan/modal/setting01/GridOption.jsx @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react' +import React, { useEffect, useState } from 'react' import { useRecoilState } from 'recoil' import { settingModalGridOptionsState } from '@/store/settingAtom' import { useMessage } from '@/hooks/useMessage' @@ -16,9 +16,11 @@ export default function GridOption(props) { const { tempGridMode, setTempGridMode } = useTempGrid() const [color, setColor] = useColor(gridColor) + const [colorPickerShow, setColorPickerShow] = useState(false) useEffect(() => { - console.log(color) + console.log('GridOption useEffect 실행') + //console.log(color) setGridColor(color.hex) }, [color]) From 3b5201a0ce7d956a775256b037ab0565bd04d3c8 Mon Sep 17 00:00:00 2001 From: basssy Date: Fri, 4 Oct 2024 09:10:11 +0900 Subject: [PATCH 025/152] =?UTF-8?q?=EB=AC=BC=EA=B1=B4=ED=98=84=ED=99=A9=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EA=B2=80=EC=83=89=EC=A1=B0?= =?UTF-8?q?=EA=B1=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/management/Stuff.jsx | 14 +++++++------- src/components/management/StuffSearchCondition.jsx | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index 638126ee..bfda6d62 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -256,7 +256,7 @@ export default function Stuff() { } async function fetchData() { - console.log('화면진입:::::::::::::', params) + // console.log('화면진입:::::::::::::', params) //api에 넘길값 startRow, endRow // let startRow // let endRow @@ -278,7 +278,7 @@ export default function Stuff() { url: apiUrl, }).then((res) => { if (!isEmptyArray(res)) { - console.log('화면진입API결과::', res) + // console.log('화면진입API결과::', res) setGridProps({ ...gridProps, gridData: res, count: res.length }) setGridCount(res.length) } @@ -293,7 +293,7 @@ export default function Stuff() { stuffSearchParams.startRow = (curPage - 1) * defaultSize + 1 stuffSearchParams.endRow = curPage * defaultSize stuffSearchParams.schSortType = defaultSortType - console.log('조회 눌럿을때 ::::::::::::::', stuffSearchParams) + // console.log('조회 눌럿을때 ::::::::::::::', stuffSearchParams) async function fetchData() { // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` @@ -324,12 +324,12 @@ export default function Stuff() { startRow: startRow, endRow: curPage * e.target.value, }) - console.log('셋팅된 검색조건:::', stuffSearchParams) + // console.log('셋팅된 검색조건:::', stuffSearchParams) //조회API호출 // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` get({ url: apiUrl }).then((res) => { - console.log('보여줄개수바꿨을때 조회 ::::::::::', res) + // console.log('보여줄개수바꿨을때 조회 ::::::::::', res) if (!isEmptyArray(res)) { setGridProps({ ...gridProps, gridData: res, count: res.length }) setGridCount(res.length) @@ -343,7 +343,7 @@ export default function Stuff() { //최근 등록일 수정일 정렬 이벤트 const onChangeSortType = (e) => { stuffSearchParams.schSortType = e.target.value - console.log('셋팅된 검색조건:::', stuffSearchParams) + // console.log('셋팅된 검색조건:::', stuffSearchParams) setDefaultSortType(e.target.value) setStuffSearch({ ...stuffSearch, @@ -354,7 +354,7 @@ export default function Stuff() { const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` // console.log('apiUrl::', apiUrl) get({ url: apiUrl }).then((res) => { - console.log('정렬바꿨을때 조회 ::::::::::', res) + // console.log('정렬바꿨을때 조회 ::::::::::', res) if (!isEmptyArray(res)) { setGridProps({ ...gridProps, gridData: res, count: res.length }) setGridCount(res.length) diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx index 420b2145..13f61bb3 100644 --- a/src/components/management/StuffSearchCondition.jsx +++ b/src/components/management/StuffSearchCondition.jsx @@ -294,7 +294,7 @@ export default function StuffSearchCondition() { setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value }) }} /> - +
From 629454c2c70b8108f962ae78ff5bf4c5154a55a6 Mon Sep 17 00:00:00 2001 From: minsik Date: Fri, 4 Oct 2024 10:30:47 +0900 Subject: [PATCH 026/152] =?UTF-8?q?fix:=20=EB=8B=A4=EA=B5=AD=EC=96=B4=20?= =?UTF-8?q?=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/locales/ko.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/ko.json b/src/locales/ko.json index 572c1eef..6497020e 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -34,7 +34,7 @@ "modal.roof.shape.setting": "지붕형상 설정", "modal.roof.shape.setting.ridge": "용마루", "modal.roof.shape.setting.patten.a": "A 패턴", - "modal.roof.shape.setting.patten.b": "A 패턴", + "modal.roof.shape.setting.patten.b": "B 패턴", "modal.roof.shape.setting.side": "변별로 설정", "plan.menu.roof.cover": "지붕덮개", "plan.menu.roof.cover.outline.drawing": "외벽선 그리기", From 3a2657c1eacd4fff5f1b4414d4b848195a5241b2 Mon Sep 17 00:00:00 2001 From: changkyu choi Date: Fri, 4 Oct 2024 14:36:08 +0900 Subject: [PATCH 027/152] =?UTF-8?q?Canvas=20=EA=B7=B8=EB=A6=AC=EA=B7=B8=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/grid/DotLineGrid.jsx | 270 +++++++++++------- .../floor-plan/modal/setting01/GridOption.jsx | 1 + 2 files changed, 171 insertions(+), 100 deletions(-) diff --git a/src/components/floor-plan/modal/grid/DotLineGrid.jsx b/src/components/floor-plan/modal/grid/DotLineGrid.jsx index 54780ab5..eb5a834e 100644 --- a/src/components/floor-plan/modal/grid/DotLineGrid.jsx +++ b/src/components/floor-plan/modal/grid/DotLineGrid.jsx @@ -8,6 +8,8 @@ import { onlyNumberInputChange } from '@/util/input-utils' import { fabric } from 'fabric' import { gridColorState } from '@/store/gridAtom' import { settingModalGridOptionsState } from '@/store/settingAtom' +import { useAxios } from '@/hooks/useAxios' +import { useSwal } from '@/hooks/useSwal' const TYPE = { DOT: 'DOT', @@ -16,6 +18,7 @@ const TYPE = { export default function DotLineGrid(props) { // const [modalOption, setModalOption] = useRecoilState(modalState); //modal 열림닫힘 state + const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요 const [close, setClose] = useState(false) const { setShowDotLineGridModal } = props const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState) @@ -27,6 +30,8 @@ export default function DotLineGrid(props) { const interval = useRecoilValue(dotLineIntervalSelector) const { getMessage } = useMessage() + const { get, post } = useAxios() + const { swalFire } = useSwal() useEffect(() => { return () => { @@ -46,6 +51,12 @@ export default function DotLineGrid(props) { ] const [selectOption, setSelectOption] = useState(SelectOption[0]) + // 데이터를 최초 한 번만 조회 + useEffect(() => { + console.log('DotLineGrid useEffect 실행') + fetchGridSettings() + }, [objectNo]) + const HandleClickClose = () => { // setClose(true) // setTimeout(() => { @@ -64,118 +75,177 @@ export default function DotLineGrid(props) { }) } - const handleSave = () => { - // 1. 점.선 그리드 설정으로 만들어진 기존 오브젝트 제거 - canvas - ?.getObjects() - .filter((obj) => obj.name === 'lineGrid') - .forEach((obj) => canvas?.remove(obj)) - canvas - ?.getObjects() - .filter((obj) => obj.name === 'dotGrid') - .forEach((obj) => canvas?.remove(obj)) + // Canvas Grid Setting 조회 및 초기화 + const fetchGridSettings = async () => { + try { + const res = await get({ url: `/api/canvas-management/canvas-grid-settings/by-object/${objectNo}` }) - const horizontalInterval = interval.horizontalInterval - const verticalInterval = interval.verticalInterval - - if (dotLineGridSetting.DOT) { - const circle = new fabric.Circle({ - radius: 2, - fill: 'red', - 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: horizontalInterval, - height: verticalInterval, - }) - - 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: canvas.width, y: 0 }, - { x: canvas.width, y: canvas.height }, - { x: 0, y: canvas.height }, - ], - { - fill: pattern, - selectable: false, - name: 'dotGrid', + const patternData = { + INTERVAL: { + type: res.gridType, + horizontalInterval: res.gridHorizon, + verticalInterval: res.gridVertical, + ratioInterval: res.gridRatio, }, - ) + dimension: res.gridDimen, + DOT: res.dotGridDisplay, + LINE: res.lineGridDisplay, + } - canvas.add(backgroundPolygon) - backgroundPolygon.sendToBack() - canvas.renderAll() + const matchedOption = SelectOption.find((option) => option.value == res.gridDimen) + + // dimension 값에 맞는 옵션을 선택 + setSelectOption(matchedOption) + + // 서버에서 받은 데이터로 상태 업데이트 + setDotLineGridSettingState(patternData) + } catch (error) { + console.error('Data fetching error:', error) } + } - if (dotLineGridSetting.LINE) { - for (let i = 0; i < canvas.height / verticalInterval + 1; i++) { - const horizontalLine = new fabric.Line( - [0, i * verticalInterval - verticalInterval / 2, canvas.width, i * verticalInterval - verticalInterval / 2], - { - stroke: gridColor, - strokeWidth: 1, - selectable: true, + const handleSave = async () => { + try { + const patternData = { + objectNo, + dotGridDisplay: dotLineGridSetting.DOT, + lineGridDisplay: dotLineGridSetting.LINE, + gridType: dotLineGridSetting.INTERVAL.type, + gridHorizon: dotLineGridSetting.INTERVAL.horizontalInterval, + gridVertical: dotLineGridSetting.INTERVAL.verticalInterval, + gridRatio: dotLineGridSetting.INTERVAL.ratioInterval, + gridDimen: dotLineGridSetting.INTERVAL.dimension, + } + + // HTTP POST 요청 보내기 + await post({ url: `/api/canvas-management/canvas-grid-settings`, data: patternData }).then((res) => { + swalFire({ text: getMessage(res.returnMessage) }) + + // 1. 점.선 그리드 설정으로 만들어진 기존 오브젝트 제거 + canvas + ?.getObjects() + .filter((obj) => obj.name === 'lineGrid') + .forEach((obj) => canvas?.remove(obj)) + canvas + ?.getObjects() + .filter((obj) => obj.name === 'dotGrid') + .forEach((obj) => canvas?.remove(obj)) + + //const horizontalInterval = interval.horizontalInterval + //const verticalInterval = interval.verticalInterval + + if (patternData.dotGridDisplay) { + const circle = new fabric.Circle({ + radius: 2, + fill: 'red', + strokeWidth: 0.7, + originX: 'center', + originY: 'center', + selectable: false, lockMovementX: true, lockMovementY: true, lockRotation: true, lockScalingX: true, lockScalingY: true, - name: 'lineGrid', - strokeDashArray: [5, 2], - opacity: 0.3, - direction: 'horizontal', - }, - ) - canvas.add(horizontalLine) - } + }) - for (let i = 0; i < canvas.width / horizontalInterval + 1; i++) { - const verticalLine = new fabric.Line( - [i * horizontalInterval - horizontalInterval / 2, 0, i * horizontalInterval - horizontalInterval / 2, canvas.height], - { - stroke: gridColor, - strokeWidth: 1, - selectable: true, - lockMovementX: true, - lockMovementY: true, - lockRotation: true, - lockScalingX: true, - lockScalingY: true, - name: 'lineGrid', - strokeDashArray: [5, 2], - opacity: 0.3, - direction: 'vertical', - }, - ) - canvas.add(verticalLine) - } + const patternSourceCanvas = new fabric.StaticCanvas(null, { + width: patternData.gridHorizon, + height: patternData.gridVertical, + }) + + 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: canvas.width, y: 0 }, + { x: canvas.width, y: canvas.height }, + { x: 0, y: canvas.height }, + ], + { + fill: pattern, + selectable: false, + name: 'dotGrid', + }, + ) + + canvas.add(backgroundPolygon) + backgroundPolygon.sendToBack() + canvas.renderAll() + } + + if (patternData.lineGridDisplay) { + for (let i = 0; i < canvas.height / patternData.gridVertical + 1; i++) { + const horizontalLine = new fabric.Line( + [ + 0, + i * patternData.gridVertical - patternData.gridVertical / 2, + canvas.width, + i * patternData.gridVertical - patternData.gridVertical / 2, + ], + { + stroke: gridColor, + strokeWidth: 1, + selectable: true, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + name: 'lineGrid', + strokeDashArray: [5, 2], + opacity: 0.3, + direction: 'horizontal', + }, + ) + canvas.add(horizontalLine) + } + + for (let i = 0; i < canvas.width / patternData.gridHorizon + 1; i++) { + const verticalLine = new fabric.Line( + [ + i * patternData.gridHorizon - patternData.gridHorizon / 2, + 0, + i * patternData.gridHorizon - patternData.gridHorizon / 2, + canvas.height, + ], + { + stroke: gridColor, + strokeWidth: 1, + selectable: true, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + name: 'lineGrid', + strokeDashArray: [5, 2], + opacity: 0.3, + direction: 'vertical', + }, + ) + canvas.add(verticalLine) + } + } + + canvas.renderAll() + }) + } catch (error) { + swalFire({ text: getMessage(res.returnMessage), icon: 'error' }) } - - canvas.renderAll() } const handleRadioChange = (e) => { diff --git a/src/components/floor-plan/modal/setting01/GridOption.jsx b/src/components/floor-plan/modal/setting01/GridOption.jsx index d9301afc..39af3a10 100644 --- a/src/components/floor-plan/modal/setting01/GridOption.jsx +++ b/src/components/floor-plan/modal/setting01/GridOption.jsx @@ -18,6 +18,7 @@ export default function GridOption(props) { const [color, setColor] = useColor(gridColor) useEffect(() => { + console.log('GridOption useEffect 실행') setGridColor(color.hex) }, [color]) From 168ba06d04975451fb25cd5a78c225bfe522c768 Mon Sep 17 00:00:00 2001 From: basssy Date: Fri, 4 Oct 2024 15:54:45 +0900 Subject: [PATCH 028/152] =?UTF-8?q?=EB=AC=BC=EA=B1=B4=ED=98=84=ED=99=A9=20?= =?UTF-8?q?-?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/management/Stuff.jsx | 42 +++--- src/components/management/StuffDetail.jsx | 149 ++++++++++++++++------ 2 files changed, 131 insertions(+), 60 deletions(-) diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index bfda6d62..4fd3b49e 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -12,20 +12,24 @@ import { queryStringFormatter, isEmptyArray } from '@/util/common-utils' import dayjs from 'dayjs' import isLeapYear from 'dayjs/plugin/isLeapYear' // 윤년 판단 플러그인 dayjs.extend(isLeapYear) -import { globalLocaleStore } from '@/store/localeAtom' +import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' +import KO from '@/locales/ko.json' +import JA from '@/locales/ja.json' +import '@/styles/grid.scss' export default function Stuff() { + const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore) const stuffSearchParams = useRecoilValue(stuffSearchState) const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState) const { getMessage } = useMessage() const [curPage, setCurPage] = useState(1) //현재 페이지 번호 const [defaultSize, setDefaultSize] = useState(100) //페이지 당 게시물 수 + const [gridCount, setGridCount] = useState(0) //총 갯수 const [defaultSortType, setDefaultSortType] = useState('R') const globalLocaleState = useRecoilValue(globalLocaleStore) const { get } = useAxios(globalLocaleState) const gridRef = useRef() - const [gridCount, setGridCount] = useState(0) const [selectedRowData, setSelectedRowData] = useState([]) const [selectedRowDataCount, setSelectedRowDataCount] = useState(0) @@ -273,14 +277,12 @@ export default function Stuff() { // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(params)}` const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(params)}` - await get({ url: apiUrl, }).then((res) => { if (!isEmptyArray(res)) { - // console.log('화면진입API결과::', res) - setGridProps({ ...gridProps, gridData: res, count: res.length }) - setGridCount(res.length) + setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) + setGridCount(res[0].totCnt) } }) } @@ -293,15 +295,14 @@ export default function Stuff() { stuffSearchParams.startRow = (curPage - 1) * defaultSize + 1 stuffSearchParams.endRow = curPage * defaultSize stuffSearchParams.schSortType = defaultSortType - // console.log('조회 눌럿을때 ::::::::::::::', stuffSearchParams) async function fetchData() { // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` await get({ url: apiUrl }).then((res) => { - console.log('API결과:::::::', res) + // console.log('검색조건 변경 조회 API결과:::::::', res) if (!isEmptyArray(res)) { - setGridProps({ ...gridProps, gridData: res, count: res.length }) - setGridCount(res.length) + setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) + setGridCount(res[0].totCnt) } else { setGridProps({ ...gridProps, gridData: [], count: 0 }) setGridCount(0) @@ -324,15 +325,14 @@ export default function Stuff() { startRow: startRow, endRow: curPage * e.target.value, }) - // console.log('셋팅된 검색조건:::', stuffSearchParams) + console.log('페이지 갯수 변경 때 셋팅된 검색조건:::', stuffSearchParams) //조회API호출 // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` get({ url: apiUrl }).then((res) => { - // console.log('보여줄개수바꿨을때 조회 ::::::::::', res) if (!isEmptyArray(res)) { - setGridProps({ ...gridProps, gridData: res, count: res.length }) - setGridCount(res.length) + setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) + setGridCount(res[0].totCnt) } else { setGridProps({ ...gridProps, gridData: [], count: 0 }) setGridCount(0) @@ -352,18 +352,24 @@ export default function Stuff() { }) // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` - // console.log('apiUrl::', apiUrl) get({ url: apiUrl }).then((res) => { - // console.log('정렬바꿨을때 조회 ::::::::::', res) if (!isEmptyArray(res)) { - setGridProps({ ...gridProps, gridData: res, count: res.length }) - setGridCount(res.length) + setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) + setGridCount(res[0].totCnt) } else { setGridProps({ ...gridProps, gridData: [], count: 0 }) setGridCount(0) } }) } + + useEffect(() => { + if (globalLocaleState === 'ko') { + setAppMessageState(KO) + } else { + setAppMessageState(JA) + } + }, [globalLocaleState]) return ( <> {/* 퍼블시작 */} diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index 898b4176..a62b35b1 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -11,6 +11,7 @@ import dayjs from 'dayjs' import { useMessage } from '@/hooks/useMessage' import { useForm } from 'react-hook-form' import { useRecoilState, useRecoilValue } from 'recoil' +import { v4 as uuidv4 } from 'uuid' export default function StuffDetail() { const router = useRouter() const searchParams = useSearchParams() @@ -38,7 +39,7 @@ export default function StuffDetail() { windSpeed: '', //기준풍속 snowCover: '', //수직적설량 coldAreaChk: false, //한랭지대책시행 - surfaceType: 'Ⅲ・Ⅳ', //면조도구분(Ⅲ・Ⅳ / Ⅱ) + surfaceType: 'III・IV', //면조도구분(III・IV / Ⅱ) saltAreaChk: false, //염해지역용아이템사용 installHeight: '', //설치높이 powerConTerms: '0', //계약조건(잉여 / 전량) @@ -77,14 +78,13 @@ export default function StuffDetail() { get({ url: `/api/object/${objectNo}/detail` }).then((res) => { // console.log('물건번호로 상세 API 호출') if (res != null) { - // console.log('상세res:::::::', res) setDetailData(res) // 신규 상세 공통APi // 도도부현API get({ url: '/api/object/prefecture/list' }).then((res) => { if (!isEmptyArray(res)) { - //console.log('도도부현API 결과:::', res) + console.log('도도부현API 결과:::', res) setPrefCodeList(res) } }) @@ -106,12 +106,11 @@ export default function StuffDetail() { } }) } else { - console.log('신규화면') // 신규 상세 공통APi // 도도부현API get({ url: '/api/object/prefecture/list' }).then((res) => { if (!isEmptyArray(res)) { - //console.log('도도부현API 결과:::', res) + // console.log('신규화면 도도부현API 결과:::', res) setPrefCodeList(res) } }) @@ -121,11 +120,11 @@ export default function StuffDetail() { //1차점 : X167 get({ url: `/api/object/saleStore/X167/list` }).then((res) => { if (!isEmptyArray(res)) { - console.log('판매점 결과:::::', res) + // console.log('판매점 결과:::::', res) const firstList = res.filter((row) => row.saleStoreLevel === '1') const otherList = res.filter((row) => row.saleStoreLevel !== '1') - console.log('first:::::', firstList) - console.log('otherList:::::', otherList) + // console.log('first:::::', firstList) + // console.log('otherList:::::', otherList) //1차점 셀렉트박스 setSaleStoreList(firstList) //1차 판매점 자동완성 값 셋팅 @@ -135,6 +134,8 @@ export default function StuffDetail() { //1차점 아닌 판매점 셀렉트박스 setOtherSaleStoreList(otherList) + form.setValue('otherSaleStoreId', otherList[0].saleStoreId) + form.setValue('otherSaleStoreName', otherList[0].saleStoreId) } }) } @@ -146,14 +147,17 @@ export default function StuffDetail() { form.setValue('saleStoreId', '') form.setValue('saleStoreName', '') } else { - form.setValue('saleStoreId', key) - form.setValue('saleStoreName', key) + const name = saleStoreList.find((obj) => obj.saleStoreId === key.target.value).saleStoreName + form.setValue('saleStoreId', key.target.value) + form.setValue('saleStoreName', name) } } //2차점 변경 이벤트 const onSelectionChange2 = (key) => { - console.log(key) + const name = otherSaleStoreList.find((obj) => obj.saleStoreId === key.target.value).saleStoreName + form.setValue('otherSaleStoreId', key.target.value) + form.setValue('otherSaleStoreNm', name) } // 우편번호 숫자만 체크 const _zipNo = watch('zipNo') @@ -187,17 +191,19 @@ export default function StuffDetail() { const _objectName = watch('objectName') const _objectNameOmit = watch('objectNameOmit') const _saleStoreId = watch('saleStoreId') + const _otherSaleStoreId = watch('otherSaleStoreId') const _prefId = watch('prefId') const _address = watch('address') const _powerSimArea = watch('powerSimArea') const _windSpeed = watch('windSpeed') const _snowCover = watch('snowCover') const _installHeight = watch('installHeight') + useEffect(() => { // console.log('mode:::::', editMode) if (editMode === 'NEW') { const formData = form.getValues() - // console.log('폼::::::::::::', formData) + console.log('폼::::::::::::', formData) let errors = {} if (!_dispCompanyName || _dispCompanyName.trim().length === 0) { errors.dispCompanyName = true @@ -212,6 +218,10 @@ export default function StuffDetail() { errors.saleStoreId = true } + // if (!_otherSaleStoreId) { + // errors.otherSaleStoreId = true + // } + if (!_zipNo || _zipNo.length != 7) { errors.zipCode = true } @@ -240,12 +250,25 @@ export default function StuffDetail() { errors.installHeight = true } - // console.log('errors::', errors) + console.log('errors::', errors) setIsFormValid(Object.keys(errors).length === 0) } else { // console.log('상세일때 폼체크') } - }, [_dispCompanyName, _objectName, _objectNameOmit, _saleStoreId, _zipNo, _prefId, _address, _powerSimArea, _windSpeed, _snowCover, _installHeight]) + }, [ + _dispCompanyName, + _objectName, + _objectNameOmit, + _saleStoreId, + // _otherSaleStoreId, + _zipNo, + _prefId, + _address, + _powerSimArea, + _windSpeed, + _snowCover, + _installHeight, + ]) // 주소검색 API const onSearchPostNumber = () => { @@ -257,7 +280,7 @@ export default function StuffDetail() { //9302226 if (res.status === 200) { if (res.results != null) { - // console.log('주소검색::', res.results) + console.log('주소검색::', res.results) // console.log('prefcode::', res.results[0].prefcode) // console.log('address::', res.results[0].address2 + res.results[0].address3) setPrefValue(res.results[0].prefcode) @@ -287,7 +310,7 @@ export default function StuffDetail() { // /api/object/prefecture/도도부현코드/list get({ url: `/api/object/prefecture/${prefValue}/list` }).then((res) => { if (!isEmptyArray(res)) { - // console.log('발전시뮬레이션::::::::', res) + console.log('발전량 시뮬레이션::::::::', res) setPowerSimAreaList(res) } }) @@ -328,7 +351,6 @@ export default function StuffDetail() { // 임시저장 const onTempSave = async () => { const formData = form.getValues() - //console.log('임시저장::::::::', formData) const params = { saleStoreId: formData.saleStoreId, @@ -348,8 +370,8 @@ export default function StuffDetail() { snowCover: formData.snowCover, surfaceType: formData.surfaceType, powerConTerms: formData.powerConTerms, - saltAreaChk: formData.saltAreaChk, coldAreaChk: formData.coldAreaChk, + saltAreaChk: formData.saltAreaChk, tempFlg: '1', workNo: null, workName: null, @@ -364,8 +386,9 @@ export default function StuffDetail() { // 발전량 시뮬레이션 변경 const handlePowerSimAreaOnChange = (e) => { // console.log('가지고있는 도도부현코드:::::::::', prefValue) - // console.log('발전량시뮬레이션변경:::::::::', e.target.value) - //값 set해주고 그거 useEffect로 api호출 + console.log('발전량시뮬레이션변경:::::::::', e.target.value) + form.setValue('powerSimArea', e.target.value) + //값 set해주고 그거 useEffect로 기준풍속, 수직적설량 api호출 } // 물건삭제 @@ -426,7 +449,7 @@ export default function StuffDetail() {
- @@ -457,16 +480,20 @@ export default function StuffDetail() {
- + {saleStoreList?.length > 0 && ( + + )}
- +
@@ -474,20 +501,34 @@ export default function StuffDetail() {
-
- 2차 판매점명 / ID * -
+
2차 판매점명 / ID
- + {otherSaleStoreList?.length > 0 && ( + + )} +
+
+
-
-
-
@@ -522,6 +563,7 @@ export default function StuffDetail() {
+ {/* {prefCodeList?.length > 0 && ( )} */} + {/* {prefCodeList?.length > 0 && ( + + )} */}
@@ -541,7 +588,19 @@ export default function StuffDetail() { 발전량시뮬레이션지역 * -
+
+ {powerSimAreaList?.length > 0 && ( + + )} +
@@ -568,11 +627,17 @@ export default function StuffDetail() {
-
+
+ +
cm
- - + +
@@ -592,8 +657,8 @@ export default function StuffDetail() {
- - + +
From 325e5632c5dd49621c8546eec99c462fedafe204 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 4 Oct 2024 16:34:26 +0900 Subject: [PATCH 029/152] =?UTF-8?q?=EC=A7=80=EB=B6=95=ED=98=95=EC=83=81=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QPolygon.js | 3 +- .../modal/roofShape/RoofShapeSetting.jsx | 86 ++- .../modal/roofShape/type/Direction.jsx | 11 +- .../modal/roofShape/type/Pattern.jsx | 10 +- .../floor-plan/modal/roofShape/type/Ridge.jsx | 10 +- .../floor-plan/modal/roofShape/type/Side.jsx | 69 ++- .../modal/roofShape/type/option/Eaves.jsx | 7 +- .../modal/roofShape/type/option/Gable.jsx | 7 +- .../roofShape/type/option/HipAndGable.jsx | 16 +- .../roofShape/type/option/Jerkinhead.jsx | 14 +- .../modal/roofShape/type/option/Shed.jsx | 5 +- .../modal/roofShape/type/option/Wall.jsx | 12 +- src/hooks/roofcover/useOuterLineWall.js | 42 +- src/hooks/roofcover/usePropertiesSetting.js | 12 +- src/hooks/roofcover/useRoofShapeSetting.js | 496 ++++++++++++++++++ src/hooks/useLine.js | 42 +- src/hooks/usePlan.js | 5 + src/hooks/usePolygon.js | 2 + src/locales/ja.json | 1 + src/locales/ko.json | 3 +- src/util/input-utils.js | 2 +- src/util/qpolygon-utils.js | 1 + 22 files changed, 757 insertions(+), 99 deletions(-) create mode 100644 src/hooks/roofcover/useRoofShapeSetting.js diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index fec9e227..360c9ddc 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -169,8 +169,9 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { attributes: { offset: 0, }, + parent: this, direction: getDirectionByPoint(point, nextPoint), - idx: i, + idx: i + 1, }) line.startPoint = point line.endPoint = nextPoint diff --git a/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx b/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx index 517a7ba3..ccf38062 100644 --- a/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx +++ b/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx @@ -1,25 +1,73 @@ -import { useMessage } from '@/hooks/useMessage' import WithDraggable from '@/components/common/draggable/WithDraggable' import Ridge from '@/components/floor-plan/modal/roofShape/type/Ridge' import Pattern from '@/components/floor-plan/modal/roofShape/type/Pattern' import Side from '@/components/floor-plan/modal/roofShape/type/Side' -import { useState } from 'react' import Image from 'next/image' import Direction from '@/components/floor-plan/modal/roofShape/type/Direction' +import { useRoofShapeSetting } from '@/hooks/roofcover/useRoofShapeSetting' +import { useMessage } from '@/hooks/useMessage' export default function RoofShapeSetting({ setShowRoofShapeSettingModal }) { const { getMessage } = useMessage() - const [shapeNum, setShapeNum] = useState(1) - const shapeMenu = [ - { id: 1, name: getMessage('modal.roof.shape.setting.ridge') }, // 용마루 - { id: 2, name: getMessage('modal.roof.shape.setting.patten.a') }, // 패턴A - { id: 3, name: getMessage('modal.roof.shape.setting.patten.b') }, // 패턴B - { id: 4, name: getMessage('modal.roof.shape.setting.side') }, // 변별로 설정 - { id: 5, name: getMessage('commons.west') }, // 서 - { id: 6, name: getMessage('commons.east') }, // 서 - { id: 7, name: getMessage('commons.south') }, // 서 - { id: 8, name: getMessage('commons.north') }, // 북 - ] + const { + shapeNum, + setShapeNum, + shapeMenu, + handleSave, + pitch, + setPitch, + eavesOffset, + setEavesOffset, + gableOffset, + setGableOffset, + sleeveOffset, + setSleeveOffset, + jerkinHeadWidth, + setJerkinHeadWidth, + jerkinHeadPitch, + setJerkinHeadPitch, + hipAndGableWidth, + setHipAndGableWidth, + shedWidth, + setShedWidth, + hasSleeve, + setHasSleeve, + buttonAct, + setButtonAct, + buttonMenu, + handleConfirm, + handleRollBack, + } = useRoofShapeSetting() + + const ridgeProps = { pitch, setPitch, eavesOffset, setEavesOffset } + const patternProps = { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset } + const sideProps = { + pitch, + setPitch, + eavesOffset, + setEavesOffset, + gableOffset, + setGableOffset, + sleeveOffset, + setSleeveOffset, + jerkinHeadWidth, + setJerkinHeadWidth, + jerkinHeadPitch, + setJerkinHeadPitch, + hipAndGableWidth, + setHipAndGableWidth, + shedWidth, + setShedWidth, + hasSleeve, + setHasSleeve, + buttonAct, + setButtonAct, + buttonMenu, + handleConfirm, + handleRollBack, + } + + const directionProps = { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset, shedWidth, setShedWidth } return ( @@ -43,13 +91,15 @@ export default function RoofShapeSetting({ setShowRoofShapeSettingModal }) {
{getMessage('setting')}
- {shapeNum === 1 && } - {(shapeNum === 2 || shapeNum === 3) && } - {shapeNum === 4 && } - {(shapeNum === 5 || shapeNum === 6 || shapeNum === 7 || shapeNum === 8) && } + {shapeNum === 1 && } + {(shapeNum === 2 || shapeNum === 3) && } + {shapeNum === 4 && } + {(shapeNum === 5 || shapeNum === 6 || shapeNum === 7 || shapeNum === 8) && }
- +
diff --git a/src/components/floor-plan/modal/roofShape/type/Direction.jsx b/src/components/floor-plan/modal/roofShape/type/Direction.jsx index a02258f9..51faffcb 100644 --- a/src/components/floor-plan/modal/roofShape/type/Direction.jsx +++ b/src/components/floor-plan/modal/roofShape/type/Direction.jsx @@ -1,6 +1,7 @@ import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' -export default function Direction() { +export default function Direction({ pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset, shedWidth, setShedWidth }) { const { getMessage } = useMessage() return (
@@ -9,7 +10,7 @@ export default function Direction() { {getMessage('slope')}
- + onlyNumberWithDotInputChange(e, setPitch)} />
{getMessage('size')}
@@ -18,7 +19,7 @@ export default function Direction() { {getMessage('eaves.offset')}
- + onlyNumberInputChange(e, setEavesOffset)} />
mm
@@ -27,7 +28,7 @@ export default function Direction() { {getMessage('gable.offset')}
- + onlyNumberInputChange(e, setGableOffset)} />
mm
@@ -36,7 +37,7 @@ export default function Direction() { {getMessage('windage.width')}
- + onlyNumberInputChange(e, setShedWidth)} />
mm
diff --git a/src/components/floor-plan/modal/roofShape/type/Pattern.jsx b/src/components/floor-plan/modal/roofShape/type/Pattern.jsx index 606c154d..0c086fbe 100644 --- a/src/components/floor-plan/modal/roofShape/type/Pattern.jsx +++ b/src/components/floor-plan/modal/roofShape/type/Pattern.jsx @@ -1,7 +1,9 @@ import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' -export default function Pattern() { +export default function Pattern(props) { const { getMessage } = useMessage() + const { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset } = props return (
@@ -9,7 +11,7 @@ export default function Pattern() { {getMessage('slope')}
- + onlyNumberWithDotInputChange(e, setPitch)} />
{getMessage('size')}
@@ -18,7 +20,7 @@ export default function Pattern() { {getMessage('eaves.offset')}
- + onlyNumberInputChange(e, setEavesOffset)} />
mm
@@ -27,7 +29,7 @@ export default function Pattern() { {getMessage('gable.offset')}
- +
mm diff --git a/src/components/floor-plan/modal/roofShape/type/Ridge.jsx b/src/components/floor-plan/modal/roofShape/type/Ridge.jsx index 7897046c..13dab6f3 100644 --- a/src/components/floor-plan/modal/roofShape/type/Ridge.jsx +++ b/src/components/floor-plan/modal/roofShape/type/Ridge.jsx @@ -1,7 +1,11 @@ import { useMessage } from '@/hooks/useMessage' +import { useEffect } from 'react' +import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' -export default function Ridge() { +export default function Ridge(props) { const { getMessage } = useMessage() + const { pitch, setPitch, eavesOffset, setEavesOffset } = props + return (
@@ -9,7 +13,7 @@ export default function Ridge() { {getMessage('slope')}
- + onlyNumberWithDotInputChange(e, setPitch)} />
{getMessage('size')}
@@ -18,7 +22,7 @@ export default function Ridge() { {getMessage('eaves.offset')}
- + onlyNumberInputChange(e, setEavesOffset)} />
mm
diff --git a/src/components/floor-plan/modal/roofShape/type/Side.jsx b/src/components/floor-plan/modal/roofShape/type/Side.jsx index 3fc1737c..b2f032ba 100644 --- a/src/components/floor-plan/modal/roofShape/type/Side.jsx +++ b/src/components/floor-plan/modal/roofShape/type/Side.jsx @@ -7,39 +7,68 @@ import Wall from '@/components/floor-plan/modal/roofShape/type/option/Wall' import Jerkinhead from '@/components/floor-plan/modal/roofShape/type/option/Jerkinhead' import Shed from '@/components/floor-plan/modal/roofShape/type/option/Shed' -export default function Side() { - const [buttonAct, setButtonAct] = useState(1) +export default function Side(props) { + const { + pitch, + setPitch, + eavesOffset, + setEavesOffset, + gableOffset, + setGableOffset, + sleeveOffset, + setSleeveOffset, + jerkinHeadWidth, + setJerkinHeadWidth, + jerkinHeadPitch, + setJerkinHeadPitch, + hipAndGableWidth, + setHipAndGableWidth, + shedWidth, + setShedWidth, + hasSleeve, + setHasSleeve, + buttonAct, + setButtonAct, + buttonMenu, + handleConfirm, + handleRollBack, + } = props + + const eavesProps = { pitch, setPitch, eavesOffset, setEavesOffset } + const gableProps = { gableOffset, setGableOffset } + const wallProps = { sleeveOffset, setSleeveOffset, hasSleeve, setHasSleeve } + const hipAndGableProps = { pitch, setPitch, eavesOffset, setEavesOffset, hipAndGableWidth, setHipAndGableWidth } + const jerkinheadProps = { gableOffset, setGableOffset, jerkinHeadWidth, setJerkinHeadWidth, jerkinHeadPitch, setJerkinHeadPitch } + const shedProps = { shedWidth, setShedWidth } + const { getMessage } = useMessage() - const buttonMenu = [ - { id: 1, name: getMessage('eaves') }, - { id: 2, name: getMessage('gable') }, - { id: 3, name: getMessage('wall') }, - { id: 4, name: getMessage('hipandgable') }, - { id: 5, name: getMessage('jerkinhead') }, - { id: 6, name: getMessage('shed') }, - ] + return (
- {buttonMenu.map((item) => ( - ))}
- {buttonAct === 1 && } - {buttonAct === 2 && } - {buttonAct === 3 && } - {buttonAct === 4 && } - {buttonAct === 5 && } - {buttonAct === 6 && } + {buttonAct === 1 && } + {buttonAct === 2 && } + {buttonAct === 3 && } + {buttonAct === 4 && } + {buttonAct === 5 && } + {buttonAct === 6 && }
- - + +
) diff --git a/src/components/floor-plan/modal/roofShape/type/option/Eaves.jsx b/src/components/floor-plan/modal/roofShape/type/option/Eaves.jsx index 303dad55..8d061a7b 100644 --- a/src/components/floor-plan/modal/roofShape/type/option/Eaves.jsx +++ b/src/components/floor-plan/modal/roofShape/type/option/Eaves.jsx @@ -1,6 +1,7 @@ import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' -export default function Eaves() { +export default function Eaves({ pitch, setPitch, eavesOffset, setEavesOffset }) { const { getMessage } = useMessage() return ( <> @@ -9,7 +10,7 @@ export default function Eaves() { {getMessage('slope')}
- + onlyNumberWithDotInputChange(e, setPitch)} />
{getMessage('size')} @@ -18,7 +19,7 @@ export default function Eaves() { {getMessage('eaves.offset')}
- + onlyNumberInputChange(e, setEavesOffset)} />
mm diff --git a/src/components/floor-plan/modal/roofShape/type/option/Gable.jsx b/src/components/floor-plan/modal/roofShape/type/option/Gable.jsx index 63092550..08e503d2 100644 --- a/src/components/floor-plan/modal/roofShape/type/option/Gable.jsx +++ b/src/components/floor-plan/modal/roofShape/type/option/Gable.jsx @@ -1,13 +1,16 @@ import { useMessage } from '@/hooks/useMessage' +import { useEffect } from 'react' +import { onlyNumberInputChange } from '@/util/input-utils' -export default function Gable() { +export default function Gable({ gableOffset, setGableOffset }) { const { getMessage } = useMessage() + return ( <>
{getMessage('gable.offset')}
- + onlyNumberInputChange(e, setGableOffset)} />
mm
diff --git a/src/components/floor-plan/modal/roofShape/type/option/HipAndGable.jsx b/src/components/floor-plan/modal/roofShape/type/option/HipAndGable.jsx index ed2e1b60..ce4a57cc 100644 --- a/src/components/floor-plan/modal/roofShape/type/option/HipAndGable.jsx +++ b/src/components/floor-plan/modal/roofShape/type/option/HipAndGable.jsx @@ -1,6 +1,7 @@ import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' -export default function HipAndGable() { +export default function HipAndGable({ pitch, setPitch, eavesOffset, setEavesOffset, hipAndGableWidth, setHipAndGableWidth }) { const { getMessage } = useMessage() return ( <> @@ -9,7 +10,7 @@ export default function HipAndGable() { {getMessage('slope')}
- + onlyNumberWithDotInputChange(e, setPitch)} />
{getMessage('size')} @@ -18,16 +19,21 @@ export default function HipAndGable() { {getMessage('eaves.offset')}
- + onlyNumberInputChange(e, setEavesOffset)} />
mm
- {getMessage('gable.offset')} + {getMessage('hipandgable.width')}
- + onlyNumberInputChange(e, setHipAndGableWidth)} + />
mm
diff --git a/src/components/floor-plan/modal/roofShape/type/option/Jerkinhead.jsx b/src/components/floor-plan/modal/roofShape/type/option/Jerkinhead.jsx index d5737470..be846e94 100644 --- a/src/components/floor-plan/modal/roofShape/type/option/Jerkinhead.jsx +++ b/src/components/floor-plan/modal/roofShape/type/option/Jerkinhead.jsx @@ -1,6 +1,7 @@ import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' -export default function Jerkinhead() { +export default function Jerkinhead({ gableOffset, setGableOffset, jerkinHeadWidth, setJerkinHeadWidth, jerkinHeadPitch, setJerkinHeadPitch }) { const { getMessage } = useMessage() return ( <> @@ -9,7 +10,7 @@ export default function Jerkinhead() { {getMessage('gable.offset')}
- + onlyNumberInputChange(e, setGableOffset)} />
mm @@ -18,7 +19,7 @@ export default function Jerkinhead() { {getMessage('jerkinhead.width')}
- + onlyNumberInputChange(e, setJerkinHeadWidth)} />
mm @@ -27,7 +28,12 @@ export default function Jerkinhead() { {getMessage('jerkinhead.slope')}
- + onlyNumberWithDotInputChange(e, setJerkinHeadPitch)} + />
{getMessage('size')} diff --git a/src/components/floor-plan/modal/roofShape/type/option/Shed.jsx b/src/components/floor-plan/modal/roofShape/type/option/Shed.jsx index c4fd4333..40ccdbef 100644 --- a/src/components/floor-plan/modal/roofShape/type/option/Shed.jsx +++ b/src/components/floor-plan/modal/roofShape/type/option/Shed.jsx @@ -1,13 +1,14 @@ import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange } from '@/util/input-utils' -export default function Shed() { +export default function Shed({ shedWidth, setShedWidth }) { const { getMessage } = useMessage() return ( <>
{getMessage('shed.width')}
- + onlyNumberInputChange(e, setShedWidth)} />
mm
diff --git a/src/components/floor-plan/modal/roofShape/type/option/Wall.jsx b/src/components/floor-plan/modal/roofShape/type/option/Wall.jsx index 6b716892..c7b04b2d 100644 --- a/src/components/floor-plan/modal/roofShape/type/option/Wall.jsx +++ b/src/components/floor-plan/modal/roofShape/type/option/Wall.jsx @@ -1,8 +1,8 @@ import { useState } from 'react' import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange } from '@/util/input-utils' -export default function Wall() { - const [hasSleeve, setHasSleeve] = useState('0') +export default function Wall({ sleeveOffset, setSleeveOffset, hasSleeve, setHasSleeve }) { const { getMessage } = useMessage() return ( <> @@ -26,7 +26,13 @@ export default function Wall() {
- + onlyNumberInputChange(e, setSleeveOffset)} + readOnly={hasSleeve === '0'} + />
mm
diff --git a/src/hooks/roofcover/useOuterLineWall.js b/src/hooks/roofcover/useOuterLineWall.js index 130593a0..72fdf91f 100644 --- a/src/hooks/roofcover/useOuterLineWall.js +++ b/src/hooks/roofcover/useOuterLineWall.js @@ -6,6 +6,7 @@ import { adsorptionPointModeState, adsorptionRangeState, canvasState, + currentCanvasPlanState, dotLineIntervalSelector, verticalHorizontalModeState, } from '@/store/canvasAtom' @@ -43,7 +44,7 @@ export function useOuterLineWall() { const adsorptionPointMode = useRecoilValue(adsorptionPointModeState) const adsorptionRange = useRecoilValue(adsorptionRangeState) const interval = useRecoilValue(dotLineIntervalSelector) // 가로 세로 간격 - + const currentCanvasPlan = useRecoilValue(currentCanvasPlanState) const length1Ref = useRef(null) const length2Ref = useRef(null) const angle1Ref = useRef(null) @@ -73,14 +74,6 @@ export function useOuterLineWall() { return } - if (points.length === 0) { - // 만약 포인트가 없다면 모든 라인과 텍스트를 삭제 후 outerLines에서 point를 뽑아 points에 넣어준다. - const lengthTxts = canvas?.getObjects().filter((obj) => obj.name === 'lengthTxt') - lengthTxts.forEach((txt) => { - canvas?.remove(txt) - }) - } - addCanvasMouseEventListener('mouse:down', mouseDown) clear() }, [verticalHorizontalMode, points, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, interval, tempGridMode]) @@ -98,6 +91,18 @@ export function useOuterLineWall() { addDocumentEventListener('keydown', document, keydown[type]) }, [type]) + useEffect(() => { + const outerLinePoints = canvas?.getObjects().filter((obj) => obj.name === 'outerLinePoint') + const newPoints = [] + if (points.length === 0 && outerLinePoints.length > 0) { + outerLinePoints.forEach((point) => { + newPoints.push({ x: point.left, y: point.top }) + }) + + setPoints(newPoints) + } + }, []) + const clear = () => { setLength1(0) setLength2(0) @@ -186,6 +191,21 @@ export function useOuterLineWall() { canvas?.add(point) } else { setOuterLineFix(false) + canvas + .getObjects() + .filter((obj) => obj.name === 'outerLinePoint') + .forEach((obj) => { + canvas.remove(obj) + }) + points.forEach((point, idx) => { + const circle = new fabric.Circle({ + left: point.x, + top: point.y, + visible: false, + name: 'outerLinePoint', + }) + canvas.add(circle) + }) points.forEach((point, idx) => { if (idx === 0) { return @@ -272,6 +292,10 @@ export function useOuterLineWall() { idx: idx, selectable: true, name: 'outerLine', + x1: point1.x, + y1: point1.y, + x2: point2.x, + y2: point2.y, }) } diff --git a/src/hooks/roofcover/usePropertiesSetting.js b/src/hooks/roofcover/usePropertiesSetting.js index d478a1bc..00ad3890 100644 --- a/src/hooks/roofcover/usePropertiesSetting.js +++ b/src/hooks/roofcover/usePropertiesSetting.js @@ -1,10 +1,11 @@ import { useEffect, useRef } from 'react' import { LINE_TYPE } from '@/common/common' -import { useRecoilValue } from 'recoil' +import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' import { canvasState, currentObjectState } from '@/store/canvasAtom' import { useMode } from '@/hooks/useMode' import { usePolygon } from '@/hooks/usePolygon' import { useLine } from '@/hooks/useLine' +import { outerLinePointsState } from '@/store/outerLineAtom' export function usePropertiesSetting() { const canvas = useRecoilValue(canvasState) @@ -12,9 +13,10 @@ export function usePropertiesSetting() { const currentObject = useRecoilValue(currentObjectState) const { drawRoofPolygon } = useMode() + const setPoints = useResetRecoilState(outerLinePointsState) const { addPolygonByLines } = usePolygon() - const { removeLine } = useLine() + const { removeLine, hideLine } = useLine() useEffect(() => { if (!currentObject) { @@ -125,7 +127,8 @@ export function usePropertiesSetting() { stroke: '#000000', strokeWidth: 4, }) - removeLine(line) + + hideLine(hideLine) }) const wall = addPolygonByLines(lines, { name: 'WallLine', fill: 'transparent', stroke: 'black' }) @@ -133,7 +136,7 @@ export function usePropertiesSetting() { wall.lines = [...lines] drawRoofPolygon(wall) - + setPoints([]) canvas.renderAll() } @@ -153,6 +156,7 @@ export function usePropertiesSetting() { }) canvas.renderAll() + setPoints([]) fn(false) } diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js new file mode 100644 index 00000000..492e52e8 --- /dev/null +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -0,0 +1,496 @@ +import { useEffect, useRef, useState } from 'react' +import { useMessage } from '@/hooks/useMessage' +import { useRecoilValue } from 'recoil' +import { canvasState, currentObjectState } from '@/store/canvasAtom' +import { LINE_TYPE } from '@/common/common' +import { usePolygon } from '@/hooks/usePolygon' +import { useMode } from '@/hooks/useMode' +import { useLine } from '@/hooks/useLine' + +export function useRoofShapeSetting() { + const [shapeNum, setShapeNum] = useState(1) + const [buttonAct, setButtonAct] = useState(1) + const { getMessage } = useMessage() + const canvas = useRecoilValue(canvasState) + const { addPolygonByLines } = usePolygon() + const [pitch, setPitch] = useState(4) + const [eavesOffset, setEavesOffset] = useState(500) // 처마출폭 + const [gableOffset, setGableOffset] = useState(300) // 케라바출폭 + const [sleeveOffset, setSleeveOffset] = useState(300) // 소매출폭 + const [jerkinHeadWidth, setJerkinHeadWidth] = useState(800) // 반절처 폭 + const [jerkinHeadPitch, setJerkinHeadPitch] = useState(4.5) // 반절처 경사 + const [hipAndGableWidth, setHipAndGableWidth] = useState(800) // 팔작지붕 폭 + const [shedWidth, setShedWidth] = useState(300) // 한쪽흐름 폭 + const [hasSleeve, setHasSleeve] = useState('0') + const currentObject = useRecoilValue(currentObjectState) + const { drawRoofPolygon } = useMode() + const { hideLine, showLine } = useLine() + + const history = useRef([]) + + useEffect(() => { + const wallLine = canvas.getObjects().find((obj) => obj.name === 'wallLine') + canvas?.remove(wallLine) + + const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + outerLines.forEach((line) => { + showLine(line) + }) + canvas?.renderAll() + }, []) + + useEffect(() => { + if (shapeNum !== 4) { + return + } + if (!currentObject) { + return + } + if (currentObject.name !== 'outerLine') { + return + } + + const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + outerLines.forEach((line) => { + line.set({ + stroke: '#000000', + strokeWidth: 4, + }) + }) + + currentObject.set({ + stroke: '#EA10AC', + strokeWidth: 4, + }) + + canvas.renderAll() + }, [currentObject]) + + useEffect(() => { + if (shapeNum === 4) { + canvas?.remove(canvas.getObjects().find((obj) => obj.name === 'wallLine')) + const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + outerLines.forEach((line) => { + showLine(line) + line.bringToFront() + }) + + canvas?.renderAll() + } + setPitch(4) + setEavesOffset(500) + setGableOffset(300) + setSleeveOffset(300) + setJerkinHeadWidth(800) + setJerkinHeadPitch(4.5) + setHipAndGableWidth(800) + setShedWidth(300) + }, [shapeNum]) + + const shapeMenu = [ + { id: 1, name: getMessage('modal.roof.shape.setting.ridge') }, // 용마루 + { id: 2, name: getMessage('modal.roof.shape.setting.patten.a') }, // 패턴A + { id: 3, name: getMessage('modal.roof.shape.setting.patten.b') }, // 패턴B + { id: 4, name: getMessage('modal.roof.shape.setting.side') }, // 변별로 설정 + { id: 5, name: getMessage('commons.west') }, // 서 + { id: 6, name: getMessage('commons.east') }, // 동 + { id: 7, name: getMessage('commons.south') }, // 남 + { id: 8, name: getMessage('commons.north') }, // 북 + ] + + const buttonMenu = [ + { id: 1, name: getMessage('eaves') }, + { id: 2, name: getMessage('gable') }, + { id: 3, name: getMessage('wall') }, + { id: 4, name: getMessage('hipandgable') }, + { id: 5, name: getMessage('jerkinhead') }, + { id: 6, name: getMessage('shed') }, + ] + + //모달 닫기위한 함수 + const handleSave = (fn) => { + //기존 wallLine 삭제 + + let outerLines + canvas?.remove(canvas.getObjects().find((obj) => obj.name === 'wallLine')) + canvas?.remove(canvas.getObjects().find((obj) => obj.name === 'roofBase')) + + switch (shapeNum) { + case 1: { + outerLines = saveRidge() + break + } + case 2: { + outerLines = saveAPattern() + break + } + case 3: { + outerLines = saveBPattern() + break + } + case 4: { + outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + outerLines.forEach((line) => { + hideLine(line) + }) + break + } + + case 5: { + // 서쪽 + initLineSetting() + outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + outerLines.forEach((line) => { + setWestAndEastRoof(line) + if (line.direction === 'bottom') { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + } + + if (line.direction === 'top') { + line.attributes = { + offset: shedWidth / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.SHED, + } + } + + hideLine(line) + }) + break + } + case 6: { + initLineSetting() + outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + outerLines.forEach((line) => { + setWestAndEastRoof(line) + if (line.direction === 'top') { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + } + + if (line.direction === 'bottom') { + line.attributes = { + offset: shedWidth / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.SHED, + } + } + + hideLine(line) + }) + break + } + case 7: { + initLineSetting() + outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + outerLines.forEach((line) => { + setWestAndEastRoof(line) + if (line.direction === 'left') { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + } + + if (line.direction === 'right') { + line.attributes = { + offset: shedWidth / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.SHED, + } + } + + hideLine(line) + }) + break + } + case 8: { + initLineSetting() + outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + outerLines.forEach((line) => { + setWestAndEastRoof(line) + if (line.direction === 'right') { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + } + + if (line.direction === 'left') { + line.attributes = { + offset: shedWidth / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.SHED, + } + } + + hideLine(line) + }) + break + } + } + + const polygon = addPolygonByLines(outerLines, { name: 'wallLine' }) + polygon.lines = [...outerLines] + + drawRoofPolygon(polygon) + + canvas?.renderAll() + + console.log(canvas.getObjects()) + + fn && fn(false) + } + + const initLineSetting = () => { + const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + const tempPolygon = addPolygonByLines(outerLines) + tempPolygon.lines.forEach((line) => { + outerLines.forEach((outerLine) => { + if ( + (line.startPoint === outerLine.startPoint && line.endPoint === outerLine.endPoint) || + (line.startPoint === outerLine.endPoint && line.endPoint === outerLine.startPoint) + ) { + outerLine.direction = line.direction + } + }) + }) + + // 첫번째 line의 방향이 right일 경우 + if (outerLines[0].direction === 'right') { + // top과 bottom의 방향을 바꾼다. + outerLines.forEach((line) => { + if (line.direction === 'top') { + line.direction = 'bottom' + } else if (line.direction === 'bottom') { + line.direction = 'top' + } + }) + } + canvas.remove(tempPolygon) + } + + // 동, 서 선택 시 가로라인을 케라바로 설정 + const setWestAndEastRoof = (line) => { + if (line.direction === 'left' || line.direction === 'right') { + line.attributes = { + offset: gableOffset / 10, + type: LINE_TYPE.WALLLINE.GABLE, + } + } + } + + // 남, 북 선택 시 세로라인을 케라바로 설정 + const setSouthAndNorthRoof = (line) => { + if (line.direction === 'top' || line.direction === 'bottom') { + line.attributes = { + offset: gableOffset / 10, + type: LINE_TYPE.WALLLINE.GABLE, + } + } + } + + const saveRidge = () => { + // 용마루 저장 + const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + outerLines.forEach((line) => { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + hideLine(line) + }) + + return outerLines + } + + // 패턴 A : 가로선이 모두 케라바 + const saveAPattern = () => { + const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + outerLines + .filter((line) => line.direction === 'left' || line.direction === 'right') + .forEach((line) => { + line.attributes = { + offset: gableOffset / 10, + type: LINE_TYPE.WALLLINE.GABLE, + } + }) + + outerLines + .filter((line) => line.direction === 'top' || line.direction === 'bottom') + .forEach((line) => { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + }) + + return outerLines + } + + // 패턴 B : 세로선이 모두 케라바 + const saveBPattern = () => { + const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + outerLines + .filter((line) => line.direction === 'left' || line.direction === 'right') + .forEach((line) => { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + }) + + outerLines + .filter((line) => line.direction === 'top' || line.direction === 'bottom') + .forEach((line) => { + line.attributes = { + offset: gableOffset / 10, + type: LINE_TYPE.WALLLINE.GABLE, + } + }) + + return outerLines + } + + // 변별로 설정 팝업 내 적용 + const handleConfirm = () => { + const selectedLine = canvas?.getActiveObject() + if (!selectedLine) { + return + } + + let attributes + switch (buttonAct) { + case 1: { + // 처마 + attributes = { + type: LINE_TYPE.WALLLINE.EAVES, + pitch: pitch, + offset: eavesOffset / 10, + } + break + } + case 2: { + // 케라바 + attributes = { + type: LINE_TYPE.WALLLINE.GABLE, + offset: gableOffset / 10, + } + break + } + case 3: { + // 벽 + attributes = { + type: LINE_TYPE.WALLLINE.WALL, + offset: hasSleeve === '0' ? 0 : sleeveOffset / 10, + } + break + } + case 4: { + // 팔작지붕 + attributes = { + type: LINE_TYPE.WALLLINE.HIPANDGABLE, + pitch: pitch, + offset: eavesOffset / 10, + width: hipAndGableWidth / 10, + } + break + } + case 5: { + // 반절처 + attributes = { + type: LINE_TYPE.WALLLINE.JERKINHEAD, + offset: gableOffset / 10, + width: jerkinHeadWidth / 10, + pitch: jerkinHeadPitch, + } + break + } + case 6: { + // 한쪽흐름 + attributes = { + type: LINE_TYPE.WALLLINE.SHED, + offset: shedWidth / 10, + } + break + } + } + selectedLine.attributes = attributes + history.current.push(selectedLine) + nextLineFocus(selectedLine) + } + + const nextLineFocus = (selectedLine) => { + const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + const index = lines.findIndex((line) => line.idx === selectedLine.idx) + + const nextLine = lines[index + 1] || lines[0] + canvas.setActiveObject(nextLine) + } + + // 변별로 설정 내 일변 전으로 돌아가기 + const handleRollBack = () => { + if (history.current.length === 0) { + return + } + const lastLine = history.current.pop() + + lastLine.set({ + stroke: '#000000', + strokeWidth: 4, + }) + + canvas.setActiveObject(lastLine) + canvas.renderAll() + } + + return { + shapeNum, + setShapeNum, + shapeMenu, + handleSave, + buttonMenu, + pitch, + setPitch, + eavesOffset, + setEavesOffset, + gableOffset, + setGableOffset, + sleeveOffset, + setSleeveOffset, + jerkinHeadWidth, + setJerkinHeadWidth, + jerkinHeadPitch, + setJerkinHeadPitch, + hipAndGableWidth, + setHipAndGableWidth, + shedWidth, + setShedWidth, + hasSleeve, + setHasSleeve, + buttonAct, + setButtonAct, + handleConfirm, + handleRollBack, + } +} diff --git a/src/hooks/useLine.js b/src/hooks/useLine.js index b6c8a532..f2941e33 100644 --- a/src/hooks/useLine.js +++ b/src/hooks/useLine.js @@ -14,26 +14,38 @@ export const useLine = () => { fontFamily: fontFamily, }) + if (line.length === 0) { + return null + } + canvas?.add(line) return line } - const addLineText = (line, length = getLengthByLine(line)) => { - removeLineText(line) - - const lengthTxt = isNaN(Number(length)) ? length : length.toFixed(0) - - const text = new fabric.Text(lengthTxt, { - left: (line.x2 + line.x1) / 2, - top: (line.y2 + line.y1) / 2, - parent: line, - name: 'lengthTxt', - fontSize: fontSize, - fontFamily: fontFamily, + const hideLine = (line) => { + line.set({ + visible: false, }) + canvas + ?.getObjects() + .find((obj) => obj.parent === line) + .set({ + visible: false, + }) + canvas?.renderAll() + } - canvas?.add(text) - return text + const showLine = (line) => { + line.set({ + visible: true, + }) + canvas + ?.getObjects() + .find((obj) => obj.parent === line) + .set({ + visible: true, + }) + canvas?.renderAll() } const removeLine = (line) => { @@ -62,5 +74,7 @@ export const useLine = () => { return { addLine, removeLine, + hideLine, + showLine, } } diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index fedbb3be..c719ba24 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -47,6 +47,11 @@ export function usePlan() { 'minY', 'x', 'y', + 'x1', + 'x2', + 'y1', + 'y2', + 'attributes', 'stickeyPoint', ]) diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 13b12fe1..2d981933 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -12,6 +12,8 @@ export const usePolygon = () => { const addPolygon = (points, options) => { const polygon = new QPolygon(points, { ...options, + fill: options.fill || 'transparent', + stroke: options.stroke || '#000000', fontSize: fontSize, fontFamily: fontFamily, selectable: true, diff --git a/src/locales/ja.json b/src/locales/ja.json index 71c6fb8d..48937cc0 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -303,6 +303,7 @@ "gable": "ケラバ", "wall": "壁", "hipandgable": "八作屋根", + "hipandgable.width": "八作屋根 出幅", "jerkinhead": "半折", "shed": "片側の流れ", "apply": "適用", diff --git a/src/locales/ko.json b/src/locales/ko.json index 572c1eef..c586d95f 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -34,7 +34,7 @@ "modal.roof.shape.setting": "지붕형상 설정", "modal.roof.shape.setting.ridge": "용마루", "modal.roof.shape.setting.patten.a": "A 패턴", - "modal.roof.shape.setting.patten.b": "A 패턴", + "modal.roof.shape.setting.patten.b": "B 패턴", "modal.roof.shape.setting.side": "변별로 설정", "plan.menu.roof.cover": "지붕덮개", "plan.menu.roof.cover.outline.drawing": "외벽선 그리기", @@ -305,6 +305,7 @@ "gable": "케라바", "wall": "벽", "hipandgable": "팔작지붕", + "hipandgable.width": "팔작지붕의 폭", "jerkinhead": "반절처", "shed": "한쪽흐름", "apply": "적용", diff --git a/src/util/input-utils.js b/src/util/input-utils.js index f674e6cd..18f93425 100644 --- a/src/util/input-utils.js +++ b/src/util/input-utils.js @@ -1,6 +1,6 @@ // 숫자만 입력 가능한 input onChange 함수 export const onlyNumberInputChange = (e, callback) => { - let value = e.target.value.replace(/^0+/, '') + let value = e.target.value value = value.replace(/[^-0-9]/g, '') callback(value, e) } diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index a7bcb0e2..6605e3b3 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1197,6 +1197,7 @@ export const drawHippedRoof = (polygon, chon) => { alert('대각선이 존재합니다.') return } + drawRidgeRoof(polygon, chon) drawHips(polygon) connectLinePoint(polygon) From 63d6103858e7998fa341ffab0dc528ada7db28ce Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 4 Oct 2024 16:52:29 +0900 Subject: [PATCH 030/152] =?UTF-8?q?=EB=82=A8,=20=EB=B6=81=20=EC=9D=B4?= =?UTF-8?q?=EC=83=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/roofcover/useRoofShapeSetting.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js index 492e52e8..f04c7005 100644 --- a/src/hooks/roofcover/useRoofShapeSetting.js +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -194,8 +194,8 @@ export function useRoofShapeSetting() { outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') outerLines.forEach((line) => { - setWestAndEastRoof(line) - if (line.direction === 'left') { + setSouthAndNorthRoof(line) + if (line.direction === 'right') { line.attributes = { offset: eavesOffset / 10, pitch: pitch, @@ -203,14 +203,13 @@ export function useRoofShapeSetting() { } } - if (line.direction === 'right') { + if (line.direction === 'left') { line.attributes = { offset: shedWidth / 10, pitch: pitch, type: LINE_TYPE.WALLLINE.SHED, } } - hideLine(line) }) break @@ -220,8 +219,9 @@ export function useRoofShapeSetting() { outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') outerLines.forEach((line) => { - setWestAndEastRoof(line) - if (line.direction === 'right') { + setSouthAndNorthRoof(line) + + if (line.direction === 'left') { line.attributes = { offset: eavesOffset / 10, pitch: pitch, @@ -229,7 +229,7 @@ export function useRoofShapeSetting() { } } - if (line.direction === 'left') { + if (line.direction === 'right') { line.attributes = { offset: shedWidth / 10, pitch: pitch, From e53bddc04c1140d428463ec82dfb1c31a5bad6d4 Mon Sep 17 00:00:00 2001 From: basssy Date: Fri, 4 Oct 2024 16:58:39 +0900 Subject: [PATCH 031/152] =?UTF-8?q?totCnt=203=EC=9E=90=EB=A6=AC=20?= =?UTF-8?q?=EC=BD=A4=EB=A7=88=20=EC=9C=A0=ED=8B=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/management/Stuff.jsx | 5 +++-- src/components/management/StuffDetail.jsx | 5 +++-- src/util/common-utils.js | 7 +++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index 4fd3b49e..8ecb1297 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -12,6 +12,7 @@ import { queryStringFormatter, isEmptyArray } from '@/util/common-utils' import dayjs from 'dayjs' import isLeapYear from 'dayjs/plugin/isLeapYear' // 윤년 판단 플러그인 dayjs.extend(isLeapYear) +import { convertNumberToPriceDecimal } from '@/util/common-utils' import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' import KO from '@/locales/ko.json' import JA from '@/locales/ja.json' @@ -380,11 +381,11 @@ export default function Stuff() {
  • 전체 - {gridCount} + {convertNumberToPriceDecimal(gridCount)}
  • 선택 - {selectedRowDataCount} + {convertNumberToPriceDecimal(selectedRowDataCount)}
diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index a62b35b1..ddd94865 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -3,6 +3,7 @@ import React, { useState, useEffect } from 'react' import { useRouter, useSearchParams } from 'next/navigation' import { Input, RadioGroup, Radio, Button, Autocomplete, AutocompleteItem, Select, SelectItem, Checkbox, Textarea, button } from '@nextui-org/react' +// import Select from 'react-dropdown-select' import Link from 'next/link' import { useAxios } from '@/hooks/useAxios' import { globalLocaleStore } from '@/store/localeAtom' @@ -203,7 +204,7 @@ export default function StuffDetail() { // console.log('mode:::::', editMode) if (editMode === 'NEW') { const formData = form.getValues() - console.log('폼::::::::::::', formData) + // console.log('폼::::::::::::', formData) let errors = {} if (!_dispCompanyName || _dispCompanyName.trim().length === 0) { errors.dispCompanyName = true @@ -250,7 +251,7 @@ export default function StuffDetail() { errors.installHeight = true } - console.log('errors::', errors) + // console.log('errors::', errors) setIsFormValid(Object.keys(errors).length === 0) } else { // console.log('상세일때 폼체크') diff --git a/src/util/common-utils.js b/src/util/common-utils.js index 1b7cd166..9244b046 100644 --- a/src/util/common-utils.js +++ b/src/util/common-utils.js @@ -59,3 +59,10 @@ export const queryStringFormatter = (params = {}) => { }) return queries.join('&') } + +// 43000 --> 43,000 +export const convertNumberToPriceDecimal = (value) => { + if (value) return Number(value).toLocaleString() + else if (value === 0) return 0 + else return '' +} From 98c37b725accd58bcaf582ccf192776e61a563eb Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 4 Oct 2024 17:40:20 +0900 Subject: [PATCH 032/152] =?UTF-8?q?console=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?=EB=B0=8F=20line=20=EA=B8=B8=EC=9D=B4=20=ED=91=9C=EC=8B=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QLine.js | 4 ++-- src/hooks/roofcover/useRoofShapeSetting.js | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index c73e442f..becf821b 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -75,7 +75,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { const y2 = this.top + this.height * scaleY const dx = x2 - x1 const dy = y2 - y1 - this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) * 10 + this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0)) }, addLengthText() { @@ -109,7 +109,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { const maxY = this.top + this.length const degree = (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI - const text = new fabric.Textbox(this.length.toFixed(0).toString(), { + const text = new fabric.Textbox(Number(this.length.toFixed(1) * 10).toString(), { left: left, top: top, fontSize: this.fontSize, diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js index f04c7005..f14148f8 100644 --- a/src/hooks/roofcover/useRoofShapeSetting.js +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -246,12 +246,10 @@ export function useRoofShapeSetting() { const polygon = addPolygonByLines(outerLines, { name: 'wallLine' }) polygon.lines = [...outerLines] - drawRoofPolygon(polygon) + const roof = drawRoofPolygon(polygon) canvas?.renderAll() - - console.log(canvas.getObjects()) - + roof.drawHelpLine() fn && fn(false) } @@ -266,6 +264,7 @@ export function useRoofShapeSetting() { (line.startPoint === outerLine.endPoint && line.endPoint === outerLine.startPoint) ) { outerLine.direction = line.direction + outerLine.idx = line.idx } }) }) From 74760ef8cefefe0d939aaab3bf370c5d9282279a Mon Sep 17 00:00:00 2001 From: basssy Date: Mon, 7 Oct 2024 09:35:12 +0900 Subject: [PATCH 033/152] =?UTF-8?q?react-dropdown-select=20=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/components/management/StuffDetail.jsx | 6 +- .../management/StuffSearchCondition.jsx | 55 ++- yarn.lock | 417 +++++++++++++++++- 4 files changed, 452 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 5355cae6..260bfe8e 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "prettier": "^3.3.3", "prisma": "^5.18.0", "react-color-palette": "^7.2.2", + "react-dropdown-select": "^4.11.3", "sass": "^1.77.8", "tailwindcss": "^3.4.1" } diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index ddd94865..c7953ed8 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -2,17 +2,15 @@ import React, { useState, useEffect } from 'react' import { useRouter, useSearchParams } from 'next/navigation' -import { Input, RadioGroup, Radio, Button, Autocomplete, AutocompleteItem, Select, SelectItem, Checkbox, Textarea, button } from '@nextui-org/react' +import { Button } from '@nextui-org/react' // import Select from 'react-dropdown-select' import Link from 'next/link' import { useAxios } from '@/hooks/useAxios' import { globalLocaleStore } from '@/store/localeAtom' import { queryStringFormatter, isEmptyArray } from '@/util/common-utils' -import dayjs from 'dayjs' import { useMessage } from '@/hooks/useMessage' import { useForm } from 'react-hook-form' -import { useRecoilState, useRecoilValue } from 'recoil' -import { v4 as uuidv4 } from 'uuid' +import { useRecoilValue } from 'recoil' export default function StuffDetail() { const router = useRouter() const searchParams = useSearchParams() diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx index 13f61bb3..e43c7c90 100644 --- a/src/components/management/StuffSearchCondition.jsx +++ b/src/components/management/StuffSearchCondition.jsx @@ -1,13 +1,11 @@ 'use client' -import React, { useEffect } from 'react' -import { useState } from 'react' -import { Autocomplete, AutocompleteItem } from '@nextui-org/react' +import React, { useEffect, useRef, useState } from 'react' import { useAxios } from '@/hooks/useAxios' import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' import { globalLocaleStore } from '@/store/localeAtom' +import Select from 'react-dropdown-select' -import RangeDatePicker from '@/components/common/datepicker/RangeDatePicker' import { stuffSearchState } from '@/store/stuffAtom' import { isEmptyArray } from '@/util/common-utils' import dayjs from 'dayjs' @@ -18,6 +16,7 @@ import SingleDatePicker from '../common/datepicker/SingleDatePicker' export default function StuffSearchCondition() { const globalLocaleState = useRecoilValue(globalLocaleStore) + const ref = useRef() const { get } = useAxios(globalLocaleState) //달력 props 관련 날짜 셋팅 @@ -90,6 +89,7 @@ export default function StuffSearchCondition() { setStartDate(dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD')) setEndDate(dayjs(new Date()).format('YYYY-MM-DD')) setSchSelSaleStoreId('') + handleClear() //판매대리점선택 자동완성 클리어 resetStuffRecoil() } @@ -102,15 +102,23 @@ export default function StuffSearchCondition() { }) }, []) + //초기화 눌렀을 때 자동완성도.. + const handleClear = () => { + // console.log('ref::', ref.current.state.values) + if (ref.current.state.dropDown) { + ref.current.methods.dropDown() + } else { + ref.current.state.values = [] + } + } //판매대리점 자동완성 변경 const onSelectionChange = (key) => { - // console.log('자동완성값변경', key) - if (key == null) { + if (!isEmptyArray(key)) { + setSchSelSaleStoreId(key[0].saleStoreId) + setStuffSearch({ ...stuffSearch, schSelSaleStoreId: key[0].saleStoreId }) + } else { setSchSelSaleStoreId('') setStuffSearch({ ...stuffSearch, schSelSaleStoreId: '' }) - } else { - setSchSelSaleStoreId(key) - setStuffSearch({ ...stuffSearch, schSelSaleStoreId: key }) } } @@ -236,15 +244,26 @@ export default function StuffSearchCondition() { */} {schSelSaleStoreList?.length > 0 && ( - - {(option) => {option.saleStoreName}} - + // + // {(option) => {option.saleStoreName}} + // + )} diff --git a/yarn.lock b/yarn.lock index affc38d7..1ffd6b98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -163,6 +163,66 @@ jsonwebtoken "^9.0.0" uuid "^8.3.0" +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.25.7.tgz#438f2c524071531d643c6f0188e1e28f130cebc7" + integrity sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g== + dependencies: + "@babel/highlight" "^7.25.7" + picocolors "^1.0.0" + +"@babel/generator@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.25.7.tgz#de86acbeb975a3e11ee92dd52223e6b03b479c56" + integrity sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA== + dependencies: + "@babel/types" "^7.25.7" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + +"@babel/helper-module-imports@^7.16.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz#dba00d9523539152906ba49263e36d7261040472" + integrity sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw== + dependencies: + "@babel/traverse" "^7.25.7" + "@babel/types" "^7.25.7" + +"@babel/helper-string-parser@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz#d50e8d37b1176207b4fe9acedec386c565a44a54" + integrity sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g== + +"@babel/helper-validator-identifier@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz#77b7f60c40b15c97df735b38a66ba1d7c3e93da5" + integrity sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg== + +"@babel/highlight@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.25.7.tgz#20383b5f442aa606e7b5e3043b0b1aafe9f37de5" + integrity sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw== + dependencies: + "@babel/helper-validator-identifier" "^7.25.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/parser@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.7.tgz#99b927720f4ddbfeb8cd195a363ed4532f87c590" + integrity sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw== + dependencies: + "@babel/types" "^7.25.7" + +"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.7.tgz#7ffb53c37a8f247c8c4d335e89cdf16a2e0d0fb6" + integrity sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/runtime@^7.20.13", "@babel/runtime@^7.24.8": version "7.25.0" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz" @@ -170,6 +230,37 @@ dependencies: regenerator-runtime "^0.14.0" +"@babel/template@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.7.tgz#27f69ce382855d915b14ab0fe5fb4cbf88fa0769" + integrity sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA== + dependencies: + "@babel/code-frame" "^7.25.7" + "@babel/parser" "^7.25.7" + "@babel/types" "^7.25.7" + +"@babel/traverse@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.7.tgz#83e367619be1cab8e4f2892ef30ba04c26a40fa8" + integrity sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg== + dependencies: + "@babel/code-frame" "^7.25.7" + "@babel/generator" "^7.25.7" + "@babel/parser" "^7.25.7" + "@babel/template" "^7.25.7" + "@babel/types" "^7.25.7" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.7.tgz#1b7725c1d3a59f328cb700ce704c46371e6eef9b" + integrity sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ== + dependencies: + "@babel/helper-string-parser" "^7.25.7" + "@babel/helper-validator-identifier" "^7.25.7" + to-fast-properties "^2.0.0" + "@bedrock-layout/use-forwarded-ref@^1.3.1": version "1.6.1" resolved "https://registry.npmjs.org/@bedrock-layout/use-forwarded-ref/-/use-forwarded-ref-1.6.1.tgz" @@ -182,6 +273,118 @@ resolved "https://registry.npmjs.org/@bedrock-layout/use-stateful-ref/-/use-stateful-ref-1.4.1.tgz" integrity sha512-4eKO2KdQEXcR5LI4QcxqlJykJUDQJWDeWYAukIn6sRQYoabcfI5kDl61PUi6FR6o8VFgQ8IEP7HleKqWlSe8SQ== +"@emotion/babel-plugin@^11.11.0": + version "11.12.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz#7b43debb250c313101b3f885eba634f1d723fcc2" + integrity sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/runtime" "^7.18.3" + "@emotion/hash" "^0.9.2" + "@emotion/memoize" "^0.9.0" + "@emotion/serialize" "^1.2.0" + babel-plugin-macros "^3.1.0" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "4.2.0" + +"@emotion/cache@^11.11.0": + version "11.13.1" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.1.tgz#fecfc54d51810beebf05bf2a161271a1a91895d7" + integrity sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw== + dependencies: + "@emotion/memoize" "^0.9.0" + "@emotion/sheet" "^1.4.0" + "@emotion/utils" "^1.4.0" + "@emotion/weak-memoize" "^0.4.0" + stylis "4.2.0" + +"@emotion/hash@^0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b" + integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g== + +"@emotion/is-prop-valid@^1.2.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz#8d5cf1132f836d7adbe42cf0b49df7816fc88240" + integrity sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw== + dependencies: + "@emotion/memoize" "^0.9.0" + +"@emotion/memoize@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102" + integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ== + +"@emotion/react@11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.0.tgz#408196b7ef8729d8ad08fc061b03b046d1460e02" + integrity sha512-ZSK3ZJsNkwfjT3JpDAWJZlrGD81Z3ytNDsxw1LKq1o+xkmO5pnWfr6gmCC8gHEFf3nSSX/09YrG67jybNPxSUw== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/cache" "^11.11.0" + "@emotion/serialize" "^1.1.2" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.2.0": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.2.tgz#e1c1a2e90708d5d85d81ccaee2dfeb3cc0cccf7a" + integrity sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA== + dependencies: + "@emotion/hash" "^0.9.2" + "@emotion/memoize" "^0.9.0" + "@emotion/unitless" "^0.10.0" + "@emotion/utils" "^1.4.1" + csstype "^3.0.2" + +"@emotion/sheet@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c" + integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg== + +"@emotion/styled@11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.0.tgz#26b75e1b5a1b7a629d7c0a8b708fbf5a9cdce346" + integrity sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/is-prop-valid" "^1.2.1" + "@emotion/serialize" "^1.1.2" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" + +"@emotion/unitless@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.10.0.tgz#2af2f7c7e5150f497bdabd848ce7b218a27cf745" + integrity sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg== + +"@emotion/use-insertion-effect-with-fallbacks@^1.0.1": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz#1a818a0b2c481efba0cf34e5ab1e0cb2dcb9dfaf" + integrity sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw== + +"@emotion/utils@^1.2.1", "@emotion/utils@^1.4.0", "@emotion/utils@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.1.tgz#b3adbb43de12ee2149541c4f1337d2eb7774f0ad" + integrity sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA== + +"@emotion/weak-memoize@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" + integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== + +"@emotion/weak-memoize@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6" + integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg== + "@floating-ui/core@^1.6.0": version "1.6.7" resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz" @@ -298,7 +501,7 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" -"@jridgewell/gen-mapping@^0.3.2": +"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": version "0.3.5" resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz" integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== @@ -322,7 +525,7 @@ resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.24": +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -3877,6 +4080,11 @@ dependencies: undici-types "~6.18.2" +"@types/parse-json@^4.0.0": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" + integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== + "@types/readable-stream@^4.0.0": version "4.0.15" resolved "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.15.tgz" @@ -3969,6 +4177,13 @@ ansi-regex@^6.0.1: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz" integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + ansi-styles@^4.0.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" @@ -4035,6 +4250,15 @@ axios@^1.7.3: form-data "^4.0.0" proxy-from-env "^1.1.0" +babel-plugin-macros@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" + integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== + dependencies: + "@babel/runtime" "^7.12.5" + cosmiconfig "^7.0.0" + resolve "^1.19.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" @@ -4112,6 +4336,11 @@ busboy@1.6.0: dependencies: streamsearch "^1.1.0" +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + camelcase-css@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz" @@ -4131,6 +4360,15 @@ canvas@^2.8.0: nan "^2.17.0" simple-get "^3.0.3" +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + "chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3: version "3.6.0" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" @@ -4171,6 +4409,13 @@ clsx@^2.0.0, clsx@^2.1.0: resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz" integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" @@ -4178,6 +4423,11 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" @@ -4261,6 +4511,11 @@ console-control-strings@^1.0.0, console-control-strings@^1.1.0: resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== +convert-source-map@^1.5.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + convertapi@^1.14.0: version "1.14.0" resolved "https://registry.yarnpkg.com/convertapi/-/convertapi-1.14.0.tgz#a291a98cb986ae1e0f2340a130adbe17f65c8c76" @@ -4273,6 +4528,17 @@ cookie@0.6.0: resolved "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz" integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== +cosmiconfig@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + cross-spawn@^7.0.0: version "7.0.3" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" @@ -4304,6 +4570,11 @@ cssstyle@^2.3.0: dependencies: cssom "~0.3.6" +csstype@^3.0.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + d3-array@1: version "1.2.4" resolved "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz" @@ -4347,6 +4618,13 @@ debug@4, debug@^4.3.3, debug@^4.3.4: dependencies: ms "2.1.2" +debug@^4.3.1: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + decimal.js@^10.3.1, decimal.js@^10.4.3: version "10.4.3" resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz" @@ -4433,11 +4711,28 @@ emoji-regex@^9.2.2: resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + escape-latex@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz" integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw== +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + escodegen@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz" @@ -4512,6 +4807,11 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + flat@^5.0.2: version "5.0.2" resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" @@ -4649,6 +4949,11 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + graceful-fs@^4.2.11: version "4.2.11" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" @@ -4659,6 +4964,11 @@ hamt_plus@1.0.2: resolved "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz" integrity sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA== +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" @@ -4671,6 +4981,13 @@ hasown@^2.0.0: dependencies: function-bind "^1.1.2" +hoist-non-react-statics@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + html-encoding-sniffer@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz" @@ -4728,6 +5045,14 @@ immutable@^4.0.0: resolved "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz" integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + inflight@^1.0.4: version "1.0.6" resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" @@ -4777,6 +5102,11 @@ iron-webcrypto@1.2.1: resolved "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz" integrity sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg== +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + is-arrayish@^0.3.1: version "0.3.2" resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz" @@ -4864,7 +5194,7 @@ js-md4@^0.3.2: resolved "https://registry.npmjs.org/js-md4/-/js-md4-0.3.2.tgz" integrity sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA== -"js-tokens@^3.0.0 || ^4.0.0": +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -4902,6 +5232,16 @@ jsdom@^19.0.0: ws "^8.2.3" xml-name-validator "^4.0.0" +jsesc@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" + integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + jsonwebtoken@^9.0.0: version "9.0.2" resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz" @@ -5155,6 +5495,11 @@ ms@2.1.2, ms@^2.1.1: resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + mssql@^11.0.1: version "11.0.1" resolved "https://registry.npmjs.org/mssql/-/mssql-11.0.1.tgz" @@ -5283,6 +5628,23 @@ open@^8.0.0: is-docker "^2.1.1" is-wsl "^2.2.0" +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + parse5@6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" @@ -5311,6 +5673,11 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + picocolors@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz" @@ -5523,6 +5890,14 @@ react-draggable@^4.4.6: clsx "^1.1.1" prop-types "^15.8.1" +react-dropdown-select@^4.11.3: + version "4.11.3" + resolved "https://registry.yarnpkg.com/react-dropdown-select/-/react-dropdown-select-4.11.3.tgz#b23b8906f3bedc9d6a1a2125af936b34d4057158" + integrity sha512-/mOGSqqhmKsxxrmotLM+qn1Ss3nxGN6QnYusyQ7f0wizsWrc7ZmbcZhGRtwkJwpL6JYDQVTn19EYxJU1XfXrDA== + dependencies: + "@emotion/react" "11.11.0" + "@emotion/styled" "11.11.0" + react-hook-form@^7.53.0: version "7.53.0" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.53.0.tgz#3cf70951bf41fa95207b34486203ebefbd3a05ab" @@ -5533,7 +5908,7 @@ react-icons@^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, react-is@^16.7.0: version "16.13.1" resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -5654,7 +6029,12 @@ requires-port@^1.0.0: resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== -resolve@^1.1.7, resolve@^1.22.2: +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^1.1.7, resolve@^1.19.0, resolve@^1.22.2: version "1.22.8" resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -5820,6 +6200,11 @@ skmeans@0.9.7: resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz" integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== +source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + source-map@~0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" @@ -5907,6 +6292,11 @@ styled-jsx@5.1.1: dependencies: client-only "0.0.1" +stylis@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" + integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== + sucrase@^3.32.0: version "3.35.0" resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz" @@ -5920,6 +6310,13 @@ sucrase@^3.32.0: pirates "^4.0.1" ts-interface-checker "^0.1.9" +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" @@ -6049,6 +6446,11 @@ tinyqueue@^2.0.0, tinyqueue@^2.0.3: resolved "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz" integrity sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA== +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" @@ -6294,6 +6696,11 @@ yallist@^4.0.0: resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^1.10.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + yaml@^2.3.4: version "2.4.5" resolved "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz" From a63c44b41d1f2a91427f16eb85579561e535b0d0 Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 10:17:29 +0900 Subject: [PATCH 034/152] =?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/compas.svg | 9 + public/static/images/canvas/compas_num.svg | 26 + public/static/images/canvas/object_img01.svg | 22 + public/static/images/canvas/object_img02.svg | 22 + public/static/images/canvas/plane_arr.svg | 3 + public/static/images/canvas/plane_arr_act.svg | 3 + public/static/images/canvas/plane_shape01.svg | 3 + .../static/images/canvas/plane_shape010.svg | 3 + .../static/images/canvas/plane_shape011.svg | 3 + .../static/images/canvas/plane_shape012.svg | 3 + .../static/images/canvas/plane_shape013.svg | 3 + .../static/images/canvas/plane_shape014.svg | 3 + .../static/images/canvas/plane_shape015.svg | 3 + .../static/images/canvas/plane_shape016.svg | 5 + .../static/images/canvas/plane_shape017.svg | 3 + .../static/images/canvas/plane_shape018.svg | 3 + public/static/images/canvas/plane_shape02.svg | 3 + public/static/images/canvas/plane_shape03.svg | 3 + public/static/images/canvas/plane_shape04.svg | 3 + public/static/images/canvas/plane_shape05.svg | 3 + public/static/images/canvas/plane_shape06.svg | 3 + public/static/images/canvas/plane_shape07.svg | 3 + public/static/images/canvas/plane_shape08.svg | 3 + public/static/images/canvas/plane_shape09.svg | 3 + public/static/images/canvas/plane_tab01.svg | 13 + public/static/images/canvas/plane_tab02.svg | 14 + public/static/images/canvas/plane_tab03.svg | 18 + public/static/images/canvas/plane_tab04.svg | 13 + public/static/images/canvas/plane_tab05.svg | 18 + public/static/images/canvas/plane_tab06.svg | 18 + public/static/images/canvas/plane_tab07.svg | 30 + public/static/images/canvas/plane_tab08.svg | 24 + public/static/images/canvas/plane_tab09.svg | 28 + public/static/images/canvas/plane_tab10.svg | 28 + public/static/images/canvas/plane_tab11.svg | 28 + public/static/images/canvas/plane_tab12.svg | 23 + public/static/images/canvas/plane_tab13.svg | 23 + public/static/images/canvas/plane_tab14.svg | 29 + public/static/images/canvas/plane_tab15.svg | 18 + public/static/images/canvas/plane_tab16.svg | 24 + public/static/images/canvas/plane_tab17.svg | 22 + public/static/images/canvas/plane_tab18.svg | 16 + .../static/images/canvas/shape_labrary01.svg | 3 + .../static/images/canvas/shape_labrary02.svg | 4 + .../static/images/canvas/shape_labrary03.svg | 4 + src/styles/_modal.scss | 615 +++++++++++++++++- 46 files changed, 1147 insertions(+), 7 deletions(-) create mode 100644 public/static/images/canvas/compas.svg create mode 100644 public/static/images/canvas/compas_num.svg create mode 100644 public/static/images/canvas/object_img01.svg create mode 100644 public/static/images/canvas/object_img02.svg create mode 100644 public/static/images/canvas/plane_arr.svg create mode 100644 public/static/images/canvas/plane_arr_act.svg create mode 100644 public/static/images/canvas/plane_shape01.svg create mode 100644 public/static/images/canvas/plane_shape010.svg create mode 100644 public/static/images/canvas/plane_shape011.svg create mode 100644 public/static/images/canvas/plane_shape012.svg create mode 100644 public/static/images/canvas/plane_shape013.svg create mode 100644 public/static/images/canvas/plane_shape014.svg create mode 100644 public/static/images/canvas/plane_shape015.svg create mode 100644 public/static/images/canvas/plane_shape016.svg create mode 100644 public/static/images/canvas/plane_shape017.svg create mode 100644 public/static/images/canvas/plane_shape018.svg create mode 100644 public/static/images/canvas/plane_shape02.svg create mode 100644 public/static/images/canvas/plane_shape03.svg create mode 100644 public/static/images/canvas/plane_shape04.svg create mode 100644 public/static/images/canvas/plane_shape05.svg create mode 100644 public/static/images/canvas/plane_shape06.svg create mode 100644 public/static/images/canvas/plane_shape07.svg create mode 100644 public/static/images/canvas/plane_shape08.svg create mode 100644 public/static/images/canvas/plane_shape09.svg create mode 100644 public/static/images/canvas/plane_tab01.svg create mode 100644 public/static/images/canvas/plane_tab02.svg create mode 100644 public/static/images/canvas/plane_tab03.svg create mode 100644 public/static/images/canvas/plane_tab04.svg create mode 100644 public/static/images/canvas/plane_tab05.svg create mode 100644 public/static/images/canvas/plane_tab06.svg create mode 100644 public/static/images/canvas/plane_tab07.svg create mode 100644 public/static/images/canvas/plane_tab08.svg create mode 100644 public/static/images/canvas/plane_tab09.svg create mode 100644 public/static/images/canvas/plane_tab10.svg create mode 100644 public/static/images/canvas/plane_tab11.svg create mode 100644 public/static/images/canvas/plane_tab12.svg create mode 100644 public/static/images/canvas/plane_tab13.svg create mode 100644 public/static/images/canvas/plane_tab14.svg create mode 100644 public/static/images/canvas/plane_tab15.svg create mode 100644 public/static/images/canvas/plane_tab16.svg create mode 100644 public/static/images/canvas/plane_tab17.svg create mode 100644 public/static/images/canvas/plane_tab18.svg create mode 100644 public/static/images/canvas/shape_labrary01.svg create mode 100644 public/static/images/canvas/shape_labrary02.svg create mode 100644 public/static/images/canvas/shape_labrary03.svg diff --git a/public/static/images/canvas/compas.svg b/public/static/images/canvas/compas.svg new file mode 100644 index 00000000..fc9bccb1 --- /dev/null +++ b/public/static/images/canvas/compas.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/static/images/canvas/compas_num.svg b/public/static/images/canvas/compas_num.svg new file mode 100644 index 00000000..5deeea27 --- /dev/null +++ b/public/static/images/canvas/compas_num.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/object_img01.svg b/public/static/images/canvas/object_img01.svg new file mode 100644 index 00000000..a4ebac98 --- /dev/null +++ b/public/static/images/canvas/object_img01.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/object_img02.svg b/public/static/images/canvas/object_img02.svg new file mode 100644 index 00000000..ab1e8f43 --- /dev/null +++ b/public/static/images/canvas/object_img02.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_arr.svg b/public/static/images/canvas/plane_arr.svg new file mode 100644 index 00000000..c3131c01 --- /dev/null +++ b/public/static/images/canvas/plane_arr.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_arr_act.svg b/public/static/images/canvas/plane_arr_act.svg new file mode 100644 index 00000000..2c91a0bc --- /dev/null +++ b/public/static/images/canvas/plane_arr_act.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape01.svg b/public/static/images/canvas/plane_shape01.svg new file mode 100644 index 00000000..a32d0c39 --- /dev/null +++ b/public/static/images/canvas/plane_shape01.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape010.svg b/public/static/images/canvas/plane_shape010.svg new file mode 100644 index 00000000..a17616fb --- /dev/null +++ b/public/static/images/canvas/plane_shape010.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape011.svg b/public/static/images/canvas/plane_shape011.svg new file mode 100644 index 00000000..4068d35a --- /dev/null +++ b/public/static/images/canvas/plane_shape011.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape012.svg b/public/static/images/canvas/plane_shape012.svg new file mode 100644 index 00000000..b7136002 --- /dev/null +++ b/public/static/images/canvas/plane_shape012.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape013.svg b/public/static/images/canvas/plane_shape013.svg new file mode 100644 index 00000000..6ef6e1a4 --- /dev/null +++ b/public/static/images/canvas/plane_shape013.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape014.svg b/public/static/images/canvas/plane_shape014.svg new file mode 100644 index 00000000..68789f56 --- /dev/null +++ b/public/static/images/canvas/plane_shape014.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape015.svg b/public/static/images/canvas/plane_shape015.svg new file mode 100644 index 00000000..76e89b3d --- /dev/null +++ b/public/static/images/canvas/plane_shape015.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape016.svg b/public/static/images/canvas/plane_shape016.svg new file mode 100644 index 00000000..54b8259c --- /dev/null +++ b/public/static/images/canvas/plane_shape016.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/static/images/canvas/plane_shape017.svg b/public/static/images/canvas/plane_shape017.svg new file mode 100644 index 00000000..d0378c1f --- /dev/null +++ b/public/static/images/canvas/plane_shape017.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape018.svg b/public/static/images/canvas/plane_shape018.svg new file mode 100644 index 00000000..4e48f83d --- /dev/null +++ b/public/static/images/canvas/plane_shape018.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape02.svg b/public/static/images/canvas/plane_shape02.svg new file mode 100644 index 00000000..aa0a756f --- /dev/null +++ b/public/static/images/canvas/plane_shape02.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape03.svg b/public/static/images/canvas/plane_shape03.svg new file mode 100644 index 00000000..fb6c7d0a --- /dev/null +++ b/public/static/images/canvas/plane_shape03.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape04.svg b/public/static/images/canvas/plane_shape04.svg new file mode 100644 index 00000000..3cbf25c8 --- /dev/null +++ b/public/static/images/canvas/plane_shape04.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape05.svg b/public/static/images/canvas/plane_shape05.svg new file mode 100644 index 00000000..36f1448c --- /dev/null +++ b/public/static/images/canvas/plane_shape05.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape06.svg b/public/static/images/canvas/plane_shape06.svg new file mode 100644 index 00000000..a87e30b8 --- /dev/null +++ b/public/static/images/canvas/plane_shape06.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape07.svg b/public/static/images/canvas/plane_shape07.svg new file mode 100644 index 00000000..526c95bc --- /dev/null +++ b/public/static/images/canvas/plane_shape07.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape08.svg b/public/static/images/canvas/plane_shape08.svg new file mode 100644 index 00000000..8ad3bf5a --- /dev/null +++ b/public/static/images/canvas/plane_shape08.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_shape09.svg b/public/static/images/canvas/plane_shape09.svg new file mode 100644 index 00000000..519294ef --- /dev/null +++ b/public/static/images/canvas/plane_shape09.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/plane_tab01.svg b/public/static/images/canvas/plane_tab01.svg new file mode 100644 index 00000000..f768a207 --- /dev/null +++ b/public/static/images/canvas/plane_tab01.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab02.svg b/public/static/images/canvas/plane_tab02.svg new file mode 100644 index 00000000..61891248 --- /dev/null +++ b/public/static/images/canvas/plane_tab02.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab03.svg b/public/static/images/canvas/plane_tab03.svg new file mode 100644 index 00000000..295e0d89 --- /dev/null +++ b/public/static/images/canvas/plane_tab03.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab04.svg b/public/static/images/canvas/plane_tab04.svg new file mode 100644 index 00000000..894bb55c --- /dev/null +++ b/public/static/images/canvas/plane_tab04.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab05.svg b/public/static/images/canvas/plane_tab05.svg new file mode 100644 index 00000000..63b3c201 --- /dev/null +++ b/public/static/images/canvas/plane_tab05.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab06.svg b/public/static/images/canvas/plane_tab06.svg new file mode 100644 index 00000000..1bad98a0 --- /dev/null +++ b/public/static/images/canvas/plane_tab06.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab07.svg b/public/static/images/canvas/plane_tab07.svg new file mode 100644 index 00000000..a358f766 --- /dev/null +++ b/public/static/images/canvas/plane_tab07.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab08.svg b/public/static/images/canvas/plane_tab08.svg new file mode 100644 index 00000000..22a72ab6 --- /dev/null +++ b/public/static/images/canvas/plane_tab08.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab09.svg b/public/static/images/canvas/plane_tab09.svg new file mode 100644 index 00000000..756c3bfa --- /dev/null +++ b/public/static/images/canvas/plane_tab09.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab10.svg b/public/static/images/canvas/plane_tab10.svg new file mode 100644 index 00000000..fe4073ea --- /dev/null +++ b/public/static/images/canvas/plane_tab10.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab11.svg b/public/static/images/canvas/plane_tab11.svg new file mode 100644 index 00000000..0ac2cf59 --- /dev/null +++ b/public/static/images/canvas/plane_tab11.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab12.svg b/public/static/images/canvas/plane_tab12.svg new file mode 100644 index 00000000..a68e7a39 --- /dev/null +++ b/public/static/images/canvas/plane_tab12.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab13.svg b/public/static/images/canvas/plane_tab13.svg new file mode 100644 index 00000000..027e91e8 --- /dev/null +++ b/public/static/images/canvas/plane_tab13.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab14.svg b/public/static/images/canvas/plane_tab14.svg new file mode 100644 index 00000000..7a3cef86 --- /dev/null +++ b/public/static/images/canvas/plane_tab14.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab15.svg b/public/static/images/canvas/plane_tab15.svg new file mode 100644 index 00000000..c0c1b0bb --- /dev/null +++ b/public/static/images/canvas/plane_tab15.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab16.svg b/public/static/images/canvas/plane_tab16.svg new file mode 100644 index 00000000..c66484e3 --- /dev/null +++ b/public/static/images/canvas/plane_tab16.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab17.svg b/public/static/images/canvas/plane_tab17.svg new file mode 100644 index 00000000..ae8ddd0f --- /dev/null +++ b/public/static/images/canvas/plane_tab17.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/plane_tab18.svg b/public/static/images/canvas/plane_tab18.svg new file mode 100644 index 00000000..12bd0ad3 --- /dev/null +++ b/public/static/images/canvas/plane_tab18.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape_labrary01.svg b/public/static/images/canvas/shape_labrary01.svg new file mode 100644 index 00000000..c55fecfc --- /dev/null +++ b/public/static/images/canvas/shape_labrary01.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/shape_labrary02.svg b/public/static/images/canvas/shape_labrary02.svg new file mode 100644 index 00000000..88e1eadc --- /dev/null +++ b/public/static/images/canvas/shape_labrary02.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/static/images/canvas/shape_labrary03.svg b/public/static/images/canvas/shape_labrary03.svg new file mode 100644 index 00000000..194fd06b --- /dev/null +++ b/public/static/images/canvas/shape_labrary03.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss index 30e19173..be8b4185 100644 --- a/src/styles/_modal.scss +++ b/src/styles/_modal.scss @@ -38,7 +38,7 @@ $alert-color: #101010; z-index: 9999999; &.xxxm { - width: 230px; + width: 240px; } &.xxm { @@ -65,6 +65,10 @@ $alert-color: #101010; width: 440px; } + &.lrr { + width: 480px; + } + &.ml { width: 530px; } @@ -73,6 +77,10 @@ $alert-color: #101010; width: 640px; } + &.lx { + width: 770px; + } + &.l { width: 800px; } @@ -308,9 +316,19 @@ $alert-color: #101010; } } +.select-form { + .sort-select { + width: 100%; + } +} + .grid-select { flex: 1; + &.no-flx { + flex: unset; + } + .sort-select { width: 100%; background-color: #313131; @@ -768,7 +786,7 @@ $alert-color: #101010; } .eaves-keraba-td { - padding-left: 15px; + padding-left: 10px; } .eaves-keraba-ico { @@ -779,6 +797,7 @@ $alert-color: #101010; background-color: #3D3D3D; border: 1px solid #3D3D3D; border-radius: 2px; + cursor: pointer; &.act { border: 1px solid #ED0004; @@ -803,6 +822,10 @@ $alert-color: #101010; &.sm { margin-bottom: 15px; } + + span { + display: block; + } } // 지붕면 할당 @@ -936,9 +959,587 @@ $alert-color: #101010; } // 면형상 배치 -.roof-shape-menu { - &.plane { - grid-template-columns: 1fr 1fr 1fr 1fr 1fr; - grid-template-rows: 1fr 1fr 1fr; +.plane-shape-menu { + display: grid; + grid-template-columns: repeat(6, 1fr); + grid-template-rows: repeat(3, 90px); + gap: 10px; + margin-bottom: 10px; + + .shape-menu-box { + border-radius: 2px; + background-color: #3D3D3D; + padding: 8px; + transition: all .15s ease-in-out; + + .shape-box { + position: relative; + width: 100%; + height: 100%; + background-color: #313131; + border-radius: 2px; + + img { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } + + &.act, + &:hover { + background-color: #008BFF; + } } -} \ No newline at end of file +} + +.shape-library { + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + padding: 5px; + background-color: #3D3D3D; + margin-bottom: 24px; + + .library-btn { + width: 30px; + height: 30px; + border: 1px solid #6C6C6C; + border-radius: 2px; + background-color: transparent; + background-repeat: no-repeat; + background-position: center; + transition: all .15s ease-in-out; + + &.ico01 { + background-image: url(../../public/static/images/canvas/shape_labrary01.svg); + background-size: 14px 14px; + } + + &.ico02 { + background-image: url(../../public/static/images/canvas/shape_labrary02.svg); + background-size: 13px 17px; + } + + &.ico03 { + background-image: url(../../public/static/images/canvas/shape_labrary03.svg); + background-size: 17px 13px; + } + + &:hover { + border-color: #1083E3; + background-color: #1083E3; + } + } +} + +.plane-shape-wrapper { + display: flex; + gap: 10px; + + .plane-box { + padding: 10px; + border-radius: 2px; + background-color: #3D3D3D; + + .plane-box-tit { + font-size: $pop-normal-size; + font-weight: 600; + color: $pop-color; + margin-bottom: 10px; + } + + &.shape-box { + flex: 1; + + .shape-box-inner { + display: flex; + gap: 10px; + min-height: 140px; + + .shape-img { + position: relative; + flex: 1; + background-color: #fff; + border-radius: 2px; + + img { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } + + .shape-data { + flex: none; + width: 190px; + background-color: #313131; + border-radius: 2px; + padding: 15px; + + .eaves-keraba-table { + .eaves-keraba-item { + .eaves-keraba-th, + .eaves-keraba-td { + padding-bottom: 10px; + } + + &:last-child { + .eaves-keraba-th, + .eaves-keraba-td { + padding-bottom: 0px; + } + } + } + } + } + } + } + + &.direction-box { + display: flex; + flex-direction: column; + flex: none; + width: 180px; + + .plane-direction-box { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + padding: 10px 5px; + } + } + } +} + +.plane-direction { + width: 150px; + position: relative; + height: 120px; + + span { + position: absolute; + font-size: 12px; + font-weight: 500; + color: #B1B1B1; + + &.top { + top: 0; + left: 50%; + transform: translateX(-50%); + } + + &.right { + top: 50%; + right: 0; + transform: translateY(-50%); + } + + &.bottom { + bottom: 0; + left: 50%; + transform: translateX(-50%); + } + + &.left { + top: 50%; + left: 0; + transform: translateY(-50%); + } + } + + .plane-btn { + position: absolute; + width: 28px; + height: 28px; + background-color: #777777; + background-image: url(../../public/static/images/canvas/plane_arr.svg); + background-size: 12px 13px; + background-repeat: no-repeat; + background-position: center; + border-radius: 50%; + transition: all .15s ease-in-out; + + &.up { + top: 22px; + left: 50%; + transform: translateX(-50%); + } + + &.right { + top: 50%; + right: 32px; + transform: translateY(-50%) rotate(90deg); + } + + &.down { + bottom: 22px; + left: 50%; + transform: translateX(-50%) rotate(180deg); + } + + &.left { + top: 50%; + left: 32px; + transform: translateY(-50%) rotate(270deg); + } + + &:hover, + &.act { + background-color: #fff; + background-image: url(../../public/static/images/canvas/plane_arr_act.svg); + } + } +} + +.plane-tab-guide { + font-size: $pop-normal-size; + font-weight: $pop-normal-weight; + color: $pop-color; + margin-top: 24px; + padding-bottom: 14px; + border-bottom: 1px solid #424242; +} + +// 오브젝트 배치 +.mb-box { + margin-bottom: 24px; +} + +.object-direction-wrap { + display: flex; + align-items: center; + justify-content: center; +} + +.discrimination-tit { + font-size: 13px; + color: #fff; + font-weight: 500; +} + +.object-size-wrap { + display: flex; + min-height: 206px; + gap: 24px; + margin-top: 14px; + + .object-size-img { + position: relative; + flex: none; + width: 200px; + background-color: #fff; + + img { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } +} + +// 표시변경 +.display-change-wrap { + margin: 24px 0; +} + +.warning { + font-size: $pop-normal-size; + font-weight: $pop-normal-weight; + color: #FFAFAF; +} + +// 각 변 속성 변경 +.radio-grid-wrap { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 24px 15px; +} + +// 면 흐름 설정 +.drawing-flow-wrap { + display: flex; + gap: 10px; + + .discrimination-box { + flex: 1; + display: flex; + flex-direction: column; + + .object-direction-wrap { + flex: 1; + } + } +} + +.compas-box { + display: flex; + align-items: center; + justify-content: center; +} + +.compas-box-inner { + position: relative; + width: 200px; + height: 200px; + border-radius: 50%; + + .circle { + position: absolute; + width: 12px; + height: 12px; + border: 1px solid #fff; + border-radius: 50%; + top: 95%; + left: 50%; + transform-origin: 0 -90px; /* 중심에서 반지름 거리만큼 떨어져 위치 */ + cursor: pointer; + z-index: 3; + /* 0번을 180도 위치(아래)에, 13번을 0도 위치(위)에 배치 */ + i { + position: absolute; + top: 12.5px; + left: 50%; + font-size: 11px; + color: #8B8B8B; + font-weight: 500; + -webkit-user-select: none; + -moz-user-select: none; + -ms-use-select: none; + user-select: none; + } + + &:nth-child(1) { + transform: rotate(180deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(180deg); + } + } + + &:nth-child(2) { + transform: rotate(195deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(165deg); + } + } + + &:nth-child(3) { + transform: rotate(210deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(150deg); + } + } + + &:nth-child(4) { + transform: rotate(225deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(135deg); + } + } + + &:nth-child(5) { + transform: rotate(240deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(120deg); + } + } + + &:nth-child(6) { + transform: rotate(255deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(105deg); + } + } + + &:nth-child(7) { + transform: rotate(270deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(90deg); + } + } + + &:nth-child(8) { + transform: rotate(285deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(75deg); + } + } + + &:nth-child(9) { + transform: rotate(300deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(60deg); + } + } + + &:nth-child(10) { + transform: rotate(315deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(45deg); + } + } + + &:nth-child(11) { + transform: rotate(330deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(30deg); + } + } + + &:nth-child(12) { + transform: rotate(345deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(15deg); + } + } + + &:nth-child(13) { + transform: rotate(0deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(0deg); + } + } + + &:nth-child(14) { + transform: rotate(15deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(-15deg); + } + } + + &:nth-child(15) { + transform: rotate(30deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(-30deg); + } + } + + &:nth-child(16) { + transform: rotate(45deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(-45deg); + } + } + + &:nth-child(17) { + transform: rotate(60deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(-60deg); + } + } + + &:nth-child(18) { + transform: rotate(75deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(-75deg); + } + } + + &:nth-child(19) { + transform: rotate(90deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(-90deg); + } + } + + &:nth-child(20) { + transform: rotate(105deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(-105deg); + } + } + + &:nth-child(21) { + transform: rotate(120deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(-120deg); + } + } + + &:nth-child(22) { + transform: rotate(135deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(-135deg); + } + } + + &:nth-child(23) { + transform: rotate(150deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(-150deg); + } + } + + &:nth-child(24) { + transform: rotate(165deg) translate(-50%, -50%); + + i { + transform: translateX(-50%) rotate(-165deg); + } + } + + &.act { + &::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 5px; + height: 5px; + background-color: #fff; + } + + i { + color: #fff; + } + } + } + + .compas { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 148px; + height: 148px; + border: 4px solid #fff; + border-radius: 50%; + + .compas-arr { + width: 100%; + height: 100%; + background: url(../../public/static/images/canvas/compas.svg) no-repeat center; + background-size: 122px 122px; + } + } +} From 5afb2349988441a6f25f4649cc1998afd1cab33b Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 10:19:02 +0900 Subject: [PATCH 035/152] =?UTF-8?q?=EB=B0=B0=EC=B9=98=EB=A9=B4=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=20=EC=84=A4=EC=A0=95=20=EC=A7=80=EB=B6=95=EC=A0=9C?= =?UTF-8?q?=EB=B3=84=20=EC=9E=85=EB=A0=A5=20=ED=95=AD=EB=AA=A9=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../placementShape/PlacementShapeSetting.jsx | 113 +++++++++++++----- src/locales/ja.json | 8 ++ src/locales/ko.json | 13 ++ 3 files changed, 107 insertions(+), 27 deletions(-) diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 606f932d..7c933c57 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -1,12 +1,13 @@ import SizeGuide from '@/components/floor-plan/modal/placementShape/SizeGuide' import MaterialGuide from '@/components/floor-plan/modal/placementShape/MaterialGuide' import WithDraggable from '@/components/common/draggable/WithDraggable' -import { useState } from 'react' +import { Fragment, useState } from 'react' import { useMessage } from '@/hooks/useMessage' export default function PlacementShapeSetting({ setShowPlaceShapeModal }) { const [showSizeGuideModal, setShowSizeGuidModal] = useState(false) const [showMaterialGuideModal, setShowMaterialGuidModal] = useState(false) + const [selectedRoofMaterial, setSelectedRoofMaterial] = useState('A') const { getMessage } = useMessage() return ( @@ -74,34 +75,92 @@ export default function PlacementShapeSetting({ setShowPlaceShapeModal }) {
- setSelectedRoofMaterial(e.target.value)}> + + + +
-
- W -
- -
-
-
- L -
- -
-
-
- {getMessage('modal.placement.initial.setting.rafter')} -
- -
-
+ {selectedRoofMaterial === 'A' ? ( + <> +
+ W +
+ +
+
+
+ L +
+ +
+
+
+ {getMessage('modal.placement.initial.setting.rafter')} +
+ +
+
+ + ) : selectedRoofMaterial === 'B' ? ( + <> +
+ {getMessage('modal.placement.initial.setting.rafter')} +
+ +
+
+
+ {getMessage('modal.placement.initial.setting.rafter')} +
+ +
+
+ + ) : selectedRoofMaterial === 'C' ? ( + <> +
+ {getMessage('hajebichi')} +
+ +
+
+ + ) : selectedRoofMaterial === 'D' ? ( + <> +
+ L +
+ +
+
+
+ {getMessage('modal.placement.initial.setting.rafter')} +
+ +
+
+ + ) : ( + '' + )}
diff --git a/src/locales/ja.json b/src/locales/ja.json index 71c6fb8d..47a366ad 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -295,13 +295,21 @@ "stuff.gridHeader.receiveUser": "담당자", "stuff.gridHeader.specDate": "사양확인", "stuff.gridHeader.createDatetime": "등록일", + "length": "長さ", "slope": "傾斜", "eaves.offset": "軒の", "gable.offset": "ケラバ出幅", "size": "寸", + "size.angle": "寸(度)", "eaves": "軒", "gable": "ケラバ", "wall": "壁", + "hajebichi": "ハゼビーチ", + "straight.line": "直線", + "right.angle": "直角", + "double.pitch": "イ・グベ", + "angle": "角度", + "diagonal": "対角線", "hipandgable": "八作屋根", "jerkinhead": "半折", "shed": "片側の流れ", diff --git a/src/locales/ko.json b/src/locales/ko.json index 6497020e..a1506270 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -65,6 +65,11 @@ "plan.menu.placement.surface": "배치면", "plan.menu.placement.surface.slope.setting": "경사설정", "plan.menu.placement.surface.drawing": "배치면 그리기", + "modal.placement.surface.drawing.straight.line": "직선", + "modal.placement.surface.drawing.right.angle": "직각", + "modal.placement.surface.drawing.double.pitch": "이구배", + "modal.placement.surface.drawing.angle": "각도", + "modal.placement.surface.drawing.diagonal": "대각선", "plan.menu.placement.surface.arrangement": "면형상 배치", "plan.menu.placement.surface.object": "오브젝트 배치", "plan.menu.placement.surface.all.remove": "배치면 전체 삭제", @@ -297,13 +302,21 @@ "stuff.gridHeader.receiveUser": "담당자", "stuff.gridHeader.specDate": "사양확인", "stuff.gridHeader.createDatetime": "등록일", + "length": "길이", "slope": "경사", "eaves.offset": "처마 출폭", "gable.offset": "케라바 출폭", "size": "치수", + "size.angle": "寸(度)", "eaves": "처마", "gable": "케라바", "wall": "벽", + "hajebichi": "하제비치", + "straight.line": "직선", + "right.angle": "직각", + "double.pitch": "이구배", + "angle": "각도", + "diagonal": "대각선", "hipandgable": "팔작지붕", "jerkinhead": "반절처", "shed": "한쪽흐름", From 74239d1c5c6f764ae58de6290fea34ce6dc09355 Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 10:20:19 +0900 Subject: [PATCH 036/152] =?UTF-8?q?=EC=A7=80=EB=B6=95=ED=98=95=EC=83=81=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20class=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx b/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx index 517a7ba3..17999df2 100644 --- a/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx +++ b/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx @@ -23,7 +23,7 @@ export default function RoofShapeSetting({ setShowRoofShapeSettingModal }) { return ( -
+

{getMessage('modal.roof.shape.setting')}

diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx new file mode 100644 index 00000000..cb93375b --- /dev/null +++ b/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx @@ -0,0 +1,152 @@ +import { useState } from 'react' +import { useMessage } from '@/hooks/useMessage' +import WithDraggable from '@/components/common/draggable/withDraggable' +import RightAngle from '@/components/floor-plan/modal/lineTypes/RightAngle' +import DoublePitch from '@/components/floor-plan/modal/lineTypes/DoublePitch' +import Angle from '@/components/floor-plan/modal/lineTypes/Angle' +import Diagonal from '@/components/floor-plan/modal/lineTypes/Diagonal' +import { OUTER_LINE_TYPE } from '@/store/outerLineAtom' +import { useOuterLineWall } from '@/hooks/roofcover/useOuterLineWall' +import OuterLineWall from '@/components/floor-plan/modal/lineTypes/OuterLineWall' + +export default function AuxiliaryDrawing() { + const { getMessage } = useMessage() + const [buttonAct, setButtonAct] = useState(1) + const types = [ + { id: 1, name: getMessage('straight.line'), type: OUTER_LINE_TYPE.OUTER_LINE }, + { id: 2, name: getMessage('right.angle'), type: OUTER_LINE_TYPE.RIGHT_ANGLE }, + { id: 3, name: getMessage('double.pitch'), type: OUTER_LINE_TYPE.DOUBLE_PITCH }, + { id: 4, name: getMessage('angle'), type: OUTER_LINE_TYPE.ANGLE }, + { id: 5, name: getMessage('diagonal'), type: OUTER_LINE_TYPE.DIAGONAL_LINE }, + ] + const { + length1, + setLength1, + length2, + setLength2, + length1Ref, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + angle1, + setAngle1, + angle1Ref, + angle2, + setAngle2, + angle2Ref, + type, + setType, + arrow1Ref, + arrow2Ref, + outerLineDiagonalLength, + setOuterLineDiagonalLength, + outerLineDiagonalLengthRef, + handleRollback, + handleFix, + } = useOuterLineWall() + + const outerLineProps = { + length1, + setLength1, + length1Ref, + arrow1, + setArrow1, + } + + const rightAngleProps = { + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + } + + const doublePitchProps = { + angle1, + setAngle1, + angle1Ref, + angle2, + setAngle2, + angle2Ref, + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + arrow1Ref, + arrow2Ref, + } + + const angleProps = { + angle1, + setAngle1, + angle1Ref, + length1, + setLength1, + length1Ref, + } + + const diagonalLineProps = { + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + outerLineDiagonalLength, + setOuterLineDiagonalLength, + outerLineDiagonalLengthRef, + arrow1, + setArrow1, + arrow2, + setArrow2, + } + + const onClickButton = (button) => { + setButtonAct(button.id) + setType(button.type) + } + return ( + +
+
+

{getMessage('modal.auxiliary.drawing')}

+ +
+
+
+ {types.map((type) => ( + + ))} +
+
+
{getMessage('setting')}
+ {buttonAct === 1 && } + {buttonAct === 2 && } + {buttonAct === 3 && } + {buttonAct === 4 && } + {buttonAct === 5 && } +
+
+ + +
+
+
+
+ ) +} diff --git a/src/components/floor-plan/modal/outerlinesetting/Angle.jsx b/src/components/floor-plan/modal/lineTypes/Angle.jsx similarity index 100% rename from src/components/floor-plan/modal/outerlinesetting/Angle.jsx rename to src/components/floor-plan/modal/lineTypes/Angle.jsx diff --git a/src/components/floor-plan/modal/outerlinesetting/Diagonal.jsx b/src/components/floor-plan/modal/lineTypes/Diagonal.jsx similarity index 100% rename from src/components/floor-plan/modal/outerlinesetting/Diagonal.jsx rename to src/components/floor-plan/modal/lineTypes/Diagonal.jsx diff --git a/src/components/floor-plan/modal/outerlinesetting/DoublePitch.jsx b/src/components/floor-plan/modal/lineTypes/DoublePitch.jsx similarity index 100% rename from src/components/floor-plan/modal/outerlinesetting/DoublePitch.jsx rename to src/components/floor-plan/modal/lineTypes/DoublePitch.jsx diff --git a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx b/src/components/floor-plan/modal/lineTypes/OuterLineWall.jsx similarity index 93% rename from src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx rename to src/components/floor-plan/modal/lineTypes/OuterLineWall.jsx index ffa5e0e7..f469fba8 100644 --- a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx +++ b/src/components/floor-plan/modal/lineTypes/OuterLineWall.jsx @@ -2,7 +2,6 @@ import { useMessage } from '@/hooks/useMessage' import { onlyNumberInputChange } from '@/util/input-utils' -import GridMove from '@/components/floor-plan/modal/grid/GridMove' export default function OuterLineWall({ props }) { const { getMessage } = useMessage() @@ -12,7 +11,7 @@ export default function OuterLineWall({ props }) {
- {getMessage('modal.cover.outline.length')} + {getMessage('straight.line')}
Date: Mon, 7 Oct 2024 10:33:22 +0900 Subject: [PATCH 038/152] =?UTF-8?q?=EB=8B=AB=EA=B8=B0=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/MenuDepth01.jsx | 20 ++++++++++++++++++- .../modal/auxiliary/AuxiliaryDrawing.jsx | 6 ++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/components/floor-plan/MenuDepth01.jsx b/src/components/floor-plan/MenuDepth01.jsx index 43a059f0..4148ac5a 100644 --- a/src/components/floor-plan/MenuDepth01.jsx +++ b/src/components/floor-plan/MenuDepth01.jsx @@ -7,7 +7,16 @@ import { currentMenuState } from '@/store/canvasAtom' import { useSetRecoilState } from 'recoil' export default function MenuDepth01(props) { - const { setShowOutlineModal, type, setShowPlaceShapeModal, setShowRoofShapeSettingModal } = props + const { + setShowOutlineModal, + type, + setShowPlaceShapeModal, + setShowRoofShapeSettingModal, + setShowRoofShapePassivitySettingModal, + setShowAuxiliaryModal, + setShowSlopeSettingModal, + setShowPlaceShapeDrawingModal, + } = props const { getMessage } = useMessage() const [activeMenu, setActiveMenu] = useState() const setCurrentMenu = useSetRecoilState(currentMenuState) @@ -15,10 +24,19 @@ export default function MenuDepth01(props) { setActiveMenu(menu) setShowOutlineModal(menu === MENU.ROOF_COVERING.EXTERIOR_WALL_LINE) setCurrentMenu(menu) + if (type === 'outline') { setShowPlaceShapeModal(false) setShowOutlineModal(id === 0) setShowRoofShapeSettingModal(id === 1) + setShowRoofShapePassivitySettingModal(id === 2) + setShowAuxiliaryModal(id === 3) + setShowPlaceShapeDrawingModal(false) + } + + if (type === 'surface') { + setShowSlopeSettingModal(id === 0) + setShowPlaceShapeDrawingModal(id === 1) } } diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx index cb93375b..4e64191e 100644 --- a/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx +++ b/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx @@ -9,7 +9,7 @@ import { OUTER_LINE_TYPE } from '@/store/outerLineAtom' import { useOuterLineWall } from '@/hooks/roofcover/useOuterLineWall' import OuterLineWall from '@/components/floor-plan/modal/lineTypes/OuterLineWall' -export default function AuxiliaryDrawing() { +export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) { const { getMessage } = useMessage() const [buttonAct, setButtonAct] = useState(1) const types = [ @@ -123,7 +123,9 @@ export default function AuxiliaryDrawing() {

{getMessage('modal.auxiliary.drawing')}

- +
From edb8695182cb56a184b7056740751da0918c0ce5 Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 10:33:34 +0900 Subject: [PATCH 039/152] =?UTF-8?q?=EB=B0=B0=EC=B9=98=EB=A9=B4=20=EA=B7=B8?= =?UTF-8?q?=EB=A6=AC=EA=B8=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../placementShape/PlacementShapeDrawing.jsx | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx new file mode 100644 index 00000000..c705b0eb --- /dev/null +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx @@ -0,0 +1,155 @@ +import { useMessage } from '@/hooks/useMessage' +import { useState } from 'react' +import WithDraggable from '@/components/common/draggable/WithDraggable' +import RightAngle from '@/components/floor-plan/modal/lineTypes/RightAngle' +import DoublePitch from '@/components/floor-plan/modal/lineTypes/DoublePitch' +import Angle from '@/components/floor-plan/modal/lineTypes/Angle' +import Diagonal from '@/components/floor-plan/modal/lineTypes/Diagonal' +import { useOuterLineWall } from '@/hooks/roofcover/useOuterLineWall' +import { OUTER_LINE_TYPE } from '@/store/outerLineAtom' +import OuterLineWall from '@/components/floor-plan/modal/lineTypes/OuterLineWall' + +export default function PlacementShapeDrawing({ setShowPlaceShapeDrawingModal }) { + const { getMessage } = useMessage() + const [buttonAct, setButtonAct] = useState(1) + const types = [ + { id: 1, name: getMessage('straight.line'), type: OUTER_LINE_TYPE.OUTER_LINE }, + { id: 2, name: getMessage('right.angle'), type: OUTER_LINE_TYPE.RIGHT_ANGLE }, + { id: 3, name: getMessage('double.pitch'), type: OUTER_LINE_TYPE.DOUBLE_PITCH }, + { id: 4, name: getMessage('angle'), type: OUTER_LINE_TYPE.ANGLE }, + { id: 5, name: getMessage('diagonal'), type: OUTER_LINE_TYPE.DIAGONAL_LINE }, + ] + const { + length1, + setLength1, + length2, + setLength2, + length1Ref, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + angle1, + setAngle1, + angle1Ref, + angle2, + setAngle2, + angle2Ref, + type, + setType, + arrow1Ref, + arrow2Ref, + outerLineDiagonalLength, + setOuterLineDiagonalLength, + outerLineDiagonalLengthRef, + handleRollback, + handleFix, + } = useOuterLineWall() + + const outerLineProps = { + length1, + setLength1, + length1Ref, + arrow1, + setArrow1, + } + + const rightAngleProps = { + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + } + + const doublePitchProps = { + angle1, + setAngle1, + angle1Ref, + angle2, + setAngle2, + angle2Ref, + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + arrow1Ref, + arrow2Ref, + } + + const angleProps = { + angle1, + setAngle1, + angle1Ref, + length1, + setLength1, + length1Ref, + } + + const diagonalLineProps = { + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + outerLineDiagonalLength, + setOuterLineDiagonalLength, + outerLineDiagonalLengthRef, + arrow1, + setArrow1, + arrow2, + setArrow2, + } + + const onClickButton = (button) => { + setButtonAct(button.id) + setType(button.type) + } + return ( + +
+
+

{getMessage('plan.menu.placement.surface.drawing')}

+ +
+
+
+ {types.map((type) => ( + + ))} +
+
+
{getMessage('setting')}
+ {buttonAct === 1 && } + {buttonAct === 2 && } + {buttonAct === 3 && } + {buttonAct === 4 && } + {buttonAct === 5 && } +
+ +
+ + +
+
+
+
+ ) +} From f2dbc7f91e43414afe01b0c26df7786c1af0a6ad Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 10:33:41 +0900 Subject: [PATCH 040/152] =?UTF-8?q?=EA=B2=BD=EC=82=AC=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/modal/Slope.jsx | 34 +++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/components/floor-plan/modal/Slope.jsx diff --git a/src/components/floor-plan/modal/Slope.jsx b/src/components/floor-plan/modal/Slope.jsx new file mode 100644 index 00000000..0ae32ab6 --- /dev/null +++ b/src/components/floor-plan/modal/Slope.jsx @@ -0,0 +1,34 @@ +import { useMessage } from '@/hooks/useMessage' +import WithDraggable from '@/components/common/draggable/WithDraggable' + +export default function Slope({ setShowSlopeSettingModal }) { + const { getMessage } = useMessage() + return ( + +
+
+

{getMessage('plan.menu.placement.surface.slope.setting')}

+ +
+
+
+
+ + {getMessage('slope')} + +
+ +
+ {getMessage('size.angle')} +
+
+
+ +
+
+
+
+ ) +} From 36077b601fd45030ba5144300299bc5401979864 Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 10:39:13 +0900 Subject: [PATCH 041/152] =?UTF-8?q?fix:=20=EC=A4=91=EB=B3=B5=20=ED=95=AD?= =?UTF-8?q?=EB=AA=A9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/placementShape/PlacementShapeSetting.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 7c933c57..637ebb0a 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -112,7 +112,7 @@ export default function PlacementShapeSetting({ setShowPlaceShapeModal }) { ) : selectedRoofMaterial === 'B' ? ( <>
- {getMessage('modal.placement.initial.setting.rafter')} + {getMessage('hajebichi')}
- {powerSimAreaList.map((row) => { + {areaIdList?.length > 0 && ( +
m/s이하 +
@@ -627,7 +628,7 @@ export default function StuffDetail() {
- @@ -635,8 +636,8 @@ export default function StuffDetail() {
cm
- - + +
@@ -656,8 +657,8 @@ export default function StuffDetail() {
- - + +
@@ -686,12 +687,12 @@ export default function StuffDetail() {
- - + +
- - + +
diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx index e43c7c90..0b394af3 100644 --- a/src/components/management/StuffSearchCondition.jsx +++ b/src/components/management/StuffSearchCondition.jsx @@ -3,19 +3,23 @@ import React, { useEffect, useRef, useState } from 'react' import { useAxios } from '@/hooks/useAxios' import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' -import { globalLocaleStore } from '@/store/localeAtom' +import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' import Select from 'react-dropdown-select' - +import KO from '@/locales/ko.json' +import JA from '@/locales/ja.json' import { stuffSearchState } from '@/store/stuffAtom' import { isEmptyArray } from '@/util/common-utils' import dayjs from 'dayjs' -import isLeapYear from 'dayjs/plugin/isLeapYear' // 윤년 판단 플러그인 -dayjs.extend(isLeapYear) import Link from 'next/link' import SingleDatePicker from '../common/datepicker/SingleDatePicker' +import { sessionStore } from '@/store/commonAtom' +import { useMessage } from '@/hooks/useMessage' export default function StuffSearchCondition() { - const globalLocaleState = useRecoilValue(globalLocaleStore) + const sessionState = useRecoilValue(sessionStore) + const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore) + const globalLocaleState = useRecoilValue(globalLocaleStore) + const { getMessage } = useMessage() const ref = useRef() const { get } = useAxios(globalLocaleState) @@ -41,7 +45,6 @@ export default function StuffSearchCondition() { const [address, setAddress] = useState('') //물건주소 const [objectName, setobjectName] = useState('') //물건명 const [saleStoreName, setSaleStoreName] = useState('') //판매대리점명 - const [specDateYn, setSpecDateYn] = useState('') //사양 확인('', 'Y', 'N') const [receiveUser, setReceiveUser] = useState('') //담당자 const [dispCompanyName, setDispCompanyName] = useState('') //견적처 const [dateType, setDateType] = useState('U') //갱신일(U)/등록일(R) @@ -52,7 +55,7 @@ export default function StuffSearchCondition() { const onSubmit = () => { let diff = dayjs(endDate).diff(startDate, 'day') if (diff > 366) { - return alert('최대1년 조회 가능합니다.') + return alert(getMessage('stuff.message.periodError')) } setStuffSearch({ @@ -61,7 +64,6 @@ export default function StuffSearchCondition() { schAddress: stuffSearch?.schAddress ? stuffSearch.schAddress : address, schObjectName: stuffSearch?.schObjectName ? stuffSearch.schObjectName : objectName, schSaleStoreName: stuffSearch?.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName, - schSpecDateYn: stuffSearch?.schSpecDateYn ? stuffSearch.schSpecDateYn : specDateYn, schReceiveUser: stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser, schDispCompanyName: stuffSearch?.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName, schDateType: stuffSearch?.schDateType ? stuffSearch.schDateType : dateType, @@ -82,7 +84,6 @@ export default function StuffSearchCondition() { setAddress('') setobjectName('') setSaleStoreName('') - setSpecDateYn('') setReceiveUser('') setDispCompanyName('') setDateType('U') @@ -94,6 +95,7 @@ export default function StuffSearchCondition() { } useEffect(() => { + // console.log('세션정보::::::::', sessionState) get({ url: `/api/object/saleStore/201TES01/list` }).then((res) => { if (!isEmptyArray(res)) { // console.log('판매점 결과:::::', res) @@ -127,6 +129,14 @@ export default function StuffSearchCondition() { setEndDate(stuffSearch?.schToDt ? stuffSearch.schToDt : dayjs(new Date()).format('YYYY-MM-DD')) }, [stuffSearch]) + useEffect(() => { + if (globalLocaleState === 'ko') { + setAppMessageState(KO) + } else { + setAppMessageState(JA) + } + }, [globalLocaleState]) + return ( <> {/* 퍼블적용시작 */} @@ -138,7 +148,7 @@ export default function StuffSearchCondition() {
*/} {schSelSaleStoreList?.length > 0 && ( - // - // {(option) => {option.saleStoreName}} - // { - setObjectNo(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schObjectNo: e.target.value }) - }} - /> - { - setSaleStoreId(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schSaleStoreId: e.target.value }) - }} - /> - { - setAddress(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schAddress: e.target.value }) - }} - /> -
- ) - } else if (i === 1) { - return ( -
- { - setobjectName(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schObjectName: e.target.value }) - }} - /> - { - setSaleStoreName(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schSaleStoreName: e.target.value }) - }} - /> -
- { - setSpecDateYn(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schSpecDateYn: e.target.value }) - }} - /> - -
-
- { - setSpecDateYn(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schSpecDateYn: e.target.value }) - }} - /> - -
-
- { - setSpecDateYn(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schSpecDateYn: e.target.value }) - }} - /> - -
-
- ) - } else if (i === 2) { - return ( -
- { - setReceiveUser(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schReceiveUser: e.target.value }) - }} - /> - { - setDispCompanyName(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schDispCompanyName: e.target.value }) - }} - /> - {schSelSaleStoreList?.length > 0 && ( - - {(option) => {option.saleStoreName}} - - )} -
- ) - } else { - return ( -
-
- { - setDateType(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value }) - }} - /> - -
-
- { - setDateType(e.target.value) - setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value }) - }} - /> - -
- -
- ) - } - })} -
*/} ) } diff --git a/src/locales/ja.json b/src/locales/ja.json index 4337ad21..d0bffc34 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -285,17 +285,18 @@ "join.complete.contents": "※ 신청한 ID가 승인되면, 담당자 정보에 입력한 이메일 주소로 로그인 관련 안내 메일이 전송됩니다.", "join.complete.email_comment": "담당자 이메일 주소", "join.complete.email": "test@naver.com", - "stuff.gridHeader.lastEditDatetime": "갱신일시", - "stuff.gridHeader.objectNo": "물건번호", - "stuff.gridHeader.planTotCnt": "플랜 수", - "stuff.gridHeader.objectName": "물건명", - "stuff.gridHeader.saleStoreId": "대리점ID", - "stuff.gridHeader.saleStoreName": "대리점명", - "stuff.gridHeader.address": "물건주소", - "stuff.gridHeader.dispCompanyName": "견적처", - "stuff.gridHeader.receiveUser": "담당자", - "stuff.gridHeader.specDate": "사양확인", - "stuff.gridHeader.createDatetime": "등록일", + "stuff.gridHeader.lastEditDatetime": "更新日時", + "stuff.gridHeader.objectNo": "品番", + "stuff.gridHeader.planTotCnt": "プラン数", + "stuff.gridHeader.objectName": "商品名", + "stuff.gridHeader.saleStoreId": "代理店ID", + "stuff.gridHeader.saleStoreName": "代理店名", + "stuff.gridHeader.address": "商品アドレス", + "stuff.gridHeader.dispCompanyName": "見積もり", + "stuff.gridHeader.receiveUser": "担当者", + "stuff.gridHeader.specDate": "仕様確認日", + "stuff.gridHeader.createDatetime": "登録日", + "stuff.message.periodError": "最大1年間閲覧可能.", "length": "長さ", "slope": "傾斜", "eaves.offset": "軒の", diff --git a/src/locales/ko.json b/src/locales/ko.json index 167aaa11..6914ffcf 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -301,8 +301,9 @@ "stuff.gridHeader.address": "물건주소", "stuff.gridHeader.dispCompanyName": "견적처", "stuff.gridHeader.receiveUser": "담당자", - "stuff.gridHeader.specDate": "사양확인", + "stuff.gridHeader.specDate": "사양확인일", "stuff.gridHeader.createDatetime": "등록일", + "stuff.message.periodError": "최대1년 조회 가능합니다.", "length": "길이", "slope": "경사", "eaves.offset": "처마 출폭", diff --git a/src/store/stuffAtom.js b/src/store/stuffAtom.js index 5de2c04e..e126fb35 100644 --- a/src/store/stuffAtom.js +++ b/src/store/stuffAtom.js @@ -10,7 +10,6 @@ export const stuffSearchState = atom({ schAddress: '', //물건주소 schObjectName: '', //물건명 schSaleStoreName: '', //판매대리점명 - schSpecDateYn: '', //사양타입 ('', 'Y', 'N') schReceiveUser: '', //담당자 schDispCompanyName: '', //견적처 schDateType: 'U', //갱신일(U)/등록일(R) From ea200a61a92d5d6eae355f51e6abca64679f2094 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 7 Oct 2024 14:03:39 +0900 Subject: [PATCH 047/152] refactor: Remove unused Axios.js file --- src/lib/Axios.js | 56 ------------------------------------------------ 1 file changed, 56 deletions(-) delete mode 100644 src/lib/Axios.js diff --git a/src/lib/Axios.js b/src/lib/Axios.js deleted file mode 100644 index d773d352..00000000 --- a/src/lib/Axios.js +++ /dev/null @@ -1,56 +0,0 @@ -'use client' - -import axios from 'axios' - -axios.defaults.baseURL = process.env.NEXT_PUBLIC_API_SERVER_PATH - -const axiosInstance = axios.create({ - // baseURL: process.env.API_SERVER_URL, - headers: { - Accept: 'application/json', - }, -}) - -axiosInstance.interceptors.request.use((config) => { - // config['Authorization'] = localStorage.getItem('token') - //TODO: 인터셉터에서 추가 로직 구현 - return config -}) - -axiosInstance.interceptors.request.use(undefined, (error) => { - //TODO: 인터셉터에서 에러 처리 로직 구현 - // if (error.isAxiosError && e.response?.status === 401) { - // localStorage.removeItem('token') - // } -}) - -export const get = ({ url }) => - axiosInstance - .get(url) - .then((res) => res.data) - .catch(console.error) - -export const post = ({ url, data }) => - axiosInstance - .post(url, data) - .then((res) => res.data) - .catch(console.error) - -export const put = ({ url, data }) => - axiosInstance - .put(url, data) - .then((res) => res.data) - .catch(console.error) - -export const patch = ({ url, data }) => - axiosInstance - .patch(url, data) - - .then((res) => res.data) - .catch(console.error) - -export const del = ({ url }) => - axiosInstance - .delete(url) - .then((res) => res.data) - .catch(console.error) From 7fd9ded5f8454dd108e18942c4240346400fc83d Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 7 Oct 2024 14:10:11 +0900 Subject: [PATCH 048/152] refactor: Update useAxios hook --- src/hooks/useAxios.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/hooks/useAxios.js b/src/hooks/useAxios.js index 53470971..39b71769 100644 --- a/src/hooks/useAxios.js +++ b/src/hooks/useAxios.js @@ -5,11 +5,22 @@ const AxiosType = { EXTERNAL: 'External', } +/** + * axios 인스턴스 생성 후 반환 + * @param {String} lang + * @returns http request instance - get, post, put, patch, delete (promise 접수사가 붙은 함수는 promise 반환) + */ export function useAxios(lang = '') { const getInstances = (url) => { + /** + * url이 http로 시작하면 외부 서버로 판단 + */ let type = AxiosType.INTERNAL url.startsWith('http') ? (type = AxiosType.EXTERNAL) : '' + /** + * 내부 서버로 요청 시 lang 헤더 추가 + */ let headerValue = { Accept: 'application/json', } @@ -21,18 +32,13 @@ export function useAxios(lang = '') { }) } + // request 추가 로직 axios.interceptors.request.use((config) => { - // config['Authorization'] = localStorage.getItem('token') - //TODO: 인터셉터에서 추가 로직 구현 return config }) - axios.interceptors.request.use(undefined, (error) => { - //TODO: 인터셉터에서 에러 처리 로직 구현 - // if (error.isAxiosError && e.response?.status === 401) { - // localStorage.removeItem('token') - // } - }) + // response 추가 로직 + axios.interceptors.request.use(undefined, (error) => {}) const get = async ({ url }) => { return await getInstances(url) From 5f4b1785069fea8bb7fea08226e373b864136823 Mon Sep 17 00:00:00 2001 From: Daseul Kim Date: Mon, 7 Oct 2024 14:30:03 +0900 Subject: [PATCH 049/152] =?UTF-8?q?feat:=20canvas=20plan=EC=9D=98=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=EB=90=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=82=AC=ED=95=AD=EC=9D=84=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=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 TODO: 신규 canvas plan 저장 시 데이터 동기화 필요 --- src/components/floor-plan/CanvasLayout.jsx | 73 +++++++++++++++------- src/hooks/usePlan.js | 33 ++++++++-- 2 files changed, 80 insertions(+), 26 deletions(-) diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx index 3abebd85..98f5f36d 100644 --- a/src/components/floor-plan/CanvasLayout.jsx +++ b/src/components/floor-plan/CanvasLayout.jsx @@ -12,7 +12,7 @@ import { sessionStore } from '@/store/commonAtom' export default function CanvasLayout() { const [objectNo, setObjectNo] = useState('test123240822001') // 이후 삭제 필요 - const [addCanvasPlans, setAddCanvasPlans] = useState([]) + const [plans, setPlans] = useState([]) const [planNum, setPlanNum] = useState(0) const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) @@ -21,25 +21,54 @@ export default function CanvasLayout() { const { getMessage } = useMessage() const { swalFire } = useSwal() - const { getCanvasByObjectNo, delCanvasById } = usePlan() + const { getCanvasByObjectNo, delCanvasById, checkModifiedCanvasPlan, saveCanvas } = usePlan() const handleCurrentPlan = (newCurrentId) => { + // console.log('currentPlan newCurrentId: ', newCurrentId) + if (!currentCanvasPlan?.id || currentCanvasPlan.id !== newCurrentId) { - setInitCanvasPlans((plans) => - plans.map((plan) => { - return { ...plan, isCurrent: plan.id === newCurrentId } - }), - ) - setAddCanvasPlans((plans) => - plans.map((plan) => { - return { ...plan, isCurrent: plan.id === newCurrentId } - }), - ) + if (currentCanvasPlan?.id && checkModifiedCanvasPlan()) { + swalFire({ + html: getMessage('common.message.confirm.save') + `
${currentCanvasPlan.name}`, + type: 'confirm', + confirmFn: async () => { + saveCanvas(sessionState.userId) + /** + * TODO: 신규 canvas plan 저장 시 id, name 등 데이터 동기화 필요 (40~51Line) + */ + initCanvasPlans.map((initPlan) => { + if ('isNew' in initPlan) { + // console.log('================ isNew initPlan: ', initPlan) + setPlans((plans) => + plans.map((plan) => { + initPlan.isNew === plan.id + ? { ...plan, id: initPlan.id, name: initPlan.name, canvasStatus: initPlan.canvasStatus, isCurrent: plan.id === newCurrentId } + : { ...plan, isCurrent: plan.id === newCurrentId } + }), + ) + } + }) + }, + denyFn: () => { + setPlans((plans) => + plans.map((plan) => { + return { ...plan, isCurrent: plan.id === newCurrentId } + }), + ) + }, + }) + } else { + setPlans((plans) => + plans.map((plan) => { + return { ...plan, isCurrent: plan.id === newCurrentId } + }), + ) + } } } useEffect(() => { - setCurrentCanvasPlan([...initCanvasPlans, ...addCanvasPlans].find((plan) => plan.isCurrent) || null) - }, [initCanvasPlans, addCanvasPlans]) + setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null) + }, [plans]) const handleDeletePlan = (e, id) => { e.stopPropagation() // 이벤트 버블링 방지 @@ -48,20 +77,21 @@ export default function CanvasLayout() { delCanvasById(id) .then((res) => { swalFire({ text: getMessage('common.message.delete') }) - console.log('[DELETE] canvas-statuses res :::::::: %o', res) + // console.log('[DELETE] canvas-statuses res :::::::: %o', res) setInitCanvasPlans((initCanvasPlans) => initCanvasPlans.filter((plan) => plan.id !== id)) + setPlans((plans) => plans.filter((plan) => plan.id !== id)) }) .catch((error) => { swalFire({ text: error.message, icon: 'error' }) - console.error('[DELETE] canvas-statuses res error :::::::: %o', error) + // console.error('[DELETE] canvas-statuses res error :::::::: %o', error) }) } else { - setAddCanvasPlans(addCanvasPlans.filter((plan) => plan.id !== id)) + setPlans(plans.filter((plan) => plan.id !== id)) swalFire({ text: getMessage('common.message.delete') }) } // 삭제 후 last 데이터에 포커싱 - const lastPlan = [...initCanvasPlans, ...addCanvasPlans].filter((plan) => plan.id !== id).at(-1) + const lastPlan = plans.filter((plan) => plan.id !== id).at(-1) if (!lastPlan) { setPlanNum(0) setCurrentCanvasPlan(null) @@ -71,7 +101,7 @@ export default function CanvasLayout() { } const addNewPlan = () => { - setAddCanvasPlans([...addCanvasPlans, { id: planNum, name: `Plan ${planNum + 1}`, objectNo: `${objectNo}` }]) + setPlans([...plans, { id: planNum, name: `Plan ${planNum + 1}`, objectNo: `${objectNo}` }]) handleCurrentPlan(planNum) setPlanNum(planNum + 1) } @@ -81,6 +111,7 @@ export default function CanvasLayout() { console.log('canvas 목록 ', res) if (res.length > 0) { setInitCanvasPlans(res) + setPlans(res) handleCurrentPlan(res.at(-1).id) // last 데이터에 포커싱 setPlanNum(res.length) } else { @@ -93,7 +124,7 @@ export default function CanvasLayout() {
- {[...initCanvasPlans, ...addCanvasPlans].map((plan) => ( + {plans.map((plan) => (
- plan.isCurrent === true)} /> + plan.isCurrent === true)} />
) } diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index c719ba24..e861f9f8 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -6,7 +6,7 @@ import { useSwal } from '@/hooks/useSwal' export function usePlan() { const [canvas, setCanvas] = useRecoilState(canvasState) - const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) + const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) const { swalFire } = useSwal() const { getMessage } = useMessage() @@ -70,6 +70,24 @@ export function usePlan() { // }, 1000) } + /** + * 실시간 캔버스 상태와 DB에 저장된 캔버스 상태를 비교하여 수정 여부를 판단 + */ + const checkModifiedCanvasPlan = () => { + removeMouseLines() + const canvasStr = addCanvas() + const canvasStatus = dbToCanvasFormat(canvasToDbFormat(canvasStr)) + if (JSON.parse(canvasStr).objects.length === 0 && currentCanvasPlan.canvasStatus === undefined) { + // 빈 캔버스 + return false + } else if (canvasStatus === currentCanvasPlan.canvasStatus) { + // 변경사항 없는 캔버스 + return false + } else { + return true + } + } + /** * DB에 저장된 데이터를 canvas에서 사용할 수 있도록 포맷화 */ @@ -106,14 +124,14 @@ export function usePlan() { await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData }) .then((res) => { swalFire({ text: getMessage('common.message.save') }) - console.log('[PUT] canvas-statuses res :::::::: %o', res) + // console.log('[PUT] canvas-statuses res :::::::: %o', res) setInitCanvasPlans((initCanvasPlans) => initCanvasPlans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)), ) }) .catch((error) => { swalFire({ text: error.message, icon: 'error' }) - console.error('[PUT] canvas-statuses error :::::::: %o', error) + // console.error('[PUT] canvas-statuses error :::::::: %o', error) }) } else { // canvas 신규 등록 @@ -127,11 +145,15 @@ export function usePlan() { await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData }) .then((res) => { swalFire({ text: getMessage('common.message.save') }) - console.log('[POST] canvas-statuses response :::::::: %o', res) + setInitCanvasPlans([ + ...initCanvasPlans, + { id: res.data, name: currentCanvasPlan.objectNo + '-' + res.data, userId: userId, canvasStatus: canvasStatus, isNew: currentCanvasPlan.id }, + ]) + // console.log('[POST] canvas-statuses response :::::::: %o', res) }) .catch((error) => { swalFire({ text: error.message, icon: 'error' }) - console.error('[POST] canvas-statuses res error :::::::: %o', error) + // console.error('[POST] canvas-statuses res error :::::::: %o', error) }) } } @@ -170,6 +192,7 @@ export function usePlan() { removeMouseLines, saveCanvas, addCanvas, + checkModifiedCanvasPlan, getCanvasByObjectNo, delCanvasById, } From 8d25b6176f583fc9c176df51003426134913292d Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 14:58:17 +0900 Subject: [PATCH 050/152] =?UTF-8?q?=F0=9F=9A=A8chore:=20Sync=20Sass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/styles/_contents.scss | 1879 +++++++++++++++++++++---------------- src/styles/_modal.scss | 117 +++ src/styles/_reset.scss | 1359 +++++++++++++++------------ src/styles/_table.scss | 354 +++---- 4 files changed, 2153 insertions(+), 1556 deletions(-) diff --git a/src/styles/_contents.scss b/src/styles/_contents.scss index 3d503b0b..7a357be7 100644 --- a/src/styles/_contents.scss +++ b/src/styles/_contents.scss @@ -1,845 +1,1140 @@ // CanvasPage -.canvas-wrap{ - height: calc(100vh - 47px); - display: flex; - flex-direction: column; - .canvas-content{ - flex: 1 1 auto; - .canvas-layout{ - height: 100%; - } +.canvas-wrap { + height: calc(100vh - 47px); + display: flex; + flex-direction: column; + + .canvas-content { + flex: 1 1 auto; + + .canvas-layout { + height: 100%; } - &.sub-wrap{ - overflow: hidden; - .canvas-content{ - height: calc(100% - 47px); - } + } + + &.sub-wrap { + overflow: hidden; + + .canvas-content { + height: calc(100% - 47px); } + } } + // CanvasMenu -.canvas-menu-wrap{ +.canvas-menu-wrap { + position: relative; + display: block; + width: 100%; + padding-bottom: 0; + background-color: #383838; + transition: padding .17s ease-in-out; + + .canvas-menu-inner { position: relative; - display: block; - width: 100%; - padding-bottom: 0; - background-color: #383838; - transition: padding .17s ease-in-out; - .canvas-menu-inner{ - position: relative; - display: flex; - align-items: center; - padding: 0 40px 0 20px; - background-color: #2C2C2C; - z-index: 999; - .canvas-menu-list{ - display: flex; - align-items: center; - height: 100%; - .canvas-menu-item{ - display: flex; - align-items: center; - height: 100%; - button{ - display: flex; - align-items: center; - font-size: 12px; - height: 100%; - color: #fff; - font-weight: 600; - padding: 15px 20px; - opacity: 0.55; - transition: all .17s ease-in-out; - .menu-icon{ - display: block; - width: 16px; - height: 16px; - background-repeat: no-repeat; - background-position: center; - background-size: cover; - margin-right: 10px; - &.con00{background-image: url(/static/images/canvas/menu_icon00.svg);} - &.con01{background-image: url(/static/images/canvas/menu_icon01.svg);} - &.con02{background-image: url(/static/images/canvas/menu_icon02.svg);} - &.con03{background-image: url(/static/images/canvas/menu_icon03.svg);} - &.con04{background-image: url(/static/images/canvas/menu_icon04.svg);} - &.con05{background-image: url(/static/images/canvas/menu_icon05.svg);} - &.con06{background-image: url(/static/images/canvas/menu_icon06.svg);} - } - } - &.active{ - background-color: #383838; - button{ - opacity: 1; - } - } - } - } - .canvas-side-btn-wrap{ - display: flex; - align-items: center; - margin-left: auto; - .select-box{ - width: 124px; - margin-right: 5px; - > div{ - width: 100%; - } - } - .btn-from{ - display: flex; - align-items: center; - gap: 5px; - button{ - display: block; - width: 30px; - height: 30px; - border-radius: 2px; - background-color: #3D3D3D; - background-position: center; - background-repeat: no-repeat; - background-size: 15px 15px; - transition: all .17s ease-in-out; - &.btn01{background-image: url(../../public/static/images/canvas/side_icon03.svg);} - &.btn02{background-image: url(../../public/static/images/canvas/side_icon02.svg);} - &.btn03{background-image: url(../../public/static/images/canvas/side_icon01.svg);} - &.btn04{background-image: url(../../public/static/images/canvas/side_icon04.svg);} - &.btn05{background-image: url(../../public/static/images/canvas/side_icon05.svg);} - &.btn06{background-image: url(../../public/static/images/canvas/side_icon06.svg);} - &.btn07{background-image: url(../../public/static/images/canvas/side_icon07.svg);} - &.btn08{background-image: url(../../public/static/images/canvas/side_icon08.svg);} - &.btn09{background-image: url(../../public/static/images/canvas/side_icon09.svg);} - &:hover{ - background-color: #1083E3; - } - &.active{ - background-color: #1083E3; - } - } - } - .ico-btn-from{ - display: flex; - align-items: center; - gap: 5px; - button{ - .ico{ - display: block; - width: 15px; - height: 15px; - background-repeat: no-repeat; - background-position: center; - background-size: contain; - &.ico01{background-image: url(../../public/static/images/canvas/ico-flx01.svg);} - &.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);} - } - .name{ - font-size: 12px; - color: #fff; - } - } - &.form06{ - .name{ - font-size: 13px; - } - } - } - .vertical-horizontal{ - display: flex; - min-width: 170px; - height: 28px; - margin: 0 5px; - border-radius: 2px; - background: #373737; - line-height: 28px; - overflow: hidden; - span{ - padding: 0 10px; - font-size: 13px; - color: #fff; - } - button{ - margin-left: auto; - height: 100%; - background-color: #4B4B4B; - font-size: 13px; - font-weight: 400; - color: #fff; - padding: 0 7.5px; - transition: all .17s ease-in-out; - } - &.on{ - button{ - background-color: #1083E3; - } - } - } - .size-control{ - display: flex; - align-items: center; - justify-content: center; - gap: 10px; - background-color: #3D3D3D; - border-radius: 2px; - width: 100px; - height: 30px; - margin: 0 5px; - span{ - font-size: 13px; - color: #fff; - } - .control-btn{ - display: block; - width: 12px; - height: 12px; - background-repeat: no-repeat; - background-size: cover; - background-position: center; - &.minus{ - background-image: url(../../public/static/images/canvas/minus.svg); - } - &.plus{ - background-image: url(../../public/static/images/canvas/plus.svg); - } - } - } - } - } - .canvas-depth2-wrap{ - position: absolute; - top: -100%; - left: 0; - background-color: #383838; - width: 100%; - height: 50px; - transition: all .17s ease-in-out; - .canvas-depth2-inner{ - display: flex; - align-items: center; - padding: 0 40px; - height: 100%; - .canvas-depth2-list{ - display: flex; - align-items: center ; - height: 100%; - .canvas-depth2-item{ - display: flex; - align-items: center; - margin-right: 26px; - height: 100%; - button{ - position: relative; - opacity: 0.55; - color: #fff; - font-size: 12px; - font-weight: normal; - height: 100%; - padding-right: 12px; - } - &.active{ - button{ - opacity: 1; - font-weight: 600; - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 5px; - height: 8px; - background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center; - } - } - } - } - } - .canvas-depth2-btn-list{ - display: flex; - align-items: center; - margin-left: auto; - height: 100%; - .depth2-btn-box{ - display: flex; - align-items: center; - margin-right: 34px; - height: 100%; - transition: all .17s ease-in-out; - button{ - position: relative; - font-size: 12px; - font-weight: 400; - height: 100%; - color: #fff; - padding-right: 12px; - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 5px; - height: 8px; - background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center; - } - } - &:last-child{ - margin-right: 0; - } - &.mouse{ - opacity: 0.55; - } - } - } - } - &.active{ - top: 47px; - } - } - &.active{ - padding-bottom: 50px; - } -} - -// canvas-layout -.canvas-layout{ - .canvas-page-list{ - display: flex; - background-color: #1C1C1C; - border-top: 1px solid #000; - width: 100%; - .canvas-plane-wrap{ - display: flex; - align-items: center; - max-width: calc(100% - 45px); - .canvas-page-box{ - display: flex; - align-items: center; - background-color: #1c1c1c; - padding: 9.6px 20px; - border-right:1px solid #000; - min-width: 0; - transition: all .17s ease-in-out; - span{ - display: flex; - align-items: center; - width: 100%; - font-size: 12px; - font-family: 'Pretendard', sans-serif; - color: #AAA; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - } - .close{ - flex: none; - display: block; - width: 7px; - height: 8px; - margin-left: 15px; - background: url(../../public/static/images/canvas/plan_close_gray.svg)no-repeat center; - background-size: cover; - } - &.on{ - background-color: #fff; - span{ - font-weight: 600; - color: #101010; - } - .close{ - background: url(../../public/static/images/canvas/plan_close_black.svg)no-repeat center; - } - &:hover{ - background-color: #fff; - } - } - &:hover{ - background-color: #000; - } - } - } - .plane-add{ - display: flex; - align-items: center; - justify-content: center; - width: 45px; - padding: 13.5px 0; - background-color: #1C1C1C; - border-right: 1px solid #000; - transition: all .17s ease-in-out; - span{ - display: block; - width: 9px; - height: 9px; - background: url(../../public/static/images/canvas/plane_add.svg)no-repeat center; - background-size: cover; - } - &:hover{ - background-color: #000; - } - } - } -} - -.canvas-frame{ - position: relative; - height: calc(100% - 36.5px); - background-color: #fff; - canvas{ - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - } -} - -// sub-page -.sub-header{ - position: fixed; - top: 46px; - left: 0; - width: 100%; - height: 46px; - border-bottom: 1px solid #000; - background: #2C2C2C; + display: flex; + align-items: center; + padding: 0 40px 0 20px; + background-color: #2C2C2C; z-index: 999; - .sub-header-inner{ + + .canvas-menu-list { + display: flex; + align-items: center; + height: 100%; + + .canvas-menu-item { display: flex; align-items: center; height: 100%; - padding: 0 100px; - .sub-header-title-wrap{ - display: flex; - align-items: center; - .title-item{ - position: relative; - padding: 0 24px; - a{ - display: flex; - align-items: center; - .icon{ - width: 22px; - height: 22px; - margin-right: 8px; - background-repeat: no-repeat; - background-position: center; - background-size: cover; - &.drawing{background-image: url(../../public/static/images/main/drawing_icon.svg);} - } - } - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 1px; - height: 16px; - background-color: #D9D9D9; - } - &:first-child{ - padding-left: 0; - } - &:last-child{ - padding-right: 0; - &:after{ - display: none; - } - } - } - } - .sub-header-title{ - font-size: 16px; - color: #fff; - font-weight: 600; - } - .sub-header-location{ - margin-left: auto; - display: flex; - align-items: center; - .location-item{ - position: relative; - display: flex; - align-items: center; - padding: 0 10px; - span{ - display: flex; - font-size: 12px; - color: #AAA; - font-weight: normal; - cursor: default; - } - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 4px; - height: 6px; - background: url(../../public/static/images/main/loaction_arr.svg)no-repeat center; - } - &:first-child{ - padding-left: 0; - } - &:last-child{ - padding-right: 0; - span{ - color: #fff; - } - &:after{ - display: none; - } - } - } - } - } -} -// sub content -.sub-content{ - padding-top: 46px; - .sub-content-inner{ - max-width: 1720px; - margin: 0 auto; - padding-top: 20px; - .sub-content-box{ - margin-bottom: 20px; - &:last-child{ - margin-bottom: 0; + button { + display: flex; + align-items: center; + font-size: 12px; + height: 100%; + color: #fff; + font-weight: 600; + padding: 15px 20px; + opacity: 0.55; + transition: all .17s ease-in-out; + + .menu-icon { + display: block; + width: 16px; + height: 16px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; + margin-right: 10px; + + &.con00 { + background-image: url(/static/images/canvas/menu_icon00.svg); } + + &.con01 { + background-image: url(/static/images/canvas/menu_icon01.svg); + } + + &.con02 { + background-image: url(/static/images/canvas/menu_icon02.svg); + } + + &.con03 { + background-image: url(/static/images/canvas/menu_icon03.svg); + } + + &.con04 { + background-image: url(/static/images/canvas/menu_icon04.svg); + } + + &.con05 { + background-image: url(/static/images/canvas/menu_icon05.svg); + } + + &.con06 { + background-image: url(/static/images/canvas/menu_icon06.svg); + } + } } - } - &.estimate{ - display: flex; - flex-direction: column; - height: calc(100% - 36.5px); - overflow-y: auto; - padding-top: 0; - .sub-content-inner{ - flex: 1; - width: 100%; + + &.active { + background-color: #383838; + + button { + opacity: 1; + } } + } } -} -.sub-table-box{ - padding: 20px; - border-radius: 6px; - border: 1px solid #E9EAED; - background: #FFF; - box-shadow: 0px 3px 30px 0px rgba(0, 0, 0, 0.02); - .table-box-title-wrap{ + + .canvas-side-btn-wrap { + display: flex; + align-items: center; + margin-left: auto; + + .select-box { + width: 124px; + margin-right: 5px; + + > div { + width: 100%; + } + } + + .btn-from { display: flex; align-items: center; - margin-bottom: 15px; - .title-wrap{ - display: flex; - align-items: center; - h3{ - display: block; - font-size: 15px; - color: #101010; - font-weight: 600; - margin-right: 14px; - } - .info-wrap{ - display: flex; - align-items: center; - li{ - position: relative; - padding: 0 6px; - font-size: 12px; - color: #101010; - font-weight: normal; - span{ - font-weight: 600; - &.red{ - color: #E23D70; - } - } - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 1px; - height: 11px; - background-color: #D9D9D9; - } - &:first-child{padding-left: 0;} - &:last-child{padding-right: 0;&::after{display: none;}} - } - } + gap: 5px; + + button { + display: block; + width: 30px; + height: 30px; + border-radius: 2px; + background-color: #3D3D3D; + background-position: center; + background-repeat: no-repeat; + background-size: 15px 15px; + transition: all .17s ease-in-out; + + &.btn01 { + background-image: url(../../public/static/images/canvas/side_icon03.svg); + } + + &.btn02 { + background-image: url(../../public/static/images/canvas/side_icon02.svg); + } + + &.btn03 { + background-image: url(../../public/static/images/canvas/side_icon01.svg); + } + + &.btn04 { + background-image: url(../../public/static/images/canvas/side_icon04.svg); + } + + &.btn05 { + background-image: url(../../public/static/images/canvas/side_icon05.svg); + } + + &.btn06 { + background-image: url(../../public/static/images/canvas/side_icon06.svg); + } + + &.btn07 { + background-image: url(../../public/static/images/canvas/side_icon07.svg); + } + + &.btn08 { + background-image: url(../../public/static/images/canvas/side_icon08.svg); + } + + &.btn09 { + background-image: url(../../public/static/images/canvas/side_icon09.svg); + } + + &:hover { + background-color: #1083E3; + } + + &.active { + background-color: #1083E3; + } } - } - .left-unit-box{ - margin-left: auto; + } + + .ico-btn-from { display: flex; align-items: center; - } - .promise-gudie{ - display: block; - font-size: 13px; - font-weight: 700; - color: #101010; - margin-bottom: 20px; - } - .important{ - color: #f00; - } - .sub-table-footer{ + gap: 5px; + + button { + .ico { + display: block; + width: 15px; + height: 15px; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + + &.ico01 { + background-image: url(../../public/static/images/canvas/ico-flx01.svg); + } + + &.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); + } + } + + .name { + font-size: 12px; + color: #fff; + } + } + + &.form06 { + .name { + font-size: 13px; + } + } + } + + .vertical-horizontal { + display: flex; + min-width: 170px; + height: 28px; + margin: 0 5px; + border-radius: 2px; + background: #373737; + line-height: 28px; + overflow: hidden; + + span { + padding: 0 10px; + font-size: 13px; + color: #fff; + } + + button { + margin-left: auto; + height: 100%; + background-color: #4B4B4B; + font-size: 13px; + font-weight: 400; + color: #fff; + padding: 0 7.5px; + transition: all .17s ease-in-out; + } + + &.on { + button { + background-color: #1083E3; + } + } + } + + .size-control { display: flex; align-items: center; justify-content: center; - margin-top: 20px; - } - .pagination-wrap{ - margin-top: 24px; - } -} + gap: 10px; + background-color: #3D3D3D; + border-radius: 2px; + width: 100px; + height: 30px; + margin: 0 5px; -.infomation-box-wrap{ - display: flex; - align-items: center; - gap: 10px; - .sub-table-box{ - flex: 1 ; - } - .info-title{ - font-size: 14px; - font-weight: 500; - color: #344356; - margin-bottom: 10px; - } - .info-inner{ - position: relative; - font-size: 13px; - color: #344356; - .copy-ico{ - position: absolute; - bottom: 0; - right: 0; - width: 16px; - height: 16px; - background: url(../../public/static/images/sub/copy_ico.svg)no-repeat center; - background-size: cover; + span { + font-size: 13px; + color: #fff; } - } -} -// 견적서 -.estimate-list-wrap{ - display: flex; - align-items: center; - margin-bottom: 10px; - .estimate-box{ - flex: 1 ; + .control-btn { + display: block; + width: 12px; + height: 12px; + background-repeat: no-repeat; + background-size: cover; + background-position: center; + + &.minus { + background-image: url(../../public/static/images/canvas/minus.svg); + } + + &.plus { + background-image: url(../../public/static/images/canvas/plus.svg); + } + } + } + } + } + + .canvas-depth2-wrap { + position: absolute; + top: -100%; + left: 0; + background-color: #383838; + width: 100%; + height: 50px; + transition: all .17s ease-in-out; + + .canvas-depth2-inner { + display: flex; + align-items: center; + padding: 0 40px; + height: 100%; + + .canvas-depth2-list { display: flex; align-items: center; - &:last-child{ - flex: none; - min-width: 220px; - } - .estimate-tit{ - width: 105px; - height: 30px; - line-height: 30px; - background-color: #F4F4F7; - border-radius: 100px; - text-align: center; - font-size: 13px; - font-weight: 500; - color: #344356; - } - .estimate-name{ - font-size: 13px; - color: #344356; - margin-left: 14px; - font-weight: 400; - } - } - &:last-child{ - margin-bottom: 0; - } -} - -// file drag box -.drag-file-box{ - padding: 10px; - .btn-area{ - padding-bottom: 15px; - border-bottom: 1px solid #ECF0F4; - } - .drag-file-area{ - position: relative; - margin-top: 15px; - p{ - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - font-size: 13px; - color: #ccc; - font-weight: 400; - cursor: default; - } - } - .file-list{ - .file-item{ - margin-bottom: 15px; - span{ - position: relative; - font-size: 13px; - color: #45576F; - font-weight: 400; - white-space: nowrap; - padding-right: 55px; - button{ - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 15px; - height: 15px; - background: url(../../public/static/images/sub/file_delete.svg)no-repeat center; - background-size: cover; - } - } - &:last-child{ - margin-bottom: 0; - } - } - } -} - -// 발전시물레이션 -.chart-wrap{ - display: flex; - gap: 20px; - width: 100%; - .sub-table-box{ height: 100%; - } - .chart-inner{ - flex: 1; - .chart-box{ - margin-bottom: 30px; - } - } - .chart-table-wrap{ - display: flex; - flex-direction: column; - flex: none; - width: 650px; - .sub-table-box{ - flex: 1; - &:first-child{ - margin-bottom: 20px; - } - } - } -} -.chart-month-table{ - table{ - table-layout: fixed; - border-collapse:collapse; - border: 1px solid #ECF0F4; - border-radius: 4px; - thead{ - th{ - padding: 4.5px 0; - border-bottom: 1px solid #ECF0F4; - text-align: center; - font-size: 13px; - color: #45576F; - font-weight: 500; - background-color: #F8F9FA; - } - } - tbody{ - td{ - font-size: 13px; - color: #45576F; - text-align: center; - padding: 4.5px 0; - } - } - } -} + .canvas-depth2-item { + display: flex; + align-items: center; + margin-right: 26px; + height: 100%; -.simulation-guide-wrap{ - display: flex; - padding: 20px; - .simulation-tit-wrap{ - padding-right: 40px; - border-right: 1px solid #EEEEEE; - span{ - display: block; + button { position: relative; - padding-left: 60px; - font-size: 15px; - color: #14324F; - font-weight: 600; - &::before{ + opacity: 0.55; + color: #fff; + font-size: 12px; + font-weight: normal; + height: 100%; + padding-right: 12px; + } + + &.active { + button { + opacity: 1; + font-weight: 600; + + &:after { content: ''; position: absolute; top: 50%; - left: 0; + right: 0; transform: translateY(-50%); - width: 40px; - height: 40px; - background: url(../../public/static/images/sub/simulation_guide.svg)no-repeat center; - background-size: cover; + width: 5px; + height: 8px; + background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center; + } } + } } - } - .simulation-guide-box{ - padding-left: 40px; - dl{ - margin-bottom: 25px; - dt{ - font-size: 13px; - color: #101010; - font-weight: 600; - margin-bottom: 5px; - } - dd{ - font-size: 12px; - color: #45576F; - font-weight: 400; - line-height: 24px; - } - &:last-child{ - margin-bottom: 0; + } + + .canvas-depth2-btn-list { + display: flex; + align-items: center; + margin-left: auto; + height: 100%; + + .depth2-btn-box { + display: flex; + align-items: center; + margin-right: 34px; + height: 100%; + transition: all .17s ease-in-out; + + button { + position: relative; + font-size: 12px; + font-weight: 400; + height: 100%; + color: #fff; + padding-right: 12px; + + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 5px; + height: 8px; + background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center; } + } + + &:last-child { + margin-right: 0; + } + + &.mouse { + opacity: 0.55; + } } + } } + + &.active { + top: 47px; + } + } + + &.active { + padding-bottom: 50px; + } } -.module-total{ +// canvas-layout +.canvas-layout { + .canvas-page-list { + display: flex; + background-color: #1C1C1C; + border-top: 1px solid #000; + width: 100%; + + .canvas-plane-wrap { + display: flex; + align-items: center; + max-width: calc(100% - 45px); + + .canvas-page-box { + display: flex; + align-items: center; + background-color: #1c1c1c; + padding: 9.6px 20px; + border-right: 1px solid #000; + min-width: 0; + transition: all .17s ease-in-out; + + span { + display: flex; + align-items: center; + width: 100%; + font-size: 12px; + font-family: 'Pretendard', sans-serif; + color: #AAA; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + + .close { + flex: none; + display: block; + width: 7px; + height: 8px; + margin-left: 15px; + background: url(../../public/static/images/canvas/plan_close_gray.svg) no-repeat center; + background-size: cover; + } + + &.on { + background-color: #fff; + + span { + font-weight: 600; + color: #101010; + } + + .close { + background: url(../../public/static/images/canvas/plan_close_black.svg) no-repeat center; + } + + &:hover { + background-color: #fff; + } + } + + &:hover { + background-color: #000; + } + } + } + + .plane-add { + display: flex; + align-items: center; + justify-content: center; + width: 45px; + padding: 13.5px 0; + background-color: #1C1C1C; + border-right: 1px solid #000; + transition: all .17s ease-in-out; + + span { + display: block; + width: 9px; + height: 9px; + background: url(../../public/static/images/canvas/plane_add.svg) no-repeat center; + background-size: cover; + } + + &:hover { + background-color: #000; + } + } + } +} + +.canvas-frame { + position: relative; + height: calc(100% - 36.5px); + background-color: #fff; + + canvas { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } +} + +// sub-page +.sub-header { + position: fixed; + top: 46px; + left: 0; + width: 100%; + height: 46px; + border-bottom: 1px solid #000; + background: #2C2C2C; + z-index: 999; + + .sub-header-inner { display: flex; align-items: center; - background-color: #F8F9FA; - padding: 9px 0; - margin-right: 4px; + height: 100%; + padding: 0 100px; + + .sub-header-title-wrap { + display: flex; + align-items: center; + + .title-item { + position: relative; + padding: 0 24px; + + a { + display: flex; + align-items: center; + + .icon { + width: 22px; + height: 22px; + margin-right: 8px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; + + &.drawing { + background-image: url(../../public/static/images/main/drawing_icon.svg); + } + } + } + + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 1px; + height: 16px; + background-color: #D9D9D9; + } + + &:first-child { + padding-left: 0; + } + + &:last-child { + padding-right: 0; + + &:after { + display: none; + } + } + } + } + + .sub-header-title { + font-size: 16px; + color: #fff; + font-weight: 600; + } + + .sub-header-location { + margin-left: auto; + display: flex; + align-items: center; + + .location-item { + position: relative; + display: flex; + align-items: center; + padding: 0 10px; + + span { + display: flex; + font-size: 12px; + color: #AAA; + font-weight: normal; + cursor: default; + } + + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 4px; + height: 6px; + background: url(../../public/static/images/main/loaction_arr.svg) no-repeat center; + } + + &:first-child { + padding-left: 0; + } + + &:last-child { + padding-right: 0; + + span { + color: #fff; + } + + &:after { + display: none; + } + } + } + } + } +} + +// sub content +.sub-content { + padding-top: 46px; + + .sub-content-inner { + max-width: 1720px; + margin: 0 auto; + padding-top: 20px; + + .sub-content-box { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } + } + + &.estimate { + display: flex; + flex-direction: column; + height: calc(100% - 36.5px); + overflow-y: auto; + padding-top: 0; + + .sub-content-inner { + flex: 1; + width: 100%; + } + } +} + +.sub-table-box { + padding: 20px; + border-radius: 6px; + border: 1px solid #E9EAED; + background: #FFF; + box-shadow: 0px 3px 30px 0px rgba(0, 0, 0, 0.02); + + .table-box-title-wrap { + display: flex; + align-items: center; + margin-bottom: 15px; + + .title-wrap { + display: flex; + align-items: center; + + h3 { + display: block; + font-size: 15px; + color: #101010; + font-weight: 600; + margin-right: 14px; + } + + .info-wrap { + display: flex; + align-items: center; + + li { + position: relative; + padding: 0 6px; + font-size: 12px; + color: #101010; + font-weight: normal; + + span { + font-weight: 600; + + &.red { + color: #E23D70; + } + } + + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 1px; + height: 11px; + background-color: #D9D9D9; + } + + &:first-child { + padding-left: 0; + } + + &:last-child { + padding-right: 0; + + &::after { + display: none; + } + } + } + } + } + } + + .left-unit-box { + margin-left: auto; + display: flex; + align-items: center; + } + + .promise-gudie { + display: block; + font-size: 13px; + font-weight: 700; + color: #101010; + margin-bottom: 20px; + } + + .important { + color: #f00; + } + + .sub-table-footer { + display: flex; + align-items: center; + justify-content: center; + margin-top: 20px; + } + + .pagination-wrap { + margin-top: 24px; + } +} + +.infomation-box-wrap { + display: flex; + align-items: center; + gap: 10px; + + .sub-table-box { + flex: 1; + } + + .info-title { + font-size: 14px; + font-weight: 500; + color: #344356; + margin-bottom: 10px; + } + + .info-inner { + position: relative; + font-size: 13px; + color: #344356; + + .copy-ico { + position: absolute; + bottom: 0; + right: 0; + width: 16px; + height: 16px; + background: url(../../public/static/images/sub/copy_ico.svg) no-repeat center; + background-size: cover; + } + } +} + +// 견적서 +.estimate-list-wrap { + display: flex; + align-items: center; + margin-bottom: 10px; + + .estimate-box { + flex: 1; + display: flex; + align-items: center; + + &:last-child { + flex: none; + min-width: 220px; + } + + .estimate-tit { + width: 105px; + height: 30px; + line-height: 30px; + background-color: #F4F4F7; + border-radius: 100px; + text-align: center; + font-size: 13px; + font-weight: 500; + color: #344356; + } + + .estimate-name { + font-size: 13px; + color: #344356; + margin-left: 14px; + font-weight: 400; + } + } + + &:last-child { + margin-bottom: 0; + } +} + +// file drag box +.drag-file-box { + padding: 10px; + + .btn-area { + padding-bottom: 15px; + border-bottom: 1px solid #ECF0F4; + } + + .drag-file-area { + position: relative; + margin-top: 15px; + + p { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 13px; + color: #ccc; + font-weight: 400; + cursor: default; + } + } + + .file-list { + .file-item { + margin-bottom: 15px; + + span { + position: relative; + font-size: 13px; + color: #45576F; + font-weight: 400; + white-space: nowrap; + padding-right: 55px; + + button { + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 15px; + height: 15px; + background: url(../../public/static/images/sub/file_delete.svg) no-repeat center; + background-size: cover; + } + } + + &:last-child { + margin-bottom: 0; + } + } + } +} + +// 발전시물레이션 +.chart-wrap { + display: flex; + gap: 20px; + width: 100%; + + .sub-table-box { + height: 100%; + } + + .chart-inner { + flex: 1; + + .chart-box { + margin-bottom: 30px; + } + } + + .chart-table-wrap { + display: flex; + flex-direction: column; + flex: none; + width: 650px; + + .sub-table-box { + flex: 1; + + &:first-child { + margin-bottom: 20px; + } + } + } +} + +.chart-month-table { + table { + table-layout: fixed; + border-collapse: collapse; border: 1px solid #ECF0F4; - border-top: none; - .total-title{ - flex: 1; + border-radius: 4px; + + thead { + th { + padding: 4.5px 0; + border-bottom: 1px solid #ECF0F4; text-align: center; font-size: 13px; - color: #344356; + color: #45576F; font-weight: 500; + background-color: #F8F9FA; + } } - .total-num{ - flex: none; - width: 121px; + + tbody { + td { + font-size: 13px; + color: #45576F; text-align: center; - font-size: 15px; - color: #344356; - font-weight: 500; + padding: 4.5px 0; + } } + } +} + +.simulation-guide-wrap { + display: flex; + padding: 20px; + + .simulation-tit-wrap { + padding-right: 40px; + border-right: 1px solid #EEEEEE; + + span { + display: block; + position: relative; + padding-left: 60px; + font-size: 15px; + color: #14324F; + font-weight: 600; + + &::before { + content: ''; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + width: 40px; + height: 40px; + background: url(../../public/static/images/sub/simulation_guide.svg) no-repeat center; + background-size: cover; + } + } + } + + .simulation-guide-box { + padding-left: 40px; + + dl { + margin-bottom: 25px; + + dt { + font-size: 13px; + color: #101010; + font-weight: 600; + margin-bottom: 5px; + } + + dd { + font-size: 12px; + color: #45576F; + font-weight: 400; + line-height: 24px; + } + + &:last-child { + margin-bottom: 0; + } + } + } +} + +.module-total { + display: flex; + align-items: center; + background-color: #F8F9FA; + padding: 9px 0; + margin-right: 4px; + border: 1px solid #ECF0F4; + border-top: none; + + .total-title { + flex: 1; + text-align: center; + font-size: 13px; + color: #344356; + font-weight: 500; + } + + .total-num { + flex: none; + width: 121px; + text-align: center; + font-size: 15px; + color: #344356; + font-weight: 500; + } +} + +// 패널 배치 집계 + +.penal-wrap { + position: fixed; + top: 200px; + left: 50px; + z-index: 999999; + width: 237px; + height: 40px; + line-height: 40px; + background-color: #fff; + border: 1px solid #DFDFDF; + padding: 0 34px 0 10px; + border-radius: 2px; + box-shadow: 0px 7px 14px 0px rgba(0, 0, 0, 0.05); + cursor: pointer; + + &::before { + content: ''; + position: absolute; + top: 50%; + right: 12px; + transform: translateY(-50%); + width: 10px; + height: 6px; + background: url(../../public/static/images/canvas/penal_arr.svg) no-repeat center; + background-size: cover; + } + + h2 { + font-size: 12px; + font-weight: 500; + color: #3D3D3D; + } + + .penal-table-wrap { + display: none; + position: absolute; + top: 100%; + left: -1px; + min-width: calc(100% + 2px); + background-color: #3D3D3D; + border: 1px solid #3D3D3D; + padding: 20px; + + .penal-table { + table-layout: fixed; + border-collapse: collapse; + + thead { + th { + text-align: center; + background-color: rgba(255, 255, 255, 0.05); + font-size: 12px; + font-weight: 500; + color: #fff; + border: 1px solid #505050; + } + } + + tbody { + td { + font-size: 12px; + color: #fff; + font-weight: 400; + text-align: center; + padding: 0 10px; + border: 1px solid #505050; + } + } + } + } + + &.act { + border: 1px solid #3D3D3D; + background-color: #3D3D3D; + + h2 { + color: #fff; + } + + &::before { + background: url(../../public/static/images/canvas/penal_arr_white.svg) no-repeat center; + } + + .penal-table-wrap { + display: block; + } + } } \ No newline at end of file diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss index be8b4185..16ef74e1 100644 --- a/src/styles/_modal.scss +++ b/src/styles/_modal.scss @@ -77,6 +77,10 @@ $alert-color: #101010; width: 640px; } + &.lx-2 { + width: 740px; + } + &.lx { width: 770px; } @@ -783,6 +787,7 @@ $alert-color: #101010; display: table-cell; vertical-align: middle; padding-bottom: 14px; + text-align: left; } .eaves-keraba-td { @@ -1543,3 +1548,115 @@ $alert-color: #101010; } } } + + +// 지붕모듈선택 +.roof-module-tab { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 14px; + + .module-tab-bx { + flex: 1; + height: 34px; + line-height: 31px; + border: 1px solid #484848; + border-radius: 2px; + background-color: transparent; + font-size: 12px; + color: #AAA; + text-align: center; + cursor: default; + transition: all .15s ease-in-out; + + &.act { + background-color: #1083E3; + border: 1px solid #1083E3; + color: #fff; + font-weight: 500; + } + } + + .tab-arr { + display: block; + width: 9px; + height: 14px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; + background-image: url(../../public/static/images/canvas/module_tab_arr.svg); + transition: all .15s ease-in-out; + + &.act { + background-image: url(../../public/static/images/canvas/module_tab_arr_white.svg); + } + } +} + +.roof-module-compas { + margin-bottom: 24px; + + .compas-box-inner { + width: 280px; + height: 253px; + + .circle { + top: 86%; + + &:nth-child(1), + &:nth-child(7), + &:nth-child(13), + &:nth-child(19) { + &::before { + content: ''; + position: absolute; + top: 20px; + left: 50%; + transform: translateX(-50%); + width: 1px; + height: 6px; + background-color: #8B8B8B; + } + } + + i { + top: 32px; + } + + &.act { + i { + color: #8B8B8B; + } + } + } + } +} + +.center-wrap { + display: flex; + flex-direction: column; + align-items: center; + gap: 20px; +} + +.module-table-flex-wrap { + display: flex; + gap: 10px; +} + +.module-table-box { + flex: 1; + background-color: #3D3D3D; + border-radius: 2px; + + .module-table-inneer { + padding: 10px; + + .outline-form { + span { + width: auto; + } + } + } +} \ No newline at end of file diff --git a/src/styles/_reset.scss b/src/styles/_reset.scss index 6d899458..bd76935a 100644 --- a/src/styles/_reset.scss +++ b/src/styles/_reset.scss @@ -1,18 +1,21 @@ * { - -webkit-text-size-adjust:none; - -moz-text-size-adjust:none; - -ms-text-size-adjust:none; - text-size-adjust: none; - box-sizing: content-box + -webkit-text-size-adjust: none; + -moz-text-size-adjust: none; + -ms-text-size-adjust: none; + text-size-adjust: none; + box-sizing: content-box } + *, ::after, ::before { - box-sizing: border-box; + box-sizing: border-box; } -html, body{ - width: 100%; - height: 100%; - font-size: 16px; + +html, body { + width: 100%; + height: 100%; + font-size: 16px; } + html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, @@ -22,693 +25,837 @@ b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, canvas, details, embed, -figure, figcaption, footer, header, hgroup, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font: inherit; - vertical-align: baseline; - font-family: 'Noto Sans JP', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-smooth: never; + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; + font-family: 'Noto Sans JP', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-smooth: never; } + /* HTML5 display-role reset for older browsers */ -article, aside, details, figcaption, figure, +article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { - display: block; + display: block; } + body { - line-height: 1.4; + line-height: 1.4; +} + +body:first-of-type caption { + display: none; } -body:first-of-type caption { display:none;} ol, ul { - list-style: none; -} -blockquote, q { - quotes: none; -} -blockquote:before, blockquote:after, -q:before, q:after { - content: ''; - content: none; -} -table { - width: 100%; - border-collapse: separate; - border-spacing:0; - border:0 none; -} -caption, th, td { - text-align:left; - font-weight: normal; - border:0; + list-style: none; } -a { - cursor:pointer; - color:#000; +blockquote, q { + quotes: none; } + +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} + +table { + width: 100%; + border-collapse: separate; + border-spacing: 0; + border: 0 none; +} + +caption, th, td { + text-align: left; + font-weight: normal; + border: 0; +} + +a { + cursor: pointer; + color: #000; +} + a, a:hover, a:active { - text-decoration:none; - -webkit-tap-highlight-color: transparent; + text-decoration: none; + -webkit-tap-highlight-color: transparent; } + /*form_style*/ input, select, textarea, button, a, label { - -webkit-tap-highlight-color:rgba(0,0,0,0); + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } -button,input[type=text], input[type=button] { - -webkit-appearance: none; - -webkit-border-radius: 0; - -webkit-appearance:none; - appearance: none; - border-radius: 0 + +button, input[type=text], input[type=button] { + -webkit-appearance: none; + -webkit-border-radius: 0; + -webkit-appearance: none; + appearance: none; + border-radius: 0 } + input[type=checkbox], input[type=radio] { - box-sizing: border-box; - padding: 0; + box-sizing: border-box; + padding: 0; } + input, select, button { - border:0 none; - outline:none; - margin:0; + border: 0 none; + outline: none; + margin: 0; } + select { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } + select::-ms-expand { - display: none; + display: none; } + ::-webkit-input-placeholder { - line-height:1; - font-weight:300; - font-size:0.938rem; - letter-spacing:-0.6px; - color:#8b8b8b; + line-height: 1; + font-weight: 300; + font-size: 0.938rem; + letter-spacing: -0.6px; + color: #8b8b8b; } -.log-box ::-webkit-input-placeholder{ - color:#8b8b8b; + +.log-box ::-webkit-input-placeholder { + color: #8b8b8b; } -button{ - background: transparent; - font-family: 'Noto Sans JP', sans-serif; - border: none; - padding: 0; - margin: 0; - line-height: 1.4; - color: inherit; - outline: none; - cursor: pointer; + +button { + background: transparent; + font-family: 'Noto Sans JP', sans-serif; + border: none; + padding: 0; + margin: 0; + line-height: 1.4; + color: inherit; + outline: none; + cursor: pointer; } -.pre{ - font-family: 'Pretendard', sans-serif !important; + +.pre { + font-family: 'Pretendard', sans-serif !important; } // margin -.mt5{margin-top: 5px !important;} -.mt10{margin-top: 10px !important;} -.mt15{margin-top: 15px !important;} -.mb5{margin-bottom: 5px !important;} -.mb10{margin-bottom: 10px !important;} -.mb15{margin-bottom: 15px !important;} -.mr5{margin-right: 5px !important;} -.mr10{margin-right: 10px !important;} -.mr15{margin-right: 15px !important;} -.ml5{margin-left: 5px !important;} -.ml10{margin-left: 10px !important;} -.ml15{margin-left: 15px !important;} - -// button -.btn-frame{ - display: inline-block; - padding: 0 7px; - height: 34px; - line-height: 34px; - border-radius: 2px; - color: #fff; - font-size: 12px; - font-weight: 400; - border: 1px solid #000; - text-align: center; - font-family: 'Pretendard', sans-serif; - transition: all .17s ease-in-out; - cursor: pointer; - &.block{ - width: 100%; - } - &.small{ - font-family: 'Noto Sans JP', sans-serif; - height: 30px; - line-height: 30px; - font-size: 13px; - } - - &.deepgray{ - background-color: #2C2C2C; - border: 1px solid #484848; - } - &.gray{ - background-color: #3C3C3C; - border: 1px solid #545454; - } - &.dark{ - background-color: #1C1C1C; - border: 1px solid #484848; - } - &.modal{ - font-family: 'Noto Sans JP', sans-serif; - background-color: #272727; - border: 1px solid #484848; - color: #aaa; - &:hover{ - background-color: #1083E3; - border: 1px solid #1083E3; - color: #fff; - font-weight: 500; - } - } - &.sub-tab{ - height: 30px; - padding: 0 10px; - line-height: 28px; - font-family: 'Noto Sans JP', sans-serif; - background-color: #2D2D2D; - border: 1px solid #393939; - color: #aaa; - &.act, - &:hover{ - background-color: #414E6C; - border: 1px solid #414E6C; - color: #fff; - font-weight: 500; - } - } - &:hover, - &.act{ - background-color: #1083E3; - border: 1px solid #1083E3; - color: #fff; - font-weight: 500; - } - &.block{ - display: block; - width: 100%; - } - &.ico-flx{ - display: flex; - align-items: center; - .ico{ - margin-right: 10px; - } - &:hover, - &.act{ - font-weight: 400; - } - } +.mt5 { + margin-top: 5px !important; } -.btn-origin{ - display: inline-block; +.mt10 { + margin-top: 10px !important; +} + +.mt15 { + margin-top: 15px !important; +} + +.mb5 { + margin-bottom: 5px !important; +} + +.mb10 { + margin-bottom: 10px !important; +} + +.mb15 { + margin-bottom: 15px !important; +} + +.mr5 { + margin-right: 5px !important; +} + +.mr10 { + margin-right: 10px !important; +} + +.mr15 { + margin-right: 15px !important; +} + +.ml5 { + margin-left: 5px !important; +} + +.ml10 { + margin-left: 10px !important; +} + +.ml15 { + margin-left: 15px !important; +} + +// align +.l { + text-align: left !important; +} + +.r { + text-align: right !important; +} + +.c { + text-align: center !important; +} + + +// button +.btn-frame { + display: inline-block; + padding: 0 7px; + height: 34px; + line-height: 34px; + border-radius: 2px; + color: #fff; + font-size: 12px; + font-weight: 400; + border: 1px solid #000; + text-align: center; + font-family: 'Pretendard', sans-serif; + transition: all .17s ease-in-out; + cursor: pointer; + + &.block { + width: 100%; + } + + &.small { + font-family: 'Noto Sans JP', sans-serif; height: 30px; - padding: 0 14px; - border-radius: 2px; - background-color: #101010; - color: #fff; + line-height: 30px; font-size: 13px; - font-weight: 400; - transition: all .15s ease-in-out; - &.navy{ - background-color: #304961; - &:hover{ - background-color: #1083E3; - } + } + + &.deepgray { + background-color: #2C2C2C; + border: 1px solid #484848; + } + + &.gray { + background-color: #3C3C3C; + border: 1px solid #545454; + } + + &.dark { + background-color: #1C1C1C; + border: 1px solid #484848; + } + + &.modal { + font-family: 'Noto Sans JP', sans-serif; + background-color: #272727; + border: 1px solid #484848; + color: #aaa; + + &:hover { + background-color: #1083E3; + border: 1px solid #1083E3; + color: #fff; + font-weight: 500; } - &.grey{ - background-color: #94A0AD; - &:hover{ - background-color: #607F9A; - } + } + + &.sub-tab { + height: 30px; + padding: 0 10px; + line-height: 28px; + font-family: 'Noto Sans JP', sans-serif; + background-color: #2D2D2D; + border: 1px solid #393939; + color: #aaa; + + &.act, + &:hover { + background-color: #414E6C; + border: 1px solid #414E6C; + color: #fff; + font-weight: 500; } + } + + &:hover, + &.act { + background-color: #1083E3; + border: 1px solid #1083E3; + color: #fff; + font-weight: 500; + } + + &.block { + display: block; + width: 100%; + } + + &.ico-flx { + display: flex; + align-items: center; + + .ico { + margin-right: 10px; + } + + &:hover, + &.act { + font-weight: 400; + } + } +} + +.btn-origin { + display: inline-block; + height: 30px; + padding: 0 14px; + border-radius: 2px; + background-color: #101010; + color: #fff; + font-size: 13px; + font-weight: 400; + transition: all .15s ease-in-out; + + &.navy { + background-color: #304961; + + &:hover { + background-color: #1083E3; + } + } + + &.grey { + background-color: #94A0AD; + + &:hover { + background-color: #607F9A; + } + } } // select -.sort-select{ - position: relative; - display: inline-block; - min-width: 100px; - height: 30px; - line-height: 30px; - padding: 0 25px 0 10px; +.sort-select { + position: relative; + display: inline-block; + min-width: 100px; + height: 30px; + line-height: 30px; + padding: 0 25px 0 10px; + background-color: #373737; + border: 1px solid #3F3F3F; + border-radius: 2px; + border-top-left-radius: 2px; + color: #fff; + cursor: pointer; + + p { + font-size: 13px; + color: #fff; + height: 100%; + } + + .select-item-wrap { + position: absolute; + top: 100%; + left: -1px; + clip-path: inset(0 0 100% 0); + width: calc(100% + 2px); + padding: 8px 0; + max-height: 100px; + overflow-y: auto; background-color: #373737; border: 1px solid #3F3F3F; border-radius: 2px; - border-top-left-radius: 2px; - color: #fff; - cursor: pointer; - p{ - font-size: 13px; + transition: all 0.17s ease-in-out; + visibility: hidden; + z-index: 999; + + .select-item { + display: flex; + align-items: center; + padding: 8px 20px; + line-height: 1.4; + transition: all .17s ease-in-out; + + button { + font-size: 12px; color: #fff; - height: 100%; + line-height: 1.4; + } + + &:hover { + background-color: #2C2C2C; + } } - .select-item-wrap{ - position: absolute; - top: 100%; - left: -1px; - clip-path:inset(0 0 100% 0); - width: calc(100% + 2px); - padding: 8px 0; - max-height: 100px; - overflow-y: auto; - background-color: #373737; - border: 1px solid #3F3F3F; - border-radius: 2px; - transition: all 0.17s ease-in-out; - visibility: hidden; - z-index: 999; - .select-item{ - display: flex; - align-items: center; - padding: 8px 20px; - line-height: 1.4; - transition: all .17s ease-in-out; - button{ - font-size: 12px; - color: #fff; - line-height: 1.4; - } - &:hover{ - background-color: #2C2C2C; - } - } - &::-webkit-scrollbar { - width: 2px; - background-color: transparent; - - } - &::-webkit-scrollbar-thumb { - background-color: #5a5a5a; - border-radius: 10px; - } - &::-webkit-scrollbar-track { - background-color: transparent; - } + + &::-webkit-scrollbar { + width: 2px; + background-color: transparent; + } - &::after{ - content: ''; - position: absolute; - top: 50%; - right: 7px; - transform: translateY(-50%); - width: 10px; - height: 6px; - background: url(/static/images/common/select-arr.svg) no-repeat center; - background-size: cover; - transition: all .17s ease-in-out; + + &::-webkit-scrollbar-thumb { + background-color: #5a5a5a; + border-radius: 10px; } - &.active{ - .select-item-wrap{ - clip-path: inset(0 0 0 0); - visibility: visible; - } - &:after{ - transform: translateY(-50%) rotate(-180deg); - } + + &::-webkit-scrollbar-track { + background-color: transparent; } + } + + &::after { + content: ''; + position: absolute; + top: 50%; + right: 7px; + transform: translateY(-50%); + width: 10px; + height: 6px; + background: url(/static/images/common/select-arr.svg) no-repeat center; + background-size: cover; + transition: all .17s ease-in-out; + } + + &.active { + .select-item-wrap { + clip-path: inset(0 0 0 0); + visibility: visible; + } + + &:after { + transform: translateY(-50%) rotate(-180deg); + } + } } -.select-light{ - position: relative; - display: block; - width: 100%; - height: 30px; - background: #FFF url(../../public/static/images/common/select_light_arr.svg) calc(100% - 11px) center no-repeat; - background-size: 10px 6px; - border: 1px solid #eee; - padding: 0 30px 0 10px; - font-size: 13px; - color: #45576F; - font-family: 'Noto Sans JP', sans-serif; - cursor: pointer; - &:disabled{ - opacity: 1; - background-color: #FAFAFA; - color: #999; - cursor: default; - } - &.black{ - color: #101010; - } - &.dark{ - background: #323234 url(../../public/static/images/common/select_dark_arr.svg) calc(100% - 11px) center no-repeat; - color: #898989; - font-size: 12px; - border-radius: 2px; - border: none; - } +.select-light { + position: relative; + display: block; + width: 100%; + height: 30px; + background: #FFF url(../../public/static/images/common/select_light_arr.svg) calc(100% - 11px) center no-repeat; + background-size: 10px 6px; + border: 1px solid #eee; + padding: 0 30px 0 10px; + font-size: 13px; + color: #45576F; + font-family: 'Noto Sans JP', sans-serif; + cursor: pointer; + + &:disabled { + opacity: 1; + background-color: #FAFAFA; + color: #999; + cursor: default; + } + + &.black { + color: #101010; + } + + &.dark { + background: #323234 url(../../public/static/images/common/select_dark_arr.svg) calc(100% - 11px) center no-repeat; + color: #898989; + font-size: 12px; + border-radius: 2px; + border: none; + } } // input -.form-input{ - label{ - display: block; - color: #aaa; - font-size: 12px; - font-weight: 500; - margin-bottom: 10px; - } -} -input[type=number], -input[type=text]{ - &.input-origin{ - display: inline-block; - height: 30px; - line-height: 30px; - border-radius: 2px; - background-color: #323234; - color: #fff; - font-size: 12px; - font-weight: 500; - font-family: 'Pretendard', sans-serif; - padding: 0 10px; - letter-spacing: 0px; - text-align: right; - &::placeholder{ - opacity: 1; - font-size: 12px; - letter-spacing: 0px; - } - &.block{ - width: 100%; - } - &:read-only{ - color: #AAA; - } - } - &.input-light{ - display: block; - width: 100%; - height: 30px; - padding: 0 10px; - border: 1px solid #eee; - border-radius: 2px; - background-color: #fff; - font-family: 'Noto Sans JP', sans-serif; - font-size: 13px; - color: #45576F; - font-weight: normal; - transition: border-color .17s ease-in-out; - text-align: left; - &:read-only{ - background-color: #FAFAFA; - color: #999999; - } - } +.form-input { + label { + display: block; + color: #aaa; + font-size: 12px; + font-weight: 500; + margin-bottom: 10px; + } } +input[type=number], +input[type=text] { + &.input-origin { + display: inline-block; + height: 30px; + line-height: 30px; + border-radius: 2px; + background-color: #323234; + color: #fff; + font-size: 12px; + font-weight: 500; + font-family: 'Pretendard', sans-serif; + padding: 0 10px; + letter-spacing: 0px; + text-align: right; + + &::placeholder { + opacity: 1; + font-size: 12px; + letter-spacing: 0px; + } + + &.block { + width: 100%; + } + + &:read-only { + color: #AAA; + } + + &.plane { + font-family: 'Noto Sans JP', sans-serif; + border: 1px solid #525252; + background-color: transparent; + } + } + + &.input-light { + display: block; + width: 100%; + height: 30px; + padding: 0 10px; + border: 1px solid #eee; + border-radius: 2px; + background-color: #fff; + font-family: 'Noto Sans JP', sans-serif; + font-size: 13px; + color: #45576F; + font-weight: normal; + transition: border-color .17s ease-in-out; + text-align: left; + + &:read-only { + background-color: #FAFAFA; + color: #999999; + } + } +} // check-btn -.check-btn{ - display: flex; - align-items: center; - height: 30px; - background-color: #3A3A3A; - border-radius: 3px; - transition: all .17s ease-in-out; - .check-area{ - flex: none; - width: 30px; - height: 100%; - border-right: 1px solid #272727; - background: url(../../public/static/images/canvas/check-grey.svg)no-repeat center; - background-size: 11px 9px; +.check-btn { + display: flex; + align-items: center; + height: 30px; + background-color: #3A3A3A; + border-radius: 3px; + transition: all .17s ease-in-out; + + .check-area { + flex: none; + width: 30px; + height: 100%; + border-right: 1px solid #272727; + background: url(../../public/static/images/canvas/check-grey.svg) no-repeat center; + background-size: 11px 9px; + } + + .title-area { + padding: 0 10px; + font-size: 12px; + color: #898989; + font-weight: 400; + } + + &.block { + width: 100%; + } + + &:hover, + &.act { + background-color: #fff; + + .check-area { + border-right: 1px solid #101010; + background: url(../../public/static/images/canvas/check-black.svg) no-repeat center; } - .title-area{ - padding: 0 10px; - font-size: 12px; - color: #898989; - font-weight: 400; - } - &.block{ - width: 100%; - } - &:hover, - &.act{ - background-color: #fff; - .check-area{ - border-right: 1px solid #101010; - background: url(../../public/static/images/canvas/check-black.svg)no-repeat center; - } - .title-area{ - color: #101010; - font-weight: 600; - } + + .title-area { + color: #101010; + font-weight: 600; } + } } // arr-btn -.arr-btn{ - display: block; - height: 30px; - border-radius: 3px; - background-color: #3A3A3A; - padding: 0 11px; - text-align: left; - transition: all .17s ease-in-out; - span{ - position: relative; - font-size: 12px; - color: #898989; - font-weight: 400; - padding-right: 15px; - &:after{ - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 5px; - height: 8px; - background: url(../../public/static/images/canvas/arr_btn_ico.svg)no-repeat center; - } +.arr-btn { + display: block; + height: 30px; + border-radius: 3px; + background-color: #3A3A3A; + padding: 0 11px; + text-align: left; + transition: all .17s ease-in-out; + + span { + position: relative; + font-size: 12px; + color: #898989; + font-weight: 400; + padding-right: 15px; + + &:after { + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 5px; + height: 8px; + background: url(../../public/static/images/canvas/arr_btn_ico.svg) no-repeat center; } + } + + &:hover, + &.act { + background-color: #fff; + + span { + color: #101010; + font-weight: 500; + + &:after { + background: url(../../public/static/images/canvas/arr_btn_ico_black.svg) no-repeat center; + } + } + } + + &.dark { + text-align: center; + background-color: #272727; + border: 1px solid #484848; + + span { + color: #Fff; + + &:after { + background: url(../../public/static/images/canvas/arr_btn_ico_white.svg) no-repeat center; + } + } + &:hover, - &.act{ - background-color: #fff; - span{ - color: #101010; - font-weight: 500; - &:after{ - background: url(../../public/static/images/canvas/arr_btn_ico_black.svg)no-repeat center; - } - } - } - &.dark{ - text-align: center; - background-color: #272727; - border: 1px solid #484848; - span{ - color: #Fff; - &:after{ - background: url(../../public/static/images/canvas/arr_btn_ico_white.svg)no-repeat center; - } - } - &:hover, - &.act{ - background-color: #1083E3; - border: 1px solid #1083E3; - } + &.act { + background-color: #1083E3; + border: 1px solid #1083E3; } + } } // radio .d-check-radio, -.d-check-box{ - line-height: 1.1; +.d-check-box { + line-height: 1.1; + cursor: pointer; + + input[type=checkbox], + input[type=radio] { + position: static; + margin-left: 0; cursor: pointer; - input[type=checkbox], - input[type=radio]{ - position: static; - margin-left: 0; - cursor: pointer; - opacity: 0; - z-index: 1; - flex: 0 0 auto; + opacity: 0; + z-index: 1; + flex: 0 0 auto; + } + + label { + position: relative; + padding-left: 10px; + margin-bottom: 0; + word-break: break-all; + line-height: 1.2; + display: inline; + vertical-align: top; + color: #fff; + font-size: 13px; + font-weight: 400; + cursor: pointer; + } + + &.light { + label { + color: #45576F; } - label{ - position: relative; - padding-left: 10px; - margin-bottom: 0; - word-break: break-all; - line-height: 1.2; - display: inline; - vertical-align: top; - color: #fff; - font-size: 13px; - font-weight: 400; - cursor: pointer; - } - &.light{ - label{ - color: #45576F; - } - } - &.no-text{ - label{ - padding-left: 0; - } + } + + &.no-text { + label { + padding-left: 0; } + } } .d-check-radio { - label{ - &::before{ - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 17px; - height: 17px; - top:2px; - left: 0; - margin-left: -12px; - border: 1px solid #999999; - border-radius: 100%; - background-color: transparent; - text-align:center; - font-size:13px; - line-height:1.4; - transition: border 0.15s ease-in-out, color 0.15s ease-in-out; - } - &::after{ - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 9px; - height: 9px; - top:6px; - left: 4px; - margin-left: -12px; - border: none; - border-radius: 100%; - background-color: #fff; - text-align:center; - font-size:13px; - line-height:1.4; - opacity: 0; - visibility: hidden; - transition: opacity 0.15s ease-in-out, color 0.15s ease-in-out; - } + label { + &::before { + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 17px; + height: 17px; + top: 2px; + left: 0; + margin-left: -12px; + border: 1px solid #999999; + border-radius: 100%; + background-color: transparent; + text-align: center; + font-size: 13px; + line-height: 1.4; + transition: border 0.15s ease-in-out, color 0.15s ease-in-out; } - &.light{ - label{ - &:before{ - border-color: #D6D6D7; - } - &:after{ - background-color: #697C8F; - } - } + + &::after { + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 9px; + height: 9px; + top: 6px; + left: 4px; + margin-left: -12px; + border: none; + border-radius: 100%; + background-color: #fff; + text-align: center; + font-size: 13px; + line-height: 1.4; + opacity: 0; + visibility: hidden; + transition: opacity 0.15s ease-in-out, color 0.15s ease-in-out; } - input[type=radio]:checked + label::after{ - opacity: 1; - visibility: visible; + } + + &.light { + label { + &:before { + border-color: #D6D6D7; + } + + &:after { + background-color: #697C8F; + } } - &.pop{ - label{ - font-size: 12px; - &:before{ - width: 16px; - height: 16px; - border-color: #fff; - } - &:after{ - width: 8px; - height: 8px; - background-color: #fff; - } - } + } + + input[type=radio]:checked + label::after { + opacity: 1; + visibility: visible; + } + + &.pop { + label { + font-size: 12px; + + &:before { + width: 16px; + height: 16px; + border-color: #fff; + } + + &:after { + width: 8px; + height: 8px; + background-color: #fff; + } } + } } // check-box -.d-check-box{ - label{ - &::before{ - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 17px; - height: 17px; - top: 2px; - left: 0; - margin-left: -12px; - border: 1px solid #D6D6D7; - background-color: transparent; - transition: border 0.15s ease-in-out, color 0.15s ease-in-out; - } - &:after{ - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 16px; - height: 16px; - top:0; - left: 0; - margin-left: -.8rem; - transition: border 0.05s ease-in-out, color 0.05s ease-in-out; - } +.d-check-box { + label { + &::before { + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 17px; + height: 17px; + top: 2px; + left: 0; + margin-left: -12px; + border: 1px solid #D6D6D7; + background-color: transparent; + transition: border 0.15s ease-in-out, color 0.15s ease-in-out; } - input[type=checkbox]:checked + label::after{ - content: ""; - display: inline-block; - position: absolute; - top: 1px; - left: -1px; - width: 5px; - height: 8px; - border: 2px solid #697C8F; - border-left: none; - border-top: none; - transform: translate(7.75px,4.5px) rotate(45deg); - -ms-transform: translate(7.75px,4.5px) rotate(45deg); + + &:after { + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 16px; + height: 16px; + top: 0; + left: 0; + margin-left: -.8rem; + transition: border 0.05s ease-in-out, color 0.05s ease-in-out; } - &.pop{ - input[type=checkbox]:checked + label::after{ - border-color: #fff; - } + } + + input[type=checkbox]:checked + label::after { + content: ""; + display: inline-block; + position: absolute; + top: 1px; + left: -1px; + width: 5px; + height: 8px; + border: 2px solid #697C8F; + border-left: none; + border-top: none; + transform: translate(7.75px, 4.5px) rotate(45deg); + -ms-transform: translate(7.75px, 4.5px) rotate(45deg); + } + + &.pop { + input[type=checkbox]:checked + label::after { + border-color: #fff; } + } } // date-picker -.date-picker{ - svg{display: none;} - .react-datepicker-wrapper{ - width: 100%; - } - input[type=text]{ - display: block; - width: 100%; - height: 30px; - padding: 0 34px 0 10px; - border-radius: 2px; - border: 1px solid #eee; - font-size: 13px; - color: #45576F; - font-weight: normal; - font-family: 'Noto Sans JP', sans-serif; - background: #fff url(../../public/static/images/common/datepicker.svg) calc(100% - 11px) center no-repeat; - background-size: 14px 15px; - cursor: pointer; - } +.date-picker { + svg { + display: none; + } + + .react-datepicker-wrapper { + width: 100%; + } + + input[type=text] { + display: block; + width: 100%; + height: 30px; + padding: 0 34px 0 10px; + border-radius: 2px; + border: 1px solid #eee; + font-size: 13px; + color: #45576F; + font-weight: normal; + font-family: 'Noto Sans JP', sans-serif; + background: #fff url(../../public/static/images/common/datepicker.svg) calc(100% - 11px) center no-repeat; + background-size: 14px 15px; + cursor: pointer; + } } \ No newline at end of file diff --git a/src/styles/_table.scss b/src/styles/_table.scss index d3c207a7..ceaea36b 100644 --- a/src/styles/_table.scss +++ b/src/styles/_table.scss @@ -1,177 +1,215 @@ -@mixin flexbox(){ - display: flex; - align-items: center; +@mixin flexbox() { + display: flex; + align-items: center; } -table{ - .overflow-lab{ - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - } - .al-l{ - text-align: left !important; - } +table { + .overflow-lab { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + + .al-l { + text-align: left !important; + } } -.common-table{ - table{ - table-layout: fixed; +.common-table { + table { + table-layout: fixed; + border: 1px solid #ECF0F4; + border-radius: 3px; + border-collapse: collapse; + + tbody { + th { + font-size: 13px; + font-weight: 500; + color: #344356; + padding: 14px 12px; border: 1px solid #ECF0F4; - border-radius: 3px; - border-collapse:collapse; - tbody{ - th{ - font-size: 13px; - font-weight: 500; - color: #344356; - padding: 14px 12px; - border: 1px solid #ECF0F4 ; - background-color: #F7F9FA; - vertical-align: middle; - } - td{ - padding: 9px; - border: 1px solid #ECF0F4 ; - font-size: 13px; - font-weight: 400; - color: #45576F; - vertical-align: middle; - .radio-wrap{ - flex: none; - @include flexbox; - } - .form-flex-wrap{ - @include flexbox; - } - .date-picker-wrap{ - width: 100%; - @include flexbox; - span{ - margin: 0 4px; - } - } - } + background-color: #F7F9FA; + vertical-align: middle; + } + + td { + padding: 9px; + border: 1px solid #ECF0F4; + font-size: 13px; + font-weight: 400; + color: #45576F; + vertical-align: middle; + + .radio-wrap { + flex: none; + @include flexbox; } + + .form-flex-wrap { + @include flexbox; + } + + .date-picker-wrap { + width: 100%; + @include flexbox; + + span { + margin: 0 4px; + } + } + } } - &.bt-able{ - margin-bottom: 30px; - } + } + + &.bt-able { + margin-bottom: 30px; + } } -.infomation-table{ - table{ - border-top: 1px solid #DEE3EA; - border-bottom: 1px solid #DEE3EA; - border-collapse:collapse; - tbody{ - tr{ - th{ - font-size: 13px; - color: #344356; - font-weight: 500; - padding: 18px 0; - border-bottom: 1px solid #F4F4F7; - .title{ - margin-right: 8px; - } - } - td{ - padding: 0 0 0 15px; - border-bottom: 1px solid #F4F4F7; - - .guide{ - font-size: 13px; - color: #697C8F; - font-weight: normal; - margin-left: 15px; - } - span{ - font-size: 13px; - color: #697C8F; - font-weight: normal; - } - } - &:last-child{ - th,td{border-bottom: none;} - } - } +.infomation-table { + table { + border-top: 1px solid #DEE3EA; + border-bottom: 1px solid #DEE3EA; + border-collapse: collapse; + + tbody { + tr { + th { + font-size: 13px; + color: #344356; + font-weight: 500; + padding: 18px 0; + border-bottom: 1px solid #F4F4F7; + + .title { + margin-right: 8px; + } } - .flx-box{ - @include flexbox; + + td { + padding: 0 0 0 15px; + border-bottom: 1px solid #F4F4F7; + + .guide { + font-size: 13px; + color: #697C8F; + font-weight: normal; + margin-left: 15px; + } + + span { + font-size: 13px; + color: #697C8F; + font-weight: normal; + } } + + &:last-child { + th, td { + border-bottom: none; + } + } + } } - .tooltips{ - display: block; - width: 14px; - height: 14px; - display: inline-block; - background: url(../../public/static/images/sub/tooltips.svg)no-repeat center; - background-size: cover; - cursor: pointer; + + .flx-box { + @include flexbox; } + } + + .tooltips { + display: block; + width: 14px; + height: 14px; + display: inline-block; + background: url(../../public/static/images/sub/tooltips.svg) no-repeat center; + background-size: cover; + cursor: pointer; + } } -.module-table{ - table{ +.module-table { + table { + table-layout: fixed; + border-collapse: collapse; + + thead { + display: table; + table-layout: fixed; + width: 100%; + + th { + padding: 13px 0; + font-size: 13px; + color: #344356; + font-weight: 500; + border-bottom: 2px solid #E0E5EB; + text-align: center; + } + } + + tbody { + display: block; + overflow-y: auto; + + tr { + display: table; table-layout: fixed; - border-collapse: collapse; - thead{ - display: table; - table-layout: fixed; - width: 100%; - th{ - padding: 13px 0; - font-size: 13px; - color: #344356; - font-weight: 500; - border-bottom: 2px solid #E0E5EB; - text-align: center; - } - } - tbody{ - display: block; - overflow-y: auto; - tr{ - display: table; - table-layout: fixed; - width: 100%; - border: 1px solid #ECF0F4; - td{ - padding: 10px 0px; - font-size: 13px; - color: #45576F; - font-weight: 400; - text-align: center; - } - } - &::-webkit-scrollbar { - width: 4px; - background-color: transparent; - } - &::-webkit-scrollbar-thumb { - background-color: #C1CCD7; - } - &::-webkit-scrollbar-track { - background-color: transparent; - } - } - &.small{ - tbody{height: 120px;} - } - &.big{ - td, - th{ - &:nth-child(2){ - width: 121px; - } - } - tbody{ - height: 160px; - td{ - padding: 10px 20px; - } - } + width: 100%; + border: 1px solid #ECF0F4; + + td { + padding: 10px 0px; + font-size: 13px; + color: #45576F; + font-weight: 400; + text-align: center; } + } + + &::-webkit-scrollbar { + width: 4px; + background-color: transparent; + } + + &::-webkit-scrollbar-thumb { + background-color: #C1CCD7; + } + + &::-webkit-scrollbar-track { + background-color: transparent; + } } + + &.small { + tbody { + height: 120px; + } + } + + &.big { + td, + th { + &:nth-child(2) { + width: 121px; + } + } + + tbody { + height: 160px; + + td { + padding: 10px 20px; + } + } + } + } +} + +.roof-module-table { + table { + table-layout: fixed; + border-collapse: collapse; + } } \ No newline at end of file From 7ddcc91d1ff3b21fa69397158400b8eeb6d03f26 Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 15:18:19 +0900 Subject: [PATCH 051/152] =?UTF-8?q?=F0=9F=9A=A8chore:=20Sync=20Sass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/styles/_contents.scss | 1892 ++++++++++++++++--------------------- src/styles/_modal.scss | 1 - src/styles/_reset.scss | 1330 ++++++++++++-------------- src/styles/_table.scss | 396 ++++---- 4 files changed, 1629 insertions(+), 1990 deletions(-) diff --git a/src/styles/_contents.scss b/src/styles/_contents.scss index 7a357be7..034955f5 100644 --- a/src/styles/_contents.scss +++ b/src/styles/_contents.scss @@ -1,1140 +1,926 @@ // CanvasPage -.canvas-wrap { - height: calc(100vh - 47px); - display: flex; - flex-direction: column; - - .canvas-content { - flex: 1 1 auto; - - .canvas-layout { - height: 100%; - } - } - - &.sub-wrap { - overflow: hidden; - - .canvas-content { - height: calc(100% - 47px); - } - } -} - -// CanvasMenu -.canvas-menu-wrap { - position: relative; - display: block; - width: 100%; - padding-bottom: 0; - background-color: #383838; - transition: padding .17s ease-in-out; - - .canvas-menu-inner { - position: relative; +.canvas-wrap{ + height: calc(100vh - 47px); display: flex; - align-items: center; - padding: 0 40px 0 20px; - background-color: #2C2C2C; - z-index: 999; - - .canvas-menu-list { - display: flex; - align-items: center; - height: 100%; - - .canvas-menu-item { - display: flex; - align-items: center; - height: 100%; - - button { - display: flex; - align-items: center; - font-size: 12px; - height: 100%; - color: #fff; - font-weight: 600; - padding: 15px 20px; - opacity: 0.55; - transition: all .17s ease-in-out; - - .menu-icon { - display: block; - width: 16px; - height: 16px; - background-repeat: no-repeat; - background-position: center; - background-size: cover; - margin-right: 10px; - - &.con00 { - background-image: url(/static/images/canvas/menu_icon00.svg); - } - - &.con01 { - background-image: url(/static/images/canvas/menu_icon01.svg); - } - - &.con02 { - background-image: url(/static/images/canvas/menu_icon02.svg); - } - - &.con03 { - background-image: url(/static/images/canvas/menu_icon03.svg); - } - - &.con04 { - background-image: url(/static/images/canvas/menu_icon04.svg); - } - - &.con05 { - background-image: url(/static/images/canvas/menu_icon05.svg); - } - - &.con06 { - background-image: url(/static/images/canvas/menu_icon06.svg); - } - } + flex-direction: column; + .canvas-content{ + flex: 1 1 auto; + .canvas-layout{ + height: 100%; } - - &.active { - background-color: #383838; - - button { - opacity: 1; - } - } - } } - - .canvas-side-btn-wrap { - display: flex; - align-items: center; - margin-left: auto; - - .select-box { - width: 124px; - margin-right: 5px; - - > div { - width: 100%; - } - } - - .btn-from { - display: flex; - align-items: center; - gap: 5px; - - button { - display: block; - width: 30px; - height: 30px; - border-radius: 2px; - background-color: #3D3D3D; - background-position: center; - background-repeat: no-repeat; - background-size: 15px 15px; - transition: all .17s ease-in-out; - - &.btn01 { - background-image: url(../../public/static/images/canvas/side_icon03.svg); - } - - &.btn02 { - background-image: url(../../public/static/images/canvas/side_icon02.svg); - } - - &.btn03 { - background-image: url(../../public/static/images/canvas/side_icon01.svg); - } - - &.btn04 { - background-image: url(../../public/static/images/canvas/side_icon04.svg); - } - - &.btn05 { - background-image: url(../../public/static/images/canvas/side_icon05.svg); - } - - &.btn06 { - background-image: url(../../public/static/images/canvas/side_icon06.svg); - } - - &.btn07 { - background-image: url(../../public/static/images/canvas/side_icon07.svg); - } - - &.btn08 { - background-image: url(../../public/static/images/canvas/side_icon08.svg); - } - - &.btn09 { - background-image: url(../../public/static/images/canvas/side_icon09.svg); - } - - &:hover { - background-color: #1083E3; - } - - &.active { - background-color: #1083E3; - } - } - } - - .ico-btn-from { - display: flex; - align-items: center; - gap: 5px; - - button { - .ico { - display: block; - width: 15px; - height: 15px; - background-repeat: no-repeat; - background-position: center; - background-size: contain; - - &.ico01 { - background-image: url(../../public/static/images/canvas/ico-flx01.svg); - } - - &.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); - } - } - - .name { - font-size: 12px; - color: #fff; - } - } - - &.form06 { - .name { - font-size: 13px; - } - } - } - - .vertical-horizontal { - display: flex; - min-width: 170px; - height: 28px; - margin: 0 5px; - border-radius: 2px; - background: #373737; - line-height: 28px; + &.sub-wrap{ overflow: hidden; - - span { - padding: 0 10px; - font-size: 13px; - color: #fff; + .canvas-content{ + height: calc(100% - 47px); } - - button { - margin-left: auto; - height: 100%; - background-color: #4B4B4B; - font-size: 13px; - font-weight: 400; - color: #fff; - padding: 0 7.5px; - transition: all .17s ease-in-out; - } - - &.on { - button { - background-color: #1083E3; - } - } - } - - .size-control { - display: flex; - align-items: center; - justify-content: center; - gap: 10px; - background-color: #3D3D3D; - border-radius: 2px; - width: 100px; - height: 30px; - margin: 0 5px; - - span { - font-size: 13px; - color: #fff; - } - - .control-btn { - display: block; - width: 12px; - height: 12px; - background-repeat: no-repeat; - background-size: cover; - background-position: center; - - &.minus { - background-image: url(../../public/static/images/canvas/minus.svg); - } - - &.plus { - background-image: url(../../public/static/images/canvas/plus.svg); - } - } - } } - } - - .canvas-depth2-wrap { - position: absolute; - top: -100%; - left: 0; - background-color: #383838; +} +// CanvasMenu +.canvas-menu-wrap{ + position: relative; + display: block; width: 100%; - height: 50px; - transition: all .17s ease-in-out; - - .canvas-depth2-inner { - display: flex; - align-items: center; - padding: 0 40px; - height: 100%; - - .canvas-depth2-list { + padding-bottom: 0; + background-color: #383838; + transition: padding .17s ease-in-out; + .canvas-menu-inner{ + position: relative; display: flex; align-items: center; - height: 100%; - - .canvas-depth2-item { - display: flex; - align-items: center; - margin-right: 26px; - height: 100%; - - button { - position: relative; - opacity: 0.55; - color: #fff; - font-size: 12px; - font-weight: normal; + padding: 0 40px 0 20px; + background-color: #2C2C2C; + z-index: 999; + .canvas-menu-list{ + display: flex; + align-items: center; height: 100%; - padding-right: 12px; - } - - &.active { - button { - opacity: 1; - font-weight: 600; - - &:after { - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 5px; - height: 8px; - background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center; - } + .canvas-menu-item{ + display: flex; + align-items: center; + height: 100%; + button{ + display: flex; + align-items: center; + font-size: 12px; + height: 100%; + color: #fff; + font-weight: 600; + padding: 15px 20px; + opacity: 0.55; + transition: all .17s ease-in-out; + .menu-icon{ + display: block; + width: 16px; + height: 16px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; + margin-right: 10px; + &.con00{background-image: url(/static/images/canvas/menu_icon00.svg);} + &.con01{background-image: url(/static/images/canvas/menu_icon01.svg);} + &.con02{background-image: url(/static/images/canvas/menu_icon02.svg);} + &.con03{background-image: url(/static/images/canvas/menu_icon03.svg);} + &.con04{background-image: url(/static/images/canvas/menu_icon04.svg);} + &.con05{background-image: url(/static/images/canvas/menu_icon05.svg);} + &.con06{background-image: url(/static/images/canvas/menu_icon06.svg);} + } + } + &.active{ + background-color: #383838; + button{ + opacity: 1; + } + } } - } } - } - - .canvas-depth2-btn-list { - display: flex; - align-items: center; - margin-left: auto; - height: 100%; - - .depth2-btn-box { - display: flex; - align-items: center; - margin-right: 34px; - height: 100%; - transition: all .17s ease-in-out; - - button { - position: relative; - font-size: 12px; - font-weight: 400; + .canvas-side-btn-wrap{ + display: flex; + align-items: center; + margin-left: auto; + .select-box{ + width: 124px; + margin-right: 5px; + > div{ + width: 100%; + } + } + .btn-from{ + display: flex; + align-items: center; + gap: 5px; + button{ + display: block; + width: 30px; + height: 30px; + border-radius: 2px; + background-color: #3D3D3D; + background-position: center; + background-repeat: no-repeat; + background-size: 15px 15px; + transition: all .17s ease-in-out; + &.btn01{background-image: url(../../public/static/images/canvas/side_icon03.svg);} + &.btn02{background-image: url(../../public/static/images/canvas/side_icon02.svg);} + &.btn03{background-image: url(../../public/static/images/canvas/side_icon01.svg);} + &.btn04{background-image: url(../../public/static/images/canvas/side_icon04.svg);} + &.btn05{background-image: url(../../public/static/images/canvas/side_icon05.svg);} + &.btn06{background-image: url(../../public/static/images/canvas/side_icon06.svg);} + &.btn07{background-image: url(../../public/static/images/canvas/side_icon07.svg);} + &.btn08{background-image: url(../../public/static/images/canvas/side_icon08.svg);} + &.btn09{background-image: url(../../public/static/images/canvas/side_icon09.svg);} + &:hover{ + background-color: #1083E3; + } + &.active{ + background-color: #1083E3; + } + } + } + .ico-btn-from{ + display: flex; + align-items: center; + gap: 5px; + button{ + .ico{ + display: block; + width: 15px; + height: 15px; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + &.ico01{background-image: url(../../public/static/images/canvas/ico-flx01.svg);} + &.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);} + } + .name{ + font-size: 12px; + color: #fff; + } + } + &.form06{ + .name{ + font-size: 13px; + } + } + } + .vertical-horizontal{ + display: flex; + min-width: 170px; + height: 28px; + margin: 0 5px; + border-radius: 2px; + background: #373737; + line-height: 28px; + overflow: hidden; + span{ + padding: 0 10px; + font-size: 13px; + color: #fff; + } + button{ + margin-left: auto; + height: 100%; + background-color: #4B4B4B; + font-size: 13px; + font-weight: 400; + color: #fff; + padding: 0 7.5px; + transition: all .17s ease-in-out; + } + &.on{ + button{ + background-color: #1083E3; + } + } + } + .size-control{ + display: flex; + align-items: center; + justify-content: center; + gap: 10px; + background-color: #3D3D3D; + border-radius: 2px; + width: 100px; + height: 30px; + margin: 0 5px; + span{ + font-size: 13px; + color: #fff; + } + .control-btn{ + display: block; + width: 12px; + height: 12px; + background-repeat: no-repeat; + background-size: cover; + background-position: center; + &.minus{ + background-image: url(../../public/static/images/canvas/minus.svg); + } + &.plus{ + background-image: url(../../public/static/images/canvas/plus.svg); + } + } + } + } + } + .canvas-depth2-wrap{ + position: absolute; + top: -100%; + left: 0; + background-color: #383838; + width: 100%; + height: 50px; + transition: all .17s ease-in-out; + .canvas-depth2-inner{ + display: flex; + align-items: center; + padding: 0 40px; height: 100%; - color: #fff; - padding-right: 12px; - - &:after { - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 5px; - height: 8px; - background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center; + .canvas-depth2-list{ + display: flex; + align-items: center ; + height: 100%; + .canvas-depth2-item{ + display: flex; + align-items: center; + margin-right: 26px; + height: 100%; + button{ + position: relative; + opacity: 0.55; + color: #fff; + font-size: 12px; + font-weight: normal; + height: 100%; + padding-right: 12px; + } + &.active{ + button{ + opacity: 1; + font-weight: 600; + &:after{ + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 5px; + height: 8px; + background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center; + } + } + } + } + } + .canvas-depth2-btn-list{ + display: flex; + align-items: center; + margin-left: auto; + height: 100%; + .depth2-btn-box{ + display: flex; + align-items: center; + margin-right: 34px; + height: 100%; + transition: all .17s ease-in-out; + button{ + position: relative; + font-size: 12px; + font-weight: 400; + height: 100%; + color: #fff; + padding-right: 12px; + &:after{ + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 5px; + height: 8px; + background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center; + } + } + &:last-child{ + margin-right: 0; + } + &.mouse{ + opacity: 0.55; + } + } } - } - - &:last-child { - margin-right: 0; - } - - &.mouse { - opacity: 0.55; - } } - } + &.active{ + top: 47px; + } } - - &.active { - top: 47px; + &.active{ + padding-bottom: 50px; } - } - - &.active { - padding-bottom: 50px; - } } // canvas-layout -.canvas-layout { - .canvas-page-list { - display: flex; - background-color: #1C1C1C; - border-top: 1px solid #000; - width: 100%; - - .canvas-plane-wrap { - display: flex; - align-items: center; - max-width: calc(100% - 45px); - - .canvas-page-box { +.canvas-layout{ + .canvas-page-list{ display: flex; - align-items: center; - background-color: #1c1c1c; - padding: 9.6px 20px; - border-right: 1px solid #000; - min-width: 0; - transition: all .17s ease-in-out; - - span { - display: flex; - align-items: center; - width: 100%; - font-size: 12px; - font-family: 'Pretendard', sans-serif; - color: #AAA; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; + background-color: #1C1C1C; + border-top: 1px solid #000; + width: 100%; + .canvas-plane-wrap{ + display: flex; + align-items: center; + max-width: calc(100% - 45px); + .canvas-page-box{ + display: flex; + align-items: center; + background-color: #1c1c1c; + padding: 9.6px 20px; + border-right:1px solid #000; + min-width: 0; + transition: all .17s ease-in-out; + span{ + display: flex; + align-items: center; + width: 100%; + font-size: 12px; + font-family: 'Pretendard', sans-serif; + color: #AAA; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + .close{ + flex: none; + display: block; + width: 7px; + height: 8px; + margin-left: 15px; + background: url(../../public/static/images/canvas/plan_close_gray.svg)no-repeat center; + background-size: cover; + } + &.on{ + background-color: #fff; + span{ + font-weight: 600; + color: #101010; + } + .close{ + background: url(../../public/static/images/canvas/plan_close_black.svg)no-repeat center; + } + &:hover{ + background-color: #fff; + } + } + &:hover{ + background-color: #000; + } + } } - - .close { - flex: none; - display: block; - width: 7px; - height: 8px; - margin-left: 15px; - background: url(../../public/static/images/canvas/plan_close_gray.svg) no-repeat center; - background-size: cover; + .plane-add{ + display: flex; + align-items: center; + justify-content: center; + width: 45px; + padding: 13.5px 0; + background-color: #1C1C1C; + border-right: 1px solid #000; + transition: all .17s ease-in-out; + span{ + display: block; + width: 9px; + height: 9px; + background: url(../../public/static/images/canvas/plane_add.svg)no-repeat center; + background-size: cover; + } + &:hover{ + background-color: #000; + } } - - &.on { - background-color: #fff; - - span { - font-weight: 600; - color: #101010; - } - - .close { - background: url(../../public/static/images/canvas/plan_close_black.svg) no-repeat center; - } - - &:hover { - background-color: #fff; - } - } - - &:hover { - background-color: #000; - } - } } - - .plane-add { - display: flex; - align-items: center; - justify-content: center; - width: 45px; - padding: 13.5px 0; - background-color: #1C1C1C; - border-right: 1px solid #000; - transition: all .17s ease-in-out; - - span { - display: block; - width: 9px; - height: 9px; - background: url(../../public/static/images/canvas/plane_add.svg) no-repeat center; - background-size: cover; - } - - &:hover { - background-color: #000; - } - } - } } -.canvas-frame { - position: relative; - height: calc(100% - 36.5px); - background-color: #fff; - - canvas { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - } +.canvas-frame{ + position: relative; + height: calc(100% - 36.5px); + background-color: #fff; + canvas{ + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } } // sub-page -.sub-header { - position: fixed; - top: 46px; - left: 0; - width: 100%; - height: 46px; - border-bottom: 1px solid #000; - background: #2C2C2C; - z-index: 999; - - .sub-header-inner { - display: flex; - align-items: center; - height: 100%; - padding: 0 100px; - - .sub-header-title-wrap { - display: flex; - align-items: center; - - .title-item { - position: relative; - padding: 0 24px; - - a { - display: flex; - align-items: center; - - .icon { - width: 22px; - height: 22px; - margin-right: 8px; - background-repeat: no-repeat; - background-position: center; - background-size: cover; - - &.drawing { - background-image: url(../../public/static/images/main/drawing_icon.svg); - } - } - } - - &:after { - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 1px; - height: 16px; - background-color: #D9D9D9; - } - - &:first-child { - padding-left: 0; - } - - &:last-child { - padding-right: 0; - - &:after { - display: none; - } - } - } - } - - .sub-header-title { - font-size: 16px; - color: #fff; - font-weight: 600; - } - - .sub-header-location { - margin-left: auto; - display: flex; - align-items: center; - - .location-item { - position: relative; +.sub-header{ + position: fixed; + top: 46px; + left: 0; + width: 100%; + height: 46px; + border-bottom: 1px solid #000; + background: #2C2C2C; + z-index: 999; + .sub-header-inner{ display: flex; align-items: center; - padding: 0 10px; - - span { - display: flex; - font-size: 12px; - color: #AAA; - font-weight: normal; - cursor: default; + height: 100%; + padding: 0 100px; + .sub-header-title-wrap{ + display: flex; + align-items: center; + .title-item{ + position: relative; + padding: 0 24px; + a{ + display: flex; + align-items: center; + .icon{ + width: 22px; + height: 22px; + margin-right: 8px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; + &.drawing{background-image: url(../../public/static/images/main/drawing_icon.svg);} + } + } + &:after{ + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 1px; + height: 16px; + background-color: #D9D9D9; + } + &:first-child{ + padding-left: 0; + } + &:last-child{ + padding-right: 0; + &:after{ + display: none; + } + } + } } - - &:after { - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 4px; - height: 6px; - background: url(../../public/static/images/main/loaction_arr.svg) no-repeat center; - } - - &:first-child { - padding-left: 0; - } - - &:last-child { - padding-right: 0; - - span { + .sub-header-title{ + font-size: 16px; color: #fff; - } - - &:after { - display: none; - } + font-weight: 600; + } + .sub-header-location{ + margin-left: auto; + display: flex; + align-items: center; + .location-item{ + position: relative; + display: flex; + align-items: center; + padding: 0 10px; + span{ + display: flex; + font-size: 12px; + color: #AAA; + font-weight: normal; + cursor: default; + } + &:after{ + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 4px; + height: 6px; + background: url(../../public/static/images/main/loaction_arr.svg)no-repeat center; + } + &:first-child{ + padding-left: 0; + } + &:last-child{ + padding-right: 0; + span{ + color: #fff; + } + &:after{ + display: none; + } + } + } } - } } - } } // sub content -.sub-content { - padding-top: 46px; - - .sub-content-inner { - max-width: 1720px; - margin: 0 auto; - padding-top: 20px; - - .sub-content-box { - margin-bottom: 20px; - - &:last-child { - margin-bottom: 0; - } +.sub-content{ + padding-top: 46px; + .sub-content-inner{ + max-width: 1720px; + margin: 0 auto; + padding-top: 20px; + .sub-content-box{ + margin-bottom: 20px; + &:last-child{ + margin-bottom: 0; + } + } } - } - - &.estimate { - display: flex; - flex-direction: column; - height: calc(100% - 36.5px); - overflow-y: auto; - padding-top: 0; - - .sub-content-inner { - flex: 1; - width: 100%; + &.estimate{ + display: flex; + flex-direction: column; + height: calc(100% - 36.5px); + overflow-y: auto; + padding-top: 0; + .sub-content-inner{ + flex: 1; + width: 100%; + } } - } } - -.sub-table-box { - padding: 20px; - border-radius: 6px; - border: 1px solid #E9EAED; - background: #FFF; - box-shadow: 0px 3px 30px 0px rgba(0, 0, 0, 0.02); - - .table-box-title-wrap { - display: flex; - align-items: center; - margin-bottom: 15px; - - .title-wrap { - display: flex; - align-items: center; - - h3 { - display: block; - font-size: 15px; - color: #101010; - font-weight: 600; - margin-right: 14px; - } - - .info-wrap { +.sub-table-box{ + padding: 20px; + border-radius: 6px; + border: 1px solid #E9EAED; + background: #FFF; + box-shadow: 0px 3px 30px 0px rgba(0, 0, 0, 0.02); + .table-box-title-wrap{ display: flex; align-items: center; - - li { - position: relative; - padding: 0 6px; - font-size: 12px; - color: #101010; - font-weight: normal; - - span { - font-weight: 600; - - &.red { - color: #E23D70; + margin-bottom: 15px; + .title-wrap{ + display: flex; + align-items: center; + h3{ + display: block; + font-size: 15px; + color: #101010; + font-weight: 600; + margin-right: 14px; } - } - - &:after { - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 1px; - height: 11px; - background-color: #D9D9D9; - } - - &:first-child { - padding-left: 0; - } - - &:last-child { - padding-right: 0; - - &::after { - display: none; + .info-wrap{ + display: flex; + align-items: center; + li{ + position: relative; + padding: 0 6px; + font-size: 12px; + color: #101010; + font-weight: normal; + span{ + font-weight: 600; + &.red{ + color: #E23D70; + } + } + &:after{ + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 1px; + height: 11px; + background-color: #D9D9D9; + } + &:first-child{padding-left: 0;} + &:last-child{padding-right: 0;&::after{display: none;}} + } } - } } - } } - } - - .left-unit-box { - margin-left: auto; - display: flex; - align-items: center; - } - - .promise-gudie { - display: block; - font-size: 13px; - font-weight: 700; - color: #101010; - margin-bottom: 20px; - } - - .important { - color: #f00; - } - - .sub-table-footer { - display: flex; - align-items: center; - justify-content: center; - margin-top: 20px; - } - - .pagination-wrap { - margin-top: 24px; - } + .left-unit-box{ + margin-left: auto; + display: flex; + align-items: center; + } + .promise-gudie{ + display: block; + font-size: 13px; + font-weight: 700; + color: #101010; + margin-bottom: 20px; + } + .important{ + color: #f00; + } + .sub-table-footer{ + display: flex; + align-items: center; + justify-content: center; + margin-top: 20px; + } + .pagination-wrap{ + margin-top: 24px; + } } -.infomation-box-wrap { - display: flex; - align-items: center; - gap: 10px; - - .sub-table-box { - flex: 1; - } - - .info-title { - font-size: 14px; - font-weight: 500; - color: #344356; - margin-bottom: 10px; - } - - .info-inner { - position: relative; - font-size: 13px; - color: #344356; - - .copy-ico { - position: absolute; - bottom: 0; - right: 0; - width: 16px; - height: 16px; - background: url(../../public/static/images/sub/copy_ico.svg) no-repeat center; - background-size: cover; +.infomation-box-wrap{ + display: flex; + align-items: center; + gap: 10px; + .sub-table-box{ + flex: 1 ; + } + .info-title{ + font-size: 14px; + font-weight: 500; + color: #344356; + margin-bottom: 10px; + } + .info-inner{ + position: relative; + font-size: 13px; + color: #344356; + .copy-ico{ + position: absolute; + bottom: 0; + right: 0; + width: 16px; + height: 16px; + background: url(../../public/static/images/sub/copy_ico.svg)no-repeat center; + background-size: cover; + } } - } } // 견적서 -.estimate-list-wrap { - display: flex; - align-items: center; - margin-bottom: 10px; - - .estimate-box { - flex: 1; +.estimate-list-wrap{ display: flex; align-items: center; - - &:last-child { - flex: none; - min-width: 220px; + margin-bottom: 10px; + .estimate-box{ + flex: 1 ; + display: flex; + align-items: center; + &:last-child{ + flex: none; + min-width: 220px; + } + .estimate-tit{ + width: 105px; + height: 30px; + line-height: 30px; + background-color: #F4F4F7; + border-radius: 100px; + text-align: center; + font-size: 13px; + font-weight: 500; + color: #344356; + } + .estimate-name{ + font-size: 13px; + color: #344356; + margin-left: 14px; + font-weight: 400; + } } - - .estimate-tit { - width: 105px; - height: 30px; - line-height: 30px; - background-color: #F4F4F7; - border-radius: 100px; - text-align: center; - font-size: 13px; - font-weight: 500; - color: #344356; + &:last-child{ + margin-bottom: 0; } - - .estimate-name { - font-size: 13px; - color: #344356; - margin-left: 14px; - font-weight: 400; - } - } - - &:last-child { - margin-bottom: 0; - } } // file drag box -.drag-file-box { - padding: 10px; - - .btn-area { - padding-bottom: 15px; - border-bottom: 1px solid #ECF0F4; - } - - .drag-file-area { - position: relative; - margin-top: 15px; - - p { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - font-size: 13px; - color: #ccc; - font-weight: 400; - cursor: default; +.drag-file-box{ + padding: 10px; + .btn-area{ + padding-bottom: 15px; + border-bottom: 1px solid #ECF0F4; } - } - - .file-list { - .file-item { - margin-bottom: 15px; - - span { + .drag-file-area{ position: relative; - font-size: 13px; - color: #45576F; - font-weight: 400; - white-space: nowrap; - padding-right: 55px; - - button { - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 15px; - height: 15px; - background: url(../../public/static/images/sub/file_delete.svg) no-repeat center; - background-size: cover; + margin-top: 15px; + p{ + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 13px; + color: #ccc; + font-weight: 400; + cursor: default; + } + } + .file-list{ + .file-item{ + margin-bottom: 15px; + span{ + position: relative; + font-size: 13px; + color: #45576F; + font-weight: 400; + white-space: nowrap; + padding-right: 55px; + button{ + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 15px; + height: 15px; + background: url(../../public/static/images/sub/file_delete.svg)no-repeat center; + background-size: cover; + } + } + &:last-child{ + margin-bottom: 0; + } } - } - - &:last-child { - margin-bottom: 0; - } } - } } // 발전시물레이션 -.chart-wrap { - display: flex; - gap: 20px; - width: 100%; - - .sub-table-box { - height: 100%; - } - - .chart-inner { - flex: 1; - - .chart-box { - margin-bottom: 30px; - } - } - - .chart-table-wrap { +.chart-wrap{ display: flex; - flex-direction: column; - flex: none; - width: 650px; - - .sub-table-box { - flex: 1; - - &:first-child { - margin-bottom: 20px; - } + gap: 20px; + width: 100%; + .sub-table-box{ + height: 100%; + } + .chart-inner{ + flex: 1; + .chart-box{ + margin-bottom: 30px; + } + } + .chart-table-wrap{ + display: flex; + flex-direction: column; + flex: none; + width: 650px; + .sub-table-box{ + flex: 1; + &:first-child{ + margin-bottom: 20px; + } + } } - } } -.chart-month-table { - table { - table-layout: fixed; - border-collapse: collapse; +.chart-month-table{ + table{ + table-layout: fixed; + border-collapse:collapse; + border: 1px solid #ECF0F4; + border-radius: 4px; + thead{ + th{ + padding: 4.5px 0; + border-bottom: 1px solid #ECF0F4; + text-align: center; + font-size: 13px; + color: #45576F; + font-weight: 500; + background-color: #F8F9FA; + } + } + tbody{ + td{ + font-size: 13px; + color: #45576F; + text-align: center; + padding: 4.5px 0; + } + } + } +} + +.simulation-guide-wrap{ + display: flex; + padding: 20px; + .simulation-tit-wrap{ + padding-right: 40px; + border-right: 1px solid #EEEEEE; + span{ + display: block; + position: relative; + padding-left: 60px; + font-size: 15px; + color: #14324F; + font-weight: 600; + &::before{ + content: ''; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + width: 40px; + height: 40px; + background: url(../../public/static/images/sub/simulation_guide.svg)no-repeat center; + background-size: cover; + } + } + } + .simulation-guide-box{ + padding-left: 40px; + dl{ + margin-bottom: 25px; + dt{ + font-size: 13px; + color: #101010; + font-weight: 600; + margin-bottom: 5px; + } + dd{ + font-size: 12px; + color: #45576F; + font-weight: 400; + line-height: 24px; + } + &:last-child{ + margin-bottom: 0; + } + } + } +} + +.module-total{ + display: flex; + align-items: center; + background-color: #F8F9FA; + padding: 9px 0; + margin-right: 4px; border: 1px solid #ECF0F4; - border-radius: 4px; - - thead { - th { - padding: 4.5px 0; - border-bottom: 1px solid #ECF0F4; + border-top: none; + .total-title{ + flex: 1; text-align: center; font-size: 13px; - color: #45576F; + color: #344356; font-weight: 500; - background-color: #F8F9FA; - } } - - tbody { - td { - font-size: 13px; - color: #45576F; + .total-num{ + flex: none; + width: 121px; text-align: center; - padding: 4.5px 0; - } + font-size: 15px; + color: #344356; + font-weight: 500; } - } -} - -.simulation-guide-wrap { - display: flex; - padding: 20px; - - .simulation-tit-wrap { - padding-right: 40px; - border-right: 1px solid #EEEEEE; - - span { - display: block; - position: relative; - padding-left: 60px; - font-size: 15px; - color: #14324F; - font-weight: 600; - - &::before { - content: ''; - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); - width: 40px; - height: 40px; - background: url(../../public/static/images/sub/simulation_guide.svg) no-repeat center; - background-size: cover; - } - } - } - - .simulation-guide-box { - padding-left: 40px; - - dl { - margin-bottom: 25px; - - dt { - font-size: 13px; - color: #101010; - font-weight: 600; - margin-bottom: 5px; - } - - dd { - font-size: 12px; - color: #45576F; - font-weight: 400; - line-height: 24px; - } - - &:last-child { - margin-bottom: 0; - } - } - } -} - -.module-total { - display: flex; - align-items: center; - background-color: #F8F9FA; - padding: 9px 0; - margin-right: 4px; - border: 1px solid #ECF0F4; - border-top: none; - - .total-title { - flex: 1; - text-align: center; - font-size: 13px; - color: #344356; - font-weight: 500; - } - - .total-num { - flex: none; - width: 121px; - text-align: center; - font-size: 15px; - color: #344356; - font-weight: 500; - } } // 패널 배치 집계 -.penal-wrap { - position: fixed; - top: 200px; - left: 50px; - z-index: 999999; - width: 237px; - height: 40px; - line-height: 40px; - background-color: #fff; - border: 1px solid #DFDFDF; - padding: 0 34px 0 10px; - border-radius: 2px; - box-shadow: 0px 7px 14px 0px rgba(0, 0, 0, 0.05); - cursor: pointer; - - &::before { - content: ''; - position: absolute; - top: 50%; - right: 12px; - transform: translateY(-50%); - width: 10px; - height: 6px; - background: url(../../public/static/images/canvas/penal_arr.svg) no-repeat center; - background-size: cover; - } - - h2 { - font-size: 12px; - font-weight: 500; - color: #3D3D3D; - } - - .penal-table-wrap { - display: none; - position: absolute; - top: 100%; - left: -1px; - min-width: calc(100% + 2px); - background-color: #3D3D3D; - border: 1px solid #3D3D3D; - padding: 20px; - - .penal-table { - table-layout: fixed; - border-collapse: collapse; - - thead { - th { - text-align: center; - background-color: rgba(255, 255, 255, 0.05); - font-size: 12px; - font-weight: 500; - color: #fff; - border: 1px solid #505050; +.penal-wrap{ + position: fixed; + top: 200px; + left: 50px; + z-index: 999999; + width: 237px; + height: 40px; + line-height: 40px; + background-color: #fff; + border: 1px solid #DFDFDF; + padding: 0 34px 0 10px; + border-radius: 2px; + box-shadow: 0px 7px 14px 0px rgba(0, 0, 0, 0.05); + cursor: pointer; + &::before{ + content: ''; + position: absolute; + top: 50%; + right: 12px; + transform: translateY(-50%); + width: 10px; + height: 6px; + background: url(../../public/static/images/canvas/penal_arr.svg)no-repeat center; + background-size: cover; + } + h2{ + font-size: 12px; + font-weight: 500; + color: #3D3D3D; + } + .penal-table-wrap{ + display: none; + position: absolute; + top: 100%; + left: -1px; + min-width: calc(100% + 2px); + background-color: #3D3D3D; + border: 1px solid #3D3D3D; + padding: 20px; + .penal-table{ + table-layout: fixed; + border-collapse: collapse; + thead{ + th{ + text-align: center; + background-color:rgba(255, 255, 255, 0.05); + font-size: 12px; + font-weight: 500; + color: #fff; + border: 1px solid #505050; + } + } + tbody{ + td{ + font-size: 12px; + color: #fff; + font-weight: 400; + text-align: center; + padding: 0 10px; + border: 1px solid #505050; + } + } } - } - - tbody { - td { - font-size: 12px; - color: #fff; - font-weight: 400; - text-align: center; - padding: 0 10px; - border: 1px solid #505050; + } + &.act{ + border: 1px solid #3D3D3D; + background-color: #3D3D3D; + h2{ + color: #fff; + } + &::before{ + background: url(../../public/static/images/canvas/penal_arr_white.svg)no-repeat center; + } + .penal-table-wrap{ + display: block; } - } } - } - - &.act { - border: 1px solid #3D3D3D; - background-color: #3D3D3D; - - h2 { - color: #fff; - } - - &::before { - background: url(../../public/static/images/canvas/penal_arr_white.svg) no-repeat center; - } - - .penal-table-wrap { - display: block; - } - } } \ No newline at end of file diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss index 16ef74e1..705550d5 100644 --- a/src/styles/_modal.scss +++ b/src/styles/_modal.scss @@ -787,7 +787,6 @@ $alert-color: #101010; display: table-cell; vertical-align: middle; padding-bottom: 14px; - text-align: left; } .eaves-keraba-td { diff --git a/src/styles/_reset.scss b/src/styles/_reset.scss index bd76935a..7804b800 100644 --- a/src/styles/_reset.scss +++ b/src/styles/_reset.scss @@ -1,21 +1,18 @@ * { - -webkit-text-size-adjust: none; - -moz-text-size-adjust: none; - -ms-text-size-adjust: none; - text-size-adjust: none; - box-sizing: content-box + -webkit-text-size-adjust:none; + -moz-text-size-adjust:none; + -ms-text-size-adjust:none; + text-size-adjust: none; + box-sizing: content-box } - *, ::after, ::before { - box-sizing: border-box; + box-sizing: border-box; } - -html, body { - width: 100%; - height: 100%; - font-size: 16px; +html, body{ + width: 100%; + height: 100%; + font-size: 16px; } - html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, @@ -25,837 +22,704 @@ b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, canvas, details, embed, -figure, figcaption, footer, header, hgroup, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font: inherit; - vertical-align: baseline; - font-family: 'Noto Sans JP', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-smooth: never; + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; + font-family: 'Noto Sans JP', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-smooth: never; } - /* HTML5 display-role reset for older browsers */ -article, aside, details, figcaption, figure, +article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { - display: block; + display: block; } - body { - line-height: 1.4; -} - -body:first-of-type caption { - display: none; + line-height: 1.4; } +body:first-of-type caption { display:none;} ol, ul { - list-style: none; + list-style: none; } - blockquote, q { - quotes: none; + quotes: none; } - blockquote:before, blockquote:after, q:before, q:after { - content: ''; - content: none; + content: ''; + content: none; } - table { - width: 100%; - border-collapse: separate; - border-spacing: 0; - border: 0 none; + width: 100%; + border-collapse: separate; + border-spacing:0; + border:0 none; } - caption, th, td { - text-align: left; - font-weight: normal; - border: 0; + text-align:left; + font-weight: normal; + border:0; } -a { - cursor: pointer; - color: #000; +a { + cursor:pointer; + color:#000; } - a, a:hover, a:active { - text-decoration: none; - -webkit-tap-highlight-color: transparent; + text-decoration:none; + -webkit-tap-highlight-color: transparent; } - /*form_style*/ input, select, textarea, button, a, label { - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + -webkit-tap-highlight-color:rgba(0,0,0,0); } - -button, input[type=text], input[type=button] { - -webkit-appearance: none; - -webkit-border-radius: 0; - -webkit-appearance: none; - appearance: none; - border-radius: 0 +button,input[type=text], input[type=button] { + -webkit-appearance: none; + -webkit-border-radius: 0; + -webkit-appearance:none; + appearance: none; + border-radius: 0 } - input[type=checkbox], input[type=radio] { - box-sizing: border-box; - padding: 0; + box-sizing: border-box; + padding: 0; } - input, select, button { - border: 0 none; - outline: none; - margin: 0; + border:0 none; + outline:none; + margin:0; } - select { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } - select::-ms-expand { - display: none; + display: none; } - ::-webkit-input-placeholder { - line-height: 1; - font-weight: 300; - font-size: 0.938rem; - letter-spacing: -0.6px; - color: #8b8b8b; + line-height:1; + font-weight:300; + font-size:0.938rem; + letter-spacing:-0.6px; + color:#8b8b8b; } - -.log-box ::-webkit-input-placeholder { - color: #8b8b8b; +.log-box ::-webkit-input-placeholder{ + color:#8b8b8b; } - -button { - background: transparent; - font-family: 'Noto Sans JP', sans-serif; - border: none; - padding: 0; - margin: 0; - line-height: 1.4; - color: inherit; - outline: none; - cursor: pointer; +button{ + background: transparent; + font-family: 'Noto Sans JP', sans-serif; + border: none; + padding: 0; + margin: 0; + line-height: 1.4; + color: inherit; + outline: none; + cursor: pointer; } - -.pre { - font-family: 'Pretendard', sans-serif !important; +.pre{ + font-family: 'Pretendard', sans-serif !important; } // margin -.mt5 { - margin-top: 5px !important; -} - -.mt10 { - margin-top: 10px !important; -} - -.mt15 { - margin-top: 15px !important; -} - -.mb5 { - margin-bottom: 5px !important; -} - -.mb10 { - margin-bottom: 10px !important; -} - -.mb15 { - margin-bottom: 15px !important; -} - -.mr5 { - margin-right: 5px !important; -} - -.mr10 { - margin-right: 10px !important; -} - -.mr15 { - margin-right: 15px !important; -} - -.ml5 { - margin-left: 5px !important; -} - -.ml10 { - margin-left: 10px !important; -} - -.ml15 { - margin-left: 15px !important; -} +.mt5{margin-top: 5px !important;} +.mt10{margin-top: 10px !important;} +.mt15{margin-top: 15px !important;} +.mb5{margin-bottom: 5px !important;} +.mb10{margin-bottom: 10px !important;} +.mb15{margin-bottom: 15px !important;} +.mr5{margin-right: 5px !important;} +.mr10{margin-right: 10px !important;} +.mr15{margin-right: 15px !important;} +.ml5{margin-left: 5px !important;} +.ml10{margin-left: 10px !important;} +.ml15{margin-left: 15px !important;} // align -.l { - text-align: left !important; -} - -.r { - text-align: right !important; -} - -.c { - text-align: center !important; -} +.al-l{text-align: left !important;} +.al-r{text-align: right !important;} +.al-c{text-align: center !important;} // button -.btn-frame { - display: inline-block; - padding: 0 7px; - height: 34px; - line-height: 34px; - border-radius: 2px; - color: #fff; - font-size: 12px; - font-weight: 400; - border: 1px solid #000; - text-align: center; - font-family: 'Pretendard', sans-serif; - transition: all .17s ease-in-out; - cursor: pointer; - - &.block { - width: 100%; - } - - &.small { - font-family: 'Noto Sans JP', sans-serif; - height: 30px; - line-height: 30px; - font-size: 13px; - } - - &.deepgray { - background-color: #2C2C2C; - border: 1px solid #484848; - } - - &.gray { - background-color: #3C3C3C; - border: 1px solid #545454; - } - - &.dark { - background-color: #1C1C1C; - border: 1px solid #484848; - } - - &.modal { - font-family: 'Noto Sans JP', sans-serif; - background-color: #272727; - border: 1px solid #484848; - color: #aaa; - - &:hover { - background-color: #1083E3; - border: 1px solid #1083E3; - color: #fff; - font-weight: 500; - } - } - - &.sub-tab { - height: 30px; - padding: 0 10px; - line-height: 28px; - font-family: 'Noto Sans JP', sans-serif; - background-color: #2D2D2D; - border: 1px solid #393939; - color: #aaa; - - &.act, - &:hover { - background-color: #414E6C; - border: 1px solid #414E6C; - color: #fff; - font-weight: 500; - } - } - - &:hover, - &.act { - background-color: #1083E3; - border: 1px solid #1083E3; +.btn-frame{ + display: inline-block; + padding: 0 7px; + height: 34px; + line-height: 34px; + border-radius: 2px; color: #fff; - font-weight: 500; - } - - &.block { - display: block; - width: 100%; - } - - &.ico-flx { - display: flex; - align-items: center; - - .ico { - margin-right: 10px; + font-size: 12px; + font-weight: 400; + border: 1px solid #000; + text-align: center; + font-family: 'Pretendard', sans-serif; + transition: all .17s ease-in-out; + cursor: pointer; + &.block{ + width: 100%; + } + &.small{ + font-family: 'Noto Sans JP', sans-serif; + height: 30px; + line-height: 30px; + font-size: 13px; } + &.deepgray{ + background-color: #2C2C2C; + border: 1px solid #484848; + } + &.gray{ + background-color: #3C3C3C; + border: 1px solid #545454; + } + &.dark{ + background-color: #1C1C1C; + border: 1px solid #484848; + } + &.modal{ + font-family: 'Noto Sans JP', sans-serif; + background-color: #272727; + border: 1px solid #484848; + color: #aaa; + &:hover{ + background-color: #1083E3; + border: 1px solid #1083E3; + color: #fff; + font-weight: 500; + } + } + &.sub-tab{ + height: 30px; + padding: 0 10px; + line-height: 28px; + font-family: 'Noto Sans JP', sans-serif; + background-color: #2D2D2D; + border: 1px solid #393939; + color: #aaa; + &.act, + &:hover{ + background-color: #414E6C; + border: 1px solid #414E6C; + color: #fff; + font-weight: 500; + } + } &:hover, - &.act { - font-weight: 400; + &.act{ + background-color: #1083E3; + border: 1px solid #1083E3; + color: #fff; + font-weight: 500; } - } + &.block{ + display: block; + width: 100%; + } + &.ico-flx{ + display: flex; + align-items: center; + .ico{ + margin-right: 10px; + } + &:hover, + &.act{ + font-weight: 400; + } + } } -.btn-origin { - display: inline-block; - height: 30px; - padding: 0 14px; - border-radius: 2px; - background-color: #101010; - color: #fff; - font-size: 13px; - font-weight: 400; - transition: all .15s ease-in-out; - - &.navy { - background-color: #304961; - - &:hover { - background-color: #1083E3; +.btn-origin{ + display: inline-block; + height: 30px; + padding: 0 14px; + border-radius: 2px; + background-color: #101010; + color: #fff; + font-size: 13px; + font-weight: 400; + transition: all .15s ease-in-out; + &.navy{ + background-color: #304961; + &:hover{ + background-color: #1083E3; + } } - } - - &.grey { - background-color: #94A0AD; - - &:hover { - background-color: #607F9A; + &.grey{ + background-color: #94A0AD; + &:hover{ + background-color: #607F9A; + } } - } } // select -.sort-select { - position: relative; - display: inline-block; - min-width: 100px; - height: 30px; - line-height: 30px; - padding: 0 25px 0 10px; - background-color: #373737; - border: 1px solid #3F3F3F; - border-radius: 2px; - border-top-left-radius: 2px; - color: #fff; - cursor: pointer; - - p { - font-size: 13px; - color: #fff; - height: 100%; - } - - .select-item-wrap { - position: absolute; - top: 100%; - left: -1px; - clip-path: inset(0 0 100% 0); - width: calc(100% + 2px); - padding: 8px 0; - max-height: 100px; - overflow-y: auto; +.sort-select{ + position: relative; + display: inline-block; + min-width: 100px; + height: 30px; + line-height: 30px; + padding: 0 25px 0 10px; background-color: #373737; border: 1px solid #3F3F3F; border-radius: 2px; - transition: all 0.17s ease-in-out; - visibility: hidden; - z-index: 999; - - .select-item { - display: flex; - align-items: center; - padding: 8px 20px; - line-height: 1.4; - transition: all .17s ease-in-out; - - button { - font-size: 12px; + border-top-left-radius: 2px; + color: #fff; + cursor: pointer; + p{ + font-size: 13px; color: #fff; - line-height: 1.4; - } - - &:hover { - background-color: #2C2C2C; - } + height: 100%; } - - &::-webkit-scrollbar { - width: 2px; - background-color: transparent; - + .select-item-wrap{ + position: absolute; + top: 100%; + left: -1px; + clip-path:inset(0 0 100% 0); + width: calc(100% + 2px); + padding: 8px 0; + max-height: 100px; + overflow-y: auto; + background-color: #373737; + border: 1px solid #3F3F3F; + border-radius: 2px; + transition: all 0.17s ease-in-out; + visibility: hidden; + z-index: 999; + .select-item{ + display: flex; + align-items: center; + padding: 8px 20px; + line-height: 1.4; + transition: all .17s ease-in-out; + button{ + font-size: 12px; + color: #fff; + line-height: 1.4; + } + &:hover{ + background-color: #2C2C2C; + } + } + &::-webkit-scrollbar { + width: 2px; + background-color: transparent; + + } + &::-webkit-scrollbar-thumb { + background-color: #5a5a5a; + border-radius: 10px; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } } - - &::-webkit-scrollbar-thumb { - background-color: #5a5a5a; - border-radius: 10px; + &::after{ + content: ''; + position: absolute; + top: 50%; + right: 7px; + transform: translateY(-50%); + width: 10px; + height: 6px; + background: url(/static/images/common/select-arr.svg) no-repeat center; + background-size: cover; + transition: all .17s ease-in-out; } - - &::-webkit-scrollbar-track { - background-color: transparent; + &.active{ + .select-item-wrap{ + clip-path: inset(0 0 0 0); + visibility: visible; + } + &:after{ + transform: translateY(-50%) rotate(-180deg); + } } - } - - &::after { - content: ''; - position: absolute; - top: 50%; - right: 7px; - transform: translateY(-50%); - width: 10px; - height: 6px; - background: url(/static/images/common/select-arr.svg) no-repeat center; - background-size: cover; - transition: all .17s ease-in-out; - } - - &.active { - .select-item-wrap { - clip-path: inset(0 0 0 0); - visibility: visible; - } - - &:after { - transform: translateY(-50%) rotate(-180deg); - } - } } -.select-light { - position: relative; - display: block; - width: 100%; - height: 30px; - background: #FFF url(../../public/static/images/common/select_light_arr.svg) calc(100% - 11px) center no-repeat; - background-size: 10px 6px; - border: 1px solid #eee; - padding: 0 30px 0 10px; - font-size: 13px; - color: #45576F; - font-family: 'Noto Sans JP', sans-serif; - cursor: pointer; - - &:disabled { - opacity: 1; - background-color: #FAFAFA; - color: #999; - cursor: default; - } - - &.black { - color: #101010; - } - - &.dark { - background: #323234 url(../../public/static/images/common/select_dark_arr.svg) calc(100% - 11px) center no-repeat; - color: #898989; - font-size: 12px; - border-radius: 2px; - border: none; - } +.select-light{ + position: relative; + display: block; + width: 100%; + height: 30px; + background: #FFF url(../../public/static/images/common/select_light_arr.svg) calc(100% - 11px) center no-repeat; + background-size: 10px 6px; + border: 1px solid #eee; + padding: 0 30px 0 10px; + font-size: 13px; + color: #45576F; + font-family: 'Noto Sans JP', sans-serif; + cursor: pointer; + &:disabled{ + opacity: 1; + background-color: #FAFAFA; + color: #999; + cursor: default; + } + &.black{ + color: #101010; + } + &.dark{ + background: #323234 url(../../public/static/images/common/select_dark_arr.svg) calc(100% - 11px) center no-repeat; + color: #898989; + font-size: 12px; + border-radius: 2px; + border: none; + } } // input -.form-input { - label { - display: block; - color: #aaa; - font-size: 12px; - font-weight: 500; - margin-bottom: 10px; - } +.form-input{ + label{ + display: block; + color: #aaa; + font-size: 12px; + font-weight: 500; + margin-bottom: 10px; + } } - input[type=number], -input[type=text] { - &.input-origin { - display: inline-block; - height: 30px; - line-height: 30px; - border-radius: 2px; - background-color: #323234; - color: #fff; - font-size: 12px; - font-weight: 500; - font-family: 'Pretendard', sans-serif; - padding: 0 10px; - letter-spacing: 0px; - text-align: right; - - &::placeholder { - opacity: 1; - font-size: 12px; - letter-spacing: 0px; +input[type=text]{ + &.input-origin{ + display: inline-block; + height: 30px; + line-height: 30px; + border-radius: 2px; + background-color: #323234; + color: #fff; + font-size: 12px; + font-weight: 500; + font-family: 'Pretendard', sans-serif; + padding: 0 10px; + letter-spacing: 0px; + text-align: right; + &::placeholder{ + opacity: 1; + font-size: 12px; + letter-spacing: 0px; + } + &.block{ + width: 100%; + } + &:read-only{ + color: #AAA; + } + &.plane{ + font-family: 'Noto Sans JP', sans-serif; + border: 1px solid #525252; + background-color: transparent; + } } - - &.block { - width: 100%; + &.input-light{ + display: block; + width: 100%; + height: 30px; + padding: 0 10px; + border: 1px solid #eee; + border-radius: 2px; + background-color: #fff; + font-family: 'Noto Sans JP', sans-serif; + font-size: 13px; + color: #45576F; + font-weight: normal; + transition: border-color .17s ease-in-out; + text-align: left; + &:read-only{ + background-color: #FAFAFA; + color: #999999; + } } - - &:read-only { - color: #AAA; - } - - &.plane { - font-family: 'Noto Sans JP', sans-serif; - border: 1px solid #525252; - background-color: transparent; - } - } - - &.input-light { - display: block; - width: 100%; - height: 30px; - padding: 0 10px; - border: 1px solid #eee; - border-radius: 2px; - background-color: #fff; - font-family: 'Noto Sans JP', sans-serif; - font-size: 13px; - color: #45576F; - font-weight: normal; - transition: border-color .17s ease-in-out; - text-align: left; - - &:read-only { - background-color: #FAFAFA; - color: #999999; - } - } } + // check-btn -.check-btn { - display: flex; - align-items: center; - height: 30px; - background-color: #3A3A3A; - border-radius: 3px; - transition: all .17s ease-in-out; - - .check-area { - flex: none; - width: 30px; - height: 100%; - border-right: 1px solid #272727; - background: url(../../public/static/images/canvas/check-grey.svg) no-repeat center; - background-size: 11px 9px; - } - - .title-area { - padding: 0 10px; - font-size: 12px; - color: #898989; - font-weight: 400; - } - - &.block { - width: 100%; - } - - &:hover, - &.act { - background-color: #fff; - - .check-area { - border-right: 1px solid #101010; - background: url(../../public/static/images/canvas/check-black.svg) no-repeat center; +.check-btn{ + display: flex; + align-items: center; + height: 30px; + background-color: #3A3A3A; + border-radius: 3px; + transition: all .17s ease-in-out; + .check-area{ + flex: none; + width: 30px; + height: 100%; + border-right: 1px solid #272727; + background: url(../../public/static/images/canvas/check-grey.svg)no-repeat center; + background-size: 11px 9px; } - - .title-area { - color: #101010; - font-weight: 600; + .title-area{ + padding: 0 10px; + font-size: 12px; + color: #898989; + font-weight: 400; + } + &.block{ + width: 100%; + } + &:hover, + &.act{ + background-color: #fff; + .check-area{ + border-right: 1px solid #101010; + background: url(../../public/static/images/canvas/check-black.svg)no-repeat center; + } + .title-area{ + color: #101010; + font-weight: 600; + } } - } } // arr-btn -.arr-btn { - display: block; - height: 30px; - border-radius: 3px; - background-color: #3A3A3A; - padding: 0 11px; - text-align: left; - transition: all .17s ease-in-out; - - span { - position: relative; - font-size: 12px; - color: #898989; - font-weight: 400; - padding-right: 15px; - - &:after { - content: ''; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - width: 5px; - height: 8px; - background: url(../../public/static/images/canvas/arr_btn_ico.svg) no-repeat center; +.arr-btn{ + display: block; + height: 30px; + border-radius: 3px; + background-color: #3A3A3A; + padding: 0 11px; + text-align: left; + transition: all .17s ease-in-out; + span{ + position: relative; + font-size: 12px; + color: #898989; + font-weight: 400; + padding-right: 15px; + &:after{ + content: ''; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + width: 5px; + height: 8px; + background: url(../../public/static/images/canvas/arr_btn_ico.svg)no-repeat center; + } } - } - - &:hover, - &.act { - background-color: #fff; - - span { - color: #101010; - font-weight: 500; - - &:after { - background: url(../../public/static/images/canvas/arr_btn_ico_black.svg) no-repeat center; - } - } - } - - &.dark { - text-align: center; - background-color: #272727; - border: 1px solid #484848; - - span { - color: #Fff; - - &:after { - background: url(../../public/static/images/canvas/arr_btn_ico_white.svg) no-repeat center; - } - } - &:hover, - &.act { - background-color: #1083E3; - border: 1px solid #1083E3; + &.act{ + background-color: #fff; + span{ + color: #101010; + font-weight: 500; + &:after{ + background: url(../../public/static/images/canvas/arr_btn_ico_black.svg)no-repeat center; + } + } + } + &.dark{ + text-align: center; + background-color: #272727; + border: 1px solid #484848; + span{ + color: #Fff; + &:after{ + background: url(../../public/static/images/canvas/arr_btn_ico_white.svg)no-repeat center; + } + } + &:hover, + &.act{ + background-color: #1083E3; + border: 1px solid #1083E3; + } } - } } // radio .d-check-radio, -.d-check-box { - line-height: 1.1; - cursor: pointer; - - input[type=checkbox], - input[type=radio] { - position: static; - margin-left: 0; +.d-check-box{ + line-height: 1.1; cursor: pointer; - opacity: 0; - z-index: 1; - flex: 0 0 auto; - } - - label { - position: relative; - padding-left: 10px; - margin-bottom: 0; - word-break: break-all; - line-height: 1.2; - display: inline; - vertical-align: top; - color: #fff; - font-size: 13px; - font-weight: 400; - cursor: pointer; - } - - &.light { - label { - color: #45576F; + input[type=checkbox], + input[type=radio]{ + position: static; + margin-left: 0; + cursor: pointer; + opacity: 0; + z-index: 1; + flex: 0 0 auto; } - } - - &.no-text { - label { - padding-left: 0; + label{ + position: relative; + padding-left: 10px; + margin-bottom: 0; + word-break: break-all; + line-height: 1.2; + display: inline; + vertical-align: top; + color: #fff; + font-size: 13px; + font-weight: 400; + cursor: pointer; + } + &.light{ + label{ + color: #45576F; + } + } + &.no-text{ + label{ + padding-left: 0; + } } - } } .d-check-radio { - label { - &::before { - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 17px; - height: 17px; - top: 2px; - left: 0; - margin-left: -12px; - border: 1px solid #999999; - border-radius: 100%; - background-color: transparent; - text-align: center; - font-size: 13px; - line-height: 1.4; - transition: border 0.15s ease-in-out, color 0.15s ease-in-out; + label{ + &::before{ + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 17px; + height: 17px; + top:2px; + left: 0; + margin-left: -12px; + border: 1px solid #999999; + border-radius: 100%; + background-color: transparent; + text-align:center; + font-size:13px; + line-height:1.4; + transition: border 0.15s ease-in-out, color 0.15s ease-in-out; + } + &::after{ + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 9px; + height: 9px; + top:6px; + left: 4px; + margin-left: -12px; + border: none; + border-radius: 100%; + background-color: #fff; + text-align:center; + font-size:13px; + line-height:1.4; + opacity: 0; + visibility: hidden; + transition: opacity 0.15s ease-in-out, color 0.15s ease-in-out; + } } - - &::after { - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 9px; - height: 9px; - top: 6px; - left: 4px; - margin-left: -12px; - border: none; - border-radius: 100%; - background-color: #fff; - text-align: center; - font-size: 13px; - line-height: 1.4; - opacity: 0; - visibility: hidden; - transition: opacity 0.15s ease-in-out, color 0.15s ease-in-out; + &.light{ + label{ + &:before{ + border-color: #D6D6D7; + } + &:after{ + background-color: #697C8F; + } + } } - } - - &.light { - label { - &:before { - border-color: #D6D6D7; - } - - &:after { - background-color: #697C8F; - } + input[type=radio]:checked + label::after{ + opacity: 1; + visibility: visible; } - } - - input[type=radio]:checked + label::after { - opacity: 1; - visibility: visible; - } - - &.pop { - label { - font-size: 12px; - - &:before { - width: 16px; - height: 16px; - border-color: #fff; - } - - &:after { - width: 8px; - height: 8px; - background-color: #fff; - } + &.pop{ + label{ + font-size: 12px; + &:before{ + width: 16px; + height: 16px; + border-color: #fff; + } + &:after{ + width: 8px; + height: 8px; + background-color: #fff; + } + } } - } } // check-box -.d-check-box { - label { - &::before { - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 17px; - height: 17px; - top: 2px; - left: 0; - margin-left: -12px; - border: 1px solid #D6D6D7; - background-color: transparent; - transition: border 0.15s ease-in-out, color 0.15s ease-in-out; +.d-check-box{ + label{ + &::before{ + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 17px; + height: 17px; + top: 2px; + left: 0; + margin-left: -12px; + border: 1px solid #D6D6D7; + background-color: transparent; + transition: border 0.15s ease-in-out, color 0.15s ease-in-out; + } + &:after{ + cursor: pointer; + content: ""; + display: inline-block; + position: absolute; + width: 16px; + height: 16px; + top:0; + left: 0; + margin-left: -.8rem; + transition: border 0.05s ease-in-out, color 0.05s ease-in-out; + } } - - &:after { - cursor: pointer; - content: ""; - display: inline-block; - position: absolute; - width: 16px; - height: 16px; - top: 0; - left: 0; - margin-left: -.8rem; - transition: border 0.05s ease-in-out, color 0.05s ease-in-out; + input[type=checkbox]:checked + label::after{ + content: ""; + display: inline-block; + position: absolute; + top: 1px; + left: -1px; + width: 5px; + height: 8px; + border: 2px solid #697C8F; + border-left: none; + border-top: none; + transform: translate(7.75px,4.5px) rotate(45deg); + -ms-transform: translate(7.75px,4.5px) rotate(45deg); } - } - - input[type=checkbox]:checked + label::after { - content: ""; - display: inline-block; - position: absolute; - top: 1px; - left: -1px; - width: 5px; - height: 8px; - border: 2px solid #697C8F; - border-left: none; - border-top: none; - transform: translate(7.75px, 4.5px) rotate(45deg); - -ms-transform: translate(7.75px, 4.5px) rotate(45deg); - } - - &.pop { - input[type=checkbox]:checked + label::after { - border-color: #fff; + &.pop{ + input[type=checkbox]:checked + label::after{ + border-color: #fff; + } } - } } // date-picker -.date-picker { - svg { - display: none; - } - - .react-datepicker-wrapper { - width: 100%; - } - - input[type=text] { - display: block; - width: 100%; - height: 30px; - padding: 0 34px 0 10px; - border-radius: 2px; - border: 1px solid #eee; - font-size: 13px; - color: #45576F; - font-weight: normal; - font-family: 'Noto Sans JP', sans-serif; - background: #fff url(../../public/static/images/common/datepicker.svg) calc(100% - 11px) center no-repeat; - background-size: 14px 15px; - cursor: pointer; - } +.date-picker{ + svg{display: none;} + .react-datepicker-wrapper{ + width: 100%; + } + input[type=text]{ + display: block; + width: 100%; + height: 30px; + padding: 0 34px 0 10px; + border-radius: 2px; + border: 1px solid #eee; + font-size: 13px; + color: #45576F; + font-weight: normal; + font-family: 'Noto Sans JP', sans-serif; + background: #fff url(../../public/static/images/common/datepicker.svg) calc(100% - 11px) center no-repeat; + background-size: 14px 15px; + cursor: pointer; + } } \ No newline at end of file diff --git a/src/styles/_table.scss b/src/styles/_table.scss index ceaea36b..a87bfc5b 100644 --- a/src/styles/_table.scss +++ b/src/styles/_table.scss @@ -1,215 +1,205 @@ -@mixin flexbox() { - display: flex; - align-items: center; +@mixin flexbox(){ + display: flex; + align-items: center; } -table { - .overflow-lab { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - } - - .al-l { - text-align: left !important; - } +table{ + .overflow-lab{ + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + .al-l{ + text-align: left !important; + } } -.common-table { - table { - table-layout: fixed; - border: 1px solid #ECF0F4; - border-radius: 3px; - border-collapse: collapse; - - tbody { - th { - font-size: 13px; - font-weight: 500; - color: #344356; - padding: 14px 12px; - border: 1px solid #ECF0F4; - background-color: #F7F9FA; - vertical-align: middle; - } - - td { - padding: 9px; - border: 1px solid #ECF0F4; - font-size: 13px; - font-weight: 400; - color: #45576F; - vertical-align: middle; - - .radio-wrap { - flex: none; - @include flexbox; - } - - .form-flex-wrap { - @include flexbox; - } - - .date-picker-wrap { - width: 100%; - @include flexbox; - - span { - margin: 0 4px; - } - } - } - } - } - - &.bt-able { - margin-bottom: 30px; - } -} - -.infomation-table { - table { - border-top: 1px solid #DEE3EA; - border-bottom: 1px solid #DEE3EA; - border-collapse: collapse; - - tbody { - tr { - th { - font-size: 13px; - color: #344356; - font-weight: 500; - padding: 18px 0; - border-bottom: 1px solid #F4F4F7; - - .title { - margin-right: 8px; - } - } - - td { - padding: 0 0 0 15px; - border-bottom: 1px solid #F4F4F7; - - .guide { - font-size: 13px; - color: #697C8F; - font-weight: normal; - margin-left: 15px; - } - - span { - font-size: 13px; - color: #697C8F; - font-weight: normal; - } - } - - &:last-child { - th, td { - border-bottom: none; - } - } - } - } - - .flx-box { - @include flexbox; - } - } - - .tooltips { - display: block; - width: 14px; - height: 14px; - display: inline-block; - background: url(../../public/static/images/sub/tooltips.svg) no-repeat center; - background-size: cover; - cursor: pointer; - } -} - -.module-table { - table { - table-layout: fixed; - border-collapse: collapse; - - thead { - display: table; - table-layout: fixed; - width: 100%; - - th { - padding: 13px 0; - font-size: 13px; - color: #344356; - font-weight: 500; - border-bottom: 2px solid #E0E5EB; - text-align: center; - } - } - - tbody { - display: block; - overflow-y: auto; - - tr { - display: table; +.common-table{ + table{ table-layout: fixed; - width: 100%; border: 1px solid #ECF0F4; - - td { - padding: 10px 0px; - font-size: 13px; - color: #45576F; - font-weight: 400; - text-align: center; + border-radius: 3px; + border-collapse:collapse; + tbody{ + th{ + font-size: 13px; + font-weight: 500; + color: #344356; + padding: 14px 12px; + border: 1px solid #ECF0F4 ; + background-color: #F7F9FA; + vertical-align: middle; + } + td{ + padding: 9px; + border: 1px solid #ECF0F4 ; + font-size: 13px; + font-weight: 400; + color: #45576F; + vertical-align: middle; + .radio-wrap{ + flex: none; + @include flexbox; + } + .form-flex-wrap{ + @include flexbox; + } + .date-picker-wrap{ + width: 100%; + @include flexbox; + span{ + margin: 0 4px; + } + } + } } - } - - &::-webkit-scrollbar { - width: 4px; - background-color: transparent; - } - - &::-webkit-scrollbar-thumb { - background-color: #C1CCD7; - } - - &::-webkit-scrollbar-track { - background-color: transparent; - } } - - &.small { - tbody { - height: 120px; - } + &.bt-able{ + margin-bottom: 30px; } - - &.big { - td, - th { - &:nth-child(2) { - width: 121px; - } - } - - tbody { - height: 160px; - - td { - padding: 10px 20px; - } - } - } - } } -.roof-module-table { - table { - table-layout: fixed; - border-collapse: collapse; - } +.infomation-table{ + table{ + border-top: 1px solid #DEE3EA; + border-bottom: 1px solid #DEE3EA; + border-collapse:collapse; + tbody{ + tr{ + th{ + font-size: 13px; + color: #344356; + font-weight: 500; + padding: 18px 0; + border-bottom: 1px solid #F4F4F7; + .title{ + margin-right: 8px; + } + } + td{ + padding: 0 0 0 15px; + border-bottom: 1px solid #F4F4F7; + + .guide{ + font-size: 13px; + color: #697C8F; + font-weight: normal; + margin-left: 15px; + } + span{ + font-size: 13px; + color: #697C8F; + font-weight: normal; + } + } + &:last-child{ + th,td{border-bottom: none;} + } + } + } + .flx-box{ + @include flexbox; + } + } + .tooltips{ + display: block; + width: 14px; + height: 14px; + display: inline-block; + background: url(../../public/static/images/sub/tooltips.svg)no-repeat center; + background-size: cover; + cursor: pointer; + } +} + +.module-table{ + table{ + table-layout: fixed; + border-collapse: collapse; + thead{ + display: table; + table-layout: fixed; + width: 100%; + th{ + padding: 13px 0; + font-size: 13px; + color: #344356; + font-weight: 500; + border-bottom: 2px solid #E0E5EB; + text-align: center; + } + } + tbody{ + display: block; + overflow-y: auto; + tr{ + display: table; + table-layout: fixed; + width: 100%; + border: 1px solid #ECF0F4; + td{ + padding: 10px 0px; + font-size: 13px; + color: #45576F; + font-weight: 400; + text-align: center; + } + } + &::-webkit-scrollbar { + width: 4px; + background-color: transparent; + } + &::-webkit-scrollbar-thumb { + background-color: #C1CCD7; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } + } + &.small{ + tbody{height: 120px;} + } + &.big{ + td, + th{ + &:nth-child(2){ + width: 121px; + } + } + tbody{ + height: 160px; + td{ + padding: 10px 20px; + } + } + } + } +} + +.roof-module-table{ + table{ + border-collapse: collapse; + thead{ + th{ + height: 40px; + padding: 0 10px; + font-size: 12px; + color: #fff; + font-weight: 500; + border: 1px solid #505050; + vertical-align: middle; + background-color: rgba(255, 255, 255, 0.05); + text-align: center; + word-break: keep-all; + } + } + tbody{ + td{ + font-size: 12px; + color: #fff; + font-weight: 400; + border: 1px solid #505050; + } + } + } } \ No newline at end of file From 547669384d99f449f0e06c1cc1afc74059f4aee1 Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 15:18:46 +0900 Subject: [PATCH 052/152] =?UTF-8?q?=EC=B2=98=EB=A7=88.=EC=BC=80=EB=9D=BC?= =?UTF-8?q?=EB=B0=94=20=EB=B3=80=EA=B2=BD=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/static/images/canvas/eaves_icon09.svg | 10 ++++++++++ public/static/images/canvas/eaves_icon10.svg | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 public/static/images/canvas/eaves_icon09.svg create mode 100644 public/static/images/canvas/eaves_icon10.svg diff --git a/public/static/images/canvas/eaves_icon09.svg b/public/static/images/canvas/eaves_icon09.svg new file mode 100644 index 00000000..fe4512b1 --- /dev/null +++ b/public/static/images/canvas/eaves_icon09.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/static/images/canvas/eaves_icon10.svg b/public/static/images/canvas/eaves_icon10.svg new file mode 100644 index 00000000..99147480 --- /dev/null +++ b/public/static/images/canvas/eaves_icon10.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + From 6edca86b6bbf8414bedd7df84463a684b6f5a5cd Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 15:19:23 +0900 Subject: [PATCH 053/152] =?UTF-8?q?=ED=8C=A8=EB=84=90,=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/static/images/canvas/module_tab_arr.svg | 3 +++ public/static/images/canvas/module_tab_arr_white.svg | 3 +++ public/static/images/canvas/penal_arr.svg | 3 +++ public/static/images/canvas/penal_arr_white.svg | 3 +++ 4 files changed, 12 insertions(+) create mode 100644 public/static/images/canvas/module_tab_arr.svg create mode 100644 public/static/images/canvas/module_tab_arr_white.svg create mode 100644 public/static/images/canvas/penal_arr.svg create mode 100644 public/static/images/canvas/penal_arr_white.svg diff --git a/public/static/images/canvas/module_tab_arr.svg b/public/static/images/canvas/module_tab_arr.svg new file mode 100644 index 00000000..f1da9ab2 --- /dev/null +++ b/public/static/images/canvas/module_tab_arr.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/module_tab_arr_white.svg b/public/static/images/canvas/module_tab_arr_white.svg new file mode 100644 index 00000000..49ac4437 --- /dev/null +++ b/public/static/images/canvas/module_tab_arr_white.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/penal_arr.svg b/public/static/images/canvas/penal_arr.svg new file mode 100644 index 00000000..0bd7560c --- /dev/null +++ b/public/static/images/canvas/penal_arr.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/static/images/canvas/penal_arr_white.svg b/public/static/images/canvas/penal_arr_white.svg new file mode 100644 index 00000000..e267fb93 --- /dev/null +++ b/public/static/images/canvas/penal_arr_white.svg @@ -0,0 +1,3 @@ + + + From a6a81f76b012da18c9d951a3d5ec591769893256 Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 15:20:20 +0900 Subject: [PATCH 054/152] =?UTF-8?q?=EC=B2=98=EB=A7=88.=EC=BA=90=EB=9D=BC?= =?UTF-8?q?=EB=B0=94=20=EB=B3=80=EA=B2=BD=20=EB=AA=A8=EB=8B=AC=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/components/floor-plan/CanvasMenu.jsx | 3 + src/components/floor-plan/MenuDepth01.jsx | 2 + .../modal/eavesGable/EavesGableEdit.jsx | 46 ++++++++++ .../modal/eavesGable/type/Eaves.jsx | 81 +++++++++++++++++ .../modal/eavesGable/type/Gable.jsx | 87 +++++++++++++++++++ .../floor-plan/modal/eavesGable/type/Shed.jsx | 20 +++++ .../modal/eavesGable/type/WallMerge.jsx | 59 +++++++++++++ src/locales/ja.json | 5 ++ src/locales/ko.json | 5 ++ 9 files changed, 308 insertions(+) create mode 100644 src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx create mode 100644 src/components/floor-plan/modal/eavesGable/type/Eaves.jsx create mode 100644 src/components/floor-plan/modal/eavesGable/type/Gable.jsx create mode 100644 src/components/floor-plan/modal/eavesGable/type/Shed.jsx create mode 100644 src/components/floor-plan/modal/eavesGable/type/WallMerge.jsx diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index b0fedf65..622320a8 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -41,6 +41,7 @@ export default function CanvasMenu(props) { setShowRoofShapeSettingModal, setShowRoofShapePassivitySettingModal, setShowAuxiliaryModal, + setShowEavesGableEditModal, } = props const [menuNumber, setMenuNumber] = useState(null) @@ -88,6 +89,7 @@ export default function CanvasMenu(props) { setShowRoofShapeSettingModal, setShowRoofShapePassivitySettingModal, setShowAuxiliaryModal, + setShowEavesGableEditModal, setShowSlopeSettingModal, setShowPlaceShapeDrawingModal, type, @@ -116,6 +118,7 @@ export default function CanvasMenu(props) { const onClickPlacementInitialMenu = () => { setShowOutlineModal(false) setShowCanvasSettingModal(false) + setShowEavesGableEditModal(false) setShowPlaceShapeModal(true) } diff --git a/src/components/floor-plan/MenuDepth01.jsx b/src/components/floor-plan/MenuDepth01.jsx index 4148ac5a..aa5c9f36 100644 --- a/src/components/floor-plan/MenuDepth01.jsx +++ b/src/components/floor-plan/MenuDepth01.jsx @@ -14,6 +14,7 @@ export default function MenuDepth01(props) { setShowRoofShapeSettingModal, setShowRoofShapePassivitySettingModal, setShowAuxiliaryModal, + setShowEavesGableEditModal, setShowSlopeSettingModal, setShowPlaceShapeDrawingModal, } = props @@ -31,6 +32,7 @@ export default function MenuDepth01(props) { setShowRoofShapeSettingModal(id === 1) setShowRoofShapePassivitySettingModal(id === 2) setShowAuxiliaryModal(id === 3) + setShowEavesGableEditModal(id === 4) setShowPlaceShapeDrawingModal(false) } diff --git a/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx b/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx new file mode 100644 index 00000000..e144e717 --- /dev/null +++ b/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx @@ -0,0 +1,46 @@ +import { useMessage } from '@/hooks/useMessage' +import WithDraggable from '@/components/common/draggable/withDraggable' +import { useState } from 'react' +import Eaves from '@/components/floor-plan/modal/eavesGable/type/Eaves' +import Gable from '@/components/floor-plan/modal/eavesGable/type/Gable' +import WallMerge from '@/components/floor-plan/modal/eavesGable/type/WallMerge' +import Shed from '@/components/floor-plan/modal/eavesGable/type/Shed' + +export default function EavesGableEdit({ setShowEavesGableEditModal }) { + const { getMessage } = useMessage() + const [buttonAct, setButtonAct] = useState(1) + const buttonMenu = [ + { id: 1, name: getMessage('eaves') }, + { id: 2, name: getMessage('gable') }, + { id: 3, name: getMessage('wall.merge') }, + { id: 4, name: getMessage('shed') }, + ] + return ( + +
+
+

{getMessage('modal.eaves.gable.edit')}

+ +
+
+
+ {buttonMenu.map((item) => ( + + ))} +
+
+
{getMessage('setting')}
+ {buttonAct === 1 && } + {buttonAct === 2 && } + {buttonAct === 3 && } + {buttonAct === 4 && } +
+
+
+
+ ) +} diff --git a/src/components/floor-plan/modal/eavesGable/type/Eaves.jsx b/src/components/floor-plan/modal/eavesGable/type/Eaves.jsx new file mode 100644 index 00000000..37ffd5e9 --- /dev/null +++ b/src/components/floor-plan/modal/eavesGable/type/Eaves.jsx @@ -0,0 +1,81 @@ +import { useMessage } from '@/hooks/useMessage' +import Image from 'next/image' +import { useState } from 'react' + +export default function Eaves() { + const { getMessage } = useMessage() + const [type, setType] = useState() + const onChange = (e) => { + console.log(e) + setType(e.target.value) + } + return ( + <> +
+
+ + {getMessage('slope')} + +
+ +
+ +
+
+ + {getMessage('offset')} + +
+ +
+ mm +
+
+
+
+
+
+
+ onChange(e)} /> + +
+
+
+
+ react +
+
+
+
+
+
+ onChange(e)} /> + +
+
+
+
+ react +
+
+
+
+
+
+
+ +
+ mm +
+
+
+
+ react +
+
+
+
+
+ + ) +} diff --git a/src/components/floor-plan/modal/eavesGable/type/Gable.jsx b/src/components/floor-plan/modal/eavesGable/type/Gable.jsx new file mode 100644 index 00000000..03a35f32 --- /dev/null +++ b/src/components/floor-plan/modal/eavesGable/type/Gable.jsx @@ -0,0 +1,87 @@ +import { useMessage } from '@/hooks/useMessage' +import Image from 'next/image' + +export default function Gable() { + const { getMessage } = useMessage() + return ( + <> +
+
+ + {getMessage('offset')} + +
+ +
+ mm +
+
+
+
+
+
+
+ + +
+
+
+
+ react +
+
+
+
+
+
+ + +
+
+
+
+ react +
+
+
+
+
+
+ + {getMessage('slope')} + +
+ +
+ +
+
+
+
+ react +
+
+
+
+
+
+ + {getMessage('offset')} + +
+ +
+ mm +
+
+
+
+ react +
+
+
+
+
+ + ) +} diff --git a/src/components/floor-plan/modal/eavesGable/type/Shed.jsx b/src/components/floor-plan/modal/eavesGable/type/Shed.jsx new file mode 100644 index 00000000..ebf20417 --- /dev/null +++ b/src/components/floor-plan/modal/eavesGable/type/Shed.jsx @@ -0,0 +1,20 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function Shed() { + const { getMessage } = useMessage() + return ( + <> +
+
+ + {getMessage('offset')} + +
+ +
+ mm +
+
+ + ) +} diff --git a/src/components/floor-plan/modal/eavesGable/type/WallMerge.jsx b/src/components/floor-plan/modal/eavesGable/type/WallMerge.jsx new file mode 100644 index 00000000..fbc335e6 --- /dev/null +++ b/src/components/floor-plan/modal/eavesGable/type/WallMerge.jsx @@ -0,0 +1,59 @@ +import { useMessage } from '@/hooks/useMessage' +import Image from 'next/image' + +export default function WallMerge() { + const { getMessage } = useMessage() + return ( + <> +
+
{getMessage('modal.eaves.gable.edit.wall.merge.info')}
+
+
+
+
+ + +
+
+
+
+ react +
+
+
+
+
+
+ + +
+
+
+
+ react +
+
+
+
+
+
+ + {getMessage('offset')} + +
+ +
+ mm +
+
+
+
+ react +
+
+
+
+
+ + ) +} diff --git a/src/locales/ja.json b/src/locales/ja.json index e7840358..1c681ff1 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -144,6 +144,9 @@ "modal.canvas.setting.wallline.properties.setting.info": "※属性を変更する外壁線を選択し、軒で設定またはケラバで設定 ボタンをクリックして設定値を適用します。", "modal.canvas.setting.wallline.properties.setting.eaves": "軒で設定", "modal.canvas.setting.wallline.properties.setting.edge": "ケラバに設定", + "modal.eaves.gable.edit": "軒・ケラバ変更", + "modal.eaves.gable.edit.basic": "通常", + "modal.eaves.gable.edit.wall.merge.info": "家屋などの壁に面する屋根を作成します。", "setting": "設定", "common.message.no.data": "No data", "common.message.no.dataDown": "ダウンロードするデータがありません", @@ -300,11 +303,13 @@ "slope": "傾斜", "eaves.offset": "軒の", "gable.offset": "ケラバ出幅", + "offset": "出幅", "size": "寸", "size.angle": "寸(度)", "eaves": "軒", "gable": "ケラバ", "wall": "壁", + "wall.merge": "壁取り", "hajebichi": "ハゼビーチ", "straight.line": "直線", "right.angle": "直角", diff --git a/src/locales/ko.json b/src/locales/ko.json index 675ec655..4f320cdc 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -151,6 +151,9 @@ "modal.canvas.setting.wallline.properties.setting.info": "※ 속성을 변경할 외벽선을 선택하고, 처마로 설정 또는 케라바로 설정\n 버튼을 클릭하여 설정값을 적용하십시오.\n", "modal.canvas.setting.wallline.properties.setting.eaves": "처마로 설정", "modal.canvas.setting.wallline.properties.setting.edge": "케라바로 설정", + "modal.eaves.gable.edit": "처마・케라바 변경", + "modal.eaves.gable.edit.basic": "통상", + "modal.eaves.gable.edit.wall.merge.info": "하옥 등 벽에 접하는 지붕을 작성합니다.", "setting": "설정", "common.message.no.data": "No data", "common.message.no.dataDown": "No data to download", @@ -307,11 +310,13 @@ "slope": "경사", "eaves.offset": "처마 출폭", "gable.offset": "케라바 출폭", + "offset": "출폭", "size": "치수", "size.angle": "寸(度)", "eaves": "처마", "gable": "케라바", "wall": "벽", + "wall.merge": "벽취합", "hajebichi": "하제비치", "straight.line": "직선", "right.angle": "직각", From 6f6ba1ace82109440dc33ad38bdedd5cefc8b745 Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 15:21:33 +0900 Subject: [PATCH 055/152] =?UTF-8?q?=EB=8F=99=EC=84=A0=EC=9D=B4=EB=8F=99.?= =?UTF-8?q?=ED=98=95=EC=98=AC=EB=A6=BC=EB=82=BC=EB=AF=B8=20=EB=AA=A8?= =?UTF-8?q?=EB=8B=AC=20=EC=B6=94=EA=B0=80(=EC=9E=91=EC=97=85=EC=A4=91)=20?= =?UTF-8?q?=EC=A7=80=EB=B6=95=ED=98=95=EC=83=81=20=EC=88=98=EB=8F=99=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EB=AA=A8=EB=8B=AC=20=EC=B6=94=EA=B0=80(?= =?UTF-8?q?=EC=9E=91=EC=97=85=EC=A4=91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/FloorPlan.jsx | 6 +++ .../floor-plan/modal/movement/Movement.jsx | 40 +++++++++++++++ .../roofShape/RoofShapePassivitySetting.jsx | 50 +++++++++++++++++++ .../modal/roofShape/passivity/eaves.jsx | 42 ++++++++++++++++ .../modal/roofShape/passivity/gable.jsx | 42 ++++++++++++++++ .../modal/roofShape/passivity/shed.js | 42 ++++++++++++++++ 6 files changed, 222 insertions(+) create mode 100644 src/components/floor-plan/modal/movement/Movement.jsx create mode 100644 src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx create mode 100644 src/components/floor-plan/modal/roofShape/passivity/eaves.jsx create mode 100644 src/components/floor-plan/modal/roofShape/passivity/gable.jsx create mode 100644 src/components/floor-plan/modal/roofShape/passivity/shed.js diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx index debfa4da..2c9a99c9 100644 --- a/src/components/floor-plan/FloorPlan.jsx +++ b/src/components/floor-plan/FloorPlan.jsx @@ -19,6 +19,8 @@ import PlacementShapeDrawing from '@/components/floor-plan/modal/placementShape/ import Slope from '@/components/floor-plan/modal/Slope' import RoofShapePassivitySetting from '@/components/floor-plan/modal/roofShape/RoofShapePassivitySetting' import AuxiliaryDrawing from '@/components/floor-plan/modal/auxiliary/AuxiliaryDrawing' +import EavesGableEdit from '@/components/floor-plan/modal/eavesGable/EavesGableEdit' +import Movement from '@/components/floor-plan/modal/movement/Movement' export default function FloorPlan() { const [showCanvasSettingModal, setShowCanvasSettingModal] = useState(false) @@ -30,6 +32,7 @@ export default function FloorPlan() { const [showAuxiliaryModal, setShowAuxiliaryModal] = useState(false) const [showSlopeSettingModal, setShowSlopeSettingModal] = useState(false) const [showPlaceShapeDrawingModal, setShowPlaceShapeDrawingModal] = useState(false) + const [showEavesGableEditModal, setShowEavesGableEditModal] = useState(false) const globalLocaleState = useRecoilValue(globalLocaleStore) const { get } = useAxios(globalLocaleState) @@ -62,6 +65,7 @@ export default function FloorPlan() { setShowRoofShapeSettingModal, setShowRoofShapePassivitySettingModal, setShowAuxiliaryModal, + setShowEavesGableEditModal, } useEffect(() => { @@ -128,6 +132,8 @@ export default function FloorPlan() { {showAuxiliaryModal && } {showSlopeSettingModal && } {showPlaceShapeDrawingModal && } + {showEavesGableEditModal && } +
diff --git a/src/components/floor-plan/modal/movement/Movement.jsx b/src/components/floor-plan/modal/movement/Movement.jsx new file mode 100644 index 00000000..a8a7cde4 --- /dev/null +++ b/src/components/floor-plan/modal/movement/Movement.jsx @@ -0,0 +1,40 @@ +import { useMessage } from '@/hooks/useMessage' +import WithDraggable from '@/components/common/draggable/WithDraggable' +import { useState } from 'react' + +export default function Movement({}) { + const { getMessage } = useMessage() + const [buttonAct, setButtonAct] = useState(1) + const buttonMenu = [ + { id: 1, name: '銅線の移動軒' }, + { id: 2, name: '型上げ・降り' }, + ] + + return ( + +
+
+

軒・ケラバ変更

+ +
+
+
+ {buttonMenu.map((item) => ( + + ))} +
+
+
設定
+ {/*{buttonAct === 1 && }*/} + {/*{buttonAct === 2 && }*/} +
+
+ +
+
+
+
+ ) +} diff --git a/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx b/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx new file mode 100644 index 00000000..2bd4988a --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx @@ -0,0 +1,50 @@ +import { useState } from 'react' +import WithDraggable from '@/components/common/draggable/WithDraggable' +import Eaves from '@/components/floor-plan/modal/roofShape/passivity/eaves' +import Gable from '@/components/floor-plan/modal/roofShape/passivity/gable' +import Shed from '@/components/floor-plan/modal/roofShape/passivity/shed' + +export default function RoofShapePassivitySetting({ setShowRoofShapePassivitySettingModal }) { + const [buttonAct, setButtonAct] = useState(1) + const buttons = [ + { id: 1, name: '軒' }, + { id: 2, name: 'ケラバ' }, + { id: 3, name: '漂流' }, + ] + return ( + +
+
+

屋根形状の設定

+ +
+
+
+ {buttons.map((button) => ( + + ))} +
+
+
設定
+
+ {buttonAct === 1 && } + {buttonAct === 2 && } + {buttonAct === 3 && } +
+
+ + +
+
+
+ +
+
+
+
+ ) +} diff --git a/src/components/floor-plan/modal/roofShape/passivity/eaves.jsx b/src/components/floor-plan/modal/roofShape/passivity/eaves.jsx new file mode 100644 index 00000000..99286117 --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/passivity/eaves.jsx @@ -0,0 +1,42 @@ +export default function Eaves() { + return ( + <> +
+ + 傾斜 + +
+ +
+ 寸法 +
+
+ + 軒の + +
+ +
+ mm +
+
+ + ケラバ 出幅 + +
+ +
+ mm +
+
+ + 片流幅 + +
+ +
+ mm +
+ + ) +} diff --git a/src/components/floor-plan/modal/roofShape/passivity/gable.jsx b/src/components/floor-plan/modal/roofShape/passivity/gable.jsx new file mode 100644 index 00000000..848d5d73 --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/passivity/gable.jsx @@ -0,0 +1,42 @@ +export default function Gable() { + return ( + <> +
+ + 傾斜 + +
+ +
+ 寸法 +
+
+ + 軒の + +
+ +
+ mm +
+
+ + ケラバ 出幅 + +
+ +
+ mm +
+
+ + 片流幅 + +
+ +
+ mm +
+ + ) +} diff --git a/src/components/floor-plan/modal/roofShape/passivity/shed.js b/src/components/floor-plan/modal/roofShape/passivity/shed.js new file mode 100644 index 00000000..8e767772 --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/passivity/shed.js @@ -0,0 +1,42 @@ +export default function Shed() { + return ( + <> +
+ + 傾斜 + +
+ +
+ 寸法 +
+
+ + 軒の + +
+ +
+ mm +
+
+ + ケラバ 出幅 + +
+ +
+ mm +
+
+ + 片流幅 + +
+ +
+ mm +
+ + ) +} From 4403e36e0f348f6e9de97220ebfc0fbb20ad182d Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 7 Oct 2024 15:27:22 +0900 Subject: [PATCH 056/152] =?UTF-8?q?=EB=8F=84=EB=A8=B8=20=EB=B0=B8=EB=A6=AC?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=ED=94=84=EB=A1=9C=ED=8D=BC=ED=8B=B0=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/hooks/useMode.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index ec0842b8..04ec7685 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -4873,13 +4873,14 @@ export function useMode() { let turfPolygon let manualDrawCells = drewRoofCells // 앞에서 자동으로 했을때 추가됨 let direction - + let trestlePolygon canvas.on('mouse:move', (e) => { //마우스 이벤트 삭제 후 재추가 const mousePoint = canvas.getPointer(e.e) for (let i = 0; i < trestlePolygons.length; i++) { turfPolygon = polygonToTurfPolygon(trestlePolygons[i]) + trestlePolygon = trestlePolygons[i] direction = trestlePolygons[i].direction //도형의 방향 let width = direction === 'south' || direction === 'north' ? 172 : 113 let height = direction === 'south' || direction === 'north' ? 113 : 172 @@ -5050,6 +5051,7 @@ export function useMode() { fabricPolygon.setCoords() canvas?.renderAll() inside = true + break } else { inside = false } @@ -5078,12 +5080,12 @@ export function useMode() { fabricPolygon.set({ points: rectPoints }) const tempTurfModule = polygonToTurfPolygon(fabricPolygon) + //도머 객체를 가져옴 if (dormerTrestlePolygons) { dormerTrestlePolygons.forEach((dormerTrestle) => { - const dormerTurfPolygon = polygonToTurfPolygon(dormerTrestle) - - const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) - + const dormerTurfPolygon = polygonToTurfPolygon(dormerTrestle) //turf객체로 변환 + const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) //겹치는지 확인 + //겹치면 안됨 if (intersection) { alert('도머위에 모듈을 올릴 수 없습니다.') isIntersection = false @@ -5097,18 +5099,21 @@ export function useMode() { if (turf.booleanWithin(tempTurfModule, turfPolygon)) { //마우스 클릭시 set으로 해당 위치에 셀을 넣음 - - const isOverlap = manualDrawCells.some((cell) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(cell))) + const isOverlap = manualDrawCells.some((cell) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(cell))) //겹치는지 확인 if (!isOverlap) { //안겹치면 넣는다 fabricPolygon.setCoords() fabricPolygon.set({ name: 'cell', fill: '#BFFD9F' }) - manualDrawCells.push(fabricPolygon) + manualDrawCells.push(fabricPolygon) //모듈배열에 추가 + //해당 모듈에 프로퍼티로 넣는다 + trestlePolygon.set({ + modules: manualDrawCells, + }) } else { alert('셀끼리 겹치면 안되죠?') } } else { - alert('나갔으요!!') + alert('나갔죠?!!') } setDrewRoofCells(manualDrawCells) } From e844f31cd1beda286457d9440632b1e72056e079 Mon Sep 17 00:00:00 2001 From: changkyu choi Date: Mon, 7 Oct 2024 15:34:09 +0900 Subject: [PATCH 057/152] =?UTF-8?q?useAxios=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/InitSettingsModal.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/InitSettingsModal.jsx b/src/components/InitSettingsModal.jsx index 58f0163f..5f0837a8 100644 --- a/src/components/InitSettingsModal.jsx +++ b/src/components/InitSettingsModal.jsx @@ -6,7 +6,6 @@ import { useRecoilState, useRecoilValue } from 'recoil' import { modalContent, modalState } from '@/store/modalAtom' import { canvasSettingState } from '@/store/canvasAtom' import { useAxios } from '@/hooks/useAxios' -import { get, post } from '@/lib/Axios' export default function InitSettingsModal(props) { const [objectNo, setObjectNo] = useState('test123240909003') // 후에 삭제 필요 @@ -25,6 +24,8 @@ export default function InitSettingsModal(props) { setOpen, } + const { get, post } = useAxios() + //const { get, post } = useAxios() useEffect(() => { From 1b28c4c1d2a39823e57d425302a93f2abe2c19cc Mon Sep 17 00:00:00 2001 From: changkyu choi Date: Mon, 7 Oct 2024 15:41:47 +0900 Subject: [PATCH 058/152] =?UTF-8?q?useAxios=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useCanvas.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index 0f506fd3..a33c0de2 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -11,7 +11,7 @@ import { defineQLine } from '@/util/qline-utils' import { defineQPloygon } from '@/util/qpolygon-utils' import { writeImage } from '@/lib/canvas' import { useCanvasEvent } from '@/hooks/useCanvasEvent' -import { post } from '@/lib/Axios' +import { useAxios } from '@/hooks/useAxios' import { v4 as uuidv4 } from 'uuid' export function useCanvas(id) { @@ -22,6 +22,7 @@ export function useCanvas(id) { const [canvasSize] = useRecoilState(canvasSizeState) const [fontSize] = useRecoilState(fontSizeState) const { setCanvasForEvent, attachDefaultEventOnCanvas } = useCanvasEvent() + const { post } = useAxios() /** * 처음 셋팅 From 60a70d9f93098462808ac9534e78f2c947af358a Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 15:52:55 +0900 Subject: [PATCH 059/152] =?UTF-8?q?=EB=8F=99=EC=84=A0=EC=9D=B4=EB=8F=99.?= =?UTF-8?q?=ED=98=95=EC=98=AC=EB=A6=BC=EB=82=B4=EB=A6=BC=20=EB=AA=A8?= =?UTF-8?q?=EB=8B=AC=20=EC=A3=BC=EC=84=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/FloorPlan.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx index 2c9a99c9..a1b33442 100644 --- a/src/components/floor-plan/FloorPlan.jsx +++ b/src/components/floor-plan/FloorPlan.jsx @@ -20,7 +20,6 @@ import Slope from '@/components/floor-plan/modal/Slope' import RoofShapePassivitySetting from '@/components/floor-plan/modal/roofShape/RoofShapePassivitySetting' import AuxiliaryDrawing from '@/components/floor-plan/modal/auxiliary/AuxiliaryDrawing' import EavesGableEdit from '@/components/floor-plan/modal/eavesGable/EavesGableEdit' -import Movement from '@/components/floor-plan/modal/movement/Movement' export default function FloorPlan() { const [showCanvasSettingModal, setShowCanvasSettingModal] = useState(false) @@ -133,7 +132,7 @@ export default function FloorPlan() { {showSlopeSettingModal && } {showPlaceShapeDrawingModal && } {showEavesGableEditModal && } - + {/**/}
From c68f7161900ef0d6e857f4211d7a09dd7479648e Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 16:37:21 +0900 Subject: [PATCH 060/152] =?UTF-8?q?=EC=99=B8=EB=B2=BD=EC=84=A0=20=ED=8E=B8?= =?UTF-8?q?=EC=A7=91=20=EB=B0=8F=20=EC=98=A4=ED=94=84=EC=85=8B=20=EB=AA=A8?= =?UTF-8?q?=EB=8B=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/CanvasMenu.jsx | 2 + src/components/floor-plan/FloorPlan.jsx | 4 + src/components/floor-plan/MenuDepth01.jsx | 2 + .../wallLineOffset/WallLineOffsetSetting.jsx | 43 ++++++++++ .../modal/wallLineOffset/type/Offset.jsx | 42 ++++++++++ .../modal/wallLineOffset/type/WallLine.jsx | 83 +++++++++++++++++++ src/locales/ja.json | 6 ++ src/locales/ko.json | 6 ++ 8 files changed, 188 insertions(+) create mode 100644 src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx create mode 100644 src/components/floor-plan/modal/wallLineOffset/type/Offset.jsx create mode 100644 src/components/floor-plan/modal/wallLineOffset/type/WallLine.jsx diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index 622320a8..350434f0 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -42,6 +42,7 @@ export default function CanvasMenu(props) { setShowRoofShapePassivitySettingModal, setShowAuxiliaryModal, setShowEavesGableEditModal, + setShowWallLineOffsetSettingModal, } = props const [menuNumber, setMenuNumber] = useState(null) @@ -92,6 +93,7 @@ export default function CanvasMenu(props) { setShowEavesGableEditModal, setShowSlopeSettingModal, setShowPlaceShapeDrawingModal, + setShowWallLineOffsetSettingModal, type, } diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx index a1b33442..544def8c 100644 --- a/src/components/floor-plan/FloorPlan.jsx +++ b/src/components/floor-plan/FloorPlan.jsx @@ -20,6 +20,7 @@ import Slope from '@/components/floor-plan/modal/Slope' import RoofShapePassivitySetting from '@/components/floor-plan/modal/roofShape/RoofShapePassivitySetting' import AuxiliaryDrawing from '@/components/floor-plan/modal/auxiliary/AuxiliaryDrawing' import EavesGableEdit from '@/components/floor-plan/modal/eavesGable/EavesGableEdit' +import WallLineOffsetSetting from '@/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting' export default function FloorPlan() { const [showCanvasSettingModal, setShowCanvasSettingModal] = useState(false) @@ -32,6 +33,7 @@ export default function FloorPlan() { const [showSlopeSettingModal, setShowSlopeSettingModal] = useState(false) const [showPlaceShapeDrawingModal, setShowPlaceShapeDrawingModal] = useState(false) const [showEavesGableEditModal, setShowEavesGableEditModal] = useState(false) + const [showWallLineOffsetSettingModal, setShowWallLineOffsetSettingModal] = useState(false) const globalLocaleState = useRecoilValue(globalLocaleStore) const { get } = useAxios(globalLocaleState) @@ -65,6 +67,7 @@ export default function FloorPlan() { setShowRoofShapePassivitySettingModal, setShowAuxiliaryModal, setShowEavesGableEditModal, + setShowWallLineOffsetSettingModal, } useEffect(() => { @@ -133,6 +136,7 @@ export default function FloorPlan() { {showPlaceShapeDrawingModal && } {showEavesGableEditModal && } {/**/} + {showWallLineOffsetSettingModal && }
diff --git a/src/components/floor-plan/MenuDepth01.jsx b/src/components/floor-plan/MenuDepth01.jsx index aa5c9f36..e5c88e9b 100644 --- a/src/components/floor-plan/MenuDepth01.jsx +++ b/src/components/floor-plan/MenuDepth01.jsx @@ -17,6 +17,7 @@ export default function MenuDepth01(props) { setShowEavesGableEditModal, setShowSlopeSettingModal, setShowPlaceShapeDrawingModal, + setShowWallLineOffsetSettingModal, } = props const { getMessage } = useMessage() const [activeMenu, setActiveMenu] = useState() @@ -33,6 +34,7 @@ export default function MenuDepth01(props) { setShowRoofShapePassivitySettingModal(id === 2) setShowAuxiliaryModal(id === 3) setShowEavesGableEditModal(id === 4) + setShowWallLineOffsetSettingModal(id === 6) setShowPlaceShapeDrawingModal(false) } diff --git a/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx b/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx new file mode 100644 index 00000000..b0f23e90 --- /dev/null +++ b/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx @@ -0,0 +1,43 @@ +import { useMessage } from '@/hooks/useMessage' +import WithDraggable from '@/components/common/draggable/WithDraggable' +import { useState } from 'react' +import WallLine from '@/components/floor-plan/modal/wallLineOffset/type/WallLine' +import Offset from '@/components/floor-plan/modal/wallLineOffset/type/Offset' + +export default function WallLineOffsetSetting({ setShowWallLineOffsetSettingModal }) { + const { getMessage } = useMessage() + const [buttonAct, setButtonAct] = useState(1) + const buttonMenu = [ + { id: 1, name: getMessage('modal.wallline.offset.setting.wallline.edit') }, + { id: 2, name: getMessage('modal.wallline.offset.setting.offset') }, + ] + return ( + +
+
+

{getMessage('modal.wallline.offset.setting')}

+ +
+
+
+ {buttonMenu.map((item) => ( + + ))} +
+
+
{getMessage('setting')}
+ {buttonAct === 1 && } + {buttonAct === 2 && } +
+
+ +
+
+
+
+ ) +} diff --git a/src/components/floor-plan/modal/wallLineOffset/type/Offset.jsx b/src/components/floor-plan/modal/wallLineOffset/type/Offset.jsx new file mode 100644 index 00000000..e700b794 --- /dev/null +++ b/src/components/floor-plan/modal/wallLineOffset/type/Offset.jsx @@ -0,0 +1,42 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function Offset({ setShowSlopeSettingModal }) { + const { getMessage } = useMessage() + return ( + <> +
+
{getMessage('modal.wallline.offset.setting.offset.info')}
+
+
+
+
+
{getMessage('length')}
+
+
+
+ +
+ mm +
+
+
+
+
{getMessage('modal.cover.outline.arrow')}
+
+
+
+ + + + +
+
+
+
+
+
+
+
+ + ) +} diff --git a/src/components/floor-plan/modal/wallLineOffset/type/WallLine.jsx b/src/components/floor-plan/modal/wallLineOffset/type/WallLine.jsx new file mode 100644 index 00000000..c394b22e --- /dev/null +++ b/src/components/floor-plan/modal/wallLineOffset/type/WallLine.jsx @@ -0,0 +1,83 @@ +import { useMessage } from '@/hooks/useMessage' +import { useState } from 'react' + +export default function WallLine({ setShowSlopeSettingModal }) { + const { getMessage } = useMessage() + const [position1, setPosition1] = useState() + const [position2, setPosition2] = useState() + return ( + <> +
+
{getMessage('modal.wallline.offset.setting.wallline.edit.info')}
+
+
+ + +
+
+
+
+
{getMessage('length')}
+
+
+
+ +
+ mm +
+
+
+
+
{getMessage('modal.cover.outline.arrow')}
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
{getMessage('length')}
+
+
+
+ +
+ mm +
+
+
+
+
{getMessage('modal.cover.outline.arrow')}
+
+
+
+ + + + +
+
+
+
+
+
+
+
+ + ) +} diff --git a/src/locales/ja.json b/src/locales/ja.json index bfc322cf..9dd89a42 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -147,6 +147,12 @@ "modal.eaves.gable.edit": "軒・ケラバ変更", "modal.eaves.gable.edit.basic": "通常", "modal.eaves.gable.edit.wall.merge.info": "家屋などの壁に面する屋根を作成します。", + "modal.wallline.offset.setting": "外壁の編集とオフセット", + "modal.wallline.offset.setting.wallline.edit": "外壁の編集", + "modal.wallline.offset.setting.wallline.edit.info": "辺と始点を選択して長さと方向を指定してください。", + "modal.wallline.offset.setting.wallline.edit.position": "支店", + "modal.wallline.offset.setting.offset": "オフセット", + "modal.wallline.offset.setting.offset.info": "オフセットしたい外壁を選択してください。", "setting": "設定", "common.message.no.data": "No data", "common.message.no.dataDown": "ダウンロードするデータがありません", diff --git a/src/locales/ko.json b/src/locales/ko.json index daae4d24..b5e6b5c2 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -154,6 +154,12 @@ "modal.eaves.gable.edit": "처마・케라바 변경", "modal.eaves.gable.edit.basic": "통상", "modal.eaves.gable.edit.wall.merge.info": "하옥 등 벽에 접하는 지붕을 작성합니다.", + "modal.wallline.offset.setting": "외벽선 편집 및 오프셋", + "modal.wallline.offset.setting.wallline.edit": "외벽선 편집", + "modal.wallline.offset.setting.wallline.edit.info": "변과 시작점을 선택하고 길이와 방향을 지정해 주세요.", + "modal.wallline.offset.setting.wallline.edit.position": "지점", + "modal.wallline.offset.setting.offset": "오프셋", + "modal.wallline.offset.setting.offset.info": "오프셋 하고 싶은 외벽선을 선택하세요.", "setting": "설정", "common.message.no.data": "No data", "common.message.no.dataDown": "No data to download", From fed54caad3d6f5e94eb5e1c1f96a9b067d89644b Mon Sep 17 00:00:00 2001 From: Daseul Kim Date: Mon, 7 Oct 2024 17:55:35 +0900 Subject: [PATCH 061/152] =?UTF-8?q?feat:=20common=20input=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 전달하는 type에 따라 input, radio, checkbox로 사용 --- src/components/Playground.jsx | 38 +++++++++++++++- src/components/common/input/QInput.jsx | 60 ++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/components/common/input/QInput.jsx diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx index 200a0337..3a85beef 100644 --- a/src/components/Playground.jsx +++ b/src/components/Playground.jsx @@ -1,6 +1,6 @@ 'use client' -import { useRef, useState } from 'react' +import { useRef, useState, useEffect } from 'react' import { useRecoilState } from 'recoil' import { v4 as uuidv4 } from 'uuid' import { FaAnglesUp } from 'react-icons/fa6' @@ -18,6 +18,7 @@ import { useSwal } from '@/hooks/useSwal' import styles from './playground.module.css' import Image from 'next/image' +import QInput from './common/input/Qinput' export default function Playground() { const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState) @@ -35,6 +36,19 @@ export default function Playground() { const [color, setColor] = useState('#ff0000') + const [textInput, setTextInput] = useState('') + const [radioInput, setRadioInput] = useState('') + const [checkboxInput, setCheckboxInput] = useState([]) + useEffect(() => { + console.log('textInput:', textInput) + }, [textInput]) + useEffect(() => { + console.log('radioInput:', radioInput) + }, [radioInput]) + useEffect(() => { + console.log('checkboxInput:', checkboxInput) + }, [checkboxInput]) + const handleUsers = async () => { // const users = await get('/api/user/find-all') const params = { @@ -115,6 +129,28 @@ export default function Playground() { <>
이 영역은 테스트입니다.
+
+ + + + +
diff --git a/src/components/common/input/QInput.jsx b/src/components/common/input/QInput.jsx new file mode 100644 index 00000000..484d9859 --- /dev/null +++ b/src/components/common/input/QInput.jsx @@ -0,0 +1,60 @@ +'use client' + +export default function QInput({ type, readOnly = false, options, value, onChange }) { + // options = options || [ + // { + // id: 'one', + // name: 'Option 1', + // value: '111', + // }, + // { + // id: 'two', + // name: 'Option 2', + // value: '222', + // }, + // { + // id: 'three', + // name: 'Option 3', + // value: '333', + // }, + // ] + + const handleChange = (e, optionValue) => { + if (type === 'radio') { + onChange(e.target.value) + } else { + const newValue = value.includes(optionValue) ? value.filter((v) => v !== optionValue) : [...value, optionValue] + onChange(newValue) + } + } + + return ( +
+
+
+ {type === 'text' ? ( +
+ onChange(e.target.value)} /> +
+ ) : type === 'radio' || type === 'checkbox' ? ( +
+ {options?.map((option) => ( +
+ handleChange(e, option.value)} + /> + +
+ ))} +
+ ) : null} +
+
+
+ ) +} From 55608b4fa33ebb1cc5ec68d4771feccc59f41d17 Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 7 Oct 2024 18:08:24 +0900 Subject: [PATCH 062/152] =?UTF-8?q?-=20=EC=A7=80=EB=B6=95=ED=98=95?= =?UTF-8?q?=EC=83=81=20=EC=88=98=EB=8F=99=EC=84=A4=EC=A0=95=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=ED=95=84=EB=93=9C=20=EC=88=98=EC=A0=95=20-=20?= =?UTF-8?q?=EC=A7=80=EB=B6=95=ED=98=95=EC=83=81=20=EC=88=98=EB=8F=99?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EB=8B=A4=EA=B5=AD=EC=96=B4=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roofShape/RoofShapePassivitySetting.jsx | 24 ++++++----- .../passivity/{eaves.jsx => Eaves.jsx} | 13 +++--- .../modal/roofShape/passivity/Gable.jsx | 27 ++++++++++++ .../modal/roofShape/passivity/Shed.js | 18 ++++++++ .../modal/roofShape/passivity/gable.jsx | 42 ------------------- .../modal/roofShape/passivity/shed.js | 42 ------------------- src/locales/ja.json | 2 + src/locales/ko.json | 1 + 8 files changed, 69 insertions(+), 100 deletions(-) rename src/components/floor-plan/modal/roofShape/passivity/{eaves.jsx => Eaves.jsx} (81%) create mode 100644 src/components/floor-plan/modal/roofShape/passivity/Gable.jsx create mode 100644 src/components/floor-plan/modal/roofShape/passivity/Shed.js delete mode 100644 src/components/floor-plan/modal/roofShape/passivity/gable.jsx delete mode 100644 src/components/floor-plan/modal/roofShape/passivity/shed.js diff --git a/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx b/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx index 2bd4988a..ccab2321 100644 --- a/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx +++ b/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx @@ -1,21 +1,23 @@ import { useState } from 'react' import WithDraggable from '@/components/common/draggable/WithDraggable' -import Eaves from '@/components/floor-plan/modal/roofShape/passivity/eaves' -import Gable from '@/components/floor-plan/modal/roofShape/passivity/gable' -import Shed from '@/components/floor-plan/modal/roofShape/passivity/shed' +import Eaves from '@/components/floor-plan/modal/roofShape/passivity/Eaves' +import Gable from '@/components/floor-plan/modal/roofShape/passivity/Gable' +import Shed from '@/components/floor-plan/modal/roofShape/passivity/Shed' +import { useMessage } from '@/hooks/useMessage' export default function RoofShapePassivitySetting({ setShowRoofShapePassivitySettingModal }) { + const { getMessage } = useMessage() const [buttonAct, setButtonAct] = useState(1) const buttons = [ - { id: 1, name: '軒' }, - { id: 2, name: 'ケラバ' }, - { id: 3, name: '漂流' }, + { id: 1, name: getMessage('eaves') }, + { id: 2, name: getMessage('gable') }, + { id: 3, name: getMessage('windage') }, ] return (
-

屋根形状の設定

+

{getMessage('plan.menu.roof.cover.roof.shape.passivity.setting')}

@@ -29,19 +31,19 @@ export default function RoofShapePassivitySetting({ setShowRoofShapePassivitySet ))}
-
設定
+
{getMessage('setting')}
{buttonAct === 1 && } {buttonAct === 2 && } {buttonAct === 3 && }
- - + +
- +
diff --git a/src/components/floor-plan/modal/roofShape/passivity/eaves.jsx b/src/components/floor-plan/modal/roofShape/passivity/Eaves.jsx similarity index 81% rename from src/components/floor-plan/modal/roofShape/passivity/eaves.jsx rename to src/components/floor-plan/modal/roofShape/passivity/Eaves.jsx index 99286117..963cfa63 100644 --- a/src/components/floor-plan/modal/roofShape/passivity/eaves.jsx +++ b/src/components/floor-plan/modal/roofShape/passivity/Eaves.jsx @@ -1,18 +1,21 @@ +import { useMessage } from '@/hooks/useMessage' + export default function Eaves() { + const { getMessage } = useMessage() return ( <>
- 傾斜 + {getMessage('slope')}
- 寸法 +
- 軒の + {getMessage('eaves.offset')}
@@ -21,7 +24,7 @@ export default function Eaves() {
- ケラバ 出幅 + {getMessage('gable.offset')}
@@ -30,7 +33,7 @@ export default function Eaves() {
- 片流幅 + {getMessage('shed.width')}
diff --git a/src/components/floor-plan/modal/roofShape/passivity/Gable.jsx b/src/components/floor-plan/modal/roofShape/passivity/Gable.jsx new file mode 100644 index 00000000..e2eb6342 --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/passivity/Gable.jsx @@ -0,0 +1,27 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function Gable() { + const { getMessage } = useMessage() + return ( + <> +
+ + {getMessage('slope')} + +
+ +
+ +
+
+ + {getMessage('gable.offset')} + +
+ +
+ mm +
+ + ) +} diff --git a/src/components/floor-plan/modal/roofShape/passivity/Shed.js b/src/components/floor-plan/modal/roofShape/passivity/Shed.js new file mode 100644 index 00000000..dfdee92c --- /dev/null +++ b/src/components/floor-plan/modal/roofShape/passivity/Shed.js @@ -0,0 +1,18 @@ +import { useMessage } from '@/hooks/useMessage' + +export default function Shed() { + const { getMessage } = useMessage() + return ( + <> +
+ + {getMessage('shed.width')} + +
+ +
+ mm +
+ + ) +} diff --git a/src/components/floor-plan/modal/roofShape/passivity/gable.jsx b/src/components/floor-plan/modal/roofShape/passivity/gable.jsx deleted file mode 100644 index 848d5d73..00000000 --- a/src/components/floor-plan/modal/roofShape/passivity/gable.jsx +++ /dev/null @@ -1,42 +0,0 @@ -export default function Gable() { - return ( - <> -
- - 傾斜 - -
- -
- 寸法 -
-
- - 軒の - -
- -
- mm -
-
- - ケラバ 出幅 - -
- -
- mm -
-
- - 片流幅 - -
- -
- mm -
- - ) -} diff --git a/src/components/floor-plan/modal/roofShape/passivity/shed.js b/src/components/floor-plan/modal/roofShape/passivity/shed.js deleted file mode 100644 index 8e767772..00000000 --- a/src/components/floor-plan/modal/roofShape/passivity/shed.js +++ /dev/null @@ -1,42 +0,0 @@ -export default function Shed() { - return ( - <> -
- - 傾斜 - -
- -
- 寸法 -
-
- - 軒の - -
- -
- mm -
-
- - ケラバ 出幅 - -
- -
- mm -
-
- - 片流幅 - -
- -
- mm -
- - ) -} diff --git a/src/locales/ja.json b/src/locales/ja.json index 9dd89a42..5250a0fa 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -39,6 +39,7 @@ "plan.menu.roof.cover": "지붕덮개", "plan.menu.roof.cover.outline.drawing": "外壁線を描", "plan.menu.roof.cover.roof.shape.setting": "屋根形状設定", + "plan.menu.roof.cover.roof.shape.passivity.setting": "屋根形状設定", "plan.menu.roof.cover.roof.shape.edit": "지붕형상 편집", "plan.menu.roof.cover.auxiliary.line.drawing": "補助線を描", "plan.menu.roof.cover.roof.surface.alloc": "지붕면 할당", @@ -333,5 +334,6 @@ "jerkinhead.width": "半折先幅", "jerkinhead.slope": "半折先傾斜", "shed.width": "片流幅", + "windage": "漂流", "windage.width": "漂流の出幅" } diff --git a/src/locales/ko.json b/src/locales/ko.json index b5e6b5c2..d29df3d0 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -340,5 +340,6 @@ "jerkinhead.width": "반절처 폭", "jerkinhead.slope": "반절처 경사", "shed.width": "한쪽흐름 폭", + "windage": "편류", "windage.width": "편류의 출폭" } From b1949e9486fd1f703d4485045955ab13802ead67 Mon Sep 17 00:00:00 2001 From: Daseul Kim Date: Mon, 7 Oct 2024 18:25:00 +0900 Subject: [PATCH 063/152] =?UTF-8?q?refactor:=20text=20value=20=EC=BB=A8?= =?UTF-8?q?=EB=B2=A4=EC=85=98=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Playground.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx index 3a85beef..dbae066f 100644 --- a/src/components/Playground.jsx +++ b/src/components/Playground.jsx @@ -130,10 +130,10 @@ export default function Playground() {
이 영역은 테스트입니다.
- - + + Date: Tue, 8 Oct 2024 09:03:18 +0900 Subject: [PATCH 064/152] refactor: modify login page --- src/app/QcastProvider.js | 4 - src/app/join/page.jsx | 6 +- src/app/layout.js | 23 +-- src/app/login/page.jsx | 3 +- src/components/auth/NewLogin.jsx | 240 +++++++++++++++++++++++++++++++ 5 files changed, 260 insertions(+), 16 deletions(-) create mode 100644 src/components/auth/NewLogin.jsx diff --git a/src/app/QcastProvider.js b/src/app/QcastProvider.js index f9431eb6..3ae0993d 100644 --- a/src/app/QcastProvider.js +++ b/src/app/QcastProvider.js @@ -16,15 +16,11 @@ export const QcastProvider = ({ children }) => { const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore) useEffect(() => { - console.log(sessionStorage.getItem('hi')) - console.log(Object.keys(appMessageState).length) - // if (Object.keys(appMessageState).length === 0) { if (globalLocale === 'ko') { setAppMessageState(KO) } else { setAppMessageState(JA) } - // } }, [globalLocale]) return ( diff --git a/src/app/join/page.jsx b/src/app/join/page.jsx index 118a25b4..c8d2424b 100644 --- a/src/app/join/page.jsx +++ b/src/app/join/page.jsx @@ -1,5 +1,9 @@ import Join from '@/components/auth/Join' export default function JoinPage() { - return <>{} + return ( + <> + + + ) } diff --git a/src/app/layout.js b/src/app/layout.js index b77e75d0..6c04bbec 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -61,16 +61,19 @@ export default async function RootLayout({ children }) { - {/*{headerPathname !== '/login' && }*/} -
-
- -
- - {children} -
-
-
+ {headerPathname !== '/login' ? ( +
+
+ +
+ + {children} +
+
+
+ ) : ( + {children} + )} diff --git a/src/app/login/page.jsx b/src/app/login/page.jsx index 0686da2e..3ff0edd7 100644 --- a/src/app/login/page.jsx +++ b/src/app/login/page.jsx @@ -1,9 +1,10 @@ import Login from '@/components/auth/Login' +import NewLogin from '@/components/auth/NewLogin' export default function LoginPage() { return ( <> - + ) } diff --git a/src/components/auth/NewLogin.jsx b/src/components/auth/NewLogin.jsx new file mode 100644 index 00000000..cf56378e --- /dev/null +++ b/src/components/auth/NewLogin.jsx @@ -0,0 +1,240 @@ +'use client' + +import { useState, useRef, useEffect } from 'react' +import Image from 'next/image' +import Link from 'next/link' +import { redirect } from 'next/navigation' +import { useRecoilState } from 'recoil' +import { useAxios } from '@/hooks/useAxios' +import { setSession } from '@/lib/authActions' +import { useMessage } from '@/hooks/useMessage' +import { globalLocaleStore } from '@/store/localeAtom' +import { sessionStore } from '@/store/commonAtom' +import { modalContent, modalState } from '@/store/modalAtom' +import '@/styles/style.scss' +import { useRouter } from 'next/navigation' + +export default function NewLogin() { + const [passwordVisible, setPasswordVisible] = useState(false) + const passwordRef = useRef(null) + const router = useRouter() + + useEffect(() => { + if (passwordVisible) { + passwordRef.current.type = 'text' + } else { + passwordRef.current.type = 'password' + } + }, [passwordVisible]) + + const { patch } = useAxios() + + const { getMessage } = useMessage() + const [globalLocaleState, setGlbalLocaleState] = useRecoilState(globalLocaleStore) + const [sessionState, setSessionState] = useRecoilState(sessionStore) + const [isSelected, setIsSelected] = useState(globalLocaleState === 'ko' ? true : false) + + const handleSelected = () => { + if (isSelected) { + setGlbalLocaleState('ja') + } else { + setGlbalLocaleState('ko') + } + + setIsSelected(!isSelected) + } + + // login process + const loginProcess = async (formData) => { + const param = { + // langCd: currentLocale + langCd: globalLocaleState, + lastEditUser: formData.get('id'), + loginId: formData.get('id'), + pwd: formData.get('password'), + } + + // await post({ url: '/api/login/v1.0/login', data: param }).then((res) => { + // if (res) { + // if (res.result.resultCode == 'S') { + // // console.log('res.data', res.data) + // // 비밀번호 초기화가 필요한 경우 + // // if (res.data.pwdInitYn != 'Y') { + // // alert('비밀번호 초기화가 필요한 경우') + // // } else { + // setSession(res.data) + // redirect('/') + // // } + // } else { + // alert(res.result.resultMsg) + // } + // } + // }) + + // 임시 로그인 처리 + setSession({ + userId: 'NEW016610', + saleStoreId: null, + name: null, + mail: null, + tel: null, + storeId: 'TEMP02', + userNm: 'ㅇㅇ6610', + userNmKana: '신규사용자 16610', + category: '인상6610', + telNo: '336610', + fax: null, + email: 't10t@naver.com', + pwdInitYn: 'N', + }) + + setSessionState({ + userId: 'NEW016610', + saleStoreId: null, + name: null, + mail: null, + tel: null, + storeId: 'TEMP02', + userNm: 'ㅇㅇ6610', + userNmKana: '신규사용자 16610', + category: '인상6610', + telNo: '336610', + fax: null, + email: 't10t@naver.com', + pwdInitYn: 'N', + }) + + // redirect('/') + router.push('/') + // 임시 로그인 처리 끝 + } + + // 비밀번호 초기화 관련 + const [open, setOpen] = useRecoilState(modalState) + const [contents, setContent] = useRecoilState(modalContent) + + const initPasswordProcess = async (formData) => { + const param = { + langCd: currentLocale, + lastEditUser: formData.get('checkId'), + loginId: formData.get('checkId'), + email: formData.get('checkEmail'), + } + + await patch({ url: '/api/login/v1.0/user/init-password', data: param }).then((res) => { + if (res) { + if (res.result.resultCode == 'S') { + alert(getMessage('login.init_password.complete_message')) + redirect('/login') + } else { + alert(res.result.resultMsg) + } + } + }) + } + + const initPasswordContent = ( +
+
+

{getMessage('login.init_password.title')}

+

{getMessage('login.init_password.sub_title')}

+
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+

+ +

+
+
+ ) + + return ( +
+
+ + react + +
+
+
+ Q.CAST III + 太陽光発電システム図面管理サイト +
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ パスワードの初期化 +
+
+
+
+
+ 当サイトをご利用の際は、事前申請が必要です。 +
+ IDがない方は ID申請 クリックしてください。 +
+
+
COPYRIGHT©2024 Hanwha Japan All Rights Reserved.
+
+ ) +} From cdf7d410333257d8a4d6b1cf273f3a7d4e98b93c Mon Sep 17 00:00:00 2001 From: basssy Date: Tue, 8 Oct 2024 09:50:55 +0900 Subject: [PATCH 065/152] =?UTF-8?q?=EB=AC=BC=EA=B1=B4=ED=98=84=ED=99=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/management/Stuff.jsx | 117 +++---- src/components/management/StuffDetail.jsx | 311 ++++-------------- .../management/StuffSearchCondition.jsx | 38 ++- src/store/stuffAtom.js | 6 +- 4 files changed, 140 insertions(+), 332 deletions(-) diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index f509b3f8..4e899bb8 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -10,8 +10,7 @@ import { useRecoilValue, useRecoilState } from 'recoil' import { stuffSearchState } from '@/store/stuffAtom' import { queryStringFormatter, isEmptyArray } from '@/util/common-utils' import dayjs from 'dayjs' -import isLeapYear from 'dayjs/plugin/isLeapYear' // 윤년 판단 플러그인 -dayjs.extend(isLeapYear) +import { isObjectNotEmpty } from '@/util/common-utils' import { convertNumberToPriceDecimal } from '@/util/common-utils' import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' import KO from '@/locales/ko.json' @@ -242,66 +241,68 @@ export default function Stuff() { // 진입시 그리드 데이터 조회 useEffect(() => { - if (stuffSearchParams?.code === 'S') { - const params = { - schObjectNo: '', - schSaleStoreId: '', - schAddress: '', - schObjectName: '', - schSaleStoreName: '', - schReceiveUser: '', - schDispCompanyName: '', - schDateType: 'U', - schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), - schToDt: dayjs(new Date()).format('YYYY-MM-DD'), - startRow: (curPage - 1) * defaultSize + 1, - endRow: curPage * defaultSize, - schSelSaleStoreId: '', - schSortType: 'R', + if (isObjectNotEmpty(sessionState)) { + if (stuffSearchParams?.code === 'S') { + const params = { + schObjectNo: '', + schAddress: '', + schObjectName: '', + schSaleStoreName: '', + schReceiveUser: '', + schDispCompanyName: '', + schDateType: 'U', + schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), + schToDt: dayjs(new Date()).format('YYYY-MM-DD'), + startRow: (curPage - 1) * defaultSize + 1, + endRow: curPage * defaultSize, + schSelSaleStoreId: '', + schSortType: 'R', + } + + async function fetchData() { + //api에 넘길값 startRow, endRow + // let startRow + // let endRow + // startRow = (curPage - 1) * size + 1 + // endRow = curPage * size + // console.log('startrow::', startRow) + // console.log('endRow::', endRow) + + // let curPage + // let totalpage + // let totalCount + // let size + // let pageCount + + // console.log('화면진입 세션정보::::::::::', sessionState) + // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(params)}` + // const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(params)}` + const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(params)}` + await get({ + url: apiUrl, + }).then((res) => { + if (!isEmptyArray(res)) { + setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) + setGridCount(res[0].totCnt) + } + }) + } + fetchData() } - - async function fetchData() { - // console.log('화면진입:::::::::::::', params) - //api에 넘길값 startRow, endRow - // let startRow - // let endRow - // startRow = (curPage - 1) * size + 1 - // endRow = curPage * size - // console.log('startrow::', startRow) - // console.log('endRow::', endRow) - - // let curPage - // let totalpage - // let totalCount - // let size - // let pageCount - - // console.log('세션정보::::::::::', sessionState) - // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(params)}` - const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(params)}` - await get({ - url: apiUrl, - }).then((res) => { - if (!isEmptyArray(res)) { - setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) - setGridCount(res[0].totCnt) - } - }) - } - fetchData() } - }, []) + }, [sessionState]) useEffect(() => { if (stuffSearchParams?.code === 'E') { stuffSearchParams.startRow = (curPage - 1) * defaultSize + 1 stuffSearchParams.endRow = curPage * defaultSize stuffSearchParams.schSortType = defaultSortType - console.log('조회누름::::::::', stuffSearchParams) + // console.log('조회누름::::::::', stuffSearchParams) async function fetchData() { - // console.log('세션정보:::::::::::::', sessionState) + // console.log('조회누름 세션정보:::::::::::::', sessionState) // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` - const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` + // const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` + const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}` await get({ url: apiUrl }).then((res) => { // console.log('검색조건 변경 조회 API결과:::::::', res) if (!isEmptyArray(res)) { @@ -329,10 +330,11 @@ export default function Stuff() { startRow: startRow, endRow: curPage * e.target.value, }) - console.log('페이지 갯수 변경 때 셋팅된 검색조건:::', stuffSearchParams) - // console.log('세션정보:::', sessionState) + // console.log('페이지 갯수 변경 때 셋팅된 검색조건:::', stuffSearchParams) + // console.log('페이지 갯수 변경 때 sessionState:::', sessionState) // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` - const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` + // const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` + const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}` get({ url: apiUrl }).then((res) => { if (!isEmptyArray(res)) { setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) @@ -354,9 +356,10 @@ export default function Stuff() { code: 'S', schSortType: e.target.value, }) - // console.log('세션정보::::::::::::', sessionState) + // console.log('정렬 변경시 세션정보::::::::::::', sessionState) // const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` - const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` + // const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}` + const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}` get({ url: apiUrl }).then((res) => { if (!isEmptyArray(res)) { setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index 0a743a52..bca2fd17 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -34,7 +34,8 @@ export default function StuffDetail() { prefId: '', //도도부현 prefName: '', address: '', //주소 - areaId: '', //발전량시뮬레이션지역new + areaId: '', //발전량시뮬레이션지역id + // areaName: '', //발전량시뮬레이션지역명 windSpeed: '', //기준풍속 verticalSnowCover: '', //수직적설량NEW coldRegionFlg: false, //한랭지대책시행(true : 1 / false : 0) @@ -56,8 +57,9 @@ export default function StuffDetail() { const [saleStoreList, setSaleStoreList] = useState([]) // 판매점 리스트 const [otherSaleStoreList, setOtherSaleStoreList] = useState([]) - const [areaIdList, setAreaIdList] = useState([]) //발전시뮬레이션 리스트 NEW + const [areaIdList, setAreaIdList] = useState([]) //발전시뮬레이션 리스트 + const [windSpeedList, setWindSpeedList] = useState([]) //기준풍속 리스트 const [isFormValid, setIsFormValid] = useState(false) //임시저장, 진짜저장 버튼 컨트롤 const [buttonValid, setButtonValid] = useState(false) //주소검색 활성화 컨트롤 const objectNo = searchParams.get('objectNo') //url에서 물건번호 꺼내서 바로 set @@ -83,7 +85,7 @@ export default function StuffDetail() { // 도도부현API get({ url: '/api/object/prefecture/list' }).then((res) => { if (!isEmptyArray(res)) { - console.log('도도부현API 결과:::', res) + // console.log('도도부현API 결과:::', res) setPrefCodeList(res) } }) @@ -274,9 +276,11 @@ export default function StuffDetail() { const params = { zipcode: _zipNo, } + get({ url: `https://zipcloud.ibsnet.co.jp/api/search?${queryStringFormatter(params)}` }).then((res) => { //7830060 //9302226 + //0790177 3개짜리 if (res.status === 200) { if (res.results != null) { console.log('주소검색::', res.results) @@ -295,6 +299,9 @@ export default function StuffDetail() { setPrefValue('') setAreaIdList([]) form.setValue('areaId', '') + // form.setValue('areaName', '') + setWindSpeedList([]) + form.setValue('windSpeed', '') } } else { alert(res.message) @@ -304,18 +311,39 @@ export default function StuffDetail() { useEffect(() => { if (prefValue !== '') { - // console.log('우편번호 검색해서 도도부현골랐을때::::', prefValue) // 발전량시뮬레이션 지역 목록 // /api/object/prefecture/도도부현코드/list get({ url: `/api/object/prefecture/${prefValue}/list` }).then((res) => { if (!isEmptyArray(res)) { - console.log('발전량 시뮬레이션::::::::', res) + // console.log('발전량 시뮬레이션::::::::', res) + form.setValue('areaId', res[0].prefId) + form.setValue('areaName', res[0].prefName) setAreaIdList(res) } }) } }, [prefValue]) + // 발전량 시뮬레이션 변경 + const handleAreaIdOnChange = (e) => { + form.setValue('areaId', e.target.value) + } + + useEffect(() => { + if (!isEmptyArray(areaIdList)) { + //도도부현넘기는지 발전량시뮬레이션지역 넘기는지 ->도도부현넘기기 + console.log('prefName::', form.watch('prefName')) + let _prefName = form.watch('prefName') + //http://localhost:8080/api/object/windSpeed/兵庫県/list + get({ url: `/api/object/windSpeed/${_prefName}/list` }).then((res) => { + if (!isEmptyArray(res)) { + // console.log('기준풍속결과:::::::::', res) + setWindSpeedList(res) + } + }) + } + }, [areaIdList]) + //필수값 다 입력했을때 const onValid = (data) => { // 수정모드일때는 PUT @@ -382,14 +410,6 @@ export default function StuffDetail() { }) } - // 발전량 시뮬레이션 변경 - const handleAreaIdOnChange = (e) => { - // console.log('가지고있는 도도부현코드:::::::::', prefValue) - console.log('발전량시뮬레이션변경:::::::::', e.target.value) - form.setValue('areaId', e.target.value) - //값 set해주고 그거 useEffect로 기준풍속, 수직적설량 api호출 - } - // 물건삭제 const onDelete = () => { //http://localhost:8080/api/object/R201TES01240910023 @@ -588,17 +608,22 @@ export default function StuffDetail() {
- {areaIdList?.length > 0 && ( - - )} +
@@ -610,10 +635,13 @@ export default function StuffDetail() {
m/s이하 @@ -756,233 +784,6 @@ export default function StuffDetail() { )} )} - {/* {(editMode === 'NEW' && ( -
-
-
(*필수 입력항목)
-
- - -
-
- - - - - - -
- -
-
-
- - -
-
- -
- {saleStoreList?.length > 0 && ( - - {(option) => {option.saleStoreName}} - - )} - -
-
-
- -
- {otherSaleStoreList?.length > 0 && ( - - {(option) => {option.saleStoreName}} - - )} -
-
-
- - - - *우편번호 7자리를 입력한 후, 주소검색 버튼을 클릭해 주십시오 -
-
- -
- {prefCodeList?.length > 0 && ( - - )} -
- - -
-
- - {powerSimAreaList?.length > 0 && ( - - )} -
-
- -
- -
-
-
- - {' '} - cm - { - form.setValue('coldAreaChk', e) - }} - {...form.register('coldAreaChk')} - > - 한랭지대책시행 - -
-
- - - - - - { - form.setValue('saltAreaChk', e) - }} - > - 염해지역용아이템사용 - -
-
- -
- -
-
-
- - - - - -
-
- -