Compare commits

..

10 Commits

Author SHA1 Message Date
042e42c2cf Merge branch 'dev' of https://git.hanasys.jp/qcast3/qcast-front into dev 2025-05-30 17:56:48 +09:00
8b81998f8c [1068] : [견적서 생성된 플랜복사 --> 복사된 플랜에서 모듈삭제 --> 견적서 진입이 됨.. ]
[작업내용] : 가대까지 완성 -> 삭제 안함, 그 전상태면 무조건 삭제 로직으로 구현
2025-05-30 17:56:39 +09:00
8b5299366f Merge branch 'dev' of https://git.hanasys.jp/qcast3/qcast-front into dev 2025-05-30 17:33:08 +09:00
94985feed8 length가 없는경우 따로 계산 추가 2025-05-30 17:29:37 +09:00
김민식
fc5b111c6e Merge remote-tracking branch 'origin/dev' into dev 2025-05-30 17:24:15 +09:00
김민식
401d752ac7 오타 수정 2025-05-30 17:23:57 +09:00
5986fe51ff 대표라인 설정 수정 2025-05-30 17:23:16 +09:00
김민식
65b778d9e5 Merge remote-tracking branch 'origin/qcast-pub' into dev
# Conflicts:
#	src/components/floor-plan/modal/basic/step/Placement.jsx
2025-05-30 17:20:57 +09:00
김민식
66827d4c87 [1069] : [【HANASYS DESIGN】不正な配置について[アラートの表示]]
[작업내용] : 모듈 배치 화면에 안내 문구 추가
2025-05-30 17:19:35 +09:00
김민식
022125759f 🚨chore: Sync Sass 2025-05-30 17:18:22 +09:00
10 changed files with 162 additions and 61 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -12,10 +12,12 @@ import {
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
import { isObjectNotEmpty } from '@/util/common-utils'
import Image from 'next/image'
const Placement = forwardRef((props, refs) => {
const { getMessage } = useMessage()
const [useTab, setUseTab] = useState(true)
const [guideType, setGuideType] = useState('batch')
const [isChidoriNotAble, setIsChidoriNotAble] = useState(false)
@ -317,13 +319,39 @@ const Placement = forwardRef((props, refs) => {
</div>
</div>
</div>
<div className="hide-tab-wrap">
<div className="hide-check-guide">
<div onClick={() => setUseTab(!useTab)}>
{getMessage('modal.module.basic.setting.module.placement.max.size.check')}
<button className={`arr ${!useTab ? 'act' : ''}`}></button>
{getMessage('modal.module.basic.setting.module.placement.info')}
<button className={`arr ${useTab ? 'act' : ''}`} onClick={() => setUseTab(!useTab)}></button>
</div>
<div className={`hide-tab-contents ${!useTab ? 'hide' : ''}`}>
<div className="roof-content-tab-wrap">
<button className={`btn-frame block modal mr5 ${guideType === 'batch' ? 'act' : ''} `} onClick={() => setGuideType('batch')}>
{getMessage('modal.module.basic.setting.module.placement.info.batch')}
</button>
<button className={`btn-frame block modal mr5 ${guideType === 'module' ? 'act' : ''}`} onClick={() => setGuideType('module')}>
{getMessage('modal.module.basic.setting.module.placement.info.module')}
</button>
</div>
{guideType === 'batch' && (
<div className={`roof-warning-wrap mt10`}>
<div className="guide">
{getMessage('modal.module.basic.setting.module.placement.info.batch.content1')}
<br />
{getMessage('modal.module.basic.setting.module.placement.info.batch.content2')}
</div>
<div className="roof-warning-img-wrap">
<div className="roof-warning-img">
<Image src={'/static/images/canvas/roof_warning_correct.png'} width={350} height={198} alt="" />
</div>
<div className="roof-warning-img">
<Image src={'/static/images/canvas/roof_warning_wrong.png'} width={350} height={198} alt="" />
</div>
</div>
<div className={`module-table-box mt10 ${useTab ? 'hide' : ''}`}>
</div>
)}
{guideType === 'module' && (
<div className={`module-table-box mt10 ${!useTab ? 'hide' : ''}`}>
<div className="module-table-inner">
<div className="roof-module-table">
<table className="">
@ -375,6 +403,9 @@ const Placement = forwardRef((props, refs) => {
</div>
</div>
</div>
)}
</div>
</div>
</>
)
})

View File

@ -489,6 +489,19 @@ export const useEstimateController = (planNo, flag) => {
})
}
const handleDeleteEstimate = async (canvasStatus) => {
try {
setIsGlobalLoading(true)
await promisePost({ url: `${ESTIMATE_API_ENDPOINT}/delete-estimate`, data: canvasStatus }).then((res) => {
if (res.status === 201) {
}
})
} catch (e) {
console.error('error::::::::::::', e.response.data.message)
}
setIsGlobalLoading(false)
}
/**
* 전각20자 (반각40자)
*/
@ -509,5 +522,6 @@ export const useEstimateController = (planNo, flag) => {
fetchSetting,
handleEstimateFileDownload,
handleEstimateCopy,
handleDeleteEstimate,
}
}

View File

@ -159,5 +159,6 @@ export const useLine = () => {
addPitchText,
removePitchText,
addPitchTextsByOuterLines,
getLengthByLine,
}
}

View File

@ -30,6 +30,7 @@ import { useCanvasPopupStatusController } from './common/useCanvasPopupStatusCon
import { useCanvasMenu } from './common/useCanvasMenu'
import { QcastContext } from '@/app/QcastProvider'
import { unescapeString } from '@/util/common-utils'
import { useTrestle } from '@/hooks/module/useTrestle'
/**
* 플랜 처리
@ -54,7 +55,7 @@ export function usePlan(params = {}) {
const { getMessage } = useMessage()
const { get, post, promisePost, promisePut, promiseDel, promiseGet } = useAxios()
const { setEstimateContextState } = useEstimateController()
const { setEstimateContextState, handleDeleteEstimate } = useEstimateController()
const resetOuterLinePoints = useResetRecoilState(outerLinePointsState)
const resetPlacementShapeDrawingPoints = useResetRecoilState(placementShapeDrawingPointsState)
@ -79,6 +80,8 @@ export function usePlan(params = {}) {
//선택된 모듈 배치면 초기화
const resetModuleSetupSurface = useResetRecoilState(moduleSetupSurfaceState)
const { isAllComplete } = useTrestle()
/**
* 마우스 포인터의 가이드라인 제거
*/
@ -172,7 +175,11 @@ export function usePlan(params = {}) {
*/
const saveCanvas = async (saveAlert = true) => {
const canvasStatus = currentCanvasData('save')
await putCanvasStatus(canvasStatus, saveAlert)
const result = await putCanvasStatus(canvasStatus, saveAlert)
//캔버스 저장 완료 후
if (result && !isAllComplete()) {
handleDeleteEstimate(currentCanvasPlan)
}
}
/**
@ -318,20 +325,24 @@ export function usePlan(params = {}) {
* @param {boolean} saveAlert - 저장 완료 알림 표시 여부
*/
const putCanvasStatus = async (canvasStatus, saveAlert = true) => {
let rtn = false
const planData = {
id: currentCanvasPlan.id,
bgImageName: currentCanvasPlan?.bgImageName ?? null,
mapPositionAddress: currentCanvasPlan?.mapPositionAddress ?? null,
canvasStatus: canvasToDbFormat(canvasStatus),
}
await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData })
.then((res) => {
setPlans((plans) => plans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)))
if (saveAlert) swalFire({ text: getMessage('plan.message.save') })
rtn = true
})
.catch((error) => {
swalFire({ text: error.message, icon: 'error' })
})
return rtn
}
/**

View File

@ -15,6 +15,7 @@ import { flowDisplaySelector } from '@/store/settingAtom'
import { fontSelector } from '@/store/fontAtom'
import { QLine } from '@/components/fabric/QLine'
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
import { useLine } from '@/hooks/useLine'
export const usePolygon = () => {
const canvas = useRecoilValue(canvasState)
@ -24,6 +25,8 @@ export const usePolygon = () => {
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const pitchText = useRecoilValue(pitchTextSelector)
const { getLengthByLine } = useLine()
const addPolygon = (points, options, isAddCanvas = true) => {
const polygon = new QPolygon(points, {
...options,
@ -1093,15 +1096,25 @@ export const usePolygon = () => {
})
if (startFlag && endFlag) {
if (!representLines.includes(line)) {
if (!representLines.includes(line) && line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
representLines.push(line)
}
}
})
// blue로 생성된 것들은 대표라인이 될 수 없음.
representLines = representLines.filter((line) => line.stroke !== 'blue')
// representLines중 가장 긴 line을 찾는다.
representLines.forEach((line) => {
if (!representLine) {
representLine = line
} else {
if (getLengthByLine(representLine) < getLengthByLine(line)) {
representLine = line
}
}
})
if (!representLine) {
representLines = representLines.filter((line) => line.stroke !== 'blue')
representLines.forEach((line) => {
if (!representLine) {
representLine = line
@ -1111,7 +1124,9 @@ export const usePolygon = () => {
}
}
})
const direction = polygon.direction ?? representLine?.direction
}
const direction = polygon.direction ?? representLine?.direction ?? ''
const polygonDirection = polygon.direction
switch (direction) {

View File

@ -1105,6 +1105,11 @@
"module.layout.setup.max.count": "モジュールの単体での最大段数は{0}、最大列数は{1}です。 (JA)",
"module.layout.setup.max.count.multiple": "モジュール{0}の単体での最大段数は{1}、最大列数は{2}です。 (JA)",
"roofAllocation.not.found": "割り当てる屋根がありません。 (JA)",
"modal.module.basic.setting.module.placement.info": "モジュール配置案内",
"modal.module.basic.setting.module.placement.info.batch": "千鳥配置を手動で行う際の注意事項",
"modal.module.basic.setting.module.placement.info.batch.content1": "千鳥配置する時に図のような配置ができてしまいますが、正常な積算ができません。",
"modal.module.basic.setting.module.placement.info.batch.content2": "千鳥で配置する時は、千鳥配置を「する」にして、モジュールが吸着されるようにして下さい。",
"modal.module.basic.setting.module.placement.info.module": "屋根材別 単一・混合モジュールの最大段数",
"modal.module.basic.setting.module.placement.max.size.check": "屋根材別モジュールの単体の単体での最大段数、2種混合の段数を確認して下さい",
"modal.module.basic.setting.module.placement.max.row": "単体で\rの最大段数",
"modal.module.basic.setting.module.placement.max.rows.multiple": "2種混合時\rの最大段数",

View File

@ -1105,6 +1105,11 @@
"module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다.",
"module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다.",
"roofAllocation.not.found": "할당할 지붕이 없습니다.",
"modal.module.basic.setting.module.placement.info": "모듈 배치 안내",
"modal.module.basic.setting.module.placement.info.batch": "치도리 수동 배치 시 유의사항",
"modal.module.basic.setting.module.placement.info.batch.content1": "치조 배치할 때 그림과 같은 배치가 되어 버립니다만, 정상적인 적산을 할 수 없습니다.",
"modal.module.basic.setting.module.placement.info.batch.content2": "치조로 배치할 때는, 치조 배치를 「한다」로 하고, 모듈이 흡착되도록 해 주세요.",
"modal.module.basic.setting.module.placement.info.module": "지붕재별 단일·혼합 모듈 최대 단수",
"modal.module.basic.setting.module.placement.max.size.check": "지붕재별 모듈 단체의 최대 단수, 2종 혼합 단수를 확인하십시오.",
"modal.module.basic.setting.module.placement.max.row": "최대 단수",
"modal.module.basic.setting.module.placement.max.rows.multiple": "2종 혼합 최대단수",

View File

@ -2457,3 +2457,22 @@ $alert-color: #101010;
}
}
}
// 2025-05-30 지붕 모듈
.roof-warning-img-wrap{
display: flex;
align-items: center;
gap: 15px;
justify-content: center;
}
.roof-content-tab-wrap{
display: flex;
padding-top: 10px;
}
.hide-tab-contents{
&.hide{
height: 0;
overflow: hidden;
}
}