diff --git a/.env.development b/.env.development index f843c86b..f59d542c 100644 --- a/.env.development +++ b/.env.development @@ -4,5 +4,5 @@ SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3" -NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-qa.q-cells.jp:8120/eos/login/autoLogin" -NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-qa.q-cells.jp:8120/qm/login/autoLogin" \ No newline at end of file +NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-stg.q-cells.jp:8120/eos/login/autoLogin" +NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-stg.q-cells.jp:8120/qm/login/autoLogin" \ No newline at end of file diff --git a/src/app/GlobalDataProvider.js b/src/app/GlobalDataProvider.js index e4162cd1..d930bbed 100644 --- a/src/app/GlobalDataProvider.js +++ b/src/app/GlobalDataProvider.js @@ -10,12 +10,14 @@ export const GlobalDataContext = createContext({ }) const GlobalDataProvider = ({ children }) => { - const [managementState, setManagementState] = useState({}) + const [managementState, setManagementState] = useState(null) // TODO: 임시 조치이며 개발 완료시 삭제 예정 -> 잊지말기... const [managementStateLoaded, setManagementStateLoaded] = useLocalStorage('managementStateLoaded', null) useEffect(() => { - setManagementStateLoaded(managementState) + if (managementState !== null) { + setManagementStateLoaded(managementState) + } }, [managementState]) return {children} diff --git a/src/app/floor-plan/FloorPlanProvider.js b/src/app/floor-plan/FloorPlanProvider.js index 37399ddd..649deb78 100644 --- a/src/app/floor-plan/FloorPlanProvider.js +++ b/src/app/floor-plan/FloorPlanProvider.js @@ -23,6 +23,17 @@ const defaultEstimateData = { priceCd: '', } +/** + * 모듈,회로 구성 상태 데이터 + * 각 설정 팝업 상태를 저장하는 데이터 + */ +const defaultProcessStep = { + gnbStep: 0, + processStep: 0, + moduleCofigureData: {}, + pcsConfigureData: {}, +} + export const FloorPlanContext = createContext({ floorPlanState: {}, setFloorPlanState: () => {}, @@ -57,8 +68,12 @@ const FloorPlanProvider = ({ children }) => { const [estimateContextState, setEstimateContextState] = useReducer(reducer, defaultEstimateData) + const [processStepState, setProcessStepState] = useReducer(reducer, defaultProcessStep) + return ( - + {children} ) diff --git a/src/app/floor-plan/estimate/[mid]/[pid]/page.jsx b/src/app/floor-plan/estimate/[mid]/[pid]/page.jsx deleted file mode 100644 index 6e793bf5..00000000 --- a/src/app/floor-plan/estimate/[mid]/[pid]/page.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import Estimate from '@/components/estimate/Estimate' - -export default function EstimatePage({ params }) { - //floor-plan/estimate/mid/pid - //mid :5 견적탭 - //pid : 넘어온 플랜번호 - return ( - <> - - - ) -} diff --git a/src/app/floor-plan/estimate/[mid]/page.jsx b/src/app/floor-plan/estimate/[mid]/page.jsx new file mode 100644 index 00000000..216ee940 --- /dev/null +++ b/src/app/floor-plan/estimate/[mid]/page.jsx @@ -0,0 +1,9 @@ +import Estimate from '@/components/estimate/Estimate' + +export default function EstimatePage({}) { + return ( + <> + + + ) +} diff --git a/src/app/floor-plan/layout.js b/src/app/floor-plan/layout.js index 19c730cf..5ea3b08c 100644 --- a/src/app/floor-plan/layout.js +++ b/src/app/floor-plan/layout.js @@ -1,9 +1,9 @@ 'use client' +import { usePathname } from 'next/navigation' import FloorPlanProvider from './FloorPlanProvider' import FloorPlan from '@/components/floor-plan/FloorPlan' import CanvasLayout from '@/components/floor-plan/CanvasLayout' -import { usePathname } from 'next/navigation' export default function FloorPlanLayout({ children }) { console.log('🚀 ~ FloorPlanLayout ~ FloorPlanLayout:') @@ -14,12 +14,12 @@ export default function FloorPlanLayout({ children }) { <> - {pathname.includes('estimate') || pathname.includes('simulator') ? ( + {/* {pathname.includes('estimate') || pathname.includes('simulator') ? (
{children}
) : ( {children} - )} - {/* {children} */} + )} */} + {children}
diff --git a/src/components/Main.jsx b/src/components/Main.jsx index 5f6c1052..a6c00444 100644 --- a/src/components/Main.jsx +++ b/src/components/Main.jsx @@ -2,24 +2,20 @@ import { useEffect, useState, useContext } from 'react' import { useRouter } from 'next/navigation' -import { useRecoilState, useRecoilValue } from 'recoil' -import { useAxios } from '@/hooks/useAxios' -import { globalLocaleStore } from '@/store/localeAtom' +import { useRecoilState } from 'recoil' import MainContents from './main/MainContents' import { useMessage } from '@/hooks/useMessage' import { stuffSearchState } from '@/store/stuffAtom' import '@/styles/contents.scss' import ChangePasswordPop from './main/ChangePasswordPop' import { searchState } from '@/store/boardAtom' -import { SessionContext } from '@/app/SessionProvider' import { QcastContext } from '@/app/QcastProvider' import { sessionStore } from '@/store/commonAtom' import { isObjectNotEmpty } from '@/util/common-utils' -export default function MainPage(mainPageProps) { +export default function MainPage() { const [sessionState, setSessionState] = useRecoilState(sessionStore) const [chagePasswordPopOpen, setChagePasswordPopOpen] = useState(false) - const { session } = useContext(SessionContext) const router = useRouter() const { getMessage } = useMessage() diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx index 1d5820ff..126a7f65 100644 --- a/src/components/Playground.jsx +++ b/src/components/Playground.jsx @@ -226,6 +226,32 @@ export default function Playground() { setMyData({ ...myData, raftBaseCd: 'HEI_500' }) } + const [myData2, setMyData2] = useState({}) + + const handleChangeMyData2 = () => { + setMyData2({ + roofMatlCd: 'ROOF_ID_WA_53A', + roofMatlNm: '화와 A', + roofMatlNmJp: '和瓦A', + widAuth: 'R', + widBase: '265.000', + lenAuth: 'R', + lenBase: '235.000', + roofPchAuth: null, + roofPchBase: null, + raftAuth: 'C', + raftBaseCd: 'HEI_455', + id: 'ROOF_ID_WA_53A', + name: '화와 A', + selected: true, + nameJp: '和瓦A', + length: 235, + width: 265, + layout: 'P', + hajebichi: null, + }) + } + return ( <>
@@ -504,6 +530,15 @@ export default function Playground() {
+
+ +
+
+ +
+
+ +
diff --git a/src/components/common/select/QSelectBox.jsx b/src/components/common/select/QSelectBox.jsx index 9f86474d..75a17bc1 100644 --- a/src/components/common/select/QSelectBox.jsx +++ b/src/components/common/select/QSelectBox.jsx @@ -17,7 +17,7 @@ import { useOnClickOutside } from 'usehooks-ts' */ export default function QSelectBox({ title = '', - options, + options = [], onChange, value, disabled = false, @@ -32,20 +32,25 @@ export default function QSelectBox({ * @returns {string} 초기 상태 */ const handleInitState = () => { - //title이 있으면 우선 보여준다(다른 키들 무시) - if (title !== '') { - return title - } - - //value가 없으면 showKey가 있으면 우선 보여준다 + if (options.length === 0) return title !== '' ? title : '선택하세요.' if (showKey !== '' && !value) { - return options[0][showKey] - } + //value가 없으면 showKey가 있으면 우선 보여준다 + // return options[0][showKey] + return title + } else if (showKey !== '' && value) { + //value가 있으면 sourceKey와 targetKey를 비교하여 보여준다 - //value가 있으면 sourceKey와 targetKey를 비교하여 보여준다 - if (showKey !== '' && value) { - const option = options.find((option) => option[sourceKey] === value[targetKey]) - return option[showKey] + const option = options.find((option) => { + return option[sourceKey] === value[targetKey] + }) + if (!option) { + return title !== '' ? title : '선택하세요.' + } else { + return option[showKey] + } + } else { + //일치하는 조건이 없으면 기본값을 보여준다. + return title !== '' ? title : '선택하세요.' } } @@ -54,6 +59,8 @@ export default function QSelectBox({ const ref = useRef(null) const handleClickSelectOption = (option) => { + console.log('🚀 ~ handleClickSelectOption ~ option:', option) + setSelected(showKey !== '' ? option[showKey] : option.name) onChange?.(option, params) } @@ -65,7 +72,7 @@ export default function QSelectBox({ useEffect(() => { // value && handleClickSelectOption(value) setSelected(handleInitState()) - }, [value, sourceKey, targetKey, showKey]) + }, [options, value, sourceKey, targetKey, showKey]) useOnClickOutside(ref, handleClose) @@ -73,11 +80,12 @@ export default function QSelectBox({
{} : () => setOpenSelect(!openSelect)}>

{selected}

    - {options?.map((option, index) => ( -
  • handleClickSelectOption(option)}> - -
  • - ))} + {options?.length > 0 && + options?.map((option, index) => ( +
  • handleClickSelectOption(option)}> + +
  • + ))}
) diff --git a/src/components/community/Table.jsx b/src/components/community/Table.jsx index 9cca84ee..ffe68fa6 100644 --- a/src/components/community/Table.jsx +++ b/src/components/community/Table.jsx @@ -79,7 +79,7 @@ export default function Table({ clsCode }) { > {/* 번호 */} - {board.rowNumber} + {board.totCnt - board.rowNumber + 1} {/* 제목 */} diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index d92ba071..f0cd97fb 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -21,7 +21,7 @@ import { v4 as uuidv4 } from 'uuid' import { correntObjectNoState } from '@/store/settingAtom' import { useSearchParams } from 'next/navigation' -export default function Estimate({ params }) { +export default function Estimate({}) { const [uniqueData, setUniqueData] = useState([]) const [handlePricingFlag, setHandlePricingFlag] = useState(false) const [specialNoteFirstFlg, setSpecialNoteFirstFlg] = useState(false) @@ -42,7 +42,8 @@ export default function Estimate({ params }) { const [selection, setSelection] = useState(new Set()) //견적특이사항 접고 펼치기 - const [hidden, setHidden] = useState(false) + // const [hidden, setHidden] = useState(false) + const [hidden, setHidden] = useState(true) //아이템 자동완성 리스트 const [displayItemList, setDisplayItemList] = useState([]) @@ -58,29 +59,28 @@ export default function Estimate({ params }) { startDate, setStartDate, } - - const objectRecoil = useRecoilValue(floorPlanObjectState) - - //견적서 상세데이터 - const { estimateContextState, setEstimateContextState, addItem, handleEstimateFileDownload } = useEstimateController(params.pid) - - //견적특이사항 List - const [specialNoteList, setSpecialNoteList] = useState([]) - const [popShowSpecialNoteList, setPopShowSpecialNoteList] = useState([]) - - const globalLocaleState = useRecoilValue(globalLocaleStore) - const { get, promisePost } = useAxios(globalLocaleState) - - const { getMessage } = useMessage() - - const { setMenuNumber } = useCanvasMenu() - /** * objectNo 셋팅 * url로 넘어온 objectNo을 리코일에 세팅 */ const setCurrentObjectNo = useSetRecoilState(correntObjectNoState) const searchParams = useSearchParams() + const objectRecoil = useRecoilValue(floorPlanObjectState) + const currentPid = searchParams.get('pid') + //견적서 상세데이터 + const { estimateContextState, setEstimateContextState, addItem, handleEstimateFileDownload } = useEstimateController(currentPid) + + //견적특이사항 List + const [specialNoteList, setSpecialNoteList] = useState([]) + const [popShowSpecialNoteList, setPopShowSpecialNoteList] = useState([]) + + const globalLocaleState = useRecoilValue(globalLocaleStore) + const { get, post, promisePost } = useAxios(globalLocaleState) + + const { getMessage } = useMessage() + + const { setMenuNumber } = useCanvasMenu() + const currentObjectNo = searchParams.get('objectNo') setCurrentObjectNo(currentObjectNo) @@ -93,7 +93,8 @@ export default function Estimate({ params }) { useEffect(() => { setMenuNumber(5) setObjectNo(objectRecoil.floorPlanObjectNo) - setPlanNo(params.pid) + + setPlanNo(currentPid) // 공통코드 const code1 = findCommonCode(200800) @@ -106,7 +107,7 @@ export default function Estimate({ params }) { saleStoreId: session.storeId, } const apiUrl = `/api/display-item/item-list?${queryStringFormatter(param)}` - get({ url: apiUrl }).then((res) => { + post({ url: apiUrl, data: param }).then((res) => { if (res.length > 0) { setDisplayItemList(res) } @@ -615,6 +616,8 @@ export default function Estimate({ params }) { const onChangeDisplayItem = (itemId, dispOrder, index) => { const param = { itemId: itemId, + coldZoneFlg: estimateContextState?.coldRegionFlg, + saltAffectedFlg: estimateContextState?.saltAreaFlg, } const apiUrl = `/api/display-item/item-detail?${queryStringFormatter(param)}` let updateList = [] @@ -992,7 +995,11 @@ export default function Estimate({ params }) { {/* 2차 판매점명 */} {getMessage('estimate.detail.otherSaleStoreId')} - {estimateContextState?.agencySaleStoreName} + + {session?.storeLvl === '1' && estimateContextState?.saleStoreLevel === '1' + ? getMessage('estimate.detail.noOtherSaleStoreId') + : estimateContextState?.agencySaleStoreName} + {/* 담당자 */} {getMessage('estimate.detail.receiveUser')} * @@ -1243,11 +1250,10 @@ export default function Estimate({ params }) {

{getMessage('estimate.detail.header.specialEstimate')}

-
{getMessage('estimate.detail.header.specialEstimateProductInfo')}
-
-
- - +
+ + +
{/* 견적 특이사항 코드영역시작 */} @@ -1547,6 +1553,7 @@ export default function Estimate({ params }) { onChangeDisplayItem(e.itemId, item.dispOrder, index) } }} + defaultInputValue={item.itemName} getOptionLabel={(x) => x.itemName} getOptionValue={(x) => x.itemId} isClearable={false} diff --git a/src/components/estimate/popup/DocDownOptionPop.jsx b/src/components/estimate/popup/DocDownOptionPop.jsx index d6b22eb2..6fe73c53 100644 --- a/src/components/estimate/popup/DocDownOptionPop.jsx +++ b/src/components/estimate/popup/DocDownOptionPop.jsx @@ -290,18 +290,18 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) {
+ -
diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index cd655841..91173b89 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -34,7 +34,7 @@ import { addedRoofsState, basicSettingState, selectedRoofMaterialSelector, setti import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom' import { commonUtilsState } from '@/store/commonUtilsAtom' import { menusState, menuTypeState } from '@/store/menuAtom' -import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom' +import { estimateState } from '@/store/floorPlanObjectAtom' import { pwrGnrSimTypeState } from '@/store/simulatorAtom' import { isObjectNotEmpty } from '@/util/common-utils' @@ -86,14 +86,68 @@ export default function CanvasMenu(props) { //견적서버튼 노출용 const [buttonStyle, setButtonStyle] = useState('') - const onClickNav = (menu) => { - setMenuNumber(menu.index) - setCurrentMenu(menu.title) + // 발전시뮬레이션 메뉴 이동 + const { objectNo, pid } = floorPlanState + // 발전시물레이션 Excel/PDF 다운 + const { promiseGet, promisePost } = useAxios(globalLocale) + const pwrGnrSimTypeRecoil = useRecoilValue(pwrGnrSimTypeState) + + const handleExcelPdfFileDown = async (donwloadType, drawingFlg) => { + const url = '/api/estimate/excel-download' + + const params = { + objectNo: objectNo, + planNo: pid, + schDownload: donwloadType, + schDrawingFlg: drawingFlg, + pwrGnrSimType: pwrGnrSimTypeRecoil.type, + } + + const options = { responseType: 'blob' } + await promisePost({ url: url, data: params, option: options }) + .then((resultData) => { + if (resultData) { + let fileName = 'unknow' + const blob = new Blob([resultData.data], { type: resultData.headers['content-type'] || 'application/octet-stream' }) + const fileUrl = window.URL.createObjectURL(blob) + + const link = document.createElement('a') + link.href = fileUrl + + //서버에서 내려오는 파일명 + const contentDisposition = resultData.headers['content-disposition'] + if (contentDisposition) { + fileName = contentDisposition.split('filename=')[1].replace(/['"]/g, '') + } + + link.download = fileName + document.body.appendChild(link) + link.click() + link.remove() + window.URL.revokeObjectURL(fileUrl) + } + }) + .catch((error) => { + alert('File does not exist.') + }) + } + + const onClickNav = (menu) => { switch (menu.index) { + case 0: + swalFire({ + text: getMessage('stuff.detail.move.confirmMsg'), + type: 'confirm', + confirmFn: () => { + router.push(`/management/stuff/detail?objectNo=${objectNo}`) + }, + }) + break case 1: setType('placementShape') onClickPlacementInitialMenu() + break case 2: setType('outline') @@ -108,12 +162,35 @@ export default function CanvasMenu(props) { case 4: setType('module') break + case 5: + setMenuNumber(menu.index) + setCurrentMenu(menu.title) + router.push(`/floor-plan/estimate/5?pid=${pid}&objectNo=${objectNo}`) + break case 6: - router.push(`/floor-plan/simulator/${menu.index}`) + promiseGet({ url: `/api/estimate/${objectNo}/${pid}/detail` }).then((res) => { + if (res.status === 200) { + const estimateDetail = res.data + if (estimateDetail.docNo) { + setMenuNumber(menu.index) + setCurrentMenu(menu.title) + router.push(`/floor-plan/simulator/${menu.index}?pid=${pid}&objectNo=${objectNo}`) + } else { + swalFire({ text: getMessage('simulator.menu.move.valid1') }) + } + } + }) break } - if (pathname !== '/floor-plan') router.push('/floor-plan') + if (menu.index !== 6 && menu.index !== 0) { + setMenuNumber(menu.index) + setCurrentMenu(menu.title) + } + + if (pathname !== '/floor-plan' && pathname !== '/floor-plan/estimate/5') { + router.push(`/floor-plan?pid=${pid}&objectNo=${objectNo}`) + } } const changeSelectedRoofMaterial = (e) => { @@ -175,6 +252,7 @@ export default function CanvasMenu(props) { // 견적서 초기화 버튼 const handleEstimateReset = () => { + return alert('개발전입니다;;;') // console.log('estimateRecoilState::', estimateRecoilState) //objectNo, planNo swalFire({ @@ -215,54 +293,6 @@ export default function CanvasMenu(props) { return (['2', '3'].includes(canvasSetting?.roofSizeSet) && menu.index === 2) || (menuNumber === 4 && menu.index === 2) } - // 발전시물레이션 Excel/PDF 다운 - const { promisePost } = useAxios(globalLocale) - const objectRecoil = useRecoilValue(floorPlanObjectState) - const pwrGnrSimTypeRecoil = useRecoilValue(pwrGnrSimTypeState) - - const { plans } = usePlan() - const plan = plans.find((plan) => plan.isCurrent === true) - - const handleExcelPdfFileDown = async (donwloadType, drawingFlg) => { - const url = '/api/estimate/excel-download' - - const params = { - objectNo: objectRecoil.floorPlanObjectNo, - planNo: plan?.id, - schDownload: donwloadType, - schDrawingFlg: drawingFlg, - pwrGnrSimType: pwrGnrSimTypeRecoil.type, - } - - const options = { responseType: 'blob' } - await promisePost({ url: url, data: params, option: options }) - .then((resultData) => { - if (resultData) { - let fileName = 'unknow' - const blob = new Blob([resultData.data], { type: resultData.headers['content-type'] || 'application/octet-stream' }) - const fileUrl = window.URL.createObjectURL(blob) - - const link = document.createElement('a') - link.href = fileUrl - - //서버에서 내려오는 파일명 - const contentDisposition = resultData.headers['content-disposition'] - if (contentDisposition) { - fileName = contentDisposition.split('filename=')[1].replace(/['"]/g, '') - } - - link.download = fileName - document.body.appendChild(link) - link.click() - link.remove() - window.URL.revokeObjectURL(fileUrl) - } - }) - .catch((error) => { - alert('File does not exist.') - }) - } - useEffect(() => { if (isObjectNotEmpty(estimateRecoilState)) { if (estimateRecoilState?.createUser === 'T01') { diff --git a/src/components/floor-plan/modal/basic/step/Module.jsx b/src/components/floor-plan/modal/basic/step/Module.jsx index e3e5c7bc..5d3456c2 100644 --- a/src/components/floor-plan/modal/basic/step/Module.jsx +++ b/src/components/floor-plan/modal/basic/step/Module.jsx @@ -1,9 +1,61 @@ -import QSelectBox from '@/components/common/select/QSelectBox' +import { useEffect, useState, useReducer } from 'react' +import { useRecoilValue, useRecoilState } from 'recoil' +import { addedRoofsState } from '@/store/settingAtom' +import { canvasSettingState, pitchSelector } from '@/store/canvasAtom' import { useMessage } from '@/hooks/useMessage' +import QSelectBox from '@/components/common/select/QSelectBox' +import { useModuleSelection } from '@/hooks/module/useModuleSelection' +import ModuleTabContents from './ModuleTabContents' +import { useDebounceCallback, useDebounceValue } from 'usehooks-ts' +import { moduleSelectionDataState } from '@/store/selectedModuleOptions' export default function Module({}) { const { getMessage } = useMessage() - const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }] + const addedRoofs = useRecoilValue(addedRoofsState) //지붕재 선택 + const [roofTab, setRoofTab] = useState(0) //지붕재 탭 + + const { + moduleSelectionInitParams, + selectedModules, + raftCodes, + roughnessCodes, + windSpeedCodes, + managementState, + moduleList, + installHeight, + verticalSnowCover, + handleChangeModule, + handleChangeSurfaceType, + handleChangeWindSpeed, + handleChangeInstallHeight, + handleChangeVerticalSnowCover, + } = useModuleSelection({ addedRoofs }) + + const [inputInstallHeight, setInputInstallHeight] = useState(installHeight) + const [inputVerticalSnowCover, setInputVerticalSnowCover] = useState(verticalSnowCover) + + const [debouncedInstallHeight] = useDebounceValue(inputInstallHeight, 500) + const [debouncedVerticalSnowCover] = useDebounceValue(inputVerticalSnowCover, 500) + + const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터 + + const [tempModuleSelectionData, setTempModuleSelectionData] = useReducer((prevState, nextState) => { + return { ...prevState, ...nextState } + }, moduleSelectionData) + + useEffect(() => { + handleChangeInstallHeight(debouncedInstallHeight) + }, [debouncedInstallHeight]) + + useEffect(() => { + handleChangeVerticalSnowCover(debouncedVerticalSnowCover) + }, [debouncedVerticalSnowCover]) + + useEffect(() => { + setInputInstallHeight(installHeight) + setInputVerticalSnowCover(verticalSnowCover) + }, [installHeight, verticalSnowCover]) + const moduleData = { header: [ { name: getMessage('module'), width: 150, prop: 'module', type: 'color-box' }, @@ -14,34 +66,15 @@ export default function Module({}) { { name: `${getMessage('width')} (mm)`, prop: 'width' }, { name: `${getMessage('output')} (W)`, prop: 'output' }, ], - rows: [ - { - module: { name: 'Re.RISE-G3 440', color: '#AA6768' }, - height: { name: '1134' }, - width: { name: '1722' }, - output: { name: '440' }, - }, - { - module: { - name: 'Re.RISE MS-G3 290', - color: '#67A2AA', - }, - height: { name: '1134' }, - width: { name: '1722' }, - output: { name: '240' }, - }, - ], + rows: [], } - const surfaceTypes = [ - { id: 1, name: 'Ⅱ', value: 'Ⅱ' }, - { id: 2, name: 'Ⅲ ∙ Ⅳ', value: 'Ⅲ ∙ Ⅳ' }, - ] - const fiftingHeights = Array.from({ length: 16 }).map((data, index) => { - return { id: index, name: index + 5, value: index + 5 } - }) - const windSpeeds = Array.from({ length: 7 }).map((data, index) => { - return { id: index, name: index * 2 + 30, value: index * 2 + 30 } - }) + + useEffect(() => {}, [roofTab]) + + const handleRoofTab = (tab) => { + setRoofTab(tab) + } + return ( <>
@@ -50,7 +83,16 @@ export default function Module({}) {
{getMessage('modal.module.basic.setting.module.setting')}
- + {moduleList && ( + + )}
@@ -67,34 +109,22 @@ export default function Module({}) { - {moduleData.rows.map((row) => ( - <> - - {moduleData.header.map((header) => ( - <> - {header.type === 'color-box' && ( - -
- - {row[header.prop].name} -
- - )} - {!header.type && header.type !== 'color-box' && {row[header.prop].name}} - - ))} - - - ))} - - {Array.from({ length: 3 - moduleData.rows.length }).map((_, i) => ( - - - - - - - ))} + {selectedModules.itemList && + selectedModules.itemList.map((row) => ( + <> + + +
+ + {row.itemNm} +
+ + {Number(row.shortAxis).toFixed(0)} + {Number(row.longAxis).toFixed(0)} + {Number(row.wpOut).toFixed(0)} + + + ))}
@@ -109,7 +139,16 @@ export default function Module({}) {
- + {roughnessCodes.length > 0 && ( + + )}
@@ -119,7 +158,12 @@ export default function Module({}) {
- + setInputInstallHeight(e.target.value)} + />
mm
@@ -130,7 +174,17 @@ export default function Module({}) {
- + {windSpeedCodes.length > 0 && managementState && ( + + )}
m/s
@@ -141,7 +195,12 @@ export default function Module({}) {
- + setInputVerticalSnowCover(e.target.value)} + />
mm
@@ -153,80 +212,30 @@ export default function Module({}) {
- - - - + {addedRoofs && + addedRoofs.map((roof, index) => ( + + ))}
-
-
-
-
{getMessage('modal.module.basic.setting.module.roof.material')}:スレーツ(4寸)
-
-
-
{getMessage('modal.module.basic.setting.module.rafter.margin')}
-
-
-
- -
-
- 垂木の間隔 -
- -
-
-
-
-
-
-
{getMessage('modal.module.basic.setting.module.trestle.maker')}
-
-
- -
-
-
-
-
{getMessage('modal.module.basic.setting.module.construction.method')}
-
-
- -
-
-
-
-
{getMessage('modal.module.basic.setting.module.under.roof')}
-
-
- -
-
-
-
+ {addedRoofs && + addedRoofs.map((roof, index) => ( +
+
-
-
- - - - - -
-
-
- - -
-
- - -
-
-
-
-
+ ))}
+
diff --git a/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx b/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx new file mode 100644 index 00000000..586991f4 --- /dev/null +++ b/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx @@ -0,0 +1,437 @@ +import { useEffect, useState, useRef, useReducer } from 'react' +import { useRecoilValue, useRecoilState } from 'recoil' +import { canvasSettingState, pitchSelector, pitchTextSelector } from '@/store/canvasAtom' +import { useMessage } from '@/hooks/useMessage' +import { useMasterController } from '@/hooks/common/useMasterController' +import { useCommonCode } from '@/hooks/common/useCommonCode' +import { moduleSelectionInitParamsState, selectedModuleState } from '@/store/selectedModuleOptions' +import { isNotEmptyArray, isObjectNotEmpty } from '@/util/common-utils' +import QSelectBox from '@/components/common/select/QSelectBox' + +export default function ModuleTabContents({ + addRoof, + roofTab, + moduleSelectionData, + setModuleSelectionData, + tempModuleSelectionData, + setTempModuleSelectionData, +}) { + const { getMessage } = useMessage() + const canvasSetting = useRecoilValue(canvasSettingState) //캔버스 기본 셋팅 + const [roofMaterial, setRoofMaterial] = useState(addRoof) //지붕재 + + const globalPitch = useRecoilValue(pitchSelector) //피치 + const globalPitchText = useRecoilValue(pitchTextSelector) //피치 텍스트 + + const { findCommonCode } = useCommonCode() + const [raftCodes, setRaftCodes] = useState([]) //가대 목록 + const [trestleList, setTrestleList] = useState([]) + const [constMthdList, setConstMthdList] = useState([]) + const [roofBaseList, setRoofBaseList] = useState([]) + const [constructionList, setConstructionList] = useState([{}]) //공법 목록 + + const [selectedRaftBase, setSelectedRaftBase] = useState({}) //선택된 가대 + const [selectedTrestle, setSelectedTrestle] = useState({}) //선택된 가대 + const [selectedConstMthd, setSelectedConstMthd] = useState({}) //선택된 공법 + const [selectedRoofBase, setSelectedRoofBase] = useState({}) //선택된 지붕밑바탕 + const [selectedConstruction, setSelectedConstruction] = useState({}) //선택된 공법 + const [constructionListParams, setConstructionListParams] = useState({}) + + const [trestleParams, setTrestleParams] = useState({}) //서까래, 가대메이커,공법,지붕밑바탕 관련 api호출 파라메터 + + const moduleSelectionInitParams = useRecoilValue(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등 + + const { getTrestleList, getConstructionList } = useMasterController() + + const constructionRef = useRef([]) + const [cvrYn, setCvrYn] = useState('N') + const [snowGdPossYn, setSnowGdPossYn] = useState('N') + + const [cvrChecked, setCvrChecked] = useState(false) + const [snowGdChecked, setSnowGdChecked] = useState(false) + + //서까래간격 변경 + const handleChangeRaftBase = (option) => { + setSelectedRaftBase(option) + setTrestleParams({ ...trestleParams, raftBaseCd: option.clCode }) + + setTrestleList([]) //가대메이커 + setConstMthdList([]) //공법 초기화 + setRoofBaseList([]) //지붕밑바탕 초기화 + } + + //가대메이커 변경 + const handleChangeTrestle = (option) => { + if (option) { + setSelectedTrestle(option) //선택값 저장 + setTrestleParams({ ...trestleParams, trestleMkrCd: option.trestleMkrCd, constMthdCd: '', roofBaseCd: '' }) + } else { + const existTrestle = moduleSelectionData.roofConstructions[roofTab].trestle + setSelectedTrestle(existTrestle) + setTrestleParams({ ...existTrestle, constMthdCd: '', roofBaseCd: '' }) + } + + setConstMthdList([]) //공법 초기화 + setRoofBaseList([]) //지붕밑바탕 초기화 + } + + //공법 변경 + const handleChangeConstMthd = (option) => { + if (option) { + setSelectedConstMthd(option) //선택된값 저장 + setTrestleParams({ ...trestleParams, constMthdCd: option.constMthdCd, roofBaseCd: '' }) + } else { + const existTrestle = moduleSelectionData.roofConstructions[roofTab].trestle + setSelectedConstMthd(existTrestle) + setTrestleParams({ ...existTrestle, constMthdCd: '', roofBaseCd: '' }) + } + + setRoofBaseList([]) + } + + //지붕밑바탕변경 + const handleChangeRoofBase = (option) => { + if (option) { + setConstructionListParams({ + ...moduleSelectionInitParams, + ...trestleParams, + roofBaseCd: option.roofBaseCd, + }) + setSelectedRoofBase(option) + } else { + const existTrestle = moduleSelectionData.roofConstructions[roofTab].trestle + setConstructionListParams({ + ...existTrestle, + }) + setSelectedRoofBase(existTrestle) + } + } + + const getModuleOptionsListData = async (params) => { + const optionsList = await getTrestleList(params) + if (optionsList.data.length > 0) { + if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd === null) { + setTrestleList(optionsList.data) + setConstMthdList([]) + setRoofBaseList([]) + } + + if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd && optionsList.data[0].roofBaseCd === null) { + setConstMthdList(optionsList.data) + setRoofBaseList([]) + } + + if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd && optionsList.data[0].roofBaseCd) { + setRoofBaseList(optionsList.data) + } + } + } + + const getConstructionListData = async (params) => { + if (params.trestleMkrCd && params.constMthdCd && params.roofBaseCd) { + const optionsList = await getConstructionList(params) + setConstructionList(optionsList.data) + } + } + + const handleConstruction = (index) => { + const isPossibleIndex = constructionRef.current + .map((el, i) => (el.classList.contains('white') || el.classList.contains('blue') ? i : -1)) + .filter((index) => index !== -1) + + isPossibleIndex.forEach((index) => { + if (constructionRef.current[index].classList.contains('blue')) { + constructionRef.current[index].classList.remove('blue') + constructionRef.current[index].classList.add('white') + } + }) + constructionRef.current[index].classList.remove('white') + constructionRef.current[index].classList.add('blue') + + const selectedConstruction = constructionList[index] + selectedConstruction.roofIndex = roofTab + selectedConstruction.setupCover = false //처마력바 설치 여부 + selectedConstruction.setupSnowCover = false //눈막이금구 설치 여부 + + setCvrYn(selectedConstruction.cvrYn) + setSnowGdPossYn(selectedConstruction.snowGdPossYn) + setSelectedConstruction(selectedConstruction) + } + + useEffect(() => { + if (isObjectNotEmpty(selectedRoofBase) && isObjectNotEmpty(selectedConstruction)) { + const newRoofConstructions = { roofIndex: roofTab, trestle: selectedRoofBase, construction: selectedConstruction } + const index = tempModuleSelectionData.roofConstructions.findIndex((obj) => obj.roofIndex === roofTab) + + if (index > -1) { + const newArray = [ + ...tempModuleSelectionData.roofConstructions.slice(0, index), + newRoofConstructions, + ...tempModuleSelectionData.roofConstructions.slice(index + 1), + ] + setTempModuleSelectionData({ roofConstructions: newArray }) + } else { + setTempModuleSelectionData({ roofConstructions: [...tempModuleSelectionData.roofConstructions, { ...newRoofConstructions }] }) + } + } + }, [selectedConstruction]) + + const handleCvrChecked = () => { + setCvrChecked(!cvrChecked) + } + + const handleSnowGdChecked = () => { + setSnowGdChecked(!snowGdChecked) + } + + useEffect(() => { + setSelectedConstruction({ ...selectedConstruction, setupCover: cvrChecked }) + }, [cvrChecked]) + + useEffect(() => { + setSelectedConstruction({ ...selectedConstruction, setupSnowCover: snowGdChecked }) + }, [snowGdChecked]) + + useEffect(() => { + // 202600 경사도 + const raftCodeList = findCommonCode('203800') + //서까래 코드 + raftCodeList.forEach((obj) => { + obj.name = obj.clCodeNm + obj.id = obj.clCode + }) + setRaftCodes(raftCodeList) + }, []) + + useEffect(() => { + //물건 상세의 데이터를 가지고 초기화 데이터를 만든다 + if ( + moduleSelectionInitParams.illuminationTp && + moduleSelectionInitParams.instHt && + moduleSelectionInitParams.stdSnowLd && + moduleSelectionInitParams.stdWindSpeed + ) { + const isModuleLoaded = moduleSelectionInitParams.hasOwnProperty('moduleTpCd') //모듈컬럼이 있으면 모듈을 변경했다는 내용 + if (isModuleLoaded) { + setTrestleParams({ moduleTpCd: moduleSelectionInitParams.moduleTpCd, roofMatlCd: addRoof.roofMatlCd, raftBaseCd: addRoof.raftBaseCd }) + setConstructionList([]) + } + } + + setTempModuleSelectionData({ common: moduleSelectionInitParams }) + }, [moduleSelectionInitParams]) + + useEffect(() => { + if (isObjectNotEmpty(trestleParams)) { + getModuleOptionsListData(trestleParams) + } + }, [trestleParams]) + + useEffect(() => { + if (isObjectNotEmpty(constructionListParams)) { + getConstructionListData(constructionListParams) + } + }, [constructionListParams]) + + useEffect(() => { + if (isObjectNotEmpty(tempModuleSelectionData)) { + setModuleSelectionData(tempModuleSelectionData) + } + }, [tempModuleSelectionData]) + + useEffect(() => { + if (isObjectNotEmpty(moduleSelectionData.roofConstructions[roofTab])) { + handleChangeTrestle() + handleChangeConstMthd() + } + }, []) + + return ( + <> +
+
+
+
+ {getMessage('modal.module.basic.setting.module.roof.material')}:{roofMaterial.nameJp}({globalPitch} + {globalPitchText}) +
+
+
+ {roofMaterial && ['C'].includes(roofMaterial.lenAuth) && ( + <> +
L
+
+
+
+
+ +
+
+
+
+ + )} + {roofMaterial && ['C', 'R'].includes(roofMaterial.raftAuth) && ( + <> +
{getMessage('modal.module.basic.setting.module.rafter.margin')}
+
+
+
+ {raftCodes.length > 0 && ( + + )} +
+
+
+ + )} + {roofMaterial && ['C', 'R'].includes(roofMaterial.roofPchAuth) && ( + <> +
{getMessage('modal.module.basic.setting.module.rafter.margin')}
+
+
+
+ 垂木の間隔 +
+ +
+
+
+
+ + )} +
+
+
{getMessage('modal.module.basic.setting.module.trestle.maker')}
+
+
+ {trestleList && ( + + )} +
+
+
+
+
{getMessage('modal.module.basic.setting.module.construction.method')}
+
+
+ {constMthdList && ( + + )} +
+
+
+
+
{getMessage('modal.module.basic.setting.module.under.roof')}
+
+
+ {roofBaseList && ( + + )} +
+
+
+
+
+
+
+ + + + + +
+
+
+ + +
+
+ + +
+
+
+
+
+ + ) +} diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index a087f3dc..72f4eab2 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -1,40 +1,45 @@ import { forwardRef, useEffect, useState } from 'react' import { useMessage } from '@/hooks/useMessage' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' +import { checkedModuleState } from '@/store/canvasAtom' +import { useRecoilValue, useRecoilState, useSetRecoilState } from 'recoil' +import { selectedModuleState, moduleSelectionDataState } from '@/store/selectedModuleOptions' const Placement = forwardRef((props, refs) => { const { getMessage } = useMessage() + const selectedModules = useRecoilValue(selectedModuleState) const [isChidori, setIsChidori] = useState('false') const [setupLocation, setSetupLocation] = useState('center') const [isMaxSetup, setIsMaxSetup] = useState('false') - const { makeModuleInstArea } = useModuleBasicSetting() + const [selectedItems, setSelectedItems] = useState({}) + const setCheckedModules = useSetRecoilState(checkedModuleState) + const moduleSelectionData = useRecoilValue(moduleSelectionDataState) + + //모듈 배치면 생성 useEffect(() => { + console.log('🚀 ~ Placement ~ moduleSelectionData:', moduleSelectionData) + console.log('🚀 ~ Placement ~ selectedModules:', selectedModules) makeModuleInstArea() }, []) + //체크된 모듈 데이터 + useEffect(() => { + const checkedModuleIds = Object.keys(selectedItems).filter((key) => selectedItems[key]) + const moduleArray = selectedModules.itemList.filter((item) => { + return checkedModuleIds.includes(item.itemId) + }) + setCheckedModules(moduleArray) + }, [selectedItems]) + const moduleData = { header: [ { type: 'check', name: '', prop: 'check', width: 70 }, { type: 'color-box', name: getMessage('module'), prop: 'module' }, { type: 'text', name: `${getMessage('output')} (W)`, prop: 'output', width: 70 }, ], - rows: [ - { - check: false, - module: { name: 'Re.RISE-G3 440', color: '#AA6768' }, - output: { name: '440' }, - }, - { - check: false, - module: { - name: 'Re.RISE MS-G3 290', - color: '#67A2AA', - }, - output: { name: '240' }, - }, - ], + rows: [], } const handleChangeChidori = (e) => { @@ -48,8 +53,6 @@ const Placement = forwardRef((props, refs) => { } const handleMaxSetup = (e) => { - console.log(e.target.checked) - if (e.target.checked) { setIsMaxSetup('true') refs.isMaxSetup.current = 'true' @@ -59,6 +62,11 @@ const Placement = forwardRef((props, refs) => { } } + //체크된 모듈 아이디 추출 + const handleSelectedItem = (e) => { + setSelectedItems({ ...selectedItems, [e.target.name]: e.target.checked }) + } + return ( <>
@@ -83,40 +91,26 @@ const Placement = forwardRef((props, refs) => { - {moduleData.rows.map((row) => ( - <> - - {moduleData.header.map((header) => ( - <> - {header.type === 'color-box' && ( - -
- - {row[header.prop].name} -
- - )} - {header.type === 'check' && ( - -
- - -
- - )} - {header.type && header.type !== 'color-box' && header.type !== 'check' && ( - {row[header.prop].name} - )} - - ))} - - - ))} - - - - - + {selectedModules.itemList && + selectedModules.itemList.map((item) => ( + <> + + +
+ + +
+ + +
+ + {item.itemNm} +
+ + {item.wpOut} + + + ))}
diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx index a71036c6..4a265f67 100644 --- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx @@ -1,23 +1,106 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' -import { useState } from 'react' +import { useState, useEffect, useContext } from 'react' import PowerConditionalSelect from '@/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect' import CircuitAllocation from '@/components/floor-plan/modal/circuitTrestle/step/CircuitAllocation' import StepUp from '@/components/floor-plan/modal/circuitTrestle/step/StepUp' import { useMessage } from '@/hooks/useMessage' import { usePopup } from '@/hooks/usePopup' +import PassivityCircuitAllocation from './step/type/PassivityCircuitAllocation' +import { useAxios } from '@/hooks/useAxios' +import { useMasterController } from '@/hooks/common/useMasterController' +import { get } from 'react-hook-form' +import { correntObjectNoState } from '@/store/settingAtom' +import { useRecoilValue } from 'recoil' +import { GlobalDataContext } from '@/app/GlobalDataProvider' +const ALLOCATION_TYPE = { + AUTO: 'auto', + PASSIVITY: 'passivity', +} export default function CircuitTrestleSetting({ id }) { const { getMessage } = useMessage() const { closePopup } = usePopup() + // 탭 번호 1: 파워 컨디셔너 선택(+수동 설정) + // 탭 번호 2: 회로 할당 const [tabNum, setTabNum] = useState(1) + const [allocationType, setAllocationType] = useState(ALLOCATION_TYPE.AUTO) + const [makers, setMakers] = useState([]) + const [series, setSeries] = useState([]) + const [models, setModels] = useState([]) + const [selectedMaker, setSelectedMaker] = useState(null) + const [selectedModels, setSelectedModels] = useState(null) + const [selectedSeries, setSelectedSeries] = useState(null) + const correntObjectNo = useRecoilValue(correntObjectNoState) + const { getPcsMakerList } = useMasterController() + const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) + const apply = () => { + closePopup(id) + } + + useEffect(() => { + getPcsMakerList().then((res) => { + setMakers(res.data) + }) + if (!managementState) { + console.log('🚀 ~ useEffect ~ managementState:', managementState) + setManagementState(managementStateLoaded) + } + console.log('🚀 ~ useEffect ~ managementState:', managementState) + // promiseGet({ url: `/api/object/${correntObjectNo}/detail` }).then((res) => { + // console.log('🚀 ~ useEffect ~ /api/object/${correntObjectNo}/detail:', res) + // // coldRegionFlg-한랭지사양, conType// 계약조건(잉여~,전량) + // }) + }, []) + + useEffect(() => { + if (selectedMaker) { + getPcsMakerList(selectedMaker).then((res) => { + const series = res.data.map((series) => { + return { ...series, selected: false } + }) + setSeries(series) + }) + } + }, [selectedMaker]) + + useEffect(() => { + console.log('🚀 ~ CircuitTrestleSetting ~ series:', series) + const selectedSeries = series.filter((s) => s.selectd).map((s) => s.pcsSerCd) + if (selectedSeries.length > 0) { + getPcsMakerList(selectedSeries).then((res) => { + setModels(res.data) + }) + } + }, [series]) + // 회로 할당 유형 const [circuitAllocationType, setCircuitAllocationType] = useState(1) + + const powerConditionalSelectProps = { + tabNum, + setTabNum, + makers, + selectedMaker, + setSelectedMaker, + series, + setSeries, + selectedSeries, + setSelectedSeries, + models, + setModels, + selectedModels, + setSelectedModels, + managementState, + } const circuitProps = { + tabNum, + setTabNum, circuitAllocationType, setCircuitAllocationType, } + return ( -
+

{getMessage('modal.circuit.trestle.setting')}

-
- {getMessage('modal.circuit.trestle.setting.power.conditional.select')} +
{getMessage('modal.circuit.trestle.setting.power.conditional.select')}
+ +
+ {getMessage('modal.circuit.trestle.setting.circuit.allocation')}({getMessage('modal.circuit.trestle.setting.step.up.allocation')})
- -
- {getMessage('modal.circuit.trestle.setting.circuit.allocation')} -
- -
{getMessage('modal.circuit.trestle.setting.step.up.allocation')}
- {tabNum === 1 && } - {tabNum === 2 && } - {tabNum === 3 && } -
- {tabNum !== 1 && ( - + +
+ )} + {tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && ( +
+ - )} - {tabNum !== 3 && ( - - )} - {tabNum === 3 && ( -
+ )} + {tabNum === 2 && ( +
+ - )} -
+ +
+ )}
diff --git a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx index 927f973b..101f2be4 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx @@ -1,89 +1,91 @@ import QSelectBox from '@/components/common/select/QSelectBox' import { useMessage } from '@/hooks/useMessage' +import { globalLocaleStore } from '@/store/localeAtom' import { useState } from 'react' +import { useRecoilValue } from 'recoil' const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }] -export default function PowerConditionalSelect({ setTabNum }) { +export default function PowerConditionalSelect(props) { + const { + makers, + selectedMaker, + setSelectedMaker, + series, + setSeries, + selectedSeries, + setSelectedSeries, + models, + selectedModels, + tabNum, + setTabNum, + managementState, + } = props const { getMessage } = useMessage() const [selectedRowIndex, setSelectedRowIndex] = useState(null) const [powerConditions, setPowerConditions] = useState([]) - const seriesData = { - header: [ - { name: getMessage('명칭'), width: '15%', prop: 'name', type: 'color-box' }, - { - name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.rated.output')} (kW)`, - width: '10%', - prop: 'ratedOutput', - }, - { - name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.circuit.amount')}`, - width: '10%', - prop: 'circuitAmount', - }, - { - name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.max.connection')}`, - width: '10%', - prop: 'maxConnection', - }, - { - name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.max.overload')}`, - width: '10%', - prop: 'maxOverload', - }, - { - name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.output.current')}`, - width: '10%', - prop: 'outputCurrent', - }, - ], - rows: [ - { - name: { name: 'PCSオプションマスター', color: '#AA6768' }, - ratedOutput: { name: '2' }, - circuitAmount: { name: '2' }, - maxConnection: { name: '-' }, - maxOverload: { name: '-' }, - outputCurrent: { name: '-' }, - }, - { - name: { name: 'HQJP-KA40-5', color: '#AA6768' }, - ratedOutput: { name: '2' }, - circuitAmount: { name: '2' }, - maxConnection: { name: '-' }, - maxOverload: { name: '-' }, - outputCurrent: { name: '-' }, - }, - { - name: { name: 'Re.RISE-G3 440', color: '#AA6768' }, - ratedOutput: { name: '2' }, - circuitAmount: { name: '2' }, - maxConnection: { name: '-' }, - maxOverload: { name: '-' }, - outputCurrent: { name: '-' }, - }, - ], + const globalLocale = useRecoilValue(globalLocaleStore) + const modelHeader = [ + { name: getMessage('명칭'), width: '15%', prop: 'name', type: 'color-box' }, + { + name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.rated.output')} (kW)`, + width: '10%', + prop: 'ratedOutput', + }, + { + name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.circuit.amount')}`, + width: '10%', + prop: 'circuitAmount', + }, + { + name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.max.connection')}`, + width: '10%', + prop: 'maxConnection', + }, + { + name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.max.overload')}`, + width: '10%', + prop: 'maxOverload', + }, + { + name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.output.current')}`, + width: '10%', + prop: 'outputCurrent', + }, + ] + const onCheckSeries = (series) => { + setSeries((prev) => prev.map((s) => ({ ...s, selected: s.pcsSerCd === series.pcsSerCd ? !s.selected : s.selected }))) } return ( <>
- 分類 (余剰) + + {getMessage('common.type')} ({getMessage(managementState?.conType === '0' ? 'stuff.detail.conType0' : 'stuff.detail.conType1')}) +
- + setSelectedMaker(option)} + />
- 寒冷地仕様 + {managementState?.conType === '1' && ( + {getMessage('modal.circuit.trestle.setting.power.conditional.select.cold.region')} + )}
-
-
- - -
-
- - -
+
+ {series?.map((series, index) => ( +
+ onCheckSeries(series)} /> + +
+ ))}
@@ -94,7 +96,7 @@ export default function PowerConditionalSelect({ setTabNum }) { - {seriesData.header.map((header) => ( + {modelHeader.map((header) => ( @@ -102,13 +104,15 @@ export default function PowerConditionalSelect({ setTabNum }) { - {seriesData.rows.map((row, index) => ( - setSelectedRowIndex(index)} className={index === selectedRowIndex ? 'on' : ''}> - {seriesData.header.map((header) => ( - - ))} - - ))} + {models + ?.filter((model) => model.series === selectedSeries?.code) + .map((row, index) => ( + setSelectedRowIndex(index)} className={index === selectedRowIndex ? 'on' : ''}> + {modelHeader.map((header) => ( + + ))} + + ))}
{header.name}
{row[header.prop].name}
{row[header.prop]}
@@ -117,22 +121,18 @@ export default function PowerConditionalSelect({ setTabNum }) {
- - HQJP-KA40-5 - - - HQJP-KA40-5 - - - HQJP-KA40-5 - + {selectedModels?.map((model) => ( + + {model.name} + + ))}
- +
@@ -141,6 +141,14 @@ export default function PowerConditionalSelect({ setTabNum }) {
+ {/*
+ + +
*/} ) } diff --git a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx index bfb8422c..287d9ff8 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx @@ -1,395 +1,114 @@ import QSelectBox from '@/components/common/select/QSelectBox' import { useMessage } from '@/hooks/useMessage' +import { useState } from 'react' const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }] export default function StepUp({}) { const { getMessage } = useMessage() + const [moduleTab, setModuleTab] = useState(1) + const [arrayLength, setArrayLength] = useState(3) //module-table-inner의 반복 개수 return ( <>
-
{getMessage('modal.circuit.trestle.setting.step.up.allocation')}
-
-
-
-
HQJP-KA55-5
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{getMessage('modal.circuit.trestle.setting.step.up.allocation.serial.amount')}{getMessage('modal.circuit.trestle.setting.step.up.allocation.total.amount')}
100
100
100
100
100
-
-
-
-
-
{getMessage('modal.circuit.trestle.setting.step.up.allocation.connected')}
-
+ {/* 3개일때 className = by-max */} +
+ {Array.from({ length: arrayLength }).map((_, idx) => ( +
+
+
HQJP-KA55-5
+
- - - + + - - - + + - - + - - + + + + + + + + + + + + +
{getMessage('modal.circuit.trestle.setting.power.conditional.select.name')}{getMessage('modal.circuit.trestle.setting.power.conditional.select.circuit.amount')}{getMessage('modal.circuit.trestle.setting.step.up.allocation.circuit.amount')}{getMessage('modal.circuit.trestle.setting.step.up.allocation.serial.amount')}{getMessage('modal.circuit.trestle.setting.step.up.allocation.total.amount')}
KTN-CBD4C4
10 0
KTN-CBD4C410 0
KTN-CBD4C4100
100
100
10 0
-
-
- -
-
- - HQJP-KA40-5 - -
-
-
-
{getMessage('modal.circuit.trestle.setting.step.up.allocation.option')}
-
- - - - - - - - - - - - - - - - - -
{getMessage('modal.circuit.trestle.setting.power.conditional.select.name')}{getMessage('modal.circuit.trestle.setting.step.up.allocation.circuit.amount')}
--
--
-
-
-
- +
+ + +
+
+ {moduleTab === 1 && ( +
+
+ + + + + + + + + + + + + + + +
{getMessage('modal.circuit.trestle.setting.power.conditional.select.name')}{getMessage('modal.circuit.trestle.setting.power.conditional.select.circuit.amount')}{getMessage('modal.circuit.trestle.setting.step.up.allocation.circuit.amount')}
KTN-CBD4C40
+
-
- - HQJP-KA40-5 - + )} + {moduleTab === 2 && ( +
+
+ + + + + + + + + + + + + +
名称昇圧回路数
--
+
-
+ )}
-
- {getMessage('modal.module.basic.setting.module.cotton.classification')} -
- -
- 回路 - (二重昇圧回路数 -
- -
- 回路) -
-
-
-
-
-
-
HQJP-KA55-5
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
シリアル枚数総回路数
100
100
100
100
100
-
-
-
-
-
接続する
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
名称回路数昇圧回路数
KTN-CBD4C40
KTN-CBD4C40
KTN-CBD4C40
-
-
-
- -
-
- - HQJP-KA40-5 - -
-
-
-
-
昇圧オプション
-
- - - - - - - - - - - - - - - - - -
名称昇圧回路数
--
--
-
-
-
- -
-
- - HQJP-KA40-5 - -
-
-
-
-
- 綿調道区分 -
- -
- 回路 - (二重昇圧回路数 -
- -
- 回路) -
-
-
-
-
-
-
HQJP-KA55-5
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
シリアル枚数総回路数
100
100
100
100
100
-
-
-
-
-
接続する
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
名称回路数昇圧回路数
KTN-CBD4C40
KTN-CBD4C40
KTN-CBD4C40
-
-
-
- -
-
- - HQJP-KA40-5 - -
-
-
-
-
昇圧オプション
-
- - - - - - - - - - - - - - - - - -
名称昇圧回路数
--
--
-
-
-
- -
-
- - HQJP-KA40-5 - -
-
-
-
-
- 綿調道区分 -
- -
- 回路 - (二重昇圧回路数 -
- -
- 回路) -
-
+ ))}
@@ -398,17 +117,11 @@ export default function StepUp({}) { {getMessage('modal.circuit.trestle.setting.step.up.allocation.select.monitor')}
- +
- {/*
*/} - {/* */} - {/* */} - {/*
*/} ) } diff --git a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx index 67bb2195..7c01cd6c 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx @@ -5,6 +5,7 @@ export default function PassivityCircuitAllocation() { const moduleData = { header: [ { name: getMessage('modal.panel.batch.statistic.roof.shape'), prop: 'roofShape' }, + { name: getMessage('modal.circuit.trestle.setting.circuit'), prop: 'circuit' }, { name: getMessage('Q.TRON M-G2'), prop: 'moduleName', @@ -17,11 +18,13 @@ export default function PassivityCircuitAllocation() { rows: [ { roofShape: { name: 'M 1' }, + circuit: { name: 'M 1' }, moduleName: { name: '8' }, powerGeneration: { name: '3,400' }, }, { roofShape: { name: 'M 1' }, + circuit: { name: 'M 1' }, moduleName: { name: '8' }, powerGeneration: { name: '3,400' }, }, @@ -29,74 +32,79 @@ export default function PassivityCircuitAllocation() { } return ( <> -
-
-
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity')}
-
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.info')}
-
- - - - {moduleData.header.map((header) => ( - - ))} - - - - {moduleData.rows.map((row, index) => ( - +
+
{getMessage('modal.circuit.trestle.setting.circuit.allocation')}
+
+
+
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity')}
+
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.info')}
+
+
{header.name}
+ + {moduleData.header.map((header) => ( - + ))} - ))} - -
{row[header.prop].name}{header.name}
+ + + {moduleData.rows.map((row, index) => ( + + {moduleData.header.map((header) => ( + + {row[header.prop].name} + + ))} + + ))} + + +
-
-
-
-
-
-
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional')}
-
-
-
- - +
+
+
+
+
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional')}
-
- - -
-
- - +
+
+ + +
+
+ + +
+
+ + +
-
-
-
-
- - {getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num')} - -
- +
+
+
+ + {getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num')} + +
+ +
+
-
-
- - - +
+ + +
diff --git a/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx b/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx index 8e072e18..18eef849 100644 --- a/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx +++ b/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx @@ -108,13 +108,16 @@ export default function FlowDirectionSetting(props) {
{ setType(FLOW_DIRECTION_TYPE.EIGHT_AZIMUTH) setSelectedOrientation(e) setCompasDeg(e.value) }} + showKey={'name'} + targetKey={'value'} + sourceKey={'value'} />
diff --git a/src/components/floor-plan/modal/grid/DotLineGrid.jsx b/src/components/floor-plan/modal/grid/DotLineGrid.jsx index 9e402a71..da41fdcf 100644 --- a/src/components/floor-plan/modal/grid/DotLineGrid.jsx +++ b/src/components/floor-plan/modal/grid/DotLineGrid.jsx @@ -29,9 +29,12 @@ export default function DotLineGrid(props) { const { SelectOptions, currentSetting, setCurrentSetting, dotLineGridSettingState, setSettingModalGridOptions, setDotLineGridSettingState } = useCanvasSetting() + const [copyCurrentSetting, setCopyCurrentSetting] = useState({ ...currentSetting }) + // 데이터를 최초 한 번만 조회 useEffect(() => { console.log('DotLineGrid useEffect 실행') + setSettingsDataSave({ ...settingsData }) // dimension 값에 맞는 옵션을 선택 @@ -57,7 +60,7 @@ export default function DotLineGrid(props) { const handleCheckBoxChange = (e) => { const { value, checked } = e.target - setCurrentSetting((prev) => { + setCopyCurrentSetting((prev) => { return { ...prev, [value]: checked, @@ -66,23 +69,23 @@ export default function DotLineGrid(props) { } const handleSave = async () => { - if (!currentSetting.DOT && !currentSetting.LINE) { + /*if (!currentSetting.DOT && !currentSetting.LINE) { swalFire({ text: '배치할 그리드를 설정해주세요.' }) return - } + }*/ setDotLineGridSettingState((prev) => { return { ...prev, INTERVAL: { - type: currentSetting.INTERVAL.type, - horizontalInterval: currentSetting.INTERVAL.horizontalInterval, - verticalInterval: currentSetting.INTERVAL.verticalInterval, - ratioInterval: currentSetting.INTERVAL.ratioInterval, - dimension: currentSetting.INTERVAL.dimension, + type: copyCurrentSetting.INTERVAL.type, + horizontalInterval: copyCurrentSetting.INTERVAL.horizontalInterval, + verticalInterval: copyCurrentSetting.INTERVAL.verticalInterval, + ratioInterval: copyCurrentSetting.INTERVAL.ratioInterval, + dimension: copyCurrentSetting.INTERVAL.dimension, }, - DOT: currentSetting.DOT, - LINE: currentSetting.LINE, + DOT: copyCurrentSetting.DOT, + LINE: copyCurrentSetting.LINE, } //setDotLineGridSettingState({ ...currentSetting }) }) @@ -90,16 +93,18 @@ export default function DotLineGrid(props) { setSettingsData({ ...settingsData, INTERVAL: { - type: currentSetting.INTERVAL.type, - horizontalInterval: currentSetting.INTERVAL.horizontalInterval, - verticalInterval: currentSetting.INTERVAL.verticalInterval, - ratioInterval: currentSetting.INTERVAL.ratioInterval, - dimension: currentSetting.INTERVAL.dimension, + type: copyCurrentSetting.INTERVAL.type, + horizontalInterval: copyCurrentSetting.INTERVAL.horizontalInterval, + verticalInterval: copyCurrentSetting.INTERVAL.verticalInterval, + ratioInterval: copyCurrentSetting.INTERVAL.ratioInterval, + dimension: copyCurrentSetting.INTERVAL.dimension, }, - DOT: currentSetting.DOT, - LINE: currentSetting.LINE, + DOT: copyCurrentSetting.DOT, + LINE: copyCurrentSetting.LINE, }) + setCurrentSetting({ ...copyCurrentSetting }) + setIsShow(false) closePopup(id, isConfig) } @@ -107,7 +112,7 @@ export default function DotLineGrid(props) { const handleRadioChange = (e) => { const { value, name, checked, selected } = e.target - setCurrentSetting((prev) => { + setCopyCurrentSetting((prev) => { return { ...prev, INTERVAL: { @@ -120,7 +125,7 @@ export default function DotLineGrid(props) { const changeInput = (value, e) => { const { name } = e.target - setCurrentSetting((prev) => { + setCopyCurrentSetting((prev) => { return { ...prev, INTERVAL: { @@ -133,7 +138,8 @@ export default function DotLineGrid(props) { const changeDimension = (result) => { const { value } = result - setCurrentSetting((prev) => { + setSelectOption(result) + setCopyCurrentSetting((prev) => { return { ...prev, INTERVAL: { @@ -146,7 +152,7 @@ export default function DotLineGrid(props) { // 초기화 const reset = () => { - canvas + /*canvas ?.getObjects() .filter((obj) => obj.name === 'lineGrid') .forEach((obj) => canvas?.remove(obj)) @@ -154,9 +160,9 @@ export default function DotLineGrid(props) { ?.getObjects() .filter((obj) => obj.name === 'dotGrid') .forEach((obj) => canvas?.remove(obj)) - +*/ // resetDotLineGridSetting() - setCurrentSetting({ + setCopyCurrentSetting({ INTERVAL: { type: 2, // 1: 가로,세로 간격 수동, 2: 비율 간격 ratioInterval: 910, @@ -188,11 +194,11 @@ export default function DotLineGrid(props) {
- +
- +
@@ -205,8 +211,8 @@ export default function DotLineGrid(props) { id="ra01" value={1} onChange={handleRadioChange} - checked={(currentSetting.DOT || currentSetting.LINE) && currentSetting.INTERVAL.type === 1} - readOnly={!currentSetting.DOT && !currentSetting.LINE} + checked={(copyCurrentSetting.DOT || copyCurrentSetting.LINE) && copyCurrentSetting.INTERVAL.type === 1} + readOnly={!copyCurrentSetting.DOT && !copyCurrentSetting.LINE} />
@@ -217,7 +223,7 @@ export default function DotLineGrid(props) { type="text" className="input-origin" name={`horizontalInterval`} - value={currentSetting.INTERVAL.horizontalInterval} + value={copyCurrentSetting.INTERVAL.horizontalInterval} onChange={(e) => onlyNumberInputChange(e, changeInput)} />
@@ -230,7 +236,7 @@ export default function DotLineGrid(props) { type="text" className="input-origin" name={`verticalInterval`} - value={currentSetting.INTERVAL.verticalInterval} + value={copyCurrentSetting.INTERVAL.verticalInterval} onChange={(e) => onlyNumberInputChange(e, changeInput)} />
@@ -245,8 +251,8 @@ export default function DotLineGrid(props) { id="ra02" value={2} onChange={handleRadioChange} - checked={(currentSetting.DOT || currentSetting.LINE) && currentSetting.INTERVAL.type === 2} - readOnly={!currentSetting.DOT && !currentSetting.LINE} + checked={(copyCurrentSetting.DOT || copyCurrentSetting.LINE) && copyCurrentSetting.INTERVAL.type === 2} + readOnly={!copyCurrentSetting.DOT && !copyCurrentSetting.LINE} />
@@ -257,14 +263,23 @@ export default function DotLineGrid(props) { type="text" className="input-origin" name={`ratioInterval`} - value={currentSetting.INTERVAL.ratioInterval} + value={copyCurrentSetting.INTERVAL.ratioInterval} onChange={(e) => onlyNumberInputChange(e, changeInput)} />
mm
- + {selectOption && ( + + )}
diff --git a/src/components/floor-plan/modal/module/PanelEdit.jsx b/src/components/floor-plan/modal/module/PanelEdit.jsx index 5d38f9a8..a6d1d4f9 100644 --- a/src/components/floor-plan/modal/module/PanelEdit.jsx +++ b/src/components/floor-plan/modal/module/PanelEdit.jsx @@ -11,6 +11,7 @@ import * as turf from '@turf/turf' import { POLYGON_TYPE } from '@/common/common' import { useModal } from '@nextui-org/react' import { useModule } from '@/hooks/module/useModule' +import { useSwal } from '@/hooks/useSwal' export const PANEL_EDIT_TYPE = { MOVE: 'move', @@ -31,6 +32,7 @@ export default function PanelEdit(props) { const [direction, setDirection] = useState('up') const { getMessage } = useMessage() const canvas = useRecoilValue(canvasState) + const { swalFire } = useSwal() const { moduleMove, moduleCopy, moduleMultiMove, moduleMultiCopy, moduleMoveAll, moduleCopyAll } = useModule() useEffect(() => { @@ -42,6 +44,14 @@ export default function PanelEdit(props) { //모듈 이동 적용 const handleApply = () => { + if (length <= 0) { + swalFire({ + title: getMessage('common.message.please.input.over', [1]), + type: 'alert', + icon: 'error', + }) + return + } switch (type) { case PANEL_EDIT_TYPE.MOVE: moduleMove(length, direction) diff --git a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx index d8f7a8ae..91268678 100644 --- a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx +++ b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx @@ -10,6 +10,10 @@ import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementSha import { useCanvasSetting } from '@/hooks/option/useCanvasSetting' import { useCommonCode } from '@/hooks/common/useCommonCode' import { globalLocaleStore } from '@/store/localeAtom' +import { useRoofShapeSetting } from '@/hooks/roofcover/useRoofShapeSetting' +import { currentAngleTypeSelector, pitchTextSelector } from '@/store/canvasAtom' +import { getDegreeByChon } from '@/util/canvas-util' +import { onlyNumberWithDotInputChange } from '@/util/input-utils' export default function RoofAllocationSetting(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) @@ -28,10 +32,13 @@ export default function RoofAllocationSetting(props) { handleChangeRaft, handleChangeLayout, currentRoofList, + handleChangeInput, } = useRoofAllocationSetting(id) + const pitchText = useRecoilValue(pitchTextSelector) const { findCommonCode } = useCommonCode() const [raftCodes, setRaftCodes] = useState([]) const globalLocale = useRecoilValue(globalLocaleStore) + const currentAngleType = useRecoilValue(currentAngleTypeSelector) useEffect(() => { const raftCodeList = findCommonCode('203800') setRaftCodes(raftCodeList.map((raft) => ({ ...raft, name: raft.clCodeNm }))) @@ -104,13 +111,35 @@ export default function RoofAllocationSetting(props) { {index !== 0 && }
+
+
+ {getMessage('slope')} +
+ { + handleChangeInput(e, 'pitch', index) + }} + defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle} + /> +
+ {pitchText} +
+
{(roof.widAuth || roof.lenAuth) && (
{roof.widAuth && (
W
- + handleChangeInput(e, 'width', index)} + readOnly={roof.widAuth === 'R'} + />
)} @@ -118,7 +147,13 @@ export default function RoofAllocationSetting(props) {
L
- + handleChangeInput(e, 'length', index)} + readOnly={roof.lenAuth === 'R'} + />
)} @@ -153,6 +188,7 @@ export default function RoofAllocationSetting(props) { handleChangeInput(e, 'hajebichi', index)} value={parseInt(roof.hajebichi)} readOnly={roof.roofPchAuth === 'R'} /> diff --git a/src/components/floor-plan/modal/roofShape/passivity/Gable.jsx b/src/components/floor-plan/modal/roofShape/passivity/Gable.jsx index e7d9718d..6da1266e 100644 --- a/src/components/floor-plan/modal/roofShape/passivity/Gable.jsx +++ b/src/components/floor-plan/modal/roofShape/passivity/Gable.jsx @@ -1,21 +1,12 @@ import { useMessage } from '@/hooks/useMessage' import { useRecoilValue } from 'recoil' -import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom' +import { currentAngleTypeSelector } from '@/store/canvasAtom' -export default function Gable({ offsetRef, pitchRef, pitchText }) { +export default function Gable({ offsetRef }) { const { getMessage } = useMessage() const currentAngleType = useRecoilValue(currentAngleTypeSelector) return ( <> -
- - {getMessage('slope')} - -
- -
- {pitchText} -
{getMessage('gable.offset')} diff --git a/src/components/floor-plan/modal/roofShape/passivity/Shed.js b/src/components/floor-plan/modal/roofShape/passivity/Shed.jsx similarity index 100% rename from src/components/floor-plan/modal/roofShape/passivity/Shed.js rename to src/components/floor-plan/modal/roofShape/passivity/Shed.jsx diff --git a/src/components/header/Header.jsx b/src/components/header/Header.jsx index 5cdbfff9..263158a4 100644 --- a/src/components/header/Header.jsx +++ b/src/components/header/Header.jsx @@ -69,20 +69,20 @@ export default function Header(props) { setSelectOptions( userSession.storeId === 'T01' ? [ - { id: 0, name: getMessage('site.header.link1') }, - { id: 1, name: 'Q.ORDER', link: `${qOrderUrl}?autoLoginParam1=${encodeURIComponent(res.data)}` }, - { id: 2, name: 'Q.Musubi', link: `${qMusubiUrl}?autoLoginParam1=${encodeURIComponent(res.data)}` }, + { id: 0, name: getMessage('site.header.link1'), target: '_blank' }, + { id: 1, name: 'Q.ORDER', link: `${qOrderUrl}?autoLoginParam1=${encodeURIComponent(res.data)}`, target: '_blank' }, + { id: 2, name: 'Q.Musubi', link: `${qMusubiUrl}?autoLoginParam1=${encodeURIComponent(res.data)}`, target: '_blank' }, { id: 3, name: getMessage('site.header.link2'), link: `https://q-warranty.q-cells.jp/seller_login`, target: '_blank' }, ] : userSession.groupId === '60000' ? [ - { id: 0, name: getMessage('site.header.link1') }, - { id: 1, name: 'Q.ORDER', link: `${qOrderUrl}?autoLoginParam1=${encodeURIComponent(res.data)}` }, + { id: 0, name: getMessage('site.header.link1'), target: '_blank' }, + { id: 1, name: 'Q.ORDER', link: `${qOrderUrl}?autoLoginParam1=${encodeURIComponent(res.data)}`, target: '_blank' }, { id: 2, name: getMessage('site.header.link2'), link: `https://q-warranty.q-cells.jp/seller_login`, target: '_blank' }, ] : [ - { id: 0, name: getMessage('site.header.link1') }, - { id: 1, name: 'Q.Musubi', link: `${qMusubiUrl}?autoLoginParam1=${encodeURIComponent(res.data)}` }, + { id: 0, name: getMessage('site.header.link1'), target: '_blank' }, + { id: 1, name: 'Q.Musubi', link: `${qMusubiUrl}?autoLoginParam1=${encodeURIComponent(res.data)}`, target: '_blank' }, { id: 2, name: getMessage('site.header.link2'), link: `https://q-warranty.q-cells.jp/seller_login`, target: '_blank' }, ], ) diff --git a/src/components/main/ChangePasswordPop.jsx b/src/components/main/ChangePasswordPop.jsx index 4eb7164d..323b332d 100644 --- a/src/components/main/ChangePasswordPop.jsx +++ b/src/components/main/ChangePasswordPop.jsx @@ -1,20 +1,17 @@ -import React, { useState } from 'react' +import React from 'react' import { useMessage } from '@/hooks/useMessage' import { useForm } from 'react-hook-form' import { sessionStore } from '@/store/commonAtom' import { useRecoilValue, useRecoilState } from 'recoil' import { useAxios } from '@/hooks/useAxios' import { globalLocaleStore } from '@/store/localeAtom' -import { useRouter } from 'next/navigation' -import { setSession } from '@/lib/authActions' -import { logout } from '@/lib/authActions' +import { logout, setSession, login } from '@/lib/authActions' export default function ChangePasswordPop(props) { const globalLocaleState = useRecoilValue(globalLocaleStore) const { patch } = useAxios(globalLocaleState) const { getMessage } = useMessage() const [sessionState, setSessionState] = useRecoilState(sessionStore) - const router = useRouter() const formInitValue = { password1: '', password2: '', @@ -56,6 +53,16 @@ export default function ChangePasswordPop(props) { const _password1 = form.watch('password1') const _password2 = form.watch('password2') + //비밀번호 미입력시 + if (_password1.trim() === '') { + alert(getMessage('main.popup.login.validate3')) + return false + } + if (_password2.trim() === '') { + alert(getMessage('main.popup.login.validate3')) + return false + } + if (_password1 !== _password2) { alert(getMessage('main.popup.login.validate1')) return false @@ -77,11 +84,11 @@ export default function ChangePasswordPop(props) { if (res?.result?.code === 200) { if (res?.result?.resultCode === 'S') { alert(getMessage('main.popup.login.success')) - logout() - //로그인 화면으로 이동해서 다시 로그인해야되서 setSessionState필요없음 - // setSessionState({ ...sessionState, pwdInitYn: 'Y' }) - //props.setChagePasswordPopOpen(false) - //router.push('/login') + const result = { ...sessionState, pwdInitYn: 'Y' } + setSession(result) + setSessionState(result) + props.setChagePasswordPopOpen(false) + login() } else { alert(res?.result?.resultMsg) } @@ -110,10 +117,7 @@ export default function ChangePasswordPop(props) {
-
- {getMessage('main.popup.login.newPassword1')} - * -
+
{getMessage('main.popup.login.newPassword1')}
{getMessage('main.popup.login.placeholder')}
@@ -133,10 +137,7 @@ export default function ChangePasswordPop(props) {
-
- {getMessage('main.popup.login.newPassword2')} - * -
+
{getMessage('main.popup.login.newPassword2')}
{getMessage('main.popup.login.placeholder')}
@@ -169,7 +170,6 @@ export default function ChangePasswordPop(props) { className="btn-origin grey" onClick={() => { logout() - // router.push('/login') }} > {getMessage('main.popup.login.btn2')} diff --git a/src/components/main/MainContents.jsx b/src/components/main/MainContents.jsx index 72034a8a..766d7efc 100644 --- a/src/components/main/MainContents.jsx +++ b/src/components/main/MainContents.jsx @@ -15,6 +15,8 @@ import { useMainContentsController } from '@/hooks/main/useMainContentsControlle import { QcastContext } from '@/app/QcastProvider' import { useSwal } from '@/hooks/useSwal' +import BoardDetailModal from '../community/modal/BoardDetailModal' + export default function MainContents() { const { swalFire } = useSwal() @@ -87,6 +89,10 @@ export default function MainContents() { } } + // FAQ 팝업 관련 + const [open, setOpen] = useState(false) + const [modalNoticeNo, setModalNoticeNo] = useState('') + return (
@@ -143,6 +149,8 @@ export default function MainContents() { )}
+ + {open && }
{recentFaqList.length > 0 ? ( @@ -151,8 +159,17 @@ export default function MainContents() { return (
  • -
    FAQ {row.totCnt - row.rowNumber}
    -
    {row.title}
    +
    FAQ {row.totCnt - row.rowNumber + 1}
    +
    { + setOpen(true) + setModalNoticeNo(row.noticeNo) + }} + > + {row.title} +
    {dayjs(row.regDt).format('YYYY.MM.DD')}
  • diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index 88f822fa..005408c4 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -207,6 +207,7 @@ export default function Stuff() { schReceiveUser: stuffSearchParams?.schReceiveUser, schDispCompanyName: stuffSearchParams?.schDispCompanyName, schDateType: stuffSearchParams.schDateType, + schTempFlg: stuffSearchParams.schTempFlg, //임시저장 물건 schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), schToDt: dayjs(new Date()).format('YYYY-MM-DD'), startRow: (stuffSearch.pageNo - 1) * stuffSearchParams.pageSize + 1, @@ -217,6 +218,7 @@ export default function Stuff() { pageNo: stuffSearchParams?.pageNo ? stuffSearchParams.pageNo : 1, pageSize: stuffSearchParams?.pageSize ? stuffSearchParams.pageSize : 100, } + async function fetchData() { const apiUrl = `/api/object/list?${queryStringFormatter(params)}` await get({ @@ -249,6 +251,7 @@ export default function Stuff() { schReceiveUser: '', schDispCompanyName: '', schDateType: 'U', + schTempFlg: '', schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), schToDt: dayjs(new Date()).format('YYYY-MM-DD'), startRow: (pageNo - 1) * pageSize + 1, @@ -322,6 +325,7 @@ export default function Stuff() { schReceiveUser: '', schDispCompanyName: '', schDateType: 'U', + schTempFlg: '', schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), schToDt: dayjs(new Date()).format('YYYY-MM-DD'), startRow: 1, diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index 77bbafcc..767c9581 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -269,8 +269,8 @@ export default function StuffDetail() { } } if (managementState?.createUser === 'T01' && session?.userId !== 'T01') { - //createUser가 T01인데 로그인사용자가 T01이 아니면 버튼숨기기 - buttonStyle = { display: 'none' } + //createUser가 T01인데 로그인사용자가 T01이 아니면 버튼숨기기 적용할지 미정!!!!!!!! + //buttonStyle = { display: 'none' } } return ( <> @@ -282,7 +282,8 @@ export default function StuffDetail() { onClick={() => { //mid:5(견적서), /pid:플랜번호 setFloorPlanObjectNo({ floorPlanObjectNo: params.data.objectNo }) - router.push(`/floor-plan/estimate/5/${params.data.planNo}`) + // router.push(`/floor-plan/estimate/5/${params.data.planNo}`) + router.push(`/floor-plan/estimate/5?pid=${params.data.planNo}&objectNo=${params.data.objectNo}`) }} > @@ -330,7 +331,7 @@ export default function StuffDetail() { //createUser가 T01인데 로그인사용자가 T01이 아니면 버튼숨기기 setShowButton('none') } - + // console.log('상세::', res.data) if (isObjectNotEmpty(res.data)) { let surfaceTypeValue if (res.data.surfaceType === 'Ⅲ・Ⅳ') { @@ -430,7 +431,6 @@ export default function StuffDetail() { setOtherSaleStoreList(otherList) } else { - //10X22, 201X112,202X217 firstList = res.filter((row) => row.firstAgentYn === 'Y') setSaleStoreList(firstList) setFavoriteStoreList(firstList) @@ -441,6 +441,7 @@ export default function StuffDetail() { form.setValue('saleStoreLevel', firstList[0].saleStoreLevel) otherList = res.filter((row) => row.firstAgentYn === 'N') + setOtherSaleStoreList(otherList) //2차 판매점명/ID는 본인을 셀렉트 setOtherSelOptions(session?.storeId) @@ -480,8 +481,6 @@ export default function StuffDetail() { } }) - //1차점 : X167 T01 - //2차점 : 10X22, 201X112 let url let firstList let otherList @@ -561,6 +560,11 @@ export default function StuffDetail() { setSelOptions(managementState.saleStoreId) form.setValue('saleStoreId', managementState.saleStoreId) form.setValue('saleStoreLevel', managementState.saleStoreLevel) + //#435 + setOtherSelOptions('') + form.setValue('otherSaleStoreId', '') + form.setValue('otherSaleStoreLevel', '') + form.setValue('otherSaleStoreName', '') } else { setOtherSelOptions(managementState.saleStoreId) form.setValue('otherSaleStoreId', managementState.saleStoreId) @@ -921,10 +925,13 @@ export default function StuffDetail() { const setPlanReqInfo = (info) => { // console.log('session 정보:::::::', session) // console.log('설계의뢰에서 넘어온 정보:::::::', info) + form.setValue('planReqNo', info.planReqNo) + form.setValue('objectStatusId', info.building) setSelectObjectStatusId(info.building) - form.setValue('objectName', info.planReqName) + + form.setValue('objectName', info.title) form.setValue('zipNo', info.zipNo) form.setValue('address', info.address2) @@ -1258,57 +1265,59 @@ export default function StuffDetail() { return alert(getMessage('stuff.detail.save.valierror2')) } - let detail_sort = Object.keys(managementState) - .sort() - .reduce((obj, key) => ((obj[key] = managementState[key]), obj), {}) - let params_sort = Object.keys(params) - .sort() - .reduce((obj, key) => ((obj[key] = params[key]), obj), {}) + if (managementState) { + let detail_sort = Object.keys(managementState) + .sort() + .reduce((obj, key) => ((obj[key] = managementState[key]), obj), {}) + let params_sort = Object.keys(params) + .sort() + .reduce((obj, key) => ((obj[key] = params[key]), obj), {}) - delete detail_sort.areaName - delete detail_sort.contentsPath - delete detail_sort.createDatetime - delete detail_sort.createUserName - delete detail_sort.dispCompanyName - delete detail_sort.firstAgentId - delete detail_sort.lastEditDatetime - delete detail_sort.lastEditUserName - delete detail_sort.planList - delete detail_sort.planNo - delete detail_sort.planTotCnt - delete detail_sort.receiveCompanyName - delete detail_sort.saleStoreName - delete detail_sort.rowNumber - delete detail_sort.prefName - delete detail_sort.sameObjectInfo - delete detail_sort.specificationConfirmDate - delete detail_sort.totCnt - delete detail_sort.workNo - delete detail_sort.workName + delete detail_sort.areaName + delete detail_sort.contentsPath + delete detail_sort.createDatetime + delete detail_sort.createUserName + delete detail_sort.dispCompanyName + delete detail_sort.firstAgentId + delete detail_sort.lastEditDatetime + delete detail_sort.lastEditUserName + delete detail_sort.planList + delete detail_sort.planNo + delete detail_sort.planTotCnt + delete detail_sort.receiveCompanyName + delete detail_sort.saleStoreName + delete detail_sort.rowNumber + delete detail_sort.prefName + delete detail_sort.sameObjectInfo + delete detail_sort.specificationConfirmDate + delete detail_sort.totCnt + delete detail_sort.workNo + delete detail_sort.workName - delete params_sort.areaName - delete params_sort.contentsPath - delete params_sort.createDatetime - delete params_sort.createUserName - delete params_sort.dispCompanyName - delete params_sort.firstAgentId - delete params_sort.lastEditDatetime - delete params_sort.lastEditUserName - delete params_sort.planList - delete params_sort.planNo - delete params_sort.planTotCnt - delete params_sort.receiveCompanyName - delete params_sort.saleStoreName - delete params_sort.rowNumber - delete params_sort.prefName - delete params_sort.sameObjectInfo - delete params_sort.specificationConfirmDate - delete params_sort.totCnt - delete params_sort.workNo - delete params_sort.workName + delete params_sort.areaName + delete params_sort.contentsPath + delete params_sort.createDatetime + delete params_sort.createUserName + delete params_sort.dispCompanyName + delete params_sort.firstAgentId + delete params_sort.lastEditDatetime + delete params_sort.lastEditUserName + delete params_sort.planList + delete params_sort.planNo + delete params_sort.planTotCnt + delete params_sort.receiveCompanyName + delete params_sort.saleStoreName + delete params_sort.rowNumber + delete params_sort.prefName + delete params_sort.sameObjectInfo + delete params_sort.specificationConfirmDate + delete params_sort.totCnt + delete params_sort.workNo + delete params_sort.workName - if (Object.entries(detail_sort).toString() === Object.entries(params_sort).toString()) { - return alert(getMessage('stuff.detail.noChgData')) + if (Object.entries(detail_sort).toString() === Object.entries(params_sort).toString()) { + return alert(getMessage('stuff.detail.noChgData')) + } } if (params?.receiveUser !== '') { @@ -1316,6 +1325,12 @@ export default function StuffDetail() { return alert(getMessage('stuff.detail.tempSave.message2')) } } + //로그인이 2차점인데 otherSaleStoreId가 없으면 알럿 + if (session.storeLvl !== '1') { + if (params.saleStoreLevel === '1') { + return alert(getMessage('stuff.detail.tempSave.message4')) + } + } if (editMode === 'NEW') { await promisePost({ url: apiUrl, data: params }) @@ -1480,7 +1495,7 @@ export default function StuffDetail() { if (params?.data?.planNo && params?.data?.objectNo) { let objectNo = params?.data?.objectNo let planNo = params?.data?.planNo - router.push(`/floor-plan?pid=${planNo}&objectNo=${objectNo}`) + router.push(`/floor-plan/estimate/5?pid=${planNo}&objectNo=${objectNo}`) } } } @@ -1724,7 +1739,10 @@ export default function StuffDetail() {
    -
    {getMessage('stuff.detail.otherSaleStoreId')}
    +
    + {getMessage('stuff.detail.otherSaleStoreId')} + {session.storeLvl !== '1' && *} +
    {getMessage('stuff.detail.tooltip.saleStoreId')}
    @@ -1745,7 +1763,16 @@ export default function StuffDetail() { onChange={onSelectionChange2} getOptionLabel={(x) => x.saleStoreName} getOptionValue={(x) => x.saleStoreId} - isDisabled={otherSaleStoreList != null && otherSaleStoreList.length > 0 ? false : true} + isDisabled={ + session?.storeLvl === '1' + ? otherSaleStoreList.length > 0 + ? false + : true + : otherSaleStoreList.length === 1 + ? true + : false + } + // isDisabled={otherSaleStoreList != null && otherSaleStoreList.length === 1 ? true : false} isClearable={true} value={otherSaleStoreList.filter(function (option) { return option.saleStoreId === otherSelOptions @@ -2295,14 +2322,16 @@ export default function StuffDetail() { onChange={onSelectionChange2} getOptionLabel={(x) => x.saleStoreName} getOptionValue={(x) => x.saleStoreId} - isDisabled={ - managementState?.tempFlg === '0' - ? true - : session?.storeLvl === '1' && form.watch('saleStoreId') != '' - ? false - : true - } - isClearable={managementState?.tempFlg === '0' ? false : session?.storeLvl === '1' ? true : false} + // isDisabled={ + // managementState?.tempFlg === '0' + // ? true + // : session?.storeLvl === '1' && form.watch('saleStoreId') != '' + // ? false + // : false + // } + isDisabled={managementState?.tempFlg === '0' ? true : false} + isClearable={managementState?.tempFlg === '0' ? false : true} + // isClearable={managementState?.tempFlg === '0' ? false : session?.storeLvl === '1' ? true : true} value={otherSaleStoreList.filter(function (option) { return option.saleStoreId === otherSelOptions })} diff --git a/src/components/management/StuffPlanQGrid.jsx b/src/components/management/StuffPlanQGrid.jsx index 72c74eb5..90bcda91 100644 --- a/src/components/management/StuffPlanQGrid.jsx +++ b/src/components/management/StuffPlanQGrid.jsx @@ -40,7 +40,6 @@ export default function StuffPlanQGrid(props) { rowData={rowData} columnDefs={colDefs} defaultColDef={defaultColDef} - rowSelection={'singleRow'} pagination={isPageable} domLayout="autoHeight" suppressCellFocus={true} diff --git a/src/components/management/StuffQGrid.jsx b/src/components/management/StuffQGrid.jsx index 32c686fb..6de31379 100644 --- a/src/components/management/StuffQGrid.jsx +++ b/src/components/management/StuffQGrid.jsx @@ -92,10 +92,6 @@ export default function StuffQGrid(props) { rowData={rowData} columnDefs={colDefs} defaultColDef={defaultColDef} - isRowSelectable={isRowSelectable} - rowSelection={'multiple'} - suppressRowClickSelection={true} - // onSelectionChanged={onSelectionChanged} onCellDoubleClicked={onCellDoubleClicked} pagination={isPageable} overlayNoRowsTemplate={`${getMessage('stuff.grid.noData')}`} diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx index 09fecdb5..96cd314a 100644 --- a/src/components/management/StuffSearchCondition.jsx +++ b/src/components/management/StuffSearchCondition.jsx @@ -60,6 +60,9 @@ export default function StuffSearchCondition() { const [schSelSaleStoreId, setSchSelSaleStoreId] = useState('') //판매대리점 선택 const [receiveUser, setReceiveUser] = useState('') //담당자 const [dateType, setDateType] = useState('U') //갱신일(U)/등록일(R) + const [tempFlg, setTempFlg] = useState('') //임시저장여부 + //내물건보기 체크박스 + const [myDataCheck, setMyDataCheck] = useState(false) const [schSelSaleStoreList, setSchSelSaleStoreList] = useState([]) //판매대리점 자동완성 SELECT 전체 const [favoriteStoreList, setFavoriteStoreList] = useState([]) //즐겨찾기한 판매점목록 @@ -95,6 +98,8 @@ export default function StuffSearchCondition() { schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : '', schReceiveUser: receiveUser ? receiveUser.trim() : '', schDateType: dateType, + schTempFlg: tempFlg, //임시저장물건 + schMyDataCheck: myDataCheck, schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '', schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '', code: 'E', @@ -105,25 +110,51 @@ export default function StuffSearchCondition() { pageSize: stuffSearch?.pageSize, }) } else { - setStuffSearch({ - schObjectNo: objectNo ? objectNo.trim() : stuffSearch.schObjectNo.trim(), - schSaleStoreName: saleStoreName ? saleStoreName.trim() : '', - schAddress: address ? address.trim() : '', - schObjectName: objectName ? objectName.trim() : '', - schDispCompanyName: dispCompanyName ? dispCompanyName.trim() : '', - schSelSaleStoreId: stuffSearch?.schSelSaleStoreId ? stuffSearch.schSelSaleStoreId : '', - schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : '', - schReceiveUser: receiveUser ? receiveUser.trim() : '', - schDateType: dateType, - schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '', - schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '', - code: 'E', - startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1, - endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100, - schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'U', - pageNo: stuffSearch?.pageNo, - pageSize: stuffSearch?.pageSize, - }) + if (session.storeId !== 'T01') { + setStuffSearch({ + schObjectNo: objectNo ? objectNo.trim() : stuffSearch.schObjectNo.trim(), + schSaleStoreName: saleStoreName ? saleStoreName.trim() : '', + schAddress: address ? address.trim() : '', + schObjectName: objectName ? objectName.trim() : '', + schDispCompanyName: dispCompanyName ? dispCompanyName.trim() : '', + schSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? '' : stuffSearch.schSelSaleStoreId, + schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : '', + schReceiveUser: receiveUser ? receiveUser.trim() : '', + schDateType: dateType, + schTempFlg: tempFlg, //임시저장물건 + schMyDataCheck: myDataCheck, + schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '', + schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '', + code: 'E', + startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1, + endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100, + schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'U', + pageNo: stuffSearch?.pageNo, + pageSize: stuffSearch?.pageSize, + }) + } else { + setStuffSearch({ + schObjectNo: objectNo ? objectNo.trim() : stuffSearch.schObjectNo.trim(), + schSaleStoreName: saleStoreName ? saleStoreName.trim() : '', + schAddress: address ? address.trim() : '', + schObjectName: objectName ? objectName.trim() : '', + schDispCompanyName: dispCompanyName ? dispCompanyName.trim() : '', + schSelSaleStoreId: stuffSearch?.schSelSaleStoreId ? stuffSearch.schSelSaleStoreId : '', + schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : '', + schReceiveUser: receiveUser ? receiveUser.trim() : '', + schDateType: dateType, + schTempFlg: tempFlg, //임시저장물건 + schMyDataCheck: myDataCheck, + schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '', + schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '', + code: 'E', + startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1, + endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100, + schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'U', + pageNo: stuffSearch?.pageNo, + pageSize: stuffSearch?.pageSize, + }) + } } } else if (stuffSearch.code === 'FINISH') { setStuffSearch({ @@ -136,6 +167,8 @@ export default function StuffSearchCondition() { schOtherSelSaleStoreId: otherSaleStoreId, schReceiveUser: receiveUser.trim(), schDateType: dateType, + schTempFlg: tempFlg, //임시저장물건 + schMyDataCheck: myDataCheck, schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '', schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '', code: 'E', @@ -151,10 +184,12 @@ export default function StuffSearchCondition() { schAddress: stuffSearch?.schAddress ? stuffSearch.schAddress.trim() : address.trim(), schObjectName: stuffSearch?.schObjectName ? stuffSearch.schObjectName.trim() : objectName.trim(), schDispCompanyName: stuffSearch?.schDispCompanyName ? stuffSearch.schDispCompanyName.trim() : dispCompanyName.trim(), - schSelSaleStoreId: otherSaleStoreId ? schSelSaleStoreId : '', - schOtherSelSaleStoreId: otherSaleStoreId, + schSelSaleStoreId: myDataCheck ? schSelSaleStoreId : otherSaleStoreId ? schSelSaleStoreId : '', + schOtherSelSaleStoreId: myDataCheck ? '' : otherSaleStoreId, schReceiveUser: stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser.trim() : receiveUser.trim(), schDateType: dateType, + schTempFlg: tempFlg, //임시저장물건 + schMyDataCheck: myDataCheck, schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '', schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '', code: 'E', @@ -176,6 +211,8 @@ export default function StuffSearchCondition() { schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : '', schReceiveUser: receiveUser ? receiveUser.trim() : '', schDateType: dateType, + schTempFlg: tempFlg, //임시저장물건 + schMyDataCheck: myDataCheck, schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '', schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '', code: 'E', @@ -196,6 +233,8 @@ export default function StuffSearchCondition() { schOtherSelSaleStoreId: otherSaleStoreId, schReceiveUser: stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser.trim() : receiveUser.trim(), schDateType: dateType, + schTempFlg: tempFlg, //임시저장물건 + schMyDataCheck: myDataCheck, schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '', schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '', code: 'E', @@ -217,6 +256,8 @@ export default function StuffSearchCondition() { schOtherSelSaleStoreId: otherSaleStoreId, schReceiveUser: stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser.trim() : receiveUser.trim(), schDateType: dateType, + schTempFlg: tempFlg, //임시저장물건 + schMyDataCheck: myDataCheck, schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '', schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '', code: 'E', @@ -238,6 +279,8 @@ export default function StuffSearchCondition() { schOtherSelSaleStoreId: otherSaleStoreId, schReceiveUser: receiveUser.trim(), schDateType: dateType, + schTempFlg: tempFlg, //임시저장물건 + schMyDataCheck: stuffSearch.schMyDataCheck, schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '', schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '', code: 'E', @@ -261,6 +304,8 @@ export default function StuffSearchCondition() { dispCompanyNameRef.current.value = '' receiveUserRef.current.value = '' stuffSearch.schDateType = 'U' + stuffSearch.schTempFlg = '' + stuffSearch.schMyDataCheck = false setObjectNo('') setAddress('') setobjectName('') @@ -268,6 +313,8 @@ export default function StuffSearchCondition() { setReceiveUser('') setDispCompanyName('') setDateType('U') + setTempFlg('') + setMyDataCheck(false) setStartDate(dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD')) setEndDate(dayjs(new Date()).format('YYYY-MM-DD')) if (session?.storeId === 'T01') { @@ -285,6 +332,8 @@ export default function StuffSearchCondition() { schSelSaleStoreId: '', schOtherSelSaleStoreId: '', schDateType: 'U', + schTempFlg: '', + schMyDataCheck: false, startRow: 1, endRow: 100, schSortType: 'U', @@ -292,36 +341,76 @@ export default function StuffSearchCondition() { pageSize: 100, }) } else { - if (otherSaleStoreList.length > 1) { - handleClear2() - setOtherSaleStoreId('') - stuffSearch.schObjectNo = '' - stuffSearch.schAddress = '' - stuffSearch.schObjectName = '' - stuffSearch.schSaleStoreName = '' - stuffSearch.schReceiveUser = '' - stuffSearch.schDispCompanyName = '' - stuffSearch.schDateType = 'U' + if (session?.storeLvl === '2') { + if (otherSaleStoreList.length > 1) { + // handleClear2() + setOtherSaleStoreId(session.storeId) + stuffSearch.schOtherSelSaleStoreId = session.storeId + stuffSearch.schObjectNo = '' + stuffSearch.schAddress = '' + stuffSearch.schObjectName = '' + stuffSearch.schSaleStoreName = '' + stuffSearch.schReceiveUser = '' + stuffSearch.schDispCompanyName = '' + stuffSearch.schDateType = 'U' + stuffSearch.schTempFlg = '' + stuffSearch.schMyDataCheck = false - stuffSearch.startRow = 1 - stuffSearch.endRow = 100 - stuffSearch.schSortType = 'U' - stuffSearch.pageNo = 1 - stuffSearch.pageSize = 100 - } else { - stuffSearch.schObjectNo = '' - stuffSearch.schAddress = '' - stuffSearch.schObjectName = '' - stuffSearch.schSaleStoreName = '' - stuffSearch.schReceiveUser = '' - stuffSearch.schDispCompanyName = '' - stuffSearch.schDateType = 'U' - - stuffSearch.startRow = 1 - stuffSearch.endRow = 100 - stuffSearch.schSortType = 'U' - stuffSearch.pageNo = 1 - stuffSearch.pageSize = 100 + stuffSearch.startRow = 1 + stuffSearch.endRow = 100 + stuffSearch.schSortType = 'U' + stuffSearch.pageNo = 1 + stuffSearch.pageSize = 100 + } else { + stuffSearch.schObjectNo = '' + stuffSearch.schAddress = '' + stuffSearch.schObjectName = '' + stuffSearch.schSaleStoreName = '' + stuffSearch.schReceiveUser = '' + stuffSearch.schDispCompanyName = '' + stuffSearch.schDateType = 'U' + stuffSearch.schTempFlg = '' + stuffSearch.schMyDataCheck = false + stuffSearch.startRow = 1 + stuffSearch.endRow = 100 + stuffSearch.schSortType = 'U' + stuffSearch.pageNo = 1 + stuffSearch.pageSize = 100 + } + } else if (session?.storeLvl === '1') { + if (otherSaleStoreList.length > 0) { + handleClear2() + setOtherSaleStoreId('') + stuffSearch.schObjectNo = '' + stuffSearch.schAddress = '' + stuffSearch.schObjectName = '' + stuffSearch.schSaleStoreName = '' + stuffSearch.schReceiveUser = '' + stuffSearch.schDispCompanyName = '' + stuffSearch.schDateType = 'U' + stuffSearch.schTempFlg = '' + stuffSearch.schMyDataCheck = false + stuffSearch.startRow = 1 + stuffSearch.endRow = 100 + stuffSearch.schSortType = 'U' + stuffSearch.pageNo = 1 + stuffSearch.pageSize = 100 + } else { + stuffSearch.schObjectNo = '' + stuffSearch.schAddress = '' + stuffSearch.schObjectName = '' + stuffSearch.schSaleStoreName = '' + stuffSearch.schReceiveUser = '' + stuffSearch.schDispCompanyName = '' + stuffSearch.schDateType = 'U' + stuffSearch.schTempFlg = '' + stuffSearch.schMyDataCheck = false + stuffSearch.startRow = 1 + stuffSearch.endRow = 100 + stuffSearch.schSortType = 'U' + stuffSearch.pageNo = 1 + stuffSearch.pageSize = 100 + } } } } @@ -393,13 +482,10 @@ export default function StuffSearchCondition() { setSchSelSaleStoreId(allList[0].saleStoreId) setOtherSaleStoreList(otherList) - if (stuffSearch.schOtherSelSaleStoreId != '') { setOtherSaleStoreId(stuffSearch.schOtherSelSaleStoreId) } } else { - //10X22, 201X112 그냥2차점 - //2차점인데 34들고있는애 202X217 setSchSelSaleStoreList(res) setFavoriteStoreList(res) setShowSaleStoreList(res) @@ -408,13 +494,31 @@ export default function StuffSearchCondition() { setOtherSaleStoreList(otherList) //선택한 2차점 세션으로 자동셋팅 - setOtherSaleStoreId(session?.storeId) - setStuffSearch({ - ...stuffSearch, - code: 'S', - schSelSaleStoreId: res[0].saleStoreId, - schOtherSelSaleStoreId: otherList[0].saleStoreId, - }) + if (otherList.length === 1) { + setOtherSaleStoreId(session?.storeId) + setStuffSearch({ + ...stuffSearch, + code: 'S', + schSelSaleStoreId: res[0].saleStoreId, + schOtherSelSaleStoreId: otherList[0].saleStoreId, + }) + } else { + if (stuffSearch.code === 'S') { + setOtherSaleStoreId(session?.storeId) + setStuffSearch({ + ...stuffSearch, + code: 'S', + schSelSaleStoreId: res[0].saleStoreId, + schOtherSelSaleStoreId: otherList[0].saleStoreId, + }) + } else { + setOtherSaleStoreId(stuffSearch?.schOtherSelSaleStoreId) + setStuffSearch({ + ...stuffSearch, + code: 'S', + }) + } + } } } } @@ -437,9 +541,11 @@ export default function StuffSearchCondition() { //자동완성 인풋 const onInputChange = (key) => { + //내 물건보기 체크 풀어주기 + setMyDataCheck(false) + if (key !== '') { setShowSaleStoreList(schSelSaleStoreList) - // setOtherSaleStoreList([]) } else { setShowSaleStoreList(favoriteStoreList) } @@ -447,6 +553,10 @@ export default function StuffSearchCondition() { //판매대리점 자동완성 변경 const onSelectionChange = (key) => { + //내 물건보기 체크 풀어주기 + setMyDataCheck(false) + stuffSearch.schMyDataCheck = false + if (isObjectNotEmpty(key)) { setOtherSaleStoreId('') setSchSelSaleStoreId(key.saleStoreId) @@ -491,12 +601,19 @@ export default function StuffSearchCondition() { //2차점 자동완성 변경 const onSelectionChange2 = (key) => { + //내 물건보기 체크 풀어주기 + setMyDataCheck(false) + stuffSearch.schMyDataCheck = false if (isObjectNotEmpty(key)) { setOtherSaleStoreId(key.saleStoreId) stuffSearch.schOtherSelSaleStoreId = key.saleStoreId //2차점 골랐을때 1차점 값 - stuffSearch.schSelSaleStoreId = schSelSaleStoreId + if (session.storeId === 'T01') { + stuffSearch.schSelSaleStoreId = schSelSaleStoreId + } else { + stuffSearch.schSelSaleStoreId = '' + } } else { //X누르면 검색조건에 1차점으로 셋팅 @@ -542,6 +659,8 @@ export default function StuffSearchCondition() { stuffSearch.schReceiveUser = '' stuffSearch.schDispCompanyName = '' stuffSearch.schDateType = 'U' + stuffSearch.schTempFlg = '' + stuffSearch.schMyDataCheck = false stuffSearch.schFromDt = dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD') stuffSearch.schToDt = dayjs(new Date()).format('YYYY-MM-DD') stuffSearch.startRow = 1 @@ -574,6 +693,8 @@ export default function StuffSearchCondition() { stuffSearch.schReceiveUser = '' stuffSearch.schDispCompanyName = '' stuffSearch.schDateType = 'U' + stuffSearch.schTempFlg = '' + stuffSearch.schMyDataCheck = false stuffSearch.schFromDt = dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD') stuffSearch.schToDt = dayjs(new Date()).format('YYYY-MM-DD') stuffSearch.startRow = 1 @@ -596,6 +717,27 @@ export default function StuffSearchCondition() { setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName) setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser) setDateType(stuffSearch.schDateType ? stuffSearch.schDateType : dateType) + setTempFlg(stuffSearch.schTempFlg ? stuffSearch.schTempFlg : tempFlg) + setMyDataCheck(stuffSearch.schMyDataCheck) + if (session.storeLvl !== '1') { + stuffSearch.schSelSaleStoreId = '' + } + } + + if (stuffSearch.schDateType === 'R') { + setDateType('R') + } + + if (stuffSearch.schTempFlg === '0') { + setTempFlg('0') + } else if (stuffSearch.schTempFlg === '1') { + setTempFlg('1') + } + + if (stuffSearch.schMyDataCheck) { + setMyDataCheck(true) + } else { + setMyDataCheck(false) } }, [stuffSearch]) @@ -615,6 +757,51 @@ export default function StuffSearchCondition() { } } + // 내 물건 보기 + const checkMyData = (e) => { + if (session?.storeId === 'T01') { + if (e.target.checked) { + stuffSearch.schMyDataCheck = e.target.value + setMyDataCheck(true) + setOtherSaleStoreId('') //2차점 비우기 + setSchSelSaleStoreId('T01') + stuffSearch.schSelSaleStoreId = 'T01' + stuffSearch.schOtherSelSaleStoreId = '' + } else { + stuffSearch.schMyDataCheck = e.target.value + setMyDataCheck(false) + } + } else if (session?.storeLvl === '1') { + if (e.target.checked) { + stuffSearch.schMyDataCheck = e.target.value + setMyDataCheck(true) + //schOtherSelSaleStoreId 초기화 + //schSelSaleStoreId에 saleStoreId담아서보내기 + setOtherSaleStoreId('') //2차점 비우기 + setSchSelSaleStoreId(schSelSaleStoreId) + stuffSearch.schSelSaleStoreId = schSelSaleStoreId + stuffSearch.schOtherSelSaleStoreId = '' + } else { + setMyDataCheck(false) + } + } else { + //2차점인제 3,4가 없으면 상관없음 + //3,4등등이 있는경우 처리필요 + if (e.target.checked) { + stuffSearch.schMyDataCheck = e.target.value + setMyDataCheck(true) + + if (otherSaleStoreList.length > 1) { + stuffSearch.schSelSaleStoreId = otherSaleStoreId + stuffSearch.schOtherSelSaleStoreId = '' + } + } else { + setMyDataCheck(false) + stuffSearch.schMyDataCheck = e.target.value + } + } + } + return ( <> {/* 퍼블적용시작 */} @@ -647,8 +834,6 @@ export default function StuffSearchCondition() { - - @@ -684,22 +869,7 @@ export default function StuffSearchCondition() { />
    - {getMessage('stuff.search.schAddress')} - -
    - { - stuffSearch.schAddress = addressRef.current.value - setAddress(addressRef.current.value) - }} - onKeyUp={handleByOnKeyUp} - /> -
    - + {getMessage('stuff.search.schDispCompanyName')}
    @@ -750,8 +920,119 @@ export default function StuffSearchCondition() { />
    - {getMessage('stuff.search.schSelSaleStoreId')} + {getMessage('stuff.search.schAddress')} + +
    + { + stuffSearch.schAddress = addressRef.current.value + setAddress(addressRef.current.value) + }} + onKeyUp={handleByOnKeyUp} + /> +
    + + + + {getMessage('stuff.search.period')} +
    +
    +
    + { + setDateType(e.target.value) + stuffSearch.schDateType = e.target.value + }} + /> + +
    +
    + { + setDateType(e.target.value) + stuffSearch.schDateType = e.target.value + }} + /> + +
    +
    +
    +
    + +
    + ~ +
    + +
    +
    +
    + + {getMessage('stuff.search.schTempFlgT')} + +
    +
    + { + setTempFlg(e.target.value) + stuffSearch.schTempFlg = e.target.value + }} + /> + +
    +
    + { + setTempFlg(e.target.value) + stuffSearch.schTempFlg = e.target.value + }} + /> + +
    +
    + { + setTempFlg(e.target.value) + stuffSearch.schTempFlg = e.target.value + }} + /> + +
    +
    + + + + {getMessage('stuff.search.schSelSaleStoreId')} +
    {session?.storeId === 'T01' && ( @@ -853,7 +1134,7 @@ export default function StuffSearchCondition() { /> )}
    -
    +
    { - setDateType(e.target.value) - stuffSearch.schDateType = e.target.value - }} - /> - -
    -
    - { - setDateType(e.target.value) - stuffSearch.schDateType = e.target.value - }} - /> - -
    -
    -
    -
    - -
    - ~ -
    - -
    +
    + { + checkMyData(e) + stuffSearch.schMyDataCheck = e.target.checked + }} + /> +
    diff --git a/src/components/management/StuffSubHeader.jsx b/src/components/management/StuffSubHeader.jsx index c92b4616..6f186bf7 100644 --- a/src/components/management/StuffSubHeader.jsx +++ b/src/components/management/StuffSubHeader.jsx @@ -37,7 +37,8 @@ export default function StuffSubHeader({ type }) { if (isObjectNotEmpty(managementState)) { if (managementState.createUser === 'T01') { if (session.userId !== 'T01') { - setButtonStyle('none') + //도면 작성은 이동 할 수 있도록 변경 #457 + // setButtonStyle('none') } } } diff --git a/src/components/management/popup/FindAddressPop.jsx b/src/components/management/popup/FindAddressPop.jsx index 0c480a52..960fd2e3 100644 --- a/src/components/management/popup/FindAddressPop.jsx +++ b/src/components/management/popup/FindAddressPop.jsx @@ -150,12 +150,12 @@ export default function FindAddressPop(props) {
    - - +
    diff --git a/src/components/management/popup/FindAddressPopQGrid.jsx b/src/components/management/popup/FindAddressPopQGrid.jsx index ba703625..6447dd48 100644 --- a/src/components/management/popup/FindAddressPopQGrid.jsx +++ b/src/components/management/popup/FindAddressPopQGrid.jsx @@ -56,7 +56,6 @@ export default function FindAddressPopGrid(props) { rowData={rowData} columnDefs={colDefs} defaultColDef={defaultColDef} - rowSelection={'singleRow'} pagination={isPageable} onSelectionChanged={onSelectionChanged} overlayNoRowsTemplate={`${getMessage('stuff.grid.noData')}`} diff --git a/src/components/management/popup/PlanRequestPop.jsx b/src/components/management/popup/PlanRequestPop.jsx index aa415edd..2dafe914 100644 --- a/src/components/management/popup/PlanRequestPop.jsx +++ b/src/components/management/popup/PlanRequestPop.jsx @@ -19,7 +19,7 @@ export default function PlanRequestPop(props) { //공통코드 const { commonCode, findCommonCode } = useCommonCode() - const [planStatCdList, setPlanStatCdList] = useState([]) + // const [planStatCdList, setPlanStatCdList] = useState([]) const globalLocaleState = useRecoilValue(globalLocaleStore) @@ -50,7 +50,6 @@ export default function PlanRequestPop(props) { const [schSaleStoreName, setSchSaleStoreName] = useState('') //판매대리점명 const [schPlanReqName, setSchPlanReqName] = useState('') //의뢰자명 const [schPlanStatCd, setSchPlanStatCd] = useState('') //상태코드 - const [schDateGbn, setSchDateGbn] = useState('S') //기간구분코드(S/R) //초기화 const resetRecoil = () => { @@ -59,7 +58,6 @@ export default function PlanRequestPop(props) { setSchAddress('') setSchSaleStoreName('') setSchPlanReqName('') - setSchDateGbn('S') setStartDate(dayjs(new Date()).add(-3, 'month').format('YYYY-MM-DD')) setEndDate(dayjs(new Date()).format('YYYY-MM-DD')) setSchPlanStatCd('') @@ -85,10 +83,7 @@ export default function PlanRequestPop(props) { // 조회 const onSubmit = (page, type) => { - //2차점 테스트 201X112 const params = { - // saleStoreId: 'X112', - // saleStoreLevel: '1', saleStoreId: props?.otherSaleStoreId ? props.otherSaleStoreId : props.saleStoreId, saleStoreLevel: props?.otherSaleStoreLevel ? props.otherSaleStoreLevel : props.saleStoreLevel, schPlanReqNo: schPlanReqNo, @@ -97,7 +92,7 @@ export default function PlanRequestPop(props) { schSaleStoreName: schSaleStoreName, schPlanReqName: schPlanReqName, schPlanStatCd: schPlanStatCd, - schDateGbn: schDateGbn, + schDateGbn: 'R', schStartDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '', schEndDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '', startRow: type === 'S' ? (1 - 1) * pageSize + 1 : (page - 1) * pageSize + 1, @@ -135,8 +130,6 @@ export default function PlanRequestPop(props) { //페이지 갯수 변경 이벤트 const onChangePerPage = (e) => { const params = { - // saleStoreId: 'T100', - // saleStoreLevel: '1', saleStoreId: props?.otherSaleStoreId ? props.otherSaleStoreId : props.saleStoreId, saleStoreLevel: props?.otherSaleStoreLevel ? props.otherSaleStoreLevel : props.saleStoreLevel, schTitle: schTitle, @@ -145,7 +138,7 @@ export default function PlanRequestPop(props) { schSaleStoreName: schSaleStoreName, schPlanReqName: schPlanReqName, schPlanStatCd: schPlanStatCd, - schDateGbn: schDateGbn, + schDateGbn: 'R', schStartDt: dayjs(startDate).format('YYYY-MM-DD'), schEndDt: dayjs(endDate).format('YYYY-MM-DD'), startRow: (1 - 1) * e.target.value + 1, @@ -176,13 +169,13 @@ export default function PlanRequestPop(props) { gridData: [], isPageable: false, gridColumns: [ - { - field: 'planStatName', - headerName: getMessage('stuff.planReqPopup.gridHeader.planStatName'), - minWidth: 150, - checkboxSelection: true, - showDisabledCheckboxes: true, - }, + // { + // field: 'planStatName', + // headerName: getMessage('stuff.planReqPopup.gridHeader.planStatName'), + // minWidth: 150, + // checkboxSelection: true, + // showDisabledCheckboxes: true, + // }, { field: 'planReqNo', headerName: getMessage('stuff.planReqPopup.gridHeader.planReqNo'), @@ -218,11 +211,6 @@ export default function PlanRequestPop(props) { headerName: getMessage('stuff.planReqPopup.gridHeader.planReqName'), minWidth: 150, }, - { - field: 'submitDt', - headerName: getMessage('stuff.planReqPopup.gridHeader.submitDt'), - minWidth: 150, - }, ], }) @@ -246,12 +234,16 @@ export default function PlanRequestPop(props) { } } + // useEffect(() => { + // const code1 = findCommonCode(115800) //상태 + // if (code1 != null) { + // setPlanStatCdList(code1) + // } + // }, [commonCode]) + useEffect(() => { - const code1 = findCommonCode(115800) //상태 - if (code1 != null) { - setPlanStatCdList(code1) - } - }, [commonCode]) + onSubmit(pageNo, 'S') + }, []) // 숫자만 입력 가능 const handleKeyUp = (e) => { @@ -388,7 +380,7 @@ export default function PlanRequestPop(props) { />
    - {getMessage('stuff.planReqPopup.search.planStatName')} + {/* {getMessage('stuff.planReqPopup.search.planStatName')}
    { - setSchDateGbn(e.target.value) - }} - /> - -
    -
    - { - setSchDateGbn(e.target.value) - }} - /> - -
    -
    @@ -474,12 +438,12 @@ export default function PlanRequestPop(props) {
    - - +
    diff --git a/src/components/management/popup/PlanRequestPopQGrid.jsx b/src/components/management/popup/PlanRequestPopQGrid.jsx index 955a24ff..f7dbba0f 100644 --- a/src/components/management/popup/PlanRequestPopQGrid.jsx +++ b/src/components/management/popup/PlanRequestPopQGrid.jsx @@ -56,7 +56,6 @@ export default function PlanRequestPopQGrid(props) { rowData={rowData} columnDefs={colDefs} defaultColDef={defaultColDef} - rowSelection={'singleRow'} pagination={isPageable} onSelectionChanged={onSelectionChanged} overlayNoRowsTemplate={`${getMessage('stuff.grid.noData')}`} diff --git a/src/components/management/popup/WindSelectPop.jsx b/src/components/management/popup/WindSelectPop.jsx index b135aa20..68d84558 100644 --- a/src/components/management/popup/WindSelectPop.jsx +++ b/src/components/management/popup/WindSelectPop.jsx @@ -105,12 +105,12 @@ export default function WindSelectPop(props) {
    - - +
    diff --git a/src/components/myInfo/UserInfoModal.jsx b/src/components/myInfo/UserInfoModal.jsx index 64677518..0d2d1898 100644 --- a/src/components/myInfo/UserInfoModal.jsx +++ b/src/components/myInfo/UserInfoModal.jsx @@ -39,6 +39,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal if (resultData) { setInfo(resultData) + setPassword(resultData.password) } else { alert(getMessage('common.message.no.data')) } diff --git a/src/components/simulator/Simulator.jsx b/src/components/simulator/Simulator.jsx index fcef3a08..0d33bbf8 100644 --- a/src/components/simulator/Simulator.jsx +++ b/src/components/simulator/Simulator.jsx @@ -3,33 +3,30 @@ import 'chart.js/auto' import { Bar } from 'react-chartjs-2' import dayjs from 'dayjs' +import { v4 as uuidv4 } from 'uuid' -import { useEffect, useState, useRef } from 'react' -import { useRecoilValue, useRecoilState } from 'recoil' -import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' +import { useEffect, useState, useRef, useContext } from 'react' +import { useRecoilState } from 'recoil' +import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider' import { pwrGnrSimTypeState } from '@/store/simulatorAtom' import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' -import { usePlan } from '@/hooks/usePlan' import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' import { convertNumberToPriceDecimal } from '@/util/common-utils' +// import { useSearchParams } from 'next/navigation' export default function Simulator() { - const { plans } = usePlan() - const plan = plans.find((plan) => plan.isCurrent === true) + const { floorPlanState } = useContext(FloorPlanContext) + const { objectNo, pid } = floorPlanState + + // const searchParams = useSearchParams() + // const objectNo = searchParams.get('objectNo') + // const pid = searchParams.get('pid') const chartRef = useRef(null) - // recoil 물건번호 - const objectRecoil = useRecoilValue(floorPlanObjectState) - const [objectNo, setObjectNo] = useState('') - - useEffect(() => { - setObjectNo(objectRecoil.floorPlanObjectNo) - }, [objectRecoil]) - // 캔버스 메뉴 넘버 셋팅 const { setMenuNumber } = useCanvasMenu() @@ -105,13 +102,23 @@ export default function Simulator() { } useEffect(() => { + /* 초기화 작업 */ + setChartData([]) + setObjectDetail({}) + setModuleInfoList([]) + setPcsInfoList([]) + setHatsudenryouAll([]) + setHatsudenryouAllSnow([]) + setHatsudenryouPeakcutAll([]) + setHatsudenryouPeakcutAllSnow([]) + if (objectNo) { fetchObjectDetail(objectNo) fetchSimulatorNotice() setPwrGnrSimType('D') setPwrRecoil({ ...pwrRecoil, type: 'D' }) } - }, [objectNo, plan]) + }, [objectNo, pid]) // 물건 상세 정보 조회 const [objectDetail, setObjectDetail] = useState({}) @@ -129,7 +136,7 @@ export default function Simulator() { const [hatsudenryouPeakcutAllSnow, setHatsudenryouPeakcutAllSnow] = useState([]) const fetchObjectDetail = async (objectNo) => { - const apiUrl = `/api/pwrGnrSimulation/calculations?objectNo=${objectNo}&planNo=${plan?.id}` + const apiUrl = `/api/pwrGnrSimulation/calculations?objectNo=${objectNo}&planNo=${pid}` const resultData = await get({ url: apiUrl }) if (resultData) { @@ -201,7 +208,8 @@ export default function Simulator() {
    {getMessage('simulator.title.sub1')}
    - {objectDetail.objectNo} (Plan No: {plan?.id}) + {objectDetail.objectNo} + {`${objectDetail.planNo ? `(Plan No: ${objectDetail.planNo})` : ''}`}
    {/* 작성일 */} @@ -219,7 +227,7 @@ export default function Simulator() { {/* 연간예측발전량 */}
    {getMessage('simulator.title.sub4')}
    -
    {chartData[chartData.length - 1]}
    +
    {convertNumberToPriceDecimal(chartData[chartData.length - 1])}
    @@ -300,7 +308,7 @@ export default function Simulator() { {chartData.length > 0 ? ( {chartData.map((data) => ( - {data} + {data} ))} ) : ( @@ -335,15 +343,15 @@ export default function Simulator() { {/* 지붕면 */} {moduleInfo.roofSurface} {/* 경사각 */} - {convertNumberToPriceDecimal(moduleInfo.slope)}寸 + {convertNumberToPriceDecimal(moduleInfo.slopeAngle)}寸 {/* 방위각(도) */} - {convertNumberToPriceDecimal(moduleInfo.angle)} + {convertNumberToPriceDecimal(moduleInfo.azimuth)} {/* 태양전지모듈 */}
    {moduleInfo.itemNo}
    {/* 매수 */} - {moduleInfo.amount} + {convertNumberToPriceDecimal(moduleInfo.amount)} ) @@ -385,7 +393,7 @@ export default function Simulator() {
    {pcsInfo.itemNo}
    {/* 대 */} - {pcsInfo.amount} + {convertNumberToPriceDecimal(pcsInfo.amount)} ) diff --git a/src/hooks/common/useGrid.js b/src/hooks/common/useGrid.js index 2b6e9ba9..abd2a6e0 100644 --- a/src/hooks/common/useGrid.js +++ b/src/hooks/common/useGrid.js @@ -15,12 +15,13 @@ export function useGrid() { if (!canvas) { return } + const patternData = { dotGridDisplay: dotLineGridSetting.DOT, lineGridDisplay: dotLineGridSetting.LINE, gridType: dotLineGridSetting.INTERVAL.type, - gridHorizon: dotLineGridSetting.INTERVAL.horizontalInterval / 10, - gridVertical: dotLineGridSetting.INTERVAL.verticalInterval / 10, + gridHorizon: (dotLineGridSetting.INTERVAL.horizontalInterval / 10) * (dotLineGridSetting.INTERVAL.dimension ?? 1), + gridVertical: (dotLineGridSetting.INTERVAL.verticalInterval / 10) * (dotLineGridSetting.INTERVAL.dimension ?? 1), gridRatio: dotLineGridSetting.INTERVAL.ratioInterval / 10, gridDimen: dotLineGridSetting.INTERVAL.dimension, } diff --git a/src/hooks/common/useMasterController.js b/src/hooks/common/useMasterController.js index 6f7a8fb9..d9362c34 100644 --- a/src/hooks/common/useMasterController.js +++ b/src/hooks/common/useMasterController.js @@ -36,7 +36,7 @@ export function useMasterController() { } const paramString = `?${paramArr.map((item) => `arrRoofMatlCd=${item}`).join('&')}` return await get({ url: `/api/v1/master/getModuleTypeItemList${paramString}` }).then((res) => { - console.log('🚀🚀 ~ getModuleTypeItemList ~ res:', res) + // console.log('🚀🚀 ~ getModuleTypeItemList ~ res:', res) return res }) } @@ -112,11 +112,28 @@ export function useMasterController() { }) } + /** + * PCS 메이커, 시리즈 목록 조회 + * @param {PCS 메이커코드} pcsMkrCd + * @param {혼합모듈번호} mixMatlNo + * @returns + */ + const getPcsMakerList = async (params = null) => { + let paramString = '' + if (params) { + paramString = getQueryString(params) + } + return await get({ url: '/api/v1/master/pcsMakerList' + paramString }).then((res) => { + return res + }) + } + return { getRoofMaterialList, getModuleTypeItemList, getTrestleList, getConstructionList, getTrestleDetailList, + getPcsMakerList, } } diff --git a/src/hooks/floorPlan/estimate/useEstimateController.js b/src/hooks/floorPlan/estimate/useEstimateController.js index 9008467f..75eb43ab 100644 --- a/src/hooks/floorPlan/estimate/useEstimateController.js +++ b/src/hooks/floorPlan/estimate/useEstimateController.js @@ -9,7 +9,7 @@ import { useMessage } from '@/hooks/useMessage' import { useRouter } from 'next/navigation' import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider' import { QcastContext } from '@/app/QcastProvider' - +import { useSwal } from '@/hooks/useSwal' // Constants const ESTIMATE_API_ENDPOINT = '/api/estimate' // API 엔드포인트 정의 @@ -19,6 +19,7 @@ const updateItemInList = (itemList, dispOrder, updates) => { } export const useEstimateController = (planNo) => { + const { swalFire } = useSwal() const [fileList, setFileList] = useState([]) const { setIsGlobalLoading } = useContext(QcastContext) @@ -353,7 +354,6 @@ export const useEstimateController = (planNo) => { estimateData.pkgAsp = estimateData.pkgAsp.replaceAll(',', '') } - console.log('최종저장::', estimateData) //2. 상세데이터 저장 // return try { @@ -361,8 +361,9 @@ export const useEstimateController = (planNo) => { setIsGlobalLoading(true) if (res.status === 201) { estimateData.newFileList = [] - alert(getMessage('estimate.detail.save.alertMsg')) - //어디로 보낼지 + //알럿창 변경 + swalFire({ text: getMessage('estimate.detail.save.alertMsg'), type: 'alert' }) + // alert(getMessage('estimate.detail.save.alertMsg')) fetchSetting(objectRecoil.floorPlanObjectNo, estimateData.planNo) } }) @@ -400,8 +401,13 @@ export const useEstimateController = (planNo) => { if (res.status === 201) { if (isObjectNotEmpty(res.data)) { let newObjectNo = res.data.objectNo - alert(getMessage('estimate.detail.estimateCopyPopup.copy.alertMessage')) - router.push(`/management/stuff/detail?objectNo=${newObjectNo.toString()}`, { scroll: false }) + swalFire({ + text: getMessage('estimate.detail.estimateCopyPopup.copy.alertMessage'), + type: 'alert', + confirmFn: () => { + router.push(`/management/stuff/detail?objectNo=${newObjectNo.toString()}`, { scroll: false }) + }, + }) } } }) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index cbd740bf..bf6bb5f0 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -1,5 +1,5 @@ import { useRecoilState, useRecoilValue } from 'recoil' -import { canvasState } from '@/store/canvasAtom' +import { canvasState, checkedModuleState, selectedModuleState } from '@/store/canvasAtom' import { rectToPolygon, setSurfaceShapePattern, polygonToTurfPolygon } from '@/util/canvas-util' import { basicSettingState, roofDisplaySelector } from '@/store/settingAtom' import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils' @@ -27,6 +27,7 @@ export function useModuleBasicSetting() { const compasDeg = useRecoilValue(compasDegAtom) const { setSurfaceShapePattern } = useRoofFn() const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) + const checkedModule = useRecoilValue(checkedModuleState) useEffect(() => { // console.log('basicSetting', basicSetting) @@ -42,21 +43,6 @@ export function useModuleBasicSetting() { // const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext) let selectedModuleInstSurfaceArray = [] - const moduleOptions = { - fill: '#BFFD9F', - stroke: 'black', - strokeWidth: 0.1, - selectable: true, // 선택 가능하게 설정 - lockMovementX: true, // X 축 이동 잠금 - lockMovementY: true, // Y 축 이동 잠금 - lockRotation: true, // 회전 잠금 - lockScalingX: true, // X 축 크기 조정 잠금 - lockScalingY: true, // Y 축 크기 조정 잠금 - parentId: moduleSetupSurface.parentId, - surfaceId: moduleSetupSurface.id, - name: 'module', - } - //모듈,회로에서 다른메뉴 -> 배치면으로 갈 경수 초기화 const restoreModuleInstArea = () => { //설치면 삭제 @@ -127,18 +113,6 @@ export function useModuleBasicSetting() { setupSurface.setViewLengthText(false) canvas.add(setupSurface) //모듈설치면 만들기 - //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 - if (canvasSetting.roofSizeSet !== 3) { - const flowLines = { - bottom: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'bottom'), - top: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'top'), - left: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'left'), - right: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'right'), - } - - setupSurface.set({ flowLines: flowLines }) - } - //지붕면 선택 금지 roof.set({ selectable: false, @@ -193,6 +167,16 @@ export function useModuleBasicSetting() { * 확인 후 셀을 이동시킴 */ const manualModuleSetup = () => { + if (checkedModule.length === 0) { + swalFire({ text: getMessage('module.place.select.module') }) + return + } + + if (checkedModule.length > 1) { + swalFire({ text: getMessage('module.place.select.one.module') }) + return + } + const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 const batchObjects = canvas ?.getObjects() @@ -204,6 +188,19 @@ export function useModuleBasicSetting() { obj.name === BATCH_TYPE.SHADOW, ) //도머s 객체 + const moduleOptions = { + fill: checkedModule[0].color, + stroke: 'black', + strokeWidth: 0.1, + selectable: true, // 선택 가능하게 설정 + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + lockScalingX: true, // X 축 크기 조정 잠금 + lockScalingY: true, // Y 축 크기 조정 잠금 + name: 'module', + } + if (moduleSetupSurfaces.length !== 0) { let tempModule let manualDrawModules = [] @@ -221,8 +218,10 @@ export function useModuleBasicSetting() { trestlePolygon = moduleSetupSurfaces[i] manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨 flowDirection = moduleSetupSurfaces[i].flowDirection //도형의 방향 - let width = flowDirection === 'south' || flowDirection === 'north' ? 172 : 113 - let height = flowDirection === 'south' || flowDirection === 'north' ? 113 : 172 + const moduleWidth = Number(checkedModule[0].longAxis) / 10 + const moduleHeight = Number(checkedModule[0].shortAxis) / 10 + let width = flowDirection === 'south' || flowDirection === 'north' ? moduleWidth : moduleHeight + let height = flowDirection === 'south' || flowDirection === 'north' ? moduleHeight : moduleWidth const points = [ { x: mousePoint.x - width / 2, y: mousePoint.y - height / 2 }, @@ -436,7 +435,7 @@ export function useModuleBasicSetting() { const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) //겹치는지 확인 //겹치면 안됨 if (intersection) { - alert('도머위에 모듈을 올릴 수 없습니다.') + swalFire({ text: getMessage('module.place.overobject') }) isIntersection = false } }) @@ -458,10 +457,10 @@ export function useModuleBasicSetting() { canvas?.add(manualModule) manualDrawModules.push(manualModule) } else { - alert('셀끼리 겹치면 안되죠?') + swalFire({ text: getMessage('module.place.overlab') }) } } else { - alert('나갔죠?!!') + swalFire({ text: getMessage('module.place.out') }) } } }) @@ -471,12 +470,17 @@ export function useModuleBasicSetting() { //자동 모듈 설치(그리드 방식) const autoModuleSetup = (placementRef) => { initEvent() //마우스 이벤트 초기화 + + if (checkedModule.length === 0) { + swalFire({ text: getMessage('module.place.select.module') }) + return + } + const isChidori = placementRef.isChidori.current === 'true' ? true : false const setupLocation = placementRef.setupLocation.current const isMaxSetup = placementRef.isMaxSetup.current === 'true' ? true : false const moduleSetupSurfaces = moduleSetupSurface //선택 설치면 - const notSelectedTrestlePolygons = canvas ?.getObjects() .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && !moduleSetupSurfaces.includes(obj)) //설치면이 아닌것 @@ -492,7 +496,7 @@ export function useModuleBasicSetting() { ) //도머s 객체 if (moduleSetupSurfaces.length === 0) { - alert('선택된 모듈 설치면이 없습니다.') + swalFire({ text: getMessage('module.place.no.surface') }) return } @@ -527,8 +531,7 @@ export function useModuleBasicSetting() { } }) - const moduleOptions = { - fill: '#BFFD9F', + let moduleOptions = { stroke: 'black', strokeWidth: 0.3, selectable: true, // 선택 가능하게 설정 @@ -537,8 +540,6 @@ export function useModuleBasicSetting() { lockRotation: true, // 회전 잠금 lockScalingX: true, // X 축 크기 조정 잠금 lockScalingY: true, // Y 축 크기 조정 잠금 - parentId: moduleSetupSurface.parentId, - surfaceId: moduleSetupSurface.id, name: 'module', } @@ -607,377 +608,519 @@ export function useModuleBasicSetting() { return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface) } - const downFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, isCenter = false) => { - const flowModuleLine = moduleSetupSurface.flowLines - let startPoint = flowModuleLine.bottom + /** + * 모듈의 너비와 높이를 계산하는 함수 + * @param {object} maxLengthLine 최대 길이 라인 + * @param {object} moduleSetupSurface 모듈 설치면 + * @param {object} module 모듈 + * @returns {object} 모듈의 너비와 높이 + */ + const getModuleWidthHeight = (maxLengthLine, moduleSetupSurface, module) => { + let width = + (maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? Number(module.longAxis) : Number(module.shortAxis)) / 10 + let height = + (maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? Number(module.shortAxis) : Number(module.longAxis)) / 10 - if (isCenter) { - //중앙배치일 경우에는 계산한다 + //배치면때는 방향쪽으로 패널이 넓게 누워져야함 + if (moduleSetupSurface.flowDirection !== undefined) { + width = + (moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north' + ? Number(module.longAxis) + : Number(module.shortAxis)) / 10 + height = + (moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north' + ? Number(module.shortAxis) + : Number(module.longAxis)) / 10 + } + return { width, height } + } - if (flowModuleLine.bottom.type === 'flat' && flowModuleLine.left.type === 'flat' && flowModuleLine.right.type === 'flat') { - //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 - const halfModuleWidthLength = width / 2 - startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } - - if (flowModuleLine.top.type === 'flat') { - //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 - const heightLength = Math.abs(flowModuleLine.left.y1 - flowModuleLine.left.y2) //옆에에 길이에서 반을 가른다 - const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 - startPoint = { ...startPoint, y1: startPoint.y1 - heightMargin } - } + const getFlowLines = (moduleSetupSurface, module) => { + let flowLines = {} + if (canvasSetting.roofSizeSet !== 3) { + flowLines = { + bottom: bottomTopFlowLine(moduleSetupSurface, module).find((obj) => obj.target === 'bottom'), + top: bottomTopFlowLine(moduleSetupSurface, module).find((obj) => obj.target === 'top'), + left: leftRightFlowLine(moduleSetupSurface, module).find((obj) => obj.target === 'left'), + right: leftRightFlowLine(moduleSetupSurface, module).find((obj) => obj.target === 'right'), } } - // else { - // //중앙배치가 아닐때도 흐름 방향 기준면으로 양면이 직선이면 가운데 배치 - // if (flowModuleLine.bottom.type === 'flat' && flowModuleLine.left.type === 'flat' && flowModuleLine.right.type === 'flat') { - // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 - // const halfModuleWidthLength = width / 2 - // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } - // } - // } - const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 - const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 - const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 + console.log('flowLines', flowLines) - let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1 - let totalTopEndPoint = maxTopEndPoint - startPoint.y1 - let totalWidth = Math.ceil(Math.abs(maxRightEndPoint - maxLeftEndPoint) / width) - let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width) - let diffTopEndPoint = Math.abs(totalTopEndPoint / height) - let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1) - let tempMaxWidth = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 - if (isMaxSetup) totalWidth = totalWidth * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 + return flowLines + } + + const downFlowSetupModule = (surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, isCenter = false) => { + let setupModule = [] + + checkedModule.forEach((module, index) => { + const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + const flowLines = getFlowLines(moduleSetupSurface, module) + //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + let startPoint = flowLines.bottom + const moduleArray = [] + + if (isCenter) { + //중앙배치일 경우에는 계산한다 + if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { + //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + const halfModuleWidthLength = width / 2 + startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + + if (flowLines.top.type === 'flat') { + //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 + const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 + startPoint = { ...startPoint, y1: startPoint.y1 - heightMargin } + } + } + } + // else { + // //중앙배치가 아닐때도 흐름 방향 기준면으로 양면이 직선이면 가운데 배치 + // if (flowModuleLine.bottom.type === 'flat' && flowModuleLine.left.type === 'flat' && flowModuleLine.right.type === 'flat') { + // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = width / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + // } + // } + + const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 + const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 + const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 + + let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1 + let totalTopEndPoint = maxTopEndPoint - startPoint.y1 + let totalWidth = Math.ceil(Math.abs(maxRightEndPoint - maxLeftEndPoint) / width) + let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width) + let diffTopEndPoint = Math.abs(totalTopEndPoint / height) + let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1) + let tempMaxWidth = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 + if (isMaxSetup) totalWidth = totalWidth * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 + + for (let j = 0; j < diffTopEndPoint; j++) { + bottomMargin = 0 + for (let i = 0; i <= totalWidth; i++) { + leftMargin = 0 + chidoriLength = 0 + if (isChidori) { + chidoriLength = j % 2 === 0 ? 0 : width / 2 + } + + square = [ + [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], + [startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], + [startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin], + [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin], + [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], + ] + + let squarePolygon = turf.polygon([square]) + let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id } + let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) + + let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) + let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + if (disjointFromTrestle && isDisjoint) { + if (index > 0) { + setupModule.forEach((item) => { + const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) + if (!isOverlap) { + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + } + }) + } else { + //최초 한번은 그냥 그린다 + //겹치는지 확인해서 포함된 모듈만 그린다 + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + } + } else { + tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + } + } + } + setupModule.push(moduleArray) + }) + } + + const leftFlowSetupModule = (surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, isCenter = false) => { + let setupModule = [] + + checkedModule.forEach((module, index) => { + const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + const flowLines = getFlowLines(moduleSetupSurface, module) + //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + let startPoint = flowLines.left + const moduleArray = [] + + //중앙배치일 경우에는 계산한다 + if (isCenter) { + if (flowLines.left.type === 'flat' && flowLines.bottom.type === 'flat' && flowLines.top.type === 'flat') { + //좌측 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + const halfWidthLength = Math.abs(startPoint.y1 + startPoint.y2) / 2 //밑에 길이에서 반을 가른다 + const halfModuleWidthLength = height / 2 + startPoint = { ...startPoint, y1: halfWidthLength - halfModuleWidthLength } + if (flowLines.right.type === 'flat') { + //우측까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + const widthLength = Math.abs(flowLines.top.x1 - flowLines.top.x2) //옆에에 길이에서 반을 가른다 + const widthMargin = Math.abs(widthLength - width * Math.floor(widthLength / width)) / 2 + startPoint = { ...startPoint, x1: startPoint.x1 + widthMargin } + } + } + } + + const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 + const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 + const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + + let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌 + let diffTopEndPoint = Math.abs(totalTopEndPoint / height) + let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height) + let totalWidth = Math.abs(startPoint.x1 - maxRightEndPoint) / width + let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) + + let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 + if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사 - for (let j = 0; j < diffTopEndPoint; j++) { - bottomMargin = 1 * j for (let i = 0; i <= totalWidth; i++) { - leftMargin = 1 * i - chidoriLength = 0 - if (isChidori) { - chidoriLength = j % 2 === 0 ? 0 : width / 2 + bottomMargin = 0 + for (let j = 0; j < totalHeight; j++) { + leftMargin = 0 + chidoriLength = 0 + if (isChidori) { + chidoriLength = i % 2 === 0 ? 0 : height / 2 + } + + square = [ + [startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin - chidoriLength], + [startPoint.x1 + width * i + width + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin - chidoriLength], + [startPoint.x1 + width * i + width + leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin - chidoriLength], + [startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin - chidoriLength], + [startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin - chidoriLength], + ] + + let squarePolygon = turf.polygon([square]) + let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + // if (disjointFromTrestle && isDisjoint) { + moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id } + let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) + let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) + let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + if (disjointFromTrestle && isDisjoint) { + if (index > 0) { + setupModule.forEach((item) => { + const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) + if (!isOverlap) { + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + } + }) + } else { + //최초 한번은 그냥 그린다 + //겹치는지 확인해서 포함된 모듈만 그린다 + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + } + } } - - square = [ - [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], - [startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], - [startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin], - [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin], - [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], - ] - - let squarePolygon = turf.polygon([square]) - let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) - let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) - - moduleOptions.surfaceId = moduleSetupSurface.id - let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) } - } + setupModule.push(moduleArray) + }) } - const leftFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, isCenter = false) => { - const flowModuleLine = moduleSetupSurface.flowLines - let startPoint = flowModuleLine.left + const topFlowSetupModule = (surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, isCenter = false) => { + let setupModule = [] - //중앙배치일 경우에는 계산한다 - if (isCenter) { - if (flowModuleLine.left.type === 'flat' && flowModuleLine.bottom.type === 'flat' && flowModuleLine.top.type === 'flat') { - //좌측 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - const halfWidthLength = Math.abs(startPoint.y1 + startPoint.y2) / 2 //밑에 길이에서 반을 가른다 - const halfModuleWidthLength = height / 2 - startPoint = { ...startPoint, y1: halfWidthLength - halfModuleWidthLength } - if (flowModuleLine.right.type === 'flat') { - //우측까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 - const widthLength = Math.abs(flowModuleLine.top.x1 - flowModuleLine.top.x2) //옆에에 길이에서 반을 가른다 - const widthMargin = Math.abs(widthLength - width * Math.floor(widthLength / width)) / 2 - startPoint = { ...startPoint, x1: startPoint.x1 + widthMargin } + checkedModule.forEach((module, index) => { + const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + const flowLines = getFlowLines(moduleSetupSurface, module) + let startPoint = flowLines.top + const moduleArray = [] + + if (isCenter) { + //중앙배치일 경우에는 계산한다 + if (flowLines.top.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { + //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + const halfModuleWidthLength = width / 2 + startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + + if (flowLines.bottom.type === 'flat') { + //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 + const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 + startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength, y1: startPoint.y1 - heightMargin } + } } } - } + // else { + // //중앙배치가 아닐때도 흐름 방향 기준면으로 양면이 직선이면 가운데 배치 + // if (flowModuleLine.bottom.type === 'flat' && flowModuleLine.left.type === 'flat' && flowModuleLine.right.type === 'flat') { + // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = width / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + // } + // } - const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 - const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 - const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 + const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 + const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 - let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌 - let diffTopEndPoint = Math.abs(totalTopEndPoint / height) - let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height) - let totalWidth = Math.abs(startPoint.x1 - maxRightEndPoint) / width - let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) + let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1 + let totalRightEndPoint = maxLeftEndPoint - maxRightEndPoint + let totalBottomEndPoint = maxBottomEndPoint - startPoint.y1 + let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width) + let diffRightEndPoint = Math.ceil(Math.abs(totalRightEndPoint / width)) + let diffBottomEndPoint = Math.ceil(Math.abs(totalBottomEndPoint / height)) + let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1) + let tempMaxWidth = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 + if (isMaxSetup) diffRightEndPoint = diffRightEndPoint * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 - let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 - if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사 + for (let j = 0; j < diffBottomEndPoint; j++) { + bottomMargin = 0 + for (let i = 0; i < diffRightEndPoint; i++) { + leftMargin = 0 + chidoriLength = 0 + if (isChidori) { + chidoriLength = j % 2 === 0 ? 0 : width / 2 + } + square = [ + [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], + [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], + [startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], + [startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], + [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], + ] - for (let i = 0; i <= totalWidth; i++) { - bottomMargin = i === 0 ? 1 : 2 - for (let j = 0; j < totalHeight; j++) { - leftMargin = i === 0 ? 1 : 2 - chidoriLength = 0 - if (isChidori) { - chidoriLength = i % 2 === 0 ? 0 : height / 2 + let squarePolygon = turf.polygon([square]) + let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + // if (disjointFromTrestle && isDisjoint) { + moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id } + let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) + + let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) + let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + if (disjointFromTrestle && isDisjoint) { + if (index > 0) { + setupModule.forEach((item) => { + const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) + if (!isOverlap) { + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + } + }) + } else { + //최초 한번은 그냥 그린다 + //겹치는지 확인해서 포함된 모듈만 그린다 + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + } + } } - - square = [ - [startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin - chidoriLength], - [startPoint.x1 + width * i + width + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin - chidoriLength], - [startPoint.x1 + width * i + width + leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin - chidoriLength], - [startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin - chidoriLength], - [startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin - chidoriLength], - ] - - let squarePolygon = turf.polygon([square]) - let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) - let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) - - // if (disjointFromTrestle && isDisjoint) { - moduleOptions.surfaceId = moduleSetupSurface.id - let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) } - } + setupModule.push(moduleArray) + }) } - const topFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, isCenter = false) => { - const flowModuleLine = moduleSetupSurface.flowLines - let startPoint = flowModuleLine.top + const rightFlowSetupModule = (surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, isCenter = false) => { + let setupModule = [] - if (isCenter) { - //중앙배치일 경우에는 계산한다 - if (flowModuleLine.top.type === 'flat' && flowModuleLine.left.type === 'flat' && flowModuleLine.right.type === 'flat') { - //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 - const halfModuleWidthLength = width / 2 - startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + checkedModule.forEach((module, index) => { + const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + const flowLines = getFlowLines(moduleSetupSurface, module) + let startPoint = flowLines.right + const moduleArray = [] - if (flowModuleLine.bottom.type === 'flat') { - //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 - const heightLength = Math.abs(flowModuleLine.left.y1 - flowModuleLine.left.y2) //옆에에 길이에서 반을 가른다 - const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 - startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength, y1: startPoint.y1 - heightMargin } + if (isCenter) { + if (flowLines.left.type === 'flat' && flowLines.bottom.type === 'flat' && flowLines.top.type === 'flat') { + //좌측 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + const halfWidthLength = Math.abs(startPoint.y1 + startPoint.y2) / 2 //밑에 길이에서 반을 가른다 + const halfModuleWidthLength = height / 2 + startPoint = { ...startPoint, y1: halfWidthLength + halfModuleWidthLength } + + if (flowLines.right.type === 'flat') { + //우측까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + const widthLength = Math.abs(flowLines.top.x1 - flowLines.top.x2) //옆에에 길이에서 반을 가른다 + const widthMargin = Math.abs(widthLength - width * Math.floor(widthLength / width)) / 2 + startPoint = { ...startPoint, x1: startPoint.x1 - widthMargin } + } } } - } - // else { - // //중앙배치가 아닐때도 흐름 방향 기준면으로 양면이 직선이면 가운데 배치 - // if (flowModuleLine.bottom.type === 'flat' && flowModuleLine.left.type === 'flat' && flowModuleLine.right.type === 'flat') { - // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 - // const halfModuleWidthLength = width / 2 - // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } - // } - // } - const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 - const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 - const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 + const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 + const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 - let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1 - let totalRightEndPoint = maxLeftEndPoint - maxRightEndPoint - let totalBottomEndPoint = maxBottomEndPoint - startPoint.y1 - let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width) - let diffRightEndPoint = Math.ceil(Math.abs(totalRightEndPoint / width)) - let diffBottomEndPoint = Math.ceil(Math.abs(totalBottomEndPoint / height)) - let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1) - let tempMaxWidth = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 - if (isMaxSetup) diffRightEndPoint = diffRightEndPoint * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 + let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌 + let diffTopEndPoint = Math.abs(totalTopEndPoint / height) + let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height) + let totalWidth = Math.abs(startPoint.x1 - maxLeftEndPoint) / width + let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) - 3 // -3으로 위치살짝 보정 - for (let j = 0; j < diffBottomEndPoint; j++) { - bottomMargin = j === 0 ? 1 : 2 - for (let i = 0; i < diffRightEndPoint; i++) { - leftMargin = i === 0 ? 1 : 2 - chidoriLength = 0 - if (isChidori) { - chidoriLength = j % 2 === 0 ? 0 : width / 2 - } - square = [ - [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], - [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], - [startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], - [startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], - [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], - ] + let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 + if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사 - let squarePolygon = turf.polygon([square]) - let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) - let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + for (let i = 0; i <= totalWidth; i++) { + bottomMargin = 0 + for (let j = 0; j < totalHeight; j++) { + leftMargin = 0 + chidoriLength = 0 + if (isChidori) { + chidoriLength = i % 2 === 0 ? 0 : height / 2 + } - // if (disjointFromTrestle && isDisjoint) { - moduleOptions.surfaceId = moduleSetupSurface.id - let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - } - } - } + square = [ + [startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin + chidoriLength], + [startPoint.x1 - width * i - width - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin + chidoriLength], + [startPoint.x1 - width * i - width - leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin + chidoriLength], + [startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin + chidoriLength], + [startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin + chidoriLength], + ] - const rightFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, isCenter = false) => { - const flowModuleLine = moduleSetupSurface.flowLines - let startPoint = flowModuleLine.right + let squarePolygon = turf.polygon([square]) + let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) - if (isCenter) { - if (flowModuleLine.left.type === 'flat' && flowModuleLine.bottom.type === 'flat' && flowModuleLine.top.type === 'flat') { - //좌측 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - const halfWidthLength = Math.abs(startPoint.y1 + startPoint.y2) / 2 //밑에 길이에서 반을 가른다 - const halfModuleWidthLength = height / 2 - startPoint = { ...startPoint, y1: halfWidthLength + halfModuleWidthLength } + // if (disjointFromTrestle && isDisjoint) { + moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id } + let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) + let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) + let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) - if (flowModuleLine.right.type === 'flat') { - //우측까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 - const widthLength = Math.abs(flowModuleLine.top.x1 - flowModuleLine.top.x2) //옆에에 길이에서 반을 가른다 - const widthMargin = Math.abs(widthLength - width * Math.floor(widthLength / width)) / 2 - startPoint = { ...startPoint, x1: startPoint.x1 - widthMargin } + if (disjointFromTrestle && isDisjoint) { + if (index > 0) { + setupModule.forEach((item) => { + const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) + if (!isOverlap) { + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + } + }) + } else { + //최초 한번은 그냥 그린다 + //겹치는지 확인해서 포함된 모듈만 그린다 + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + } + } } } - } - - const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 - const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 - const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 - - let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌 - let diffTopEndPoint = Math.abs(totalTopEndPoint / height) - let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height) - let totalWidth = Math.abs(startPoint.x1 - maxLeftEndPoint) / width - let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) - 3 // -3으로 위치살짝 보정 - - let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 - if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사 - - for (let i = 0; i <= totalWidth; i++) { - bottomMargin = i === 0 ? 1 : 2 - for (let j = 0; j < totalHeight; j++) { - leftMargin = j === 0 ? 1 : 2 - chidoriLength = 0 - if (isChidori) { - chidoriLength = i % 2 === 0 ? 0 : height / 2 - } - - square = [ - [startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin + chidoriLength], - [startPoint.x1 - width * i - width - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin + chidoriLength], - [startPoint.x1 - width * i - width - leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin + chidoriLength], - [startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin + chidoriLength], - [startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin + chidoriLength], - ] - - let squarePolygon = turf.polygon([square]) - let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) - let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) - - // if (disjointFromTrestle && isDisjoint) { - moduleOptions.surfaceId = moduleSetupSurface.id - let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - } - } + setupModule.push(moduleArray) + }) } moduleSetupSurfaces.forEach((moduleSetupSurface, index) => { moduleSetupSurface.fire('mousedown') const moduleSetupArray = [] + const turfModuleSetupSurface = polygonToTurfPolygon(moduleSetupSurface) //폴리곤을 turf 객체로 변환 + const containsBatchObjects = objectsIncludeSurface(turfModuleSetupSurface) //배치면에 오브젝트(도머, 개구등)이 있는지 확인하는 로직 + const surfaceMaxLines = findSetupSurfaceMaxLines(moduleSetupSurface) + let maxLengthLine = moduleSetupSurface.lines.reduce((acc, cur) => { return acc.length > cur.length ? acc : cur }) - const turfModuleSetupSurface = polygonToTurfPolygon(moduleSetupSurface) //폴리곤을 turf 객체로 변환 - const containsBatchObjects = objectsIncludeSurface(turfModuleSetupSurface) //배치면에 오브젝트(도머, 개구등)이 있는지 확인하는 로직 - - let width = maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? 172.2 : 113.4 - let height = maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? 113.4 : 172.2 - - //배치면때는 방향쪽으로 패널이 넓게 누워져야함 - if (moduleSetupSurface.flowDirection !== undefined) { - width = moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north' ? 172.2 : 113.4 - height = moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north' ? 113.4 : 172.2 - } - - const surfaceMaxLines = findSetupSurfaceMaxLines(moduleSetupSurface) - //처마면 배치 if (setupLocation === 'eaves') { // 흐름방향이 남쪽일때 if (moduleSetupSurface.flowDirection === 'south') { - downFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface) + downFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) } if (moduleSetupSurface.flowDirection === 'west') { - leftFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface) + leftFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) } if (moduleSetupSurface.flowDirection === 'east') { - rightFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface) + rightFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) } if (moduleSetupSurface.flowDirection === 'north') { - topFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface) + topFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) } } else if (setupLocation === 'ridge') { //용마루 if (moduleSetupSurface.flowDirection === 'south') { - topFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface) + topFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) } if (moduleSetupSurface.flowDirection === 'west') { - rightFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface) + rightFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) } if (moduleSetupSurface.flowDirection === 'east') { - leftFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface) + leftFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) } if (moduleSetupSurface.flowDirection === 'north') { - downFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface) + downFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) } } else if (setupLocation === 'center') { //중가면 if (moduleSetupSurface.flowDirection === 'south') { - downFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, true) + downFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true) } if (moduleSetupSurface.flowDirection === 'west') { - leftFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, true) + leftFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true) } if (moduleSetupSurface.flowDirection === 'east') { - rightFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, true) + rightFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true) } if (moduleSetupSurface.flowDirection === 'north') { - topFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, true) + topFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true) } } - const setupedModules = moduleSetupArray.filter((module, index) => { - let disjointFromTrestle = checkModuleDisjointSurface(module.turfPoints, turfModuleSetupSurface) - let isDisjoint = checkModuleDisjointObjects(module.turfPoints, containsBatchObjects) + // const setupedModules = moduleSetupArray.filter((module, index) => { + // let disjointFromTrestle = checkModuleDisjointSurface(module.turfPoints, turfModuleSetupSurface) + // let isDisjoint = checkModuleDisjointObjects(module.turfPoints, containsBatchObjects) - if (!(disjointFromTrestle && isDisjoint)) { - canvas?.remove(module) - // module.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) - return false - } else { - return module - } - }) + // if (!(disjointFromTrestle && isDisjoint)) { + // canvas?.remove(module) + // // module.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // return false + // } else { + // return module + // } + // }) - canvas?.renderAll() + // canvas?.renderAll() //나간애들 제외하고 설치된 애들로 겹친애들 삭제 하기 - setupedModules.forEach((module, index) => { + moduleSetupArray.forEach((module, index) => { if (isMaxSetup && index > 0) { - const isOverlap = turf.booleanOverlap(polygonToTurfPolygon(setupedModules[index - 1]), polygonToTurfPolygon(module)) + const isOverlap = turf.booleanOverlap(polygonToTurfPolygon(moduleSetupArray[index - 1]), polygonToTurfPolygon(module)) //겹치는지 확인 if (isOverlap) { //겹쳐있으면 삭제 canvas?.remove(module) // module.set({ fill: 'rgba(72, 161, 250, 0.4)', stroke: 'black', strokeWidth: 0.1 }) canvas.renderAll() - setupedModules.splice(index, 1) + moduleSetupArray.splice(index, 1) return false } } }) - moduleSetupSurface.set({ modules: setupedModules }) + // moduleSetupSurface.set({ modules: moduleSetupArray }) // const moduleArray = [...moduleIsSetup] // moduleArray.push({ @@ -986,7 +1129,7 @@ export function useModuleBasicSetting() { // }) // setModuleIsSetup(moduleArray) }) - calculateForApi() + // calculateForApi() } const calculateForApi = () => { @@ -1248,8 +1391,9 @@ export function useModuleBasicSetting() { return hull } - const bottomTopFlowLine = (surface) => { + const bottomTopFlowLine = (surface, module) => { const flowArray = [] + const bottomFlow = surface.lines.reduce( (acc, line, index) => { if (line.y1 > acc.y1 || (line.y1 === acc.y1 && line.x1 > acc.x1)) { @@ -1306,7 +1450,7 @@ export function useModuleBasicSetting() { const angle2 = Math.abs(Math.round(Math.atan(height2 / adjust2) * (180 / Math.PI) * 1000) / 1000) const angle3 = 180 - (angle1 + angle2) - const charlie = 173.3 // 평행선길이 약간 여유를 줌 + const charlie = Number(module.longAxis) / 10 + 3 // 평행선길이 약간 여유를 줌 const alpha = (charlie * Math.sin((angle1 * Math.PI) / 180)) / Math.sin((angle3 * Math.PI) / 180) const beta = Math.sqrt(alpha ** 2 + charlie ** 2 - 2 * alpha * charlie * Math.cos((angle2 * Math.PI) / 180)) const h = beta * Math.sin((angle1 * Math.PI) / 180) // 높이 @@ -1323,8 +1467,8 @@ export function useModuleBasicSetting() { strokeWidth: 1, selectable: true, }) - // canvas?.add(finalLine) - // canvas?.renderAll() + canvas?.add(finalLine) + canvas?.renderAll() let rtnObj //평평하면 @@ -1365,7 +1509,7 @@ export function useModuleBasicSetting() { return rtnObjArray } - const leftRightFlowLine = (surface) => { + const leftRightFlowLine = (surface, module) => { const flowArray = [] const leftFlow = surface.lines.reduce( (acc, line, index) => { @@ -1421,7 +1565,7 @@ export function useModuleBasicSetting() { const angle2 = Math.abs(Math.round(Math.atan(adjust2 / height2) * (180 / Math.PI) * 1000) / 1000) const angle3 = 180 - (angle1 + angle2) - const charlie = 173.3 // 평행선길이 약간 여유를줌 + const charlie = Number(module.shortAxis) / 10 + 3 // 평행선길이 약간 여유를 줌 const alpha = (charlie * Math.sin((angle1 * Math.PI) / 180)) / Math.sin((angle3 * Math.PI) / 180) const beta = Math.sqrt(alpha ** 2 + charlie ** 2 - 2 * alpha * charlie * Math.cos((angle2 * Math.PI) / 180)) @@ -1446,8 +1590,8 @@ export function useModuleBasicSetting() { strokeWidth: 1, selectable: true, }) - // canvas?.add(finalLine) - // canvas?.renderAll() + canvas?.add(finalLine) + canvas?.renderAll() let rtnObj //평평하면 @@ -1828,7 +1972,7 @@ export function useModuleBasicSetting() { const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) //겹치는지 확인 //겹치면 안됨 if (intersection) { - alert('도머위에 모듈을 올릴 수 없습니다.') + swalFire({ text: getMessage('module.place.overobject') }) isIntersection = false } }) @@ -1845,10 +1989,10 @@ export function useModuleBasicSetting() { canvas?.add(manualModule) manualDrawModules.push(tempModule) } else { - alert('셀끼리 겹치면 안되죠?') + swalFire({ text: getMessage('module.place.overlab') }) } } else { - alert('나갔죠?!!') + swalFire({ text: getMessage('module.place.out') }) } } }) diff --git a/src/hooks/module/useModuleSelection.js b/src/hooks/module/useModuleSelection.js new file mode 100644 index 00000000..13fc543e --- /dev/null +++ b/src/hooks/module/useModuleSelection.js @@ -0,0 +1,177 @@ +import { useRecoilState, useRecoilValue } from 'recoil' +import { useContext, useEffect, useReducer, useState, useRef } from 'react' +import { GlobalDataContext } from '@/app/GlobalDataProvider' +import { useMasterController } from '@/hooks/common/useMasterController' +import { useCommonCode } from '@/hooks/common/useCommonCode' + +import { selectedModuleState, moduleSelectionInitParamsState } from '@/store/selectedModuleOptions' +import { pitchSelector } from '@/store/canvasAtom' +import { useDebounceValue } from 'usehooks-ts' + +export function useModuleSelection(props) { + const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) + + const globalPitch = useRecoilValue(pitchSelector) //피치 + + const [roughnessCodes, setRoughnessCodes] = useState([]) //면조도 목록 + const [windSpeedCodes, setWindSpeedCodes] = useState([]) //기준풍속 목록 + const [moduleList, setModuleList] = useState([{}]) //모듈 목록 + + const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈 + const [selectedSurfaceType, setSelectedSurfaceType] = useState({}) //선택된 면조도 + const [installHeight, setInstallHeight] = useState('0') //설치 높이 + const [standardWindSpeed, setStandardWindSpeed] = useState('0') //기준풍속 + const [verticalSnowCover, setVerticalSnowCover] = useState('0') //수직적설량 + const [moduleSelectionInitParams, setModuleSelectionInitParams] = useRecoilState(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등 + + const { getModuleTypeItemList } = useMasterController() + + const { findCommonCode } = useCommonCode() + + //탭별 파라메터 초기화 + useEffect(() => { + setInstallHeight(managementState?.installHeight) + setStandardWindSpeed(managementState?.standardWindSpeedId) + setVerticalSnowCover(managementState?.verticalSnowCover) + setSelectedSurfaceType(managementState?.surfaceType) + + const initParams = { + illuminationTp: managementState?.surfaceTypeValue, //면조도 + instHt: managementState?.installHeight, //설치높이 + stdWindSpeed: managementState?.standardWindSpeedId, //기준풍속 + stdSnowLd: managementState?.verticalSnowCover, //기준적설량 + inclCd: globalPitch, + } + setModuleSelectionInitParams(initParams) + }, [managementState]) + + useEffect(() => { + //새로고침시 데이터 날아가는거 방지 + if (!managementState) { + setManagementState(managementStateLoaded) + } + + // 113700 면조도 + const roughnessCodeList = findCommonCode('113700') + roughnessCodeList.forEach((obj) => { + obj.name = obj.clCodeNm + obj.id = obj.clCode + }) + setRoughnessCodes(roughnessCodeList) + + // 202000 풍속 + const windCodeList = findCommonCode('202000') + windCodeList.forEach((obj) => { + obj.name = obj.clCodeNm + obj.id = obj.clCode + }) + setWindSpeedCodes(windCodeList) + + //지붕재 선택 + const roofsIds = props.addedRoofs.filter((obj) => obj.roofMatlCd).map((obj) => obj.roofMatlCd) + + if (roofsIds.length === 0) { + return + } + getModuleData(roofsIds) + }, []) + + const getModuleData = async (roofsIds) => { + const list = await getModuleTypeItemList(roofsIds) + //selectbox에 이름을 넣는다 + list.data.forEach((item) => { + item.name = item.itemNm + }) + //셀렉트박스 데이터 초기화 + setModuleList(list.data) + } + + const handleChangeModule = (option) => { + //선택된 모듈 + setSelectedModules(option) //선택값 저장 + + //init 데이터에 선택된 모듈 추가 + setModuleSelectionInitParams({ + ...moduleSelectionInitParams, + moduleTpCd: option.itemTp, + }) + } + + const handleChangeSurfaceType = (option) => { + setModuleSelectionInitParams({ + ...moduleSelectionInitParams, + illuminationTp: option.clCode, + }) + } + + const handleChangeWindSpeed = (option) => { + setModuleSelectionInitParams({ + ...moduleSelectionInitParams, + surfaceType: option.clCode, + }) + } + + const handleChangeInstallHeight = (option) => { + setInstallHeight(option) + + setModuleSelectionInitParams({ + ...moduleSelectionInitParams, + instHt: option, + }) + } + + const handleChangeVerticalSnowCover = (option) => { + setVerticalSnowCover(option) + + setModuleSelectionInitParams({ + ...moduleSelectionInitParams, + stdSnowLd: option, + }) + } + + //TODO: 설치높이, 기준적설량 debounce 적용해서 추가해야됨 + + // useEffect(() => { + // getConstructionListData(constructionListParams) + // }, [constructionListParams]) + + // const getConstructionListData = async (params) => { + // if (params.trestleMkrCd && params.constMthdCd && params.roofBaseCd) { + // const optionsList = await getConstructionList(params) + // console.log('optionsList', optionsList) + // setConstructionList(optionsList.data) + // } + // } + + //state 배열에 데이터 추가 함수 + // const addRoofTabParams = (key, value, excludeArray = []) => { + // const index = roofTabParams.findIndex((obj) => obj.roofTab === roofTab) + // if (index !== -1) { + // roofTabParams[index][key] = value + // if (excludeArray.length > 0) { + // excludeArray.forEach((exclude) => { + // roofTabParams[index][exclude] = '' + // }) + // } + // setRoofTabParams((prev) => [...prev.slice(0, index), roofTabParams[index], ...prev.slice(index + 1)]) + // } + // } + + return { + moduleSelectionInitParams, + selectedModules, + roughnessCodes, + windSpeedCodes, + managementState, + moduleList, + selectedSurfaceType, + installHeight, + standardWindSpeed, + verticalSnowCover, + handleChangeModule, + handleChangeSurfaceType, + handleChangeWindSpeed, + handleChangeInstallHeight, + handleChangeVerticalSnowCover, + } +} diff --git a/src/hooks/object/useObjectBatch.js b/src/hooks/object/useObjectBatch.js index 6fd858a1..27676eab 100644 --- a/src/hooks/object/useObjectBatch.js +++ b/src/hooks/object/useObjectBatch.js @@ -36,10 +36,10 @@ export function useObjectBatch({ isHidden, setIsHidden }) { }, []) const dbClickEvent = () => { - console.log('dbClickEvent 실행') + // console.log('dbClickEvent 실행') const dormerObject = canvas.getObjects().filter((obj) => obj.name === BATCH_TYPE.TRIANGLE_DORMER || obj.name === BATCH_TYPE.PENTAGON_DORMER) - console.log('dormerObject', dormerObject) + // console.log('dormerObject', dormerObject) if (dormerObject) { canvas.off('mouse:dblclick') diff --git a/src/hooks/option/useCanvasSetting.js b/src/hooks/option/useCanvasSetting.js index e4c02664..c4ac79c9 100644 --- a/src/hooks/option/useCanvasSetting.js +++ b/src/hooks/option/useCanvasSetting.js @@ -135,6 +135,8 @@ export function useCanvasSetting() { raft: item.raftBase && parseInt(item.raftBase), layout: ['ROOF_ID_SLATE', 'ROOF_ID_SINGLE'].includes(item.roofMatlCd) ? ROOF_MATERIAL_LAYOUT.STAIRS : ROOF_MATERIAL_LAYOUT.PARALLEL, hajebichi: item.roofPchBase && parseInt(item.roofPchBase), + pitch: item.pitch ? parseInt(item.pitch) : 4, + angle: item.angle ? parseInt(item.angle) : 21.8, })) setRoofMaterials(roofLists) const selectedRoofMaterial = roofLists[0] @@ -272,7 +274,7 @@ export function useCanvasSetting() { // 기본설정(PlacementShapeSetting) 조회 및 초기화 const fetchBasicSettings = async () => { try { - await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/0/${correntObjectNo}` }).then((res) => { + await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/1/${correntObjectNo}` }).then((res) => { let roofsRow = {} let roofsArray = {} @@ -287,7 +289,7 @@ export function useCanvasSetting() { roofsArray = res.map((item) => { return { roofApply: true, - roofSeq: 1, + roofSeq: 0, roofMatlCd: item.roofMatlCd, roofWidth: item.roofWidth, roofHeight: item.roofHeight, @@ -307,7 +309,7 @@ export function useCanvasSetting() { roofsArray = [ { roofApply: true, - roofSeq: 1, + roofSeq: 0, roofMatlCd: 'ROOF_ID_WA_53A', roofWidth: 265, roofHeight: 235, @@ -390,7 +392,7 @@ export function useCanvasSetting() { setCanvasSetting({ ...basicSetting }) fetchBasicSettings() } catch (error) { - swalFire({ text: getMessage(res.returnMessage), icon: 'error' }) + swalFire({ text: error.message, icon: 'error' }) } } diff --git a/src/hooks/roofcover/useAuxiliaryDrawing.js b/src/hooks/roofcover/useAuxiliaryDrawing.js index 55053b7e..4997bdf8 100644 --- a/src/hooks/roofcover/useAuxiliaryDrawing.js +++ b/src/hooks/roofcover/useAuxiliaryDrawing.js @@ -651,7 +651,7 @@ export function useAuxiliaryDrawing(id) { { stroke: 'black', strokeWidth: 1, - selectable: false, + selectable: true, name: 'auxiliaryLine', isFixed: true, }, @@ -721,7 +721,7 @@ export function useAuxiliaryDrawing(id) { newLine = addLine([line1.x1, line1.y1, intersectionPoint.x, intersectionPoint.y], { stroke: 'black', strokeWidth: 1, - selectable: false, + selectable: true, name: 'auxiliaryLine', isFixed: true, intersectionPoint, @@ -730,7 +730,7 @@ export function useAuxiliaryDrawing(id) { newLine = addLine([line1.x2, line1.y2, intersectionPoint.x, intersectionPoint.y], { stroke: 'black', strokeWidth: 1, - selectable: false, + selectable: true, name: 'auxiliaryLine', isFixed: true, intersectionPoint, diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index 0671f502..3e999380 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -1,9 +1,17 @@ import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' -import { canvasState, currentMenuState, currentObjectState } from '@/store/canvasAtom' +import { canvasState, currentAngleTypeSelector, currentMenuState, currentObjectState } from '@/store/canvasAtom' import { useEffect, useRef, useState } from 'react' +import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' import { usePolygon } from '@/hooks/usePolygon' -import { addedRoofsState, basicSettingState, roofDisplaySelector, roofMaterialsSelector, selectedRoofMaterialSelector } from '@/store/settingAtom' +import { + correntObjectNoState, + addedRoofsState, + basicSettingState, + roofDisplaySelector, + roofMaterialsSelector, + selectedRoofMaterialSelector, +} from '@/store/settingAtom' import { usePopup } from '@/hooks/usePopup' import { POLYGON_TYPE } from '@/common/common' import { v4 as uuidv4 } from 'uuid' @@ -14,10 +22,13 @@ import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' import { menuTypeState } from '@/store/menuAtom' import { useRoofFn } from '@/hooks/common/useRoofFn' import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting' +import { globalLocaleStore } from '@/store/localeAtom' +import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util' // 지붕면 할당 export function useRoofAllocationSetting(id) { const canvas = useRecoilValue(canvasState) + const [correntObjectNo, setCorrentObjectNo] = useRecoilState(correntObjectNoState) const roofDisplay = useRecoilValue(roofDisplaySelector) const { drawDirectionArrow, addLengthText, splitPolygonWithLines, splitPolygonWithSeparate } = usePolygon() const [popupId, setPopupId] = useState(uuidv4()) @@ -34,6 +45,10 @@ export function useRoofAllocationSetting(id) { const [roofList, setRoofList] = useRecoilState(addedRoofsState) // 배치면 초기설정에서 선택한 지붕재 배열 const [editingLines, setEditingLines] = useState([]) const [currentRoofList, setCurrentRoofList] = useState(roofList) + const currentAngleType = useRecoilValue(currentAngleTypeSelector) + + const globalLocaleState = useRecoilValue(globalLocaleStore) + const { get, post } = useAxios(globalLocaleState) const { setSurfaceShapePattern } = useRoofFn() @@ -74,8 +89,118 @@ export function useRoofAllocationSetting(id) { swalFire({ text: '할당할 지붕이 없습니다.' }) closePopup(id) } + + // console.log('🚀 ~ useEffect ~ roofMaterials >>>>>>>>>>>>> :', roofMaterials) + // console.log('🚀 ~ useEffect ~ basicSetting >>>>>>>>>>>>> :', basicSetting) + // console.log('🚀 ~ useEffect ~ roofList >>>>>>>>>>>>> :', roofList) + // console.log('🚀 ~ useEffect ~ currentRoofList >>>>>>>>>>>>> :', currentRoofList) + + fetchBasicSettings() }, []) + // 조회 및 초기화 + const fetchBasicSettings = async () => { + try { + await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/1/${correntObjectNo}` }).then((res) => { + console.log('🚀 ~ useRoofAllocationSetting ~ fetchBasicSettings ~ res >>>>>>>>>>>>>>>>>>>>> :', res) + let roofsArray = {} + + if (res.length > 0) { + roofsArray = res.map((item) => { + return { + roofApply: item.roofApply, + roofSeq: item.roofSeq, + roofMatlCd: item.roofMatlCd, + roofWidth: item.roofWidth, + roofHeight: item.roofHeight, + roofHajebichi: item.roofHajebichi, + roofGap: item.roofGap, + roofLayout: item.roofLayout, + } + }) + } else { + roofsArray = [ + { + roofApply: true, + roofSeq: 0, + roofMatlCd: 'ROOF_ID_WA_53A', + roofWidth: 265, + roofHeight: 235, + roofHajebichi: 0, + roofGap: 'HEI_455', + roofLayout: 'P', + }, + ] + } + + // 나머지 데이터와 함께 'roofs' 배열을 patternData에 넣음 + const patternData = { + roofs: roofsArray, // 만들어진 roofs 배열 + } + + console.log('fetchBasicSettings roofsArray', roofsArray) + + // 데이터 설정 + const selectRoofs = [] + for (let i = 0; i < roofsArray.length; i++) { + roofMaterials?.map((material) => { + if (material.roofMatlCd === roofsArray[i].roofMatlCd) { + selectRoofs.push({ + ...material, + selected: roofsArray[i].roofApply, + index: roofsArray[i].roofSeq, + id: roofsArray[i].roofMatlCd, + width: roofsArray[i].roofWidth, + length: roofsArray[i].roofHeight, + hajebichi: roofsArray[i].roofHajebichi, + raft: roofsArray[i].roofGap, + layout: roofsArray[i].roofLayout, + }) + setCurrentRoofList(selectRoofs) + } + }) + } + setBasicSetting({ ...basicSetting, roofsData: roofsArray }) + }) + } catch (error) { + console.error('Data fetching error:', error) + } + } + + // 저장 + const basicSettingSave = async () => { + const patternData = { + objectNo: correntObjectNo, + roofSizeSet: basicSetting.roofSizeSet, + roofAngleSet: basicSetting.roofAngleSet, + roofMaterialsAddList: currentRoofList.map((item) => ({ + roofApply: item.selected === null || item.selected === undefined ? 'true' : item.selected, + roofSeq: item.index === null || item.index === undefined ? 0 : item.index, + roofMatlCd: item.roofMatlCd === null || item.roofMatlCd === undefined ? 'ROOF_ID_WA_53A' : item.roofMatlCd, + roofWidth: item.width === null || item.width === undefined ? 0 : item.width, + roofHeight: item.length === null || item.length === undefined ? 0 : item.length, + roofHajebichi: item.hajebichi === null || item.hajebichi === undefined ? 0 : item.hajebichi, + roofGap: item.raft === null || item.raft === undefined ? 'HEI_455' : item.raft, + roofLayout: item.layout === null || item.layout === undefined ? 'P' : item.layout, + })), + } + + console.log('🚀 ~ basicSettingSave ~ patternData >>>>>>>>>>>>> :', patternData) + + // HTTP POST 요청 보내기 + await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }) + .then((res) => { + swalFire({ text: getMessage(res.returnMessage) }) + + //Recoil 설정 + // setCanvasSetting({ ...basicSetting }) + fetchBasicSettings() + }) + .catch((error) => { + swalFire({ text: error.message, icon: 'error' }) + }) + } + const onAddRoofMaterial = () => { if (currentRoofList.length >= 4) { swalFire({ type: 'alert', icon: 'error', text: getMessage('지붕재는 4개까지 선택 가능합니다.') }) @@ -104,6 +229,8 @@ export function useRoofAllocationSetting(id) { // 선택한 지붕재로 할당 const handleSave = () => { + basicSettingSave() + // 모두 actualSize 있으면 바로 적용 없으면 actualSize 설정 if (checkInnerLines()) { addPopup(popupId, 1, ) @@ -295,6 +422,67 @@ export function useRoofAllocationSetting(id) { setCurrentRoofList(newRoofList) } + const handleChangeInput = (e, type, index) => { + const value = e.target.value + if (type === 'pitch') { + // type이 pitch인 경우 소수점 1자리까지만 입력 가능 + const reg = /^[0-9]+(\.[0-9]{0,1})?$/ + + if (!reg.test(value)) { + e.target.value = value.substring(0, value.length - 1) + const newRoofList = currentRoofList.map((roof, idx) => { + if (idx === index) { + return { + ...roof, + [type]: currentAngleType === 'slope' ? value.substring(0, value.length - 1) : getChonByDegree(value.substring(0, value.length - 1)), + } + } + return roof + }) + + setCurrentRoofList(newRoofList) + + return + } else { + const newRoofList = currentRoofList.map((roof, idx) => { + if (idx === index) { + return { + ...roof, + [type]: currentAngleType === 'slope' ? value : getChonByDegree(value), + } + } + return roof + }) + + setCurrentRoofList(newRoofList) + } + + return + } + const newRoofList = currentRoofList.map((roof, idx) => { + if (idx === index) { + return { ...roof, [type]: value } + } + return roof + }) + + setCurrentRoofList(newRoofList) + } + + const handleChangePitch = (e, index) => { + const value = e.target.value + const newRoofList = currentRoofList.map((roof, idx) => { + if (idx === index) { + const result = + currentAngleType === 'slope' ? { pitch: value, angle: getDegreeByChon(value) } : { pitch: getChonByDegree(value), angle: value } + return { ...roof, ...result } + } + return roof + }) + + setCurrentRoofList(newRoofList) + } + return { handleSave, onAddRoofMaterial, @@ -313,5 +501,7 @@ export function useRoofAllocationSetting(id) { handleChangeLayout, handleSaveContext, currentRoofList, + handleChangeInput, + handleChangePitch, } } diff --git a/src/hooks/roofcover/useRoofShapePassivitySetting.js b/src/hooks/roofcover/useRoofShapePassivitySetting.js index 7c29dd8d..c51da066 100644 --- a/src/hooks/roofcover/useRoofShapePassivitySetting.js +++ b/src/hooks/roofcover/useRoofShapePassivitySetting.js @@ -159,7 +159,6 @@ export function useRoofShapePassivitySetting(id) { } else if (type === TYPES.GABLE) { attributes = { type: LINE_TYPE.WALLLINE.GABLE, - pitch: currentAngleType === ANGLE_TYPE.SLOPE ? pitchRef.current.value : getChonByDegree(pitchRef.current.value), offset, } } else if (type === TYPES.SHED) { diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js index 82dbf53f..05f9ae43 100644 --- a/src/hooks/roofcover/useRoofShapeSetting.js +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -60,11 +60,11 @@ export function useRoofShapeSetting(id) { useEffect(() => { const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') - if (!outerLineFix || outerLines.length === 0) { - swalFire({ text: '외벽선이 없습니다.' }) - // setShowRoofShapeSettingModal(false) - closePopup(id) - } + // if (!outerLineFix || outerLines.length === 0) { + // swalFire({ text: '외벽선이 없습니다.' }) + // // setShowRoofShapeSettingModal(false) + // closePopup(id) + // } return () => { if (!isFixRef.current) { diff --git a/src/hooks/useContextMenu.js b/src/hooks/useContextMenu.js index 837c489a..3f2db9f0 100644 --- a/src/hooks/useContextMenu.js +++ b/src/hooks/useContextMenu.js @@ -572,6 +572,29 @@ export function useContextMenu() { ], ]) break + case 'adsorptionPoint': + setContextMenu([ + [ + { + id: 'remove', + name: getMessage('contextmenu.remove'), + fn: () => { + canvas.remove(currentObject) + canvas.discardActiveObject() + }, + }, + { + id: 'removeAll', + name: getMessage('contextmenu.remove.all'), + fn: () => { + removeGrid() + removeAdsorptionPoint() + canvas.discardActiveObject() + }, + }, + ], + ]) + break case 'dimensionGroup': setContextMenu([ [ diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index b49d1eca..cd2b662d 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -1,15 +1,23 @@ -import { useEffect, useState } from 'react' +'use client' + +import { useContext, useEffect, useState } from 'react' +import { usePathname, useRouter } from 'next/navigation' + import { useRecoilState } from 'recoil' import { v4 as uuidv4 } from 'uuid' + import { canvasState, currentCanvasPlanState, plansState } from '@/store/canvasAtom' import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' import { useSwal } from '@/hooks/useSwal' +import { useCanvas } from '@/hooks/useCanvas' import { SAVE_KEY } from '@/common/common' import { readImage, removeImage } from '@/lib/fileAction' -import { useCanvas } from '@/hooks/useCanvas' +import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider' + +export function usePlan(params = {}) { + const { floorPlanState } = useContext(FloorPlanContext) -export function usePlan() { const [planNum, setPlanNum] = useState(0) const [selectedPlan, setSelectedPlan] = useState(null) @@ -18,6 +26,9 @@ export function usePlan() { const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [plans, setPlans] = useRecoilState(plansState) // 전체 plan + const router = useRouter() + const pathname = usePathname() + const { swalFire } = useSwal() const { getMessage } = useMessage() const { get, promisePost, promisePut, promiseDel } = useAxios() @@ -192,10 +203,12 @@ export function usePlan() { * 현재 plan의 작업상태를 저장 후 이동 */ const handleCurrentPlan = async (newCurrentId) => { - if (!currentCanvasPlan || currentCanvasPlan.id !== newCurrentId) { - await saveCanvas() - updateCurrentPlan(newCurrentId) + if (pathname === '/floor-plan') { + if (!currentCanvasPlan || currentCanvasPlan.id !== newCurrentId) { + await saveCanvas() + } } + updateCurrentPlan(newCurrentId) } const updateCurrentPlan = (newCurrentId) => { @@ -211,6 +224,11 @@ export function usePlan() { // setBgImage() }, [plans]) + // 현재 plan이 변경될 때 마다 현재 plan의 링크로 이동 + useEffect(() => { + handlePlanMove() + }, [currentCanvasPlan]) + const setBgImage = () => { // readImage(selectedPlan?.id) } @@ -296,6 +314,13 @@ export function usePlan() { }) } + /** + * 현재 plan 이동 -> 새로운 링크로 이동 + */ + const handlePlanMove = () => { + router.push(`${pathname}?objectNo=${floorPlanState.objectNo}&pid=${currentCanvasPlan?.ordering}`) + } + return { canvas, plans, diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index a844dd6b..3a5c88f5 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -268,7 +268,7 @@ export const usePolygon = () => { surfaceCompass: polygon.surfaceCompass, moduleCompass: polygon.moduleCompass, visible: isFlowDisplay, - pitch: polygon.pitch, + pitch: polygon.roofMaterial.pitch ?? 4, parentId: polygon.id, }) diff --git a/src/locales/ja.json b/src/locales/ja.json index a4d8c6ad..74d13d6b 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -129,6 +129,7 @@ "modal.circuit.trestle.setting": "回路と架台設定", "modal.circuit.trestle.setting.alloc.trestle": "仮割り当て", "modal.circuit.trestle.setting.power.conditional.select": "パワーコンディショナーを選択", + "modal.circuit.trestle.setting.power.conditional.select.cold.region": "寒冷地仕様", "modal.circuit.trestle.setting.power.conditional.select.name": "名称", "modal.circuit.trestle.setting.power.conditional.select.rated.output": "定格出力", "modal.circuit.trestle.setting.power.conditional.select.circuit.amount": "回路数", @@ -475,6 +476,7 @@ "common.message.pleaseSelect": "{0}を選択してください", "common.message.pleaseInput": "{0}を入力してください。", "common.message.pleaseInputOr": "{0}または{1}を入力してください。", + "common.message.please.input.over": "{0} 이상 값을 입력해주세요.(JA)", "common.message.approved ": "承認済み", "common.message.errorFieldExist": "エラー項目が存在します", "common.message.storeIdExist ": "既に利用されている販売店IDです", @@ -499,6 +501,8 @@ "commons.east": "ドン", "commons.south": "南", "commons.north": "北", + "commons.none": "선택안함(JA)", + "common.type": "分類", "font.style.normal": "보통(JA)", "font.style.italic": "기울임꼴(JA)", "font.style.bold": "굵게(JA)", @@ -685,6 +689,8 @@ "stuff.detail.save.valierror1": "垂直説説は0より大きい値を入力してください", "stuff.detail.save.valierror2": "設置高さ0より大きい値を入力してください", "stuff.detail.save.valierror3": "{0} 必須入力項目です.", + "stuff.detail.save.valierror4": "二次販売店名は必須オプションです.", + "stuff.detail.move.confirmMsg": "商品情報画面に移動します。 [保存]していない図面情報は削除されます。商品情報画面に移動しますか?", "stuff.planReqPopup.popTitle": "設計依頼検索", "stuff.planReqPopup.btn1": "検索", "stuff.planReqPopup.btn2": "初期化", @@ -724,6 +730,11 @@ "stuff.search.period": "期間検索", "stuff.search.schDateTypeU": "更新日", "stuff.search.schDateTypeR": "登録日", + "stuff.search.schTempFlgT": "一時保存物", + "stuff.search.schTempFlg": "含む", + "stuff.search.schTempFlg0": "除外", + "stuff.search.schTempFlg1": "一時的なものだけを見る", + "stuff.search.schMine": "私のものを見る", "stuff.search.grid.title": "商品リスト", "stuff.search.grid.all": "全体", "stuff.search.grid.selected": "選択", @@ -820,6 +831,7 @@ "main.popup.login.btn2": "変更しない", "main.popup.login.validate1": "入力したパスワードが異なります。", "main.popup.login.validate2": "半角10文字以内で入力してください。", + "main.popup.login.validate3": "비밀번호를 입력해주세요.", "main.popup.login.success": "パスワードが変更されました。", "common.canvas.validate.size": "寸法を入力してください.", "surface.shape.validate.size.1to2": "①길이는 ②보다 큰 값을 넣어주세요.", @@ -836,6 +848,7 @@ "estimate.detail.saleStoreId": "一次販売店名", "estimate.detail.estimateDate": "見積日", "estimate.detail.otherSaleStoreId": "二次販売店名", + "estimate.detail.noOtherSaleStoreId": "二次点なし", "estimate.detail.receiveUser": "担当者 ", "estimate.detail.objectName": "案件名", "estimate.detail.objectRemarks": "メモ", @@ -940,6 +953,7 @@ "simulator.table.sub9": "予測発電量 (kWh)", "simulator.notice.sub1": "Hanwha Japan 年間発電量", "simulator.notice.sub2": "シミュレーション案内事項", + "simulator.menu.move.valid1": "見積書を作成した後に、発電シミュレーションの結果を照会することができます。", "master.moduletypeitem.message.error": "지붕재 코드를 입력하세요.", "can.not.move.module": "모듈을 이동할 수 없습니다.(JA)", "can.not.copy.module": "모듈을 복사할 수 없습니다.(JA)", diff --git a/src/locales/ko.json b/src/locales/ko.json index 71e7943f..7a86f924 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -133,6 +133,7 @@ "modal.circuit.trestle.setting": "회로 및 가대설정", "modal.circuit.trestle.setting.alloc.trestle": "가대할당", "modal.circuit.trestle.setting.power.conditional.select": "파워컨디셔너 선택", + "modal.circuit.trestle.setting.power.conditional.select.cold.region": "한랭지사양", "modal.circuit.trestle.setting.power.conditional.select.name": "명칭", "modal.circuit.trestle.setting.power.conditional.select.rated.output": "정격출력", "modal.circuit.trestle.setting.power.conditional.select.circuit.amount": "회로수", @@ -484,6 +485,7 @@ "common.message.pleaseSelect": "Please Select {0}", "common.message.pleaseInput": "Please Input a {0}.", "common.message.pleaseInputOr": "Please Input a {0} or {1}.", + "common.message.please.input.over": "{0} 이상 값을 입력해주세요.", "common.message.approved ": "Approved.", "common.message.errorFieldExist": "Error Field Exist", "common.message.storeIdExist ": "이미 사용하고 있는 판매점 ID 입니다.", @@ -509,6 +511,7 @@ "commons.south": "남", "commons.north": "북", "commons.none": "선택안함", + "common.type": "분류", "font.style.normal": "보통", "font.style.italic": "기울임꼴", "font.style.bold": "굵게", @@ -695,7 +698,9 @@ "stuff.detail.save.valierror1": "수직적설량은 0보다 큰 값을 입력하세요", "stuff.detail.save.valierror2": "설치높이는 0보다 큰 값을 입력하세요", "stuff.detail.save.valierror3": "{0} 필수 입력 항목입니다.", - "stuff.planReqPopup.popTitle": "설계 요청 검색", + "stuff.detail.save.valierror4": "2차 판매점명은 필수 선택사항입니다.", + "stuff.detail.move.confirmMsg": "물건정보 화면으로 이동합니다. [저장]하지 않은 도면정보는 삭제됩니다. 물건정보 화면으로 이동하시겠습니까?", + "stuff.planReqPopup.popTitle": "설계 의뢰 검색", "stuff.planReqPopup.btn1": "검색", "stuff.planReqPopup.btn2": "초기화", "stuff.planReqPopup.btn3": "닫기", @@ -734,6 +739,11 @@ "stuff.search.period": "기간검색", "stuff.search.schDateTypeU": "갱신일", "stuff.search.schDateTypeR": "등록일", + "stuff.search.schTempFlgT": "임시저장 물건", + "stuff.search.schTempFlg": "포함", + "stuff.search.schTempFlg0": "제외", + "stuff.search.schTempFlg1": "임시물건만 조회", + "stuff.search.schMine": "내물건보기", "stuff.search.grid.title": "물건목록", "stuff.search.grid.all": "전체", "stuff.search.grid.selected": "선택", @@ -830,6 +840,7 @@ "main.popup.login.btn2": "변경안함", "main.popup.login.validate1": "입력한 패스워드가 다릅니다.", "main.popup.login.validate2": "반각 10자 이내로 입력해주세요.", + "main.popup.login.validate3": "비밀번호를 입력해주세요.", "main.popup.login.success": "비밀번호가 변경되었습니다.", "common.canvas.validate.size": "사이즈를 입력해 주세요.", "surface.shape.validate.size.1to2": "①길이는 ②보다 큰 값을 넣어주세요.", @@ -846,6 +857,7 @@ "estimate.detail.saleStoreId": "1차 판매점명", "estimate.detail.estimateDate": "견적일", "estimate.detail.otherSaleStoreId": "2차 판매점명", + "estimate.detail.noOtherSaleStoreId": "2차점 없음", "estimate.detail.receiveUser": "담당자", "estimate.detail.objectName": "안건명", "estimate.detail.objectRemarks": "메모", @@ -950,10 +962,18 @@ "simulator.table.sub9": "예측발전량 (kWh)", "simulator.notice.sub1": "Hanwha Japan 연간 발전량", "simulator.notice.sub2": "시뮬레이션 안내사항", + "simulator.menu.move.valid1": "견적서를 생성한 후에, 발전시뮬레이션 결과를 조회할 수 있습니다.", "master.moduletypeitem.message.error": "지붕재 코드를 입력하세요.", "can.not.move.module": "모듈을 이동할 수 없습니다.", "can.not.copy.module": "모듈을 복사할 수 없습니다.", "can.not.remove.module": "모듈을 삭제할 수 없습니다.", "can.not.insert.module": "모듈을 삽입할 수 없습니다.", - "can.not.align.module": "모듈을 정렬할 수 없습니다." + "selectbox.title": "선택하세요.", + "can.not.align.module": "모듈을 정렬할 수 없습니다.", + "module.place.overobject": "오브젝트 위에 모듈을 설치 할 수 없습니다.", + "module.place.overlab": "모듈을 겹쳐서 설치 할 수 없습니다.", + "module.place.out": "설치면 밖으로 모듈을 설치 할 수 없습니다.", + "module.place.no.surface": "선택된 모듈 설치면이 없습니다.", + "module.place.select.module": "모듈을 선택해주세요.", + "module.place.select.one.module": "모듈은 하나만 선택해주세요." } diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index 89f7e14d..3b49c782 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -373,3 +373,9 @@ export const moduleIsSetupState = atom({ default: [], dangerouslyAllowMutability: true, }) + +export const checkedModuleState = atom({ + key: 'checkedModuleState', + default: [], + dangerouslyAllowMutability: true, +}) diff --git a/src/store/selectedModuleOptions.js b/src/store/selectedModuleOptions.js new file mode 100644 index 00000000..faa979fd --- /dev/null +++ b/src/store/selectedModuleOptions.js @@ -0,0 +1,87 @@ +import { atom } from 'recoil' + +export const selectedModuleState = atom({ + key: 'selectedModuleState', + default: [], + dangerouslyAllowMutability: true, +}) + +export const selectedModuleOptionsState = atom({ + key: 'selectedModuleOptionsState', + default: { + module: {}, + roofMaterials: [ + { + surfaceType: '', //면조도 + installHeight: '', //설치 노 ㅍ이 + standardWindSpeedId: '', //기준풍속 + verticalSnowCover: '', //수직적설량 + moduleTpCd: '', + roofMatlCd: '', + raftBaseCd: '', + trestleMkrCd: '', + constMthdCd: '', + roofBaseCd: '', + }, + ], + }, + dangerouslyAllowMutability: true, +}) + +export const moduleSelectionOptionParamsState = atom({ + key: 'moduleSelectionOptionParams', + default: { + moduleTpCd: '', + roofMatlCd: '', + raftBaseCd: '', + trestleMkrCd: '', + constMthdCd: '', + roofBaseCd: '', + illuminationTp: '', + instHt: '', + stdWindSpeed: '', + stdSnowLd: '', + inclCd: '', + roofMatlCd: '', + }, + dangerouslyAllowMutability: true, +}) + +export const selectedConstructionListDataState = atom({ + key: 'selectedConstructionListDataState', + default: [], + dangerouslyAllowMutability: true, +}) + +export const trestleListState = atom({ + key: 'trestleListState', + default: [], + dangerouslyAllowMutability: true, +}) + +export const constMthdListState = atom({ + key: 'constMthdListState', + default: [], + dangerouslyAllowMutability: true, +}) + +export const roofBaseListState = atom({ + key: 'roofBaseListState', + default: [], + dangerouslyAllowMutability: true, +}) + +export const moduleSelectionInitParamsState = atom({ + key: 'moduleSelectionInitParamsState', + default: {}, + dangerouslyAllowMutability: true, +}) + +export const moduleSelectionDataState = atom({ + key: 'moduleSelectionDataState', + default: { + common: {}, + roofConstructions: [], + }, + dangerouslyAllowMutability: true, +}) diff --git a/src/store/stuffAtom.js b/src/store/stuffAtom.js index d30baab7..ed48ef99 100644 --- a/src/store/stuffAtom.js +++ b/src/store/stuffAtom.js @@ -20,6 +20,8 @@ export const stuffSearchState = atom({ schSortType: 'U', //정렬조건 (R:최근등록일 U:최근수정일) pageNo: 1, pageSize: 100, + schTempFlg: '', //임시저장여부 + schMyDataCheck: false, //내데이터만 보기 }, dangerouslyAllowMutability: true, }) diff --git a/src/styles/_contents.scss b/src/styles/_contents.scss index e9d41117..1a13f77e 100644 --- a/src/styles/_contents.scss +++ b/src/styles/_contents.scss @@ -17,1563 +17,1525 @@ // } // } // CanvasMenu -.canvas-menu-wrap { - position: fixed; - top: 46px; - left: 0; - display: block; - width: 100%; - min-width: 1280px; - padding-bottom: 0; - background-color: #383838; - transition: padding 0.17s ease-in-out; - z-index: 999; - .canvas-menu-inner { - position: relative; - display: flex; - align-items: center; - padding: 0 40px 0 20px; - background-color: #2c2c2c; - height: 46.8px; - 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 0.17s ease-in-out; - .menu-icon { - display: block; - width: 14px; - height: 14px; - background-repeat: no-repeat; - background-position: center; - background-size: contain; - 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: 0 5px; - height: 30px; - > 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 0.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); - } - &.btn10 { - background-image: url(../../public/static/images/canvas/side_icon10.svg); - background-size: 15px 14px; - } - &: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); - } - &.ico05 { - background-image: url(../../public/static/images/canvas/ico-flx05.svg); - } - } - .name { - font-size: 12px; - color: #fff; - } - } - &.form06 { - .name { - font-size: 13px; - } - } - } - .vertical-horizontal { - display: flex; - min-width: 170px; - height: 28px; - margin-right: 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 0.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; - cursor: pointer; - } - .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%; +.canvas-menu-wrap{ + position: fixed; + top: 46px; left: 0; - background-color: #383838; + display: block; width: 100%; - height: 50px; - transition: all 0.17s ease-in-out; - .canvas-depth2-inner { - display: flex; - align-items: center; - padding: 0 40px; - height: 100%; - .canvas-depth2-list { + min-width: 1280px; + padding-bottom: 0; + background-color: #383838; + transition: padding .17s ease-in-out; + z-index: 999; + .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; + height: 46.8px; + 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: 14px; + height: 14px; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + 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 0.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: 0 5px; + height: 30px; + > 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);} + &.btn10{background-image: url(../../public/static/images/canvas/side_icon10.svg); background-size: 15px 14px;} + &: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);} + &.ico05{background-image: url(../../public/static/images/canvas/ico-flx05.svg);} + } + .name{ + font-size: 12px; + color: #fff; + } + } + &.form06{ + .name{ + font-size: 13px; + } + } + } + .vertical-horizontal{ + display: flex; + min-width: 170px; + height: 28px; + margin-right: 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; + cursor: pointer; + } + .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-content { - padding-top: 46.8px; - transition: all 0.17s ease-in-out; - .canvas-frame { - height: calc(100vh - 129.3px); - } - &.active { - padding-top: calc(46.8px + 50px); - .canvas-frame { - height: calc(100vh - 179.4px); +.canvas-content{ + padding-top: 46.8px; + transition: all .17s ease-in-out; + .canvas-frame{ + height: calc(100vh - 129.3px); + } + &.active{ + padding-top: calc(46.8px + 50px); + .canvas-frame{ + height: calc(100vh - 179.4px); + } } - } } -.canvas-layout { - padding-top: 37px; - .canvas-page-list { - position: fixed; - top: 92.8px; - left: 0; - display: flex; - background-color: #1c1c1c; - border-top: 1px solid #000; - width: 100%; - min-width: 1280px; - transition: all 0.17s ease-in-out; - z-index: 99; - &.active { - top: calc(92.8px + 50px); - } - .canvas-plane-wrap { - display: flex; - align-items: center; - max-width: calc(100% - 45px); - .canvas-page-box { +.canvas-layout{ + padding-top: 37px; + .canvas-page-list{ + position: fixed; + top: 92.8px; + left: 0; display: flex; - align-items: center; - background-color: #1c1c1c; - padding: 9.6px 20px; - border-right: 1px solid #000; - min-width: 0; - transition: all 0.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%; + min-width: 1280px; + transition: all .17s ease-in-out; + z-index: 99; + &.active{ + top: calc(92.8px + 50px); } - .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; + .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; + } + } } - &.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; - } + .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; + } } - &: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 0.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: #f4f4f7; - overflow: auto; - transition: all 0.17s ease-in-out; - // &::-webkit-scrollbar { - // width: 10px; - // height: 10px; - // background-color: #fff; - // } - // &::-webkit-scrollbar-thumb { - // background-color: #C1CCD7; - // border-radius: 30px; - // } - // &::-webkit-scrollbar-track { - // background-color: #fff; - // } - .canvas-container { - margin: 0 auto; - 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: #F4F4F7; + overflow: auto; + transition: all .17s ease-in-out; + // &::-webkit-scrollbar { + // width: 10px; + // height: 10px; + // background-color: #fff; + // } + // &::-webkit-scrollbar-thumb { + // background-color: #C1CCD7; + // border-radius: 30px; + // } + // &::-webkit-scrollbar-track { + // background-color: #fff; + // } + .canvas-container{ + margin: 0 auto; + 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%; - min-width: 1280px; - 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%; + min-width: 1280px; + 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: 1760px; - margin: 0 auto; - padding: 20px 20px 0; - .sub-content-box { - margin-bottom: 20px; - &:last-child { - margin-bottom: 0; - } +.sub-content{ + padding-top: 46px; + .sub-content-inner{ + max-width: 1760px; + margin: 0 auto; + padding: 20px 20px 0; + .sub-content-box{ + margin-bottom: 20px; + &:last-child{ + margin-bottom: 0; + } + } } - } - &.estimate { - display: flex; - flex-direction: column; - padding-top: 0; - .sub-content-inner { - flex: 1; - width: 100%; + &.estimate{ + display: flex; + flex-direction: column; + 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; - &.product { - margin-right: 10px; - } - } - .product_tit { - position: relative; - font-size: 15px; - font-weight: 600; - color: #1083e3; - padding-left: 10px; - &::before { - content: ''; - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); - width: 1px; - height: 11px; - background-color: #d9d9d9; - } - } - .option { - padding-left: 5px; - font-size: 13px; - color: #101010; - font-weight: 400; - } - .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; + &.product{ + margin-right: 10px; + } } - } - &: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; + .estimate-check-btn{ + position: relative; + display: flex; + align-items: center; + padding-left: 10px; + &::before{ + content: ''; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + width: 1px; + height: 11px; + background-color: #D9D9D9; + } + } + .product_tit{ + position: relative; + font-size: 15px; + font-weight: 600; + color: #1083E3; + padding-left: 10px; + &::before{ + content: ''; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + width: 1px; + height: 11px; + background-color: #D9D9D9; + } + } + .option{ + padding-left: 5px; + font-size: 13px; + color: #101010; + font-weight: 400; + } + .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-title-wrap { - display: flex; - align-items: center; - margin-bottom: 15px; - .promise-gudie { - margin-bottom: 0; + .left-unit-box{ + margin-left: auto; + display: flex; + align-items: center; + } + .promise-title-wrap{ + display: flex; + align-items: center; + margin-bottom: 15px; + .promise-gudie{ + margin-bottom: 0; + } + } + .promise-gudie{ + display: block; + font-size: 13px; + font-weight: 700; + color: #101010; + margin-bottom: 20px; + } + .important{ + color: #f00; + } + .sub-center-footer{ + display: flex; + align-items: center; + justify-content: center; + margin-top: 20px; + } + .sub-right-footer{ + display: flex; + align-items: center; + justify-content: flex-end; + margin-top: 20px; } - } - .promise-gudie { - display: block; - font-size: 13px; - font-weight: 700; - color: #101010; - margin-bottom: 20px; - } - .important { - color: #f00; - } - .sub-center-footer { - display: flex; - align-items: center; - justify-content: center; - margin-top: 20px; - } - .sub-right-footer { - display: flex; - align-items: center; - justify-content: flex-end; - margin-top: 20px; - } } -.pagination-wrap { - margin-top: 24px; +.pagination-wrap{ + margin-top: 24px; } -.infomation-wrap { - margin-bottom: 30px; +.infomation-wrap{ + margin-bottom: 30px; } -.infomation-box-wrap { - display: flex; - 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; + 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; - &.one { - .estimate-box { - &:last-child { - flex: 1; - min-width: unset; - } - } - } - .estimate-box { - flex: 1; +.estimate-list-wrap{ display: flex; align-items: center; - &:last-child { - flex: none; - min-width: 220px; + margin-bottom: 10px; + &.one{ + .estimate-box{ + &:last-child{ + flex: 1; + min-width: unset; + } + } } - .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-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; + &.blue{ + font-size: 16px; + font-weight: 700; + color: #1083E3; + } + &.red{ + font-size: 16px; + font-weight: 700; + color: #D72A2A; + } + } } - .estimate-name { - font-size: 13px; - color: #344356; - margin-left: 14px; - font-weight: 400; - &.blue { - font-size: 16px; - font-weight: 700; - color: #1083e3; - } - &.red { - font-size: 16px; - font-weight: 700; - color: #d72a2a; - } + &:last-child{ + margin-bottom: 0; } - } - &:last-child { - margin-bottom: 0; - } } // file drag box -.drag-file-box { - padding: 10px; - .btn-area { - padding-bottom: 15px; - border-bottom: 1px solid #ecf0f4; - .file-upload { - display: inline-block; - height: 30px; - background-color: #94a0ad; - padding: 0 10px; - border-radius: 2px; - font-size: 13px; - line-height: 30px; - color: #fff; - font-weight: 500; - cursor: pointer; - transition: background 0.15s ease-in-out; - &:hover { - background-color: #607f9a; - } +.drag-file-box{ + padding: 10px; + .btn-area{ + padding-bottom: 15px; + border-bottom: 1px solid #ECF0F4; + .file-upload{ + display: inline-block; + height: 30px; + background-color: #94A0AD; + padding: 0 10px; + border-radius: 2px; + font-size: 13px; + line-height: 30px; + color: #fff; + font-weight: 500; + cursor: pointer; + transition: background .15s ease-in-out; + &:hover{ + background-color: #607F9A; + } + } } - } - .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 { - min-height: 52px; - .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; - cursor: pointer; - 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{ + min-height: 52px; + .file-item{ + margin-bottom: 15px; + span{ + position: relative; + font-size: 13px; + color: #45576F; + font-weight: 400; + white-space: nowrap; + padding-right: 55px; + cursor: pointer; + 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; + } + .file-item-wrap{ + display: flex; + align-items: center; + gap: 30px; + .return-wrap{ + display: flex; + align-items: center; + } + .return{ + padding: 0; + font-size: 13px; + color: #B0BCCD; + text-decoration: line-through; + } + .return-btn{ + flex: none; + position: relative; + top: 0; + left: 0; + transform: none; + display: flex; + align-items: center; + height: 24px; + padding: 0 9px; + margin-left: 10px; + background: none; + border: 1px solid #B0BCCD; + border-radius: 2px; + font-size: 12px; + color: #B0BCCD; + font-weight: 500; + .return-ico{ + display: block; + width: 14px; + height: 14px; + background: url(../../public/static/images/canvas/return-btn.svg)no-repeat center; + background-size: contain; + margin-right: 5px; + } + } + } } - } - &:last-child { - margin-bottom: 0; - } - .file-item-wrap { - display: flex; - align-items: center; - gap: 30px; - .return-wrap { - display: flex; - align-items: center; - } - .return { - padding: 0; - font-size: 13px; - color: #b0bccd; - text-decoration: line-through; - } - .return-btn { - flex: none; - position: relative; - top: 0; - left: 0; - transform: none; - display: flex; - align-items: center; - height: 24px; - padding: 0 9px; - margin-left: 10px; - background: none; - border: 1px solid #b0bccd; - border-radius: 2px; - font-size: 12px; - color: #b0bccd; - font-weight: 500; - .return-ico { - display: block; - width: 14px; - height: 14px; - background: url(../../public/static/images/canvas/return-btn.svg) no-repeat center; - background-size: contain; - margin-right: 5px; - } - } - } } - } } -.estimate-arr-btn { - display: block; - width: 20px; - height: 20px; - background-color: #94a0ad; - border: 1px solid #94a0ad; - background-position: center; - background-repeat: no-repeat; - background-image: url(../../public/static/images/canvas/estiment_arr.svg); - background-size: 11px 7px; - border-radius: 2px; - &.up { - rotate: 180deg; - } - &.on { - background-color: #fff; - border-color: #c2d0dd; - background-image: url(../../public/static/images/canvas/estiment_arr_color.svg); - } -} -.estimate-check-wrap { - .estimate-check-inner { +.estimate-arr-btn{ display: block; - } - &.hide { - border-bottom: 1px solid #ecf0f4; - margin-bottom: 15px; - .estimate-check-inner { - display: none; + width: 20px; + height: 20px; + background-color: #94A0AD; + border: 1px solid #94A0AD; + background-position: center; + background-repeat: no-repeat; + background-image: url(../../public/static/images/canvas/estiment_arr.svg); + background-size: 11px 7px; + border-radius: 2px; + &.up{ + rotate: 180deg; + } + &.on{ + background-color: #fff; + border-color: #C2D0DD; + background-image: url(../../public/static/images/canvas/estiment_arr_color.svg) } - } } - -.special-note-check-wrap { - display: grid; - grid-template-columns: repeat(5, 1fr); - border-radius: 3px; - margin-bottom: 30px; - .special-note-check-item { - padding: 14px 10px; - border: 1px solid #ecf0f4; - margin-top: -1px; - margin-right: -1px; - &.act { - background-color: #f7f9fa; +.estimate-check-wrap{ + .estimate-check-inner{ + display: block; } - .special-note-check-box { - display: flex; - align-items: center; - .check-name { - font-size: 13px; - color: #45576f; - cursor: pointer; - line-height: 1.3; - } - } - } -} - -.calculation-estimate { - border: 1px solid #ecf0f4; - border-radius: 3px; - padding: 24px; - height: 350px; - overflow-y: auto; - margin-bottom: 30px; - dl { - margin-bottom: 35px; - &:last-child { - margin-bottom: 0; - } - dt { - font-size: 13px; - font-weight: 600; - color: #1083e3; - margin-bottom: 15px; - } - dd { - font-size: 12px; - font-weight: 400; - color: #45576f; - margin-bottom: 8px; - &:last-child { - margin-bottom: 0; - } - } - } - &::-webkit-scrollbar { - width: 4px; - background-color: transparent; - } - &::-webkit-scrollbar-thumb { - background-color: #d9dee2; - } - &::-webkit-scrollbar-track { - background-color: transparent; - } -} -.esimate-wrap { - margin-bottom: 20px; -} - -.estimate-product-option { - display: flex; - align-items: center; - margin-bottom: 15px; - .product-price-wrap { - display: flex; - align-items: center; - .product-price-tit { - font-size: 13px; - font-weight: 400; - color: #45576f; - margin-right: 10px; - } - .select-wrap { - width: 110px; - } - } - .product-edit-wrap { - display: flex; - align-items: center; - margin-left: auto; - .product-edit-explane { - display: flex; - align-items: center; - margin-right: 15px; - .explane-item { - position: relative; - display: flex; - align-items: center; - padding: 0 10px; - font-size: 12px; - font-weight: 400; - span { - width: 20px; - height: 20px; - margin-right: 5px; - background-size: cover; - background-repeat: no-repeat; - background-position: center; - } - &:before { - content: ''; - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); - width: 1px; - height: 12px; - background-color: #d9d9d9; - } - &:first-child { - padding-left: 0; - &::before { + &.hide{ + border-bottom: 1px solid #ECF0F4; + margin-bottom: 15px; + .estimate-check-inner{ display: none; - } } - &:last-child { - padding-right: 0; - } - &.item01 { - color: #3bbb48; - span { - background-image: url(../../public/static/images/sub/open_ico.svg); - } - } - &.item02 { - color: #909000; - span { - background-image: url(../../public/static/images/sub/change_ico.svg); - } - } - &.item03 { - color: #0191c9; - span { - background-image: url(../../public/static/images/sub/attachment_ico.svg); - } - } - &.item04 { - color: #f16a6a; - span { - background-image: url(../../public/static/images/sub/click_check_ico.svg); - } - } - } } - .product-edit-btn { - display: flex; - align-items: center; - button { +} + +.special-note-check-wrap{ + display: grid; + grid-template-columns: repeat(5, 1fr); + border-radius: 3px; + margin-bottom: 30px; + .special-note-check-item{ + padding: 14px 10px; + border: 1px solid #ECF0F4; + margin-top: -1px; + margin-right: -1px; + &.act{ + background-color: #F7F9FA; + } + .special-note-check-box{ + display: flex; + align-items: center; + .check-name{ + font-size: 13px; + color: #45576F; + cursor: pointer; + line-height: 1.3; + } + } + } +} + +.calculation-estimate{ + border: 1px solid #ECF0F4; + border-radius: 3px; + padding: 24px; + height: 170px; + overflow-y: auto; + margin-bottom: 30px; + dl{ + margin-bottom: 35px; + &:last-child{ + margin-bottom: 0; + } + dt{ + font-size: 13px; + font-weight: 600; + color: #1083E3; + margin-bottom: 15px; + } + dd{ + font-size: 12px; + font-weight: 400; + color: #45576F; + margin-bottom: 8px; + &:last-child{ + margin-bottom: 0; + } + } + } + &::-webkit-scrollbar { + width: 4px; + background-color: transparent; + } + &::-webkit-scrollbar-thumb { + background-color: #d9dee2; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } +} +.esimate-wrap{ + margin-bottom: 20px; +} + +.estimate-product-option{ + display: flex; + align-items: center; + margin-bottom: 15px; + .product-price-wrap{ display: flex; align-items: center; - span { - width: 13px; - height: 13px; - margin-right: 5px; - background-size: cover; - &.plus { - background: url(../../public/static/images/sub/plus_btn.svg) no-repeat center; - } - &.minus { - background: url(../../public/static/images/sub/minus_btn.svg) no-repeat center; - } + .product-price-tit{ + font-size: 13px; + font-weight: 400; + color: #45576F; + margin-right: 10px; + } + .select-wrap{ + width: 150px; + } + } + .product-edit-wrap{ + display: flex; + align-items: center; + margin-left: auto; + .product-edit-explane{ + display: flex; + align-items: center; + margin-right: 15px; + .explane-item{ + position: relative; + display: flex; + align-items: center; + padding: 0 10px; + font-size: 12px; + font-weight: 400; + span{ + width: 20px; + height: 20px; + margin-right: 5px; + background-size: cover; + background-repeat: no-repeat; + background-position: center; + } + &:before{ + content: ''; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + width: 1px; + height: 12px; + background-color: #D9D9D9; + } + &:first-child{ + padding-left: 0; + &::before{ + display: none; + } + } + &:last-child{ + padding-right: 0; + } + &.item01{ + color: #3BBB48; + span{ + background-image: url(../../public/static/images/sub/open_ico.svg); + } + } + &.item02{ + color: #909000; + span{ + background-image: url(../../public/static/images/sub/change_ico.svg); + } + } + &.item03{ + color: #0191C9; + span{ + background-image: url(../../public/static/images/sub/attachment_ico.svg); + } + } + &.item04{ + color: #F16A6A; + span{ + background-image: url(../../public/static/images/sub/click_check_ico.svg); + } + } + } + } + .product-edit-btn{ + display: flex; + align-items: center; + button{ + display: flex; + align-items: center; + span{ + width: 13px; + height: 13px; + margin-right: 5px; + background-size: cover; + &.plus{ + background: url(../../public/static/images/sub/plus_btn.svg)no-repeat center; + } + &.minus{ + background: url(../../public/static/images/sub/minus_btn.svg)no-repeat center; + } + } + } } - } } - } } // 발전시물레이션 -.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; - border: 1px solid #ecf0f4; - border-radius: 4px; - thead { - th { - padding: 4.5px 0; - border-bottom: 1px solid #ecf0f4; +.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{ + flex: none; + 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{ + flex: 1; + 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; + } + } + ul, ol{ + list-style: unset; + } + } +} + +.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: #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 { - flex: none; - 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 { - flex: 1; - 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; - } - } - ul, - ol { - list-style: unset; - } - } -} - -.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; - } } // 물건상세 -.information-help-wrap { - display: flex; - padding: 24px; - background-color: #f4f4f4; - border-radius: 4px; - margin-bottom: 15px; - .information-help-tit-wrap { - position: relative; +.information-help-wrap{ display: flex; - align-items: center; - padding-right: 40px; - border-right: 1px solid #e0e0e3; - .help-tit-icon { - width: 40px; - height: 40px; - border-radius: 50%; - margin-right: 10px; - background: #fff url(../../public/static/images/sub/information_help.svg) no-repeat center; - background-size: 20px 20px; + padding: 24px; + background-color: #F4F4F4; + border-radius: 4px; + margin-bottom: 15px; + .information-help-tit-wrap{ + position: relative; + display: flex; + align-items: center; + padding-right: 40px; + border-right: 1px solid #E0E0E3; + .help-tit-icon{ + width: 40px; + height: 40px; + border-radius: 50%; + margin-right: 10px; + background: #fff url(../../public/static/images/sub/information_help.svg)no-repeat center; + background-size: 20px 20px; + } + .help-tit{ + font-size: 13px; + font-weight: 600; + color: #45576F; + } } - .help-tit { - font-size: 13px; - font-weight: 600; - color: #45576f; + .information-help-guide{ + padding-left: 40px; + span{ + display: block; + font-size: 12px; + font-weight: 400; + color: #45576F; + margin-bottom: 7px; + &:last-child{ + margin-bottom: 0; + } + } } - } - .information-help-guide { - padding-left: 40px; - span { - display: block; - font-size: 12px; - font-weight: 400; - color: #45576f; - margin-bottom: 7px; - &:last-child { - margin-bottom: 0; - } - } - } } -.community-search-warp { - display: flex; - flex-direction: column; - align-items: center; - padding: 10px 0 30px 0; - border-bottom: 1px solid #e5e5e5; - margin-bottom: 24px; - .community-search-box { - position: relative; +.community-search-warp{ display: flex; + flex-direction: column; align-items: center; - width: 580px; - height: 45px; - padding: 0 45px 0 20px; - margin-bottom: 20px; - border-radius: 2px; - border: 1px solid #101010; - .community-input { - width: 100%; - height: 100%; - font-size: 13px; - font-weight: 400; - color: #101010; - &::placeholder { - color: #c8c8c8; - } + padding: 10px 0 30px 0; + border-bottom: 1px solid #E5E5E5; + margin-bottom: 24px; + .community-search-box{ + position: relative; + display: flex; + align-items: center; + width: 580px; + height: 45px; + padding: 0 45px 0 20px; + margin-bottom: 20px; + border-radius: 2px; + border: 1px solid #101010; + .community-input{ + width: 100%; + height: 100%; + font-size: 13px; + font-weight: 400; + color: #101010; + &::placeholder{ + color: #C8C8C8; + } + } + .community-search-ico{ + position: absolute; + top: 50%; + right: 20px; + transform: translateY(-50%); + flex: none; + width: 21px; + height: 100%; + background: url(../../public/static/images/sub/community_search.svg)no-repeat center; + background-size: 21px 21px; + z-index: 3; + } } - .community-search-ico { - position: absolute; - top: 50%; - right: 20px; - transform: translateY(-50%); - flex: none; - width: 21px; - height: 100%; - background: url(../../public/static/images/sub/community_search.svg) no-repeat center; - background-size: 21px 21px; - z-index: 3; + .community-search-keyword{ + font-size: 13px; + font-weight: 400; + color: #45576F; + span{ + font-weight: 600; + color: #F16A6A; + } } - } - .community-search-keyword { - font-size: 13px; - font-weight: 400; - color: #45576f; - span { - font-weight: 600; - color: #f16a6a; - } - } } // 자료 다운로드 -.file-down-list { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 14px; - .file-down-item { - display: flex; - align-items: center; - padding: 24px; - border-radius: 4px; - border: 1px solid #e5e5e5; - background: #fff; - transition: all 0.15s ease-in-out; - .file-item-info { - .item-num { - display: inline-block; - padding: 6px 17.5px; - border-radius: 60px; - background-color: #f4f4f7; - font-size: 13px; - font-weight: 600; - color: #101010; - margin-bottom: 15px; - } - .item-name { - font-size: 16px; - color: #101010; - font-weight: 500; - margin-bottom: 13px; - } - .item-date { - font-size: 13px; - font-weight: 400; - color: #344356; - } +.file-down-list{ + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 14px; + .file-down-item{ + display: flex; + align-items: center; + padding: 24px; + border-radius: 4px; + border: 1px solid #E5E5E5; + background: #FFF; + transition: all .15s ease-in-out; + .file-item-info{ + .item-num{ + display: inline-block; + padding: 6px 17.5px; + border-radius: 60px; + background-color: #F4F4F7; + font-size: 13px; + font-weight: 600; + color: #101010; + margin-bottom: 15px; + } + .item-name{ + font-size: 16px; + color: #101010; + font-weight: 500; + margin-bottom: 13px; + } + .item-date{ + font-size: 13px; + font-weight: 400; + color: #344356; + } + } + .file-down-box{ + display: flex; + align-items: center; + flex: none; + margin-left: auto; + height: 100%; + .file-down-btn{ + width: 36px; + height: 36px; + background: url(../../public/static/images/sub/file_down_btn.svg)no-repeat center; + background-size: cover; + } + } + &:hover{ + background-color: #F4F4F7; + } } - .file-down-box { - display: flex; - align-items: center; - flex: none; - margin-left: auto; - height: 100%; - .file-down-btn { - width: 36px; - height: 36px; - background: url(../../public/static/images/sub/file_down_btn.svg) no-repeat center; - background-size: cover; - } - } - &:hover { - background-color: #f4f4f7; - } - } } -.file-down-nodata { - display: flex; - align-items: center; - justify-content: center; - width: 100%; - height: 148px; - padding: 24px; - border-radius: 4px; - border: 1px solid #e5e5e5; - font-size: 16px; - font-weight: 500; - color: #344356; +.file-down-nodata{ + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 148px; + padding: 24px; + border-radius: 4px; + border: 1px solid #E5E5E5; + font-size: 16px; + font-weight: 500; + color: #344356; } //신규물건 등록 -.product-input-wrap { - display: flex; - align-items: center; - width: 200px; - height: 30px; - background-color: #fafafa; - border: 1px solid #eee; - padding: 0 10px; - input { - font-size: 13px; - font-weight: 400; - color: #999999; - padding: 0; - width: 100%; - height: 100%; - flex: 1; - background-color: inherit; - } - .product-delete { - flex: none; - display: block; - width: 15px; - height: 100%; - background: url(../../public/static/images/sub/product-del.svg) no-repeat center; - background-size: 15px 15px; - } +.product-input-wrap{ + display: flex; + align-items: center; + width: 200px; + height: 30px; + background-color: #FAFAFA; + border: 1px solid #EEE; + padding: 0 10px; + input{ + font-size: 13px; + font-weight: 400; + color: #999999; + padding: 0; + width: 100%; + height: 100%; + flex: 1 ; + background-color: inherit; + } + .product-delete{ + flex: none; + display: block; + width: 15px; + height: 100%; + background: url(../../public/static/images/sub/product-del.svg)no-repeat center; + background-size: 15px 15px; + } } @media screen and (max-width: 1800px) { - .canvas-menu-wrap { - .canvas-menu-inner { - .canvas-menu-list { - .canvas-menu-item button { - .menu-icon { - margin-right: 5px; - } - } - .canvas-menu-item { - button { - padding: 15px 15px; - font-size: 11px; - } - } - } - } - .canvas-depth2-wrap { - .canvas-depth2-inner { - .canvas-depth2-list { - .canvas-depth2-item { - button { - font-size: 11px; + .canvas-menu-wrap{ + .canvas-menu-inner{ + .canvas-menu-list{ + .canvas-menu-item button{ + .menu-icon{ + margin-right: 5px; + } + } + .canvas-menu-item{ + button{ + padding: 15px 15px; + font-size: 11px; + } + } } - } } - } - } - } + .canvas-depth2-wrap{ + .canvas-depth2-inner{ + .canvas-depth2-list{ + .canvas-depth2-item{ + button{ + font-size: 11px; + } + } + } + } + } + } } @media screen and (max-width: 1600px) { - .canvas-menu-wrap { - .canvas-menu-inner { - .canvas-menu-list { - .canvas-menu-item button { - .menu-icon { - display: none; - } + .canvas-menu-wrap{ + .canvas-menu-inner{ + .canvas-menu-list{ + .canvas-menu-item button{ + .menu-icon{ + display: none; + } + } + } } - } - } - } - .canvas-content { - .canvas-frame { - height: calc(100vh - 129.5px); - } - &.active { - .canvas-frame { - height: calc(100vh - 179.5px); - } - } - } + } + .canvas-content{ + .canvas-frame{ + height: calc(100vh - 129.5px); + } + &.active{ + .canvas-frame{ + height: calc(100vh - 179.5px); + } + } + } } @media screen and (max-width: 1500px) { - .canvas-menu-wrap { - .canvas-menu-inner { - .canvas-menu-list { - .canvas-menu-item { - button { - padding: 15px 10px; - font-size: 10px; - } - } - } - .canvas-side-btn-wrap { - .btn-from { - gap: 3px; - } - .vertical-horizontal { - margin-right: 3px; - min-width: 150px; - } - .select-box { - width: 100px; - margin: 0 3px; - } - .size-control { - width: 90px; - margin: 0 3px; - } - } - } - } - .sub-header { - .sub-header-inner { - .sub-header-title { - font-size: 15px; - } - .sub-header-title-wrap { - .title-item { - a { - .icon { - width: 20px; - height: 20px; + .canvas-menu-wrap{ + .canvas-menu-inner{ + .canvas-menu-list{ + .canvas-menu-item{ + button{ + padding: 15px 10px; + font-size: 10px; + } + } } - } + .canvas-side-btn-wrap{ + .btn-from{ + gap: 3px; + } + .vertical-horizontal{ + margin-right: 3px; + min-width: 150px; + } + .select-box{ + width: 100px; + margin: 0 3px; + } + .size-control{ + width: 90px; + margin: 0 3px; + } + } } - } } - } + .sub-header{ + .sub-header-inner{ + .sub-header-title{ + font-size: 15px; + } + .sub-header-title-wrap{ + .title-item{ + a{ + .icon{ + width: 20px; + height: 20px; + } + } + } + } + } + } + } diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss index 296deefe..66519217 100644 --- a/src/styles/_modal.scss +++ b/src/styles/_modal.scss @@ -4,497 +4,477 @@ $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 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 unmountpop{ + from{opacity: 1; scale: 1;} + to{opacity: 0; scale: 0.95;} } -.normal-font { - font-size: 12px; - font-weight: 400; - color: #fff; +.normal-font{ + font-size: 12px; + font-weight: 400; + color: #fff; } -.bold-font { - font-size: 12px; - font-weight: 500; - color: #fff; +.bold-font{ + font-size: 12px; + font-weight: 500; + color: #fff; } -.modal-pop-wrap { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: -webkit-fit-content; - height: -moz-fit-content; - height: fit-content; - border: 1px solid #000; - border-radius: 4px; - background-color: #272727; - z-index: 9999999; - &.xsm { - width: 200px; - } - &.xxxm { - width: 240px; - } - &.xxm { - width: 270px; - } - &.xm { - width: 300px; - } - &.ssm { - width: 380px; - } - &.sm { - width: 580px; - } - &.r { - width: 400px; - } - &.lr { - width: 440px; - } - &.lr-2 { - width: 450px; - } - &.lrr { - width: 480px; - } - &.ml { - width: 530px; - } - &.l-2 { - width: 640px; - } - &.lx-2 { - width: 740px; - } - &.lx { - width: 770px; - } - &.l { - width: 800px; - } - &.ll { - width: 900px; - } - &.mount { - animation: mountpop 0.17s ease-in-out forwards; - } - &.unmount { - animation: unmountpop 0.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-pop-wrap{ + position: fixed; + top: 0; + left: 0; + width: 100%; + height: -webkit-fit-content; + height: -moz-fit-content; + height: fit-content; + border: 1px solid #000; + border-radius: 4px; + background-color: #272727; + z-index: 9999999; + &.xsm{ + width: 200px; } - .modal-body { - background-color: #fff; - padding: 22px; - border-radius: 4px; - border: 1px solid #101010; - color: $alert-color; - .alert-title { + &.xxxm{ + width: 240px; + } + &.xxm{ + width: 270px; + } + &.xm{ + width: 300px; + } + &.ssm{ + width: 380px; + } + &.sm{ + width: 580px; + } + &.r{ + width: 400px; + } + &.lr{ + width: 440px; + } + &.lr-2{ + width: 450px; + } + &.lrr{ + width: 480px; + } + &.ml{ + width: 530px; + } + &.l-2{ + width: 640px; + } + &.lx-2{ + width: 740px; + } + &.lx{ + width: 770px; + } + &.l{ + width: 800px; + } + &.ll{ + width: 900px; + } + &.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; + } + } + } +} +.modal-head{ + display: flex; + align-items: center; + padding: 10px 24px; + background-color: #000; + // overflow: hidden; + h1.title{ font-size: 13px; + color: $pop-color; font-weight: 700; - color: $alert-color; + } + .modal-close{ + margin-left: auto; + color: transparent; + font-size: 0; + 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; + } + &.sub{ + button{ + flex: 1 1 auto; + padding: 0; + } + margin-bottom: 14px; + } + } + .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-head { - display: flex; - align-items: center; - padding: 10px 24px; - background-color: #000; - // overflow: hidden; - h1.title { - font-size: 13px; - color: $pop-color; - font-weight: 700; - } - .modal-close { - margin-left: auto; - color: transparent; - font-size: 0; - 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; - } - &.sub { - button { - flex: 1 1 auto; - padding: 0; - } - margin-bottom: 14px; - } - } - .modal-check-btn-wrap { - margin-top: 15px; - .check-wrap-title { - font-size: $pop-normal-size; - color: $pop-color; - font-weight: 600; - &.light { + .modal-guide{ + display: block; + font-size: $pop-normal-size; + color: $alert-color; 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; - } } -.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 { +.adsorption-point{ 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; + 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 { - display: flex; - align-items: center; - gap: 15px; - padding-bottom: 15px; - &.border { - border-bottom: 1px solid #424242; - } -} -.grid-option-overflow { - max-height: 350px; - overflow-y: auto; - &::-webkit-scrollbar { - width: 4px; - background-color: transparent; - } - &::-webkit-scrollbar-thumb { - background-color: #d9d9d9; - } - &::-webkit-scrollbar-track { - background-color: transparent; - } -} -.grid-option-wrap { - .grid-option-box { +.grid-check-form{ display: flex; align-items: center; - background-color: transparent; - border: 1px solid #3d3d3d; - border-radius: 2px; - padding: 15px 10px; - gap: 20px; - margin-bottom: 10px; - .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%; + gap: 15px; + padding-bottom: 15px; + &.border{ + border-bottom: 1px solid #424242; + } +} +.grid-option-overflow{ + max-height: 350px; + overflow-y: auto; + &::-webkit-scrollbar { + width: 4px; + background-color: transparent; + } + &::-webkit-scrollbar-thumb { + background-color: #D9D9D9; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } +} +.grid-option-wrap{ + .grid-option-box{ + display: flex; + align-items: center; + background-color: transparent; + border: 1px solid #3D3D3D; + border-radius: 2px; + padding: 15px 10px; + gap: 20px; + margin-bottom: 10px; + .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; } - } } - &:last-child { - margin-bottom: 0; + .grid-option-block-form{ + flex: 1; } - } - .grid-option-block-form { +} +.select-form{ + .sort-select{width: 100%;} +} +.grid-select{ flex: 1; - } + &.no-flx{ + flex: unset; + } + .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; + } + } + } } -.select-form { - .sort-select { - width: 100%; - } -} -.grid-select { - flex: 1; - &.no-flx { - flex: unset; - } - .sort-select { - width: 100%; - background-color: #313131; - min-width: auto; - font-size: 12px; - border: none; - p { - font-size: 12px; +.grid-btn-wrap{ + padding-top: 15px; + text-align: right; + button{ + padding: 0 10px; } - > ul { - border: none; - } - } - &.right { - p { - text-align: right; - } - ul { - li { - justify-content: flex-end; - } - } - } -} -.grid-btn-wrap { - padding-top: 15px; - text-align: right; - button { - padding: 0 10px; - } } // grid copy -.grid-option-tit { - font-size: $pop-normal-size; - color: $pop-color; - font-weight: $pop-normal-weight; - padding-bottom: 15px; +.grid-option-tit{ + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-normal-weight; + padding-bottom: 15px; + } -.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 0.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 { - width: 100%; - 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%; - } - } -} -.direction-move-wrap { - flex: none; - display: grid; - grid-template-columns: 1fr 1fr; - gap: 5px; - margin-left: auto; -} - -// 배치면 초기 설정 -.placement-table { - table { - table-layout: fixed; - tr { - th { +.move-form{ + width: 100%; + p{ font-size: $pop-normal-size; color: $pop-color; font-weight: $pop-bold-weight; - padding: 18px 0; - border-bottom: 1px solid #424242; - vertical-align: middle; - .tip-wrap { - display: flex; - align-items: center; - } - } - td { - font-size: $pop-normal-size; + } +} +.input-move-wrap{ + display: flex; + align-items: center; + gap: 5px; + span{ color: $pop-color; - border-bottom: 1px solid #424242; - padding: 18px 0 18px 20px; - vertical-align: middle; - .flex-box { - display: flex; - align-items: center; - } - } - &:first-child { - td, - th { - padding-top: 0; - } - } + font-size: $pop-normal-size; } - } - .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; + .input-move{ + width: 130px; + input{ + width: 100%; + } + } +} +.direction-move-wrap{ + flex: none; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 5px; + margin-left: auto; +} + +// 배치면 초기 설정 +.placement-table{ + table{ + table-layout: fixed; + tr{ + th{ + font-size: $pop-normal-size; + color: $pop-color; + font-weight: $pop-bold-weight; + padding: 18px 0; + border-bottom: 1px solid #424242; + vertical-align: middle; + .tip-wrap{ + display: flex; + align-items: center; + } + } + td{ + font-size: $pop-normal-size; + color: $pop-color; + border-bottom: 1px solid #424242; + padding: 18px 0 18px 20px; + vertical-align: middle; + .flex-box{ + display: flex; + align-items: center; + } + } + &: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; + } + } } - } - &:last-child { - td, - th { - padding-bottom: 0px; - } - } } - } } // 2024-12-11 @@ -505,1732 +485,1583 @@ $alert-color: #101010; // max-width: 250px; // } -.pop-form-radio { - display: flex; - align-items: center; - gap: 10px; -} -.placement-option { - display: flex; - align-items: center; - gap: 20px; -} -.select-wrap { - .sort-select { - 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; - } -} - -.img-edit-wrap { - flex: none; - .img-edit-btn { +.pop-form-radio{ display: flex; align-items: center; - height: 30px; - padding: 0 10px; - font-size: 12px; - font-weight: 400; - color: #101010; - background-color: #fff; - border-radius: 2px; - cursor: pointer; - transition: all 0.15s ease-in-out; - .img-edit { - width: 16px; - height: 16px; - background: url(../../public/static/images/canvas/img_edit_ico.svg) no-repeat center; - background-size: cover; - margin-right: 5px; - } - &:hover { - background-color: #ebebeb; - } - } + gap: 10px; } -.img-name-wrap { - display: flex; - align-items: center; - width: 100%; - margin-left: 10px; - input { - flex: 1; - } - .img-check { - flex: none; - width: 18px; - height: 18px; - margin-left: 5px; - background-repeat: no-repeat; - background-position: center; - background-size: cover; - background-image: url(../../public/static/images/canvas/img_check_fail.svg); - } +.placement-option{ + display: flex; + align-items: center; + gap: 20px; +} +.select-wrap{ + .sort-select{ + 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; + } + } -.for-address { - input { - flex: 1; - } - .check-address { +.img-edit-wrap{ flex: none; - width: 18px; - height: 18px; - margin-left: 5px; - background-repeat: no-repeat; - background-position: center; - background-size: cover; - &.fail { - background-image: url(../../public/static/images/canvas/img_check_fail.svg); + .img-edit-btn{ + display: flex; + align-items: center; + height: 30px; + padding: 0 10px; + font-size: 12px; + font-weight: 400; + color: #101010; + background-color: #fff; + border-radius: 2px; + cursor: pointer; + transition: all .15s ease-in-out; + .img-edit{ + width: 16px; + height: 16px; + background: url(../../public/static/images/canvas/img_edit_ico.svg)no-repeat center; + background-size: cover; + margin-right: 5px; + } + &:hover{ + background-color: #ebebeb; + } } - &.success { - background-image: url(../../public/static/images/canvas/img_check_success.svg); +} +.img-name-wrap{ + display: flex; + align-items: center; + width: 100%; + margin-left: 10px; + input{ + flex: 1; + + } + .img-check{ + flex: none; + width: 18px; + height: 18px; + margin-left: 5px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; + background-image: url(../../public/static/images/canvas/img_check_fail.svg); + } +} + +.for-address{ + input{ + flex: 1; + } + .check-address{ + flex: none; + width: 18px; + height: 18px; + margin-left: 5px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; + &.fail{background-image: url(../../public/static/images/canvas/img_check_fail.svg);} + &.success{background-image: url(../../public/static/images/canvas/img_check_success.svg);} } - } } // 외벽선 그리기 -.outline-wrap { - padding: 24px 0; - border-top: 1px solid #424242; - - .outline-inner { +.outline-wrap{ + padding: 24px 0; + border-top: 1px solid #424242; + + .outline-inner{ + display: flex; + align-items: center; + margin-bottom: 14px; + &:last-child{ + margin-bottom: 0; + } + .outline-form{ + // width: 50%; + margin-right: 15px; + } + } + &:last-child{ + border-bottom: 1px solid #424242; + } +} +.outline-form{ display: flex; align-items: center; - margin-bottom: 14px; - &:last-child { - margin-bottom: 0; + + span{ + width: 60px; + flex: none; + font-size: $pop-normal-size; + font-weight: $pop-bold-weight; + color: $pop-color; + margin-right: 10px; + &.thin{ + width: auto; + font-weight: $pop-normal-weight; + margin-right: 0; + } } - .outline-form { - // width: 50%; - margin-right: 15px; - } - } - &:last-child { - border-bottom: 1px solid #424242; - } -} -.outline-form { - display: flex; - align-items: center; - span { - width: 60px; - flex: none; - font-size: $pop-normal-size; - font-weight: $pop-bold-weight; - color: $pop-color; - margin-right: 10px; - &.thin { - width: auto; - font-weight: $pop-normal-weight; - margin-right: 0; + .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; } - } - - .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 { +.cul-wrap{ display: flex; - align-items: center; - justify-content: center; - width: 50%; - background-color: #3d3d3d; - border-radius: 2px; - } + .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; + 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-guide{ + font-size: $pop-normal-size; + color: #AAA; + font-weight: $pop-normal-weight; + margin-bottom: 14px; } -.setting-tit { - font-size: 13px; - color: $pop-color; - font-weight: $pop-bold-weight; - margin-bottom: 10px; +.setting-tit{ + font-size: 13px; + color: $pop-color; + font-weight: $pop-bold-weight; + margin-bottom: 10px; } -.properties-setting-wrap { - &.outer { - margin-top: 24px; - } - .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 0.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; - } - } +.properties-setting-wrap{ + &.outer{ + margin-top: 24px; + } + .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; + } + } + } } - } } // 지붕형상 설정 -.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 0.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 0.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; -} -.padding-form { - padding-left: 23px; -} -.discrimination-box { - padding: 16px 12px; - border: 1px solid #3d3d3d; - border-radius: 2px; -} - -.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: 10px; - } - .eaves-keraba-ico { - display: flex; - align-items: center; - justify-content: center; - padding: 5px; - background-color: #3d3d3d; - border: 1px solid #3d3d3d; - border-radius: 2px; - cursor: pointer; - &.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; - } - span { - display: block; - } -} - -// 지붕면 할당 -.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 0.15s ease-in-out; - i { - height: 15px; - display: block; - margin-left: 10px; - background-repeat: no-repeat; - background-position: center; - background-size: cover; - transition: all 0.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; -} - -// 면형상 배치 -.plane-frame-wrap { - display: flex; - gap: 10px; - .plane-shape-wrap { - flex: none; - width: 73px; - } -} - -.plane-shape-menu { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 5px; - .shape-menu-box { - border-radius: 2px; - width: 34px; - height: 34px; - background-color: #373737; - border: 1px solid #676767; - transition: - background 0.15s ease-in-out, - border 0.15s ease-in-out; - .shape-box { - display: flex; - justify-content: center; - align-items: center; - position: relative; - width: 100%; - height: 100%; - border-radius: 2px; - } - &.act, - &:hover { - border-color: #008bff; - background-color: #008bff; - } - } -} - -.shape-library { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 5px; - padding-top: 5px; - .library-btn { - width: 100%; - height: 34px; - border: 1px solid #6c6c6c; - border-radius: 2px; - background-color: #373737; - background-repeat: no-repeat; - background-position: center; - transition: all 0.15s ease-in-out; - &.ico01 { - background-image: url(../../public/static/images/canvas/shape_labrary01.svg); - background-size: 19px 18px; - } - &.ico02 { - background-image: url(../../public/static/images/canvas/shape_labrary02.svg); - background-size: 15px 20px; - } - &.ico03 { - background-image: url(../../public/static/images/canvas/shape_labrary03.svg); - background-size: 19px 16px; - } - &:hover { - border-color: #1083e3; - background-color: #1083e3; - } - } -} - -.plane-detail-wrap { - display: flex; - flex-direction: column; - flex: 1; -} -.plane-shape-wrapper { - flex: 1; - display: flex; - flex-direction: column; - gap: 10px; - .plane-box { - width: 100%; - padding: 10px 18px; - border-radius: 2px; - background-color: #313131; - border: 1px solid #484848; - .plane-box-tit { - font-size: $pop-normal-size; - font-weight: 600; - color: $pop-color; - margin-bottom: 10px; - } - &.shape-box { - .shape-box-inner { - display: flex; - gap: 15px; - min-height: 140px; - .shape-img { - position: relative; - flex: none; - width: 150px; - background-color: #fff; - border-radius: 2px; - img { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - } - .shape-data { - flex: 1; - .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 { - flex: 1; - display: flex; - flex-direction: column; - .plane-direction-box { - flex: 1; +.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%; + } } - } -} -.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%); + .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; } - &.right { - top: 50%; - right: 0; - transform: translateY(-50%); + .shape-menu-box{ + &.act, + &:hover{ + .shape-box{background-color: #008BFF;} + .shape-title{color: #008BFF;} + } } - &.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 0.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: 10px; +.setting-box{ + padding: 14px 0; + border-top: 1px solid #424242; + border-bottom: 1px solid #424242; } -.plane-shape-btn { - padding-top: 10px; - margin-top: auto; - button { - display: block; - width: 100%; - } +.padding-form{ + padding-left: 23px; +} +.discrimination-box{ + padding: 16px 12px; + border: 1px solid #3D3D3D; + border-radius: 2px; } -// 오브젝트 배치 -.mb-box { - margin-bottom: 24px; +.modal-bottom-border-bx{ + margin-top: 24px; + padding-bottom: 14px; + border-bottom: 1px solid #424242; } -.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%); +// 처마∙케라바 변경 +.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: 10px; + } + .eaves-keraba-ico{ + display: flex; + align-items: center; + justify-content: center; + padding: 5px; + background-color: #3D3D3D; + border: 1px solid #3D3D3D; + border-radius: 2px; + cursor: pointer; + &.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; + } + span{ + display: block; } - } } -// 표시변경 -.display-change-wrap { - margin: 24px 0; -} -.warning { - font-size: $pop-normal-size; - font-weight: $pop-normal-weight; - color: #ffafaf; +// 지붕면 할당 +.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; + } + } } -// 각 변 속성 변경 -.radio-grid-wrap { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 24px 15px; +.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; + } } -// 면 흐름 설정 -.drawing-flow-wrap { - display: flex; - gap: 10px; - .discrimination-box { +.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; +} + +// 면형상 배치 +.plane-frame-wrap{ + display: flex; + gap: 10px; + .plane-shape-wrap{ + flex: none; + width: 73px; + } +} + +.plane-shape-menu{ + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 5px; + .shape-menu-box{ + border-radius: 2px; + width: 34px; + height: 34px; + background-color: #373737; + border: 1px solid #676767; + transition: background .15s ease-in-out, border .15s ease-in-out; + .shape-box{ + display: flex; + justify-content: center; + align-items: center; + position: relative; + width: 100%; + height: 100%; + border-radius: 2px; + } + &.act, + &:hover{ + border-color: #008BFF; + background-color: #008BFF; + } + } +} + +.shape-library{ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 5px; + padding-top: 5px; + .library-btn{ + width: 100%; + height: 34px; + border: 1px solid #6C6C6C; + border-radius: 2px; + background-color: #373737; + 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: 19px 18px;} + &.ico02{background-image: url(../../public/static/images/canvas/shape_labrary02.svg); background-size: 15px 20px;} + &.ico03{background-image: url(../../public/static/images/canvas/shape_labrary03.svg); background-size: 19px 16px;} + &:hover{ + border-color: #1083E3; + background-color: #1083E3; + } + } +} + +.plane-detail-wrap{ + display: flex; + flex-direction: column; + flex: 1; +} +.plane-shape-wrapper{ flex: 1; display: flex; flex-direction: column; - .object-direction-wrap { - flex: 1; + gap: 10px; + .plane-box{ + width: 100%; + padding: 10px 18px; + border-radius: 2px; + background-color: #313131; + border: 1px solid #484848; + .plane-box-tit{ + font-size: $pop-normal-size; + font-weight: 600; + color: $pop-color; + margin-bottom: 10px; + } + &.shape-box{ + .shape-box-inner{ + display: flex; + gap:15px; + min-height: 140px; + .shape-img{ + position: relative; + flex: none; + width: 150px; + background-color: #fff; + border-radius: 2px; + img{ + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } + .shape-data{ + flex: 1; + .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{ + flex: 1; + display: flex; + flex-direction: column; + .plane-direction-box{ + flex: 1; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + } + } } - &:first-child { - flex: none; - width: 195px; +} +.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); + } } - } } -.compas-box { - display: flex; - align-items: center; - justify-content: center; +.plane-tab-guide{ + font-size: $pop-normal-size; + font-weight: $pop-normal-weight; + color: $pop-color; + margin-top: 10px; +} +.plane-shape-btn{ + padding-top: 10px; + margin-top: auto; + button{ + display: block; + width: 100%; + } +} + +// 오브젝트 배치 +.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; + } + &:first-child{ + flex: none; + width: 195px; + } + } +} + +.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; + position: relative; + width: 200px; + height: 200px; 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; + + .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; + border-radius: 50%; + } + i{ + color: #fff; + } + } } - &: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: ''; + .compas{ position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); - width: 5px; - height: 5px; - background-color: #fff; + width: 148px; + height: 148px; + border: 4px solid #fff; border-radius: 50%; - } - i { - color: #fff; - } + .compas-arr{ + width: 100%; + height: 100%; + background: url(../../public/static/images/canvas/compas.svg)no-repeat center; + background-size: 122px 122px; + } } - } - .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; - } - } } -.draw-flow-wrap { - margin: 10px 0; +.draw-flow-wrap{ + margin: 10px 0; } // 지붕모듈선택 -.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 0.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 0.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: 22px; - } - &.act { - i { - color: #8b8b8b; +.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); } - } } - } -} -.center-wrap { - display: flex; - flex-direction: column; - align-items: center; - gap: 20px; } -.module-table-flex-wrap { - display: flex; - gap: 10px; - .outline-form { +.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: 22px; + } + &.act{ + i{color: #8B8B8B;} + } + } + } +} +.center-wrap{ + display: flex; + flex-direction: column; + align-items: center; + gap: 20px; +} + +.module-table-flex-wrap{ + display: flex; + gap: 10px; + .outline-form{ + flex: 1; + } +} + +.module-box-tab{ + display: flex; + .module-btn{ + flex: 1; + border-top: 1px solid #505050; + border-bottom: 1px solid #505050; + border-right: 1px solid #505050; + background-color: #454545; + color: #fff; + height: 30px; + font-size: 12px; + font-weight: 400; + transition: all .15s ease-in-out; + &:first-child{ + border-left: 1px solid #505050; + } + &.act{ + border-color: #fff; + background-color: #fff; + color: #101010; + } + } +} + +.module-table-box{ flex: 1; - } + background-color: #3D3D3D; + border-radius: 2px; + .module-table-inner{ + padding: 10px; + .outline-form{ + span{ + width: auto; + } + } + .module-table-tit{ + padding: 10px 0; + font-size: 12px; + color: #fff; + border-bottom: 1px solid #4D4D4D; + } + .eaves-keraba-table{ + width: 100%; + margin-top: 15px; + .eaves-keraba-th{ + width: 72px; + } + .eaves-keraba-th, + .eaves-keraba-td{ + padding-bottom: 5px; + } + } + .self-table-tit{ + font-size: 12px; + font-weight: 500; + color: #fff; + padding-bottom: 15px; + } + } + .warning-guide{ + padding: 20px; + .warning{ + color: #FFCACA; + max-height: 55px; + overflow-y: auto; + padding-right: 30px; + &::-webkit-scrollbar { + width: 4px; + background-color: transparent; + } + &::-webkit-scrollbar-thumb { + background-color: #D9D9D9; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } + } + } } -.module-box-tab { - display: flex; - .module-btn { - flex: 1; - border-top: 1px solid #505050; - border-bottom: 1px solid #505050; - border-right: 1px solid #505050; - background-color: #454545; - color: #fff; - height: 30px; - font-size: 12px; - font-weight: 400; - transition: all 0.15s ease-in-out; - &:first-child { - border-left: 1px solid #505050; +.module-self-table{ + display: table; + border-top: 1px solid #4D4D4D; + border-collapse: collapse; + width: 100%; + .self-table-item{ + display: table-row; + .self-item-td, + .self-item-th{ + display: table-cell; + vertical-align: middle; + border-bottom: 1px solid #4D4D4D; + } + .self-item-th{ + width: 60px; + font-size: 12px; + font-weight: 500; + color: #fff; + } + .self-item-td{ + font-size: 12px; + font-weight: 400; + color: #fff; + padding: 15px 20px; + } } - &.act { - border-color: #fff; - background-color: #fff; - color: #101010; - } - } } -.module-table-box { - flex: 1; - background-color: #3d3d3d; - border-radius: 2px; - .module-table-inner { - padding: 10px; - .outline-form { - span { - width: auto; - } - } - .module-table-tit { - padding: 10px 0; - font-size: 12px; - color: #fff; - border-bottom: 1px solid #4d4d4d; - } - .eaves-keraba-table { - width: 100%; - margin-top: 15px; - .eaves-keraba-th { - width: 72px; - } - .eaves-keraba-th, - .eaves-keraba-td { - padding-bottom: 5px; - } - } - .self-table-tit { - font-size: 12px; - font-weight: 500; - color: #fff; - padding-bottom: 15px; - } - } - .warning-guide { - padding: 20px; - .warning { - color: #ffcaca; - max-height: 55px; - overflow-y: auto; - padding-right: 30px; - &::-webkit-scrollbar { - width: 4px; - background-color: transparent; - } - &::-webkit-scrollbar-thumb { - background-color: #d9d9d9; - } - &::-webkit-scrollbar-track { - background-color: transparent; - } - } - } -} - -.module-self-table { - display: table; - border-top: 1px solid #4d4d4d; - border-collapse: collapse; - width: 100%; - .self-table-item { - display: table-row; - .self-item-td, - .self-item-th { - display: table-cell; - vertical-align: middle; - border-bottom: 1px solid #4d4d4d; - } - .self-item-th { - width: 60px; - font-size: 12px; - font-weight: 500; - color: #fff; - } - .self-item-td { - font-size: 12px; - font-weight: 400; - color: #fff; - padding: 15px 20px; - } - } -} - -.self-table-flx { - display: flex; - align-items: center; - margin-top: 15px; - button { - margin-left: auto; - } -} -.hexagonal-wrap { - .hexagonal-item { - padding: 15px 0; - border-bottom: 1px solid #4d4d4d; - &:first-child { - padding-top: 0; - } - &:last-child { - padding-bottom: 0; - border: none; - } - .hexagonal-flx-auto { - display: flex; - justify-content: space-between; - } - .hexagonal-flx { - display: flex; - align-items: center; - button { +.self-table-flx{ + display: flex; + align-items: center; + margin-top: 15px; + button{ margin-left: auto; - } } - } +} +.hexagonal-wrap{ + .hexagonal-item{ + padding: 15px 0; + border-bottom: 1px solid #4D4D4D; + &:first-child{ + padding-top: 0; + } + &:last-child{ + padding-bottom: 0; + border: none; + } + .hexagonal-flx-auto{ + display: flex; + justify-content: space-between; + } + .hexagonal-flx{ + display: flex; + align-items: center; + button{ + margin-left: auto; + } + } + } } // 회로 및 가대설정 -.circuit-check-inner { - padding: 5px 0; -} - -.x-scroll-table { - overflow-x: auto; - padding-bottom: 5px; - .roof-module-table { - min-width: 1200px; - } - &::-webkit-scrollbar { - height: 4px; - background-color: transparent; - } - &::-webkit-scrollbar-thumb { - background-color: #d9d9d9; - } - &::-webkit-scrollbar-track { - background-color: transparent; - } -} - -.circuit-right-wrap { - display: flex; - justify-content: flex-end; -} - -.circuit-data-form { - display: flex; - flex-direction: column; - gap: 5px; - min-height: 60px; - padding: 12px; - border: 1px solid rgba(255, 255, 255, 0.2); - span { - display: inline-flex; - align-items: center; - .del { - display: block; - margin-left: 10px; - width: 15px; - height: 15px; - background: url(../../public/static/images/canvas/circuit_del.svg) no-repeat center; - background-size: cover; +.circuit-check-inner{ + padding: 5px 0; + &.overflow{ + overflow-y: auto; + max-height: 100px; + min-height: 60px; + &::-webkit-scrollbar { + width: 4px; + background-color: transparent; + } + &::-webkit-scrollbar-thumb { + background-color: #D9D9D9; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } + } + .d-check-box{ + margin-bottom: 15px; + &:last-child{ + margin-bottom: 0; + } } - } -} -.circuit-table-tit { - color: #fff; - font-size: 12px; - font-weight: 600; - padding: 11px 10px; - background-color: #474747; - border: 1px solid #505050; - border-bottom: none; } -.circuit-overflow { - max-height: 400px; - overflow-y: auto; - margin-bottom: 15px; - &::-webkit-scrollbar { - width: 4px; +.x-scroll-table{ + overflow: auto; + padding-bottom: 5px; background-color: transparent; - } - &::-webkit-scrollbar-thumb { - background-color: #d9d9d9; - } - &::-webkit-scrollbar-track { - background-color: transparent; - } + max-height: 170px; + .roof-module-table{ + min-width: 1200px; + } + &::-webkit-scrollbar { + width: 4px; + height: 4px; + background-color: transparent; + } + &::-webkit-scrollbar-thumb { + background-color: #b4b4b4; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } + &::-webkit-scrollbar-corner{ + background-color: transparent; + } } -.circuit-table-flx-wrap { - display: flex; - gap: 10px; - margin-bottom: 10px; - .circuit-table-flx-box { - flex: 1; +.circuit-right-wrap{ + display: flex; + justify-content: flex-end; +} + +.circuit-data-form{ display: flex; flex-direction: column; - .bottom-wrap { - margin-top: auto; + gap: 5px; + min-height: 60px; + padding: 12px; + border: 1px solid rgba(255, 255, 255, 0.20); + span{ + display: inline-flex; + align-items: center; + .del{ + display: block; + margin-left: 10px; + width: 15px; + height: 15px; + background: url(../../public/static/images/canvas/circuit_del.svg)no-repeat center; + background-size: cover; + } } - .roof-module-table { - table { - table-layout: fixed; - } - } - } +} +.circuit-table-tit{ + color: #fff; + font-size: 12px; + font-weight: 600; + padding: 11px 10px; + background-color: #474747; + border: 1px solid #505050; + border-bottom: none; } -.circuit-count-input { - display: flex; - align-items: center; - gap: 10px; +.circuit-overflow{ + overflow-x: auto; + margin-bottom: 25px; + &::-webkit-scrollbar { + height: 4px; + background-color: transparent; + } + &::-webkit-scrollbar-thumb { + background-color: #D9D9D9; + } + &::-webkit-scrollbar-track { + background-color: transparent; + } + .module-table-box{ + display: flex; + &.by-max{ + min-width: 886px; + } + } +} + +.circuit-table-flx-wrap{ + display: flex; + gap: 10px; + margin-bottom: 10px; + .circuit-table-flx-box{ + flex: 1; + display: flex; + flex-direction: column; + .bottom-wrap{ + margin-top: auto; + } + .roof-module-table{ + table{ + table-layout: fixed; + } + } + } +} + +.circuit-count-input{ + display: flex; + align-items: center; + gap: 10px; } // 모듈부가기능 -.additional-radio-wrap { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 15px 0; - margin-bottom: 24px; +.additional-radio-wrap{ + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 15px 0; + margin-bottom: 24px; } -.additional-wrap { - padding: 24px 0; - border-top: 1px solid #424242; +.additional-wrap{ + padding: 24px 0; + border-top: 1px solid #424242; } -.additional-color-wrap { - display: flex; - align-items: center; - padding: 5px 0; - gap: 15px; - .additional-color-box { +.additional-color-wrap{ display: flex; align-items: center; - gap: 8px; - .additional-color { - display: block; - width: 16px; - height: 16px; - &.pink { - border: 2px solid #ce1c9c; - background-color: #16417d; - } - &.white { - border: 2px solid #fff; - background-color: #001027; - } + padding: 5px 0; + gap: 15px; + .additional-color-box{ + display: flex; + align-items: center; + gap: 8px; + .additional-color{ + display: block; + width: 16px; + height: 16px; + &.pink{ + border: 2px solid #ce1c9c; + background-color: #16417D; + } + &.white{ + border: 2px solid #FFF; + background-color: #001027; + } + } } - } } // color setting -.color-setting-wrap { - padding-bottom: 15px; - border-bottom: 1px solid #424242; - .color-tit { - font-size: 13px; - font-weight: 500; - color: #ffffff; - margin-bottom: 10px; - } - .color-picker { - .react-colorful { - width: 100%; - height: auto; - gap: 20px; - .react-colorful__pointer { - width: 15px; - height: 15px; - border: 4px solid #fff; - } - .react-colorful__saturation { - border-radius: 2px; - height: 200px; - border-bottom: 5px solid #000; - } - .react-colorful__last-control { - border-radius: 2px; - height: 10px; - } - } - .hex-color-box { - display: flex; - align-items: center; - margin-top: 15px; - .color-box-tit { - font-size: 12px; - color: #fff; +.color-setting-wrap{ + padding-bottom: 15px; + border-bottom: 1px solid #424242; + .color-tit{ + font-size: 13px; font-weight: 500; - margin-right: 10px; - } - .color-hex-input { - width: 150px; - margin-right: 5px; - input { - width: 100%; - } - } - .color-box { - display: block; - width: 30px; - height: 30px; - border-radius: 4px; - } + color: #ffffff; + margin-bottom: 10px; } - .default-color-wrap { - margin-top: 25px; - .default-tit { + .color-picker{ + .react-colorful{ + width: 100%; + height: auto; + gap: 20px; + .react-colorful__pointer{ + width: 15px; + height: 15px; + border: 4px solid #Fff; + } + .react-colorful__saturation{ + border-radius: 2px; + height: 200px; + border-bottom: 5px solid #000; + } + .react-colorful__last-control{ + border-radius: 2px; + height: 10px; + } + } + .hex-color-box{ + display: flex; + align-items: center; + margin-top: 15px; + .color-box-tit{ + font-size: 12px; + color: #fff; + font-weight: 500; + margin-right: 10px; + } + .color-hex-input{ + width: 150px; + margin-right: 5px; + input{ + width: 100%; + } + } + .color-box{ + display: block; + width: 30px; + height: 30px; + border-radius: 4px; + } + } + .default-color-wrap{ + margin-top: 25px; + .default-tit{ + font-size: 12px; + font-weight: 500; + color: #fff; + margin-bottom: 10px; + } + .color-button-wrap{ + display: grid; + grid-template-columns: repeat(8, 1fr); + gap: 21px; + .default-color{ + display: block; + width: 100%; + height: 30px; + border-radius: 4px; + } + } + } + } +} + +// 글꼴 설정 팝업 +.font-option-warp{ + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 15px 5px; + margin-bottom: 15px; + .font-option-item{ + .option-item-tit{ + font-size: 12px; + font-weight: 500; + color: #fff; + margin-bottom: 10px; + } + } +} +.font-ex-wrap{ + margin-bottom: 15px; + .font-ex-tit{ font-size: 12px; font-weight: 500; color: #fff; margin-bottom: 10px; - } - .color-button-wrap { - display: grid; - grid-template-columns: repeat(8, 1fr); - gap: 21px; - .default-color { - display: block; - width: 100%; - height: 30px; - border-radius: 4px; - } - } } - } -} - -// 글꼴 설정 팝업 -.font-option-warp { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 15px 5px; - margin-bottom: 15px; - .font-option-item { - .option-item-tit { - font-size: 12px; - font-weight: 500; - color: #fff; - margin-bottom: 10px; + .font-ex-box{ + display: flex; + align-items: center; + justify-content: center; + width: 100%; + min-height: 80px; + background-color: #fff; } - } -} -.font-ex-wrap { - margin-bottom: 15px; - .font-ex-tit { - font-size: 12px; - font-weight: 500; - color: #fff; - margin-bottom: 10px; - } - .font-ex-box { - display: flex; - align-items: center; - justify-content: center; - width: 100%; - min-height: 80px; - background-color: #fff; - } + } // 치수선 설정 -.font-btn-wrap { - margin-bottom: 15px; - button { - width: 100%; - height: 30px; - line-height: 28px; - } -} - -.line-color-wrap { - margin-bottom: 15px; - .color-btn { - display: block; - width: 100%; - height: 30px; - border-radius: 2px; - } -} - -.form-box { - width: 100%; - background-color: #fff; - padding: 10px 15px 20px; - .line-form { - position: relative; - display: flex; - flex-direction: column; - justify-content: flex-end; - min-width: 102px; - min-height: 40px; - margin: 0 auto; - - &::before { - content: ''; - position: absolute; - bottom: 0px; - left: 0; - width: 100%; - height: 40px; - border-left: 1px dashed #101010; - border-right: 1px dashed #101010; +.font-btn-wrap{ + margin-bottom: 15px; + button{ + width: 100%; + height: 30px; + line-height: 28px; } - .line-font-box { - .font { - display: block; - padding-bottom: 15px; - color: #101010; - text-align: center; - line-height: 1; - } - .line { - position: relative; +} + +.line-color-wrap{ + margin-bottom: 15px; + .color-btn{ display: block; width: 100%; - height: 1px; - border-radius: 30px; - &::before { - content: ''; - position: absolute; - top: 50%; - transform: translateY(-50%) rotate(45deg); - left: 1px; - width: 9px; - height: +9px; - border: 1px solid; - border-color: inherit; - border-top: none; - border-right: none; - } - &::after { - content: ''; - position: absolute; - top: 50%; - transform: translateY(-50%) rotate(45deg); - right: 1px; - width: 9px; - height: 9px; - border: 1px solid; - border-color: inherit; - border-bottom: none; - border-left: none; - } - } + height: 30px; + border-radius: 2px; + } +} + +.form-box{ + width: 100%; + background-color: #fff; + padding: 10px 15px 20px; + .line-form{ + position: relative; + display: flex; + flex-direction: column; + justify-content: flex-end; + min-width: 102px; + min-height: 40px; + margin: 0 auto; + + &::before{ + content: ''; + position: absolute; + bottom: 0px; + left: 0; + width: 100%; + height: 40px; + border-left: 1px dashed #101010; + border-right: 1px dashed #101010; + } + .line-font-box{ + .font{ + display: block; + padding-bottom: 15px; + color: #101010; + text-align: center; + line-height: 1; + } + .line{ + position: relative; + display: block; + width: 100%; + height: 1px; + border-radius: 30px; + &::before{ + content: ''; + position: absolute; + top: 50%; + transform: translateY(-50%) rotate(45deg); + left: 1px; + width: 9px; + height:+ 9px; + border: 1px solid; + border-color: inherit; + border-top: none; + border-right: none; + } + &::after{ + content: ''; + position: absolute; + top: 50%; + transform: translateY(-50%) rotate(45deg); + right: 1px; + width: 9px; + height: 9px; + border: 1px solid; + border-color: inherit; + border-bottom: none; + border-left: none; + } + } + } } - } } // 사이즈 변경 -.size-inner-warp { - position: relative; +.size-inner-warp{ + position: relative; } -.size-check-wrap { - position: relative; - display: block; - width: 132px; - height: 132px; - margin: 0 auto; - .size-btn { - position: absolute; - width: 16px; - height: 16px; - border: 1px solid #fff; - border-radius: 50%; - &.act { - &::after { - content: ''; +.size-check-wrap{ + position: relative; + display: block; + width: 132px; + height: 132px; + margin: 0 auto; + .size-btn{ + position: absolute; + width: 16px; + height: 16px; + border: 1px solid #fff; + border-radius: 50%; + &.act{ + &::after{ + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 8px; + height: 8px; + background-color: #fff; + border-radius: 50%; + } + } + &:nth-child(1){ top: 0; left: 0; } + &:nth-child(2){ top: 0; right: 0; } + &:nth-child(3){ bottom: 0; left: 0; } + &:nth-child(4){ bottom: 0; right: 0; } + } + .size-box{ position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); - width: 8px; - height: 8px; + width: 100px; + height: 100px; background-color: #fff; - border-radius: 50%; - } } - &:nth-child(1) { - top: 0; - left: 0; - } - &:nth-child(2) { - top: 0; - right: 0; - } - &:nth-child(3) { - bottom: 0; - left: 0; - } - &:nth-child(4) { - bottom: 0; - right: 0; - } - } - .size-box { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 100px; - height: 100px; - background-color: #fff; - } } -.size-option-top { - margin-bottom: 15px; +.size-option-top{ + margin-bottom: 15px; } -.size-option-side { - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); +.size-option-side{ + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); } -.size-option-wrap { - width: 88px; - margin: 0 auto; - .size-option { - display: flex; - align-items: center; - input { - width: 100%; - flex: 1; +.size-option-wrap{ + width: 88px; + margin: 0 auto; + .size-option{ + display: flex; + align-items: center; + input{ + width: 100%; + flex: 1; + } + span{ + flex: none; + } } - span { - flex: none; - } - } } //이미지 크기 설정 -.range-wrap { - display: flex; - align-items: center; - input { - flex: 1; - margin-right: 10px; - } - label { - flex: none; - text-align: right; - width: 38px; - font-size: 13px; - color: #fff; - font-weight: 500; - } +.range-wrap{ + display: flex; + align-items: center; + input{ + flex: 1; + margin-right: 10px; + } + label{ + flex: none; + text-align: right; + width: 38px; + font-size: 13px; + color: #fff; + font-weight: 500; + } } // 이미지 불러오기 -.img-flex-box { - display: flex; - align-items: center; +.img-flex-box{ + display: flex; + align-items: center; } -.img-load-from { - margin-top: 20px; - .img-load-item { - border-top: 1px solid #424242; - padding: 18px 0; - .d-check-radio { - margin-bottom: 20px; +.img-load-from{ + margin-top: 20px; + .img-load-item{ + border-top: 1px solid #424242; + padding: 18px 0; + .d-check-radio{ + margin-bottom: 20px; + } } - } - border-bottom: 1px solid #424242; + border-bottom: 1px solid #424242; } // 지붕모듈선택 변경 -.module-table-box { - &.none-flex { - flex: none; - width: 230px; - } +.module-table-box{ + &.none-flex{ + flex: none; + width: 230px; + } } -.module-table-flex-wrap { - &.tab2 { - margin-top: 10px; - gap: 15px; - } - .module-flex-item { - flex: 1; - .module-flex-item-tit { - font-size: 12px; - font-weight: 500; - color: #fff; - padding-bottom: 10px; - border-bottom: 1px solid #4d4d4d; +.module-table-flex-wrap{ + &.tab2{ + margin-top: 10px; + gap: 15px; + } - .flex-item-btn-wrap { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 8px; - margin-bottom: 24px; - } - &.non-flex { - display: flex; - flex-direction: column; - justify-content: flex-end; - flex: none; - width: 260px; - } - } -} - -.module-table-box { - .module-table-inner { - .module-table-flex-wrap { - &.tab2 { - .eaves-keraba-table { - .eaves-keraba-th { - width: 90px; - } - .eaves-keraba-td { - padding-left: 0; - padding-bottom: 5px; - } + .module-flex-item{ + flex: 1; + .module-flex-item-tit{ + font-size: 12px; + font-weight: 500; + color: #fff; + padding-bottom: 10px; + border-bottom: 1px solid #4D4D4D; + } + .flex-item-btn-wrap{ + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 8px; + margin-bottom: 24px; + } + &.non-flex{ + display: flex; + flex-direction: column; + justify-content: flex-end; + flex: none; + width: 260px; } - } } - } -} -.keraba-flex { - display: flex; - align-items: center; - .grid-select { - flex: none; - width: 110px; - } - .outline-form { - justify-content: flex-end; - } -} -.module-bottom { - padding-bottom: 15px; - border-bottom: 1px solid #4d4d4d; } -.reset-word { - font-size: 12px; - color: #ffcaca; - font-weight: 400; - margin-top: 10px; +.module-table-box{ + .module-table-inner{ + .module-table-flex-wrap{ + &.tab2{ + .eaves-keraba-table{ + .eaves-keraba-th{ + width: 90px; + } + .eaves-keraba-td{ + padding-left: 0; + padding-bottom: 5px; + } + } + } + } + } +} +.keraba-flex{ + display: flex; + align-items: center; + .grid-select{ + flex: none; + width: 110px; + } + .outline-form{ + justify-content: flex-end; + } } +.module-bottom{ + padding-bottom: 15px; + border-bottom: 1px solid #4D4D4D; +} + +.reset-word{ + font-size: 12px; + color: #FFCACA; + font-weight: 400; + margin-top: 10px; +} \ No newline at end of file diff --git a/src/styles/_table.scss b/src/styles/_table.scss index 4dcef37a..da26923c 100644 --- a/src/styles/_table.scss +++ b/src/styles/_table.scss @@ -311,6 +311,25 @@ table{ } } } + &.min{ + table{ + tbody{ + max-height: 150px; + td{ + height: 30px; + } + } + } + } + } + &.min{ + table{ + tbody{ + td{ + font-size: 11px; + } + } + } } } diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index 991facc0..d9a9b4d2 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -259,7 +259,7 @@ export const getDegreeByChon = (chon) => { // tan(theta) = height / base const radians = Math.atan(chon / 10) // 라디안을 도 단위로 변환 - return Number((radians * (180 / Math.PI)).toFixed(2)) + return Number((radians * (180 / Math.PI)).toFixed(1)) } /** @@ -268,7 +268,7 @@ export const getDegreeByChon = (chon) => { * @returns {number} */ export const getChonByDegree = (degree) => { - return Number((Math.tan((degree * Math.PI) / 180) * 10).toFixed(2)) + return Number((Math.tan((degree * Math.PI) / 180) * 10).toFixed(1)) } /**