Merge branch 'dev' of https://git.jetbrains.space/nalpari/q-cast-iii/qcast-front into feature/outer-lines
This commit is contained in:
commit
594a1abbb1
@ -96,6 +96,10 @@ export const BATCH_TYPE = {
|
||||
OPENING_TEMP: 'openingTemp',
|
||||
SHADOW: 'shadow',
|
||||
SHADOW_TEMP: 'shadowTemp',
|
||||
TRIANGLE_DORMER: 'triangleDormer',
|
||||
TRIANGLE_DORMER_TEMP: 'triangleDormerTemp',
|
||||
PENTAGON_DORMER: 'pentagonDormer',
|
||||
PENTAGON_DORMER_TEMP: 'pentagonDormerTemp',
|
||||
}
|
||||
// 오브젝트 배치 > 프리입력, 치수입력
|
||||
export const INPUT_TYPE = {
|
||||
|
||||
@ -5,7 +5,7 @@ import { useEffect, useState } from 'react'
|
||||
import { MENU } from '@/common/common'
|
||||
import { currentMenuState } from '@/store/canvasAtom'
|
||||
import { useSetRecoilState } from 'recoil'
|
||||
|
||||
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
||||
export default function MenuDepth01(props) {
|
||||
const {
|
||||
setShowOutlineModal,
|
||||
@ -28,6 +28,9 @@ export default function MenuDepth01(props) {
|
||||
const { getMessage } = useMessage()
|
||||
const [activeMenu, setActiveMenu] = useState()
|
||||
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
||||
|
||||
const { deleteAllSurfacesAndObjects } = useSurfaceShapeBatch()
|
||||
|
||||
const onClickMenu = ({ id, menu, name }) => {
|
||||
setActiveMenu(menu)
|
||||
setShowOutlineModal(menu === MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
||||
@ -60,6 +63,11 @@ export default function MenuDepth01(props) {
|
||||
setShowPlaceShapeDrawingModal(id === 1)
|
||||
setShowPlacementSurfaceSettingModal(id === 2)
|
||||
setShowObjectSettingModal(id === 3)
|
||||
|
||||
//배치면 전체 삭제
|
||||
if (id === 4) {
|
||||
deleteAllSurfacesAndObjects()
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'module') {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import WithDraggable from '@/components/common/draggable/withDraggable'
|
||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||
import { useState } from 'react'
|
||||
import Orientation from '@/components/floor-plan/modal/basic/step/Orientation'
|
||||
import Module from '@/components/floor-plan/modal/basic/step/Module'
|
||||
|
||||
@ -3,12 +3,10 @@
|
||||
import { useState, useRef } from 'react'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { INPUT_TYPE, BATCH_TYPE } from '@/common/common'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import { polygonToTurfPolygon, rectToPolygon, pointsToTurfPolygon } from '@/util/canvas-util'
|
||||
import * as turf from '@turf/turf'
|
||||
import { useObjectBatch } from '@/hooks/object/useObjectBatch'
|
||||
|
||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||
import OpenSpace from '@/components/floor-plan/modal/object/type/OpenSpace'
|
||||
@ -20,9 +18,8 @@ export default function ObjectSetting({ setShowObjectSettingModal }) {
|
||||
const { getMessage } = useMessage()
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const [buttonAct, setButtonAct] = useState(1)
|
||||
const [preObjects, setPreObjects] = useState([])
|
||||
const { addCanvasMouseEventListener, initEvent } = useEvent()
|
||||
const { swalFire } = useSwal()
|
||||
const { applyOpeningAndShadow } = useObjectBatch()
|
||||
|
||||
/**
|
||||
* 개구배치, 그림자배치
|
||||
@ -35,13 +32,8 @@ export default function ObjectSetting({ setShowObjectSettingModal }) {
|
||||
}
|
||||
|
||||
const applyObject = () => {
|
||||
setShowObjectSettingModal(false)
|
||||
|
||||
let preObjectsArray = preObjects
|
||||
const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === 'surfaceShapeBatch')
|
||||
|
||||
console.log(preObjectsArray)
|
||||
|
||||
if (surfaceShapePolygons.length === 0) {
|
||||
swalFire({ text: '지붕이 없어요 지붕부터 그리세요', icon: 'error' })
|
||||
return
|
||||
@ -49,121 +41,7 @@ export default function ObjectSetting({ setShowObjectSettingModal }) {
|
||||
|
||||
//개구배치, 그림자배치
|
||||
if (buttonAct === 1 || buttonAct === 2) {
|
||||
const type = objectPlacement.typeRef.current.find((radio) => radio.checked).value
|
||||
const isCrossChecked = objectPlacement.isCrossRef.current.checked
|
||||
|
||||
let rect, isDown, origX, origY
|
||||
let selectedSurface
|
||||
|
||||
//프리입력
|
||||
if (type === INPUT_TYPE.FREE) {
|
||||
addCanvasMouseEventListener('mouse:down', (e) => {
|
||||
isDown = true
|
||||
const pointer = canvas.getPointer(e.e)
|
||||
|
||||
surfaceShapePolygons.forEach((surface) => {
|
||||
if (surface.inPolygon({ x: pointer.x, y: pointer.y })) {
|
||||
selectedSurface = surface
|
||||
}
|
||||
})
|
||||
|
||||
if (!selectedSurface) {
|
||||
swalFire({ text: '지붕안에 그려야해요', icon: 'error' })
|
||||
setShowObjectSettingModal(true) //메뉴보이고
|
||||
initEvent() //이벤트 초기화
|
||||
return
|
||||
}
|
||||
|
||||
origX = pointer.x
|
||||
origY = pointer.y
|
||||
|
||||
rect = new fabric.Rect({
|
||||
left: origX,
|
||||
top: origY,
|
||||
originX: 'left',
|
||||
originY: 'top',
|
||||
width: 0,
|
||||
height: 0,
|
||||
angle: 0,
|
||||
stroke: 'black',
|
||||
})
|
||||
|
||||
//개구냐 그림자냐에 따라 변경
|
||||
rect.set({
|
||||
fill: buttonAct === 1 ? 'white' : 'rgba(0, 0, 0, 0.3)',
|
||||
name: buttonAct === 1 ? BATCH_TYPE.OPENING_TEMP : BATCH_TYPE.SHADOW_TEMP,
|
||||
})
|
||||
|
||||
canvas?.add(rect)
|
||||
})
|
||||
|
||||
addCanvasMouseEventListener('mouse:move', (e) => {
|
||||
if (!isDown) return
|
||||
|
||||
if (selectedSurface) {
|
||||
const pointer = canvas.getPointer(e.e)
|
||||
const width = pointer.x - origX
|
||||
const height = pointer.y - origY
|
||||
|
||||
rect.set({ width: Math.abs(width), height: Math.abs(height) })
|
||||
|
||||
if (width < 0) {
|
||||
rect.set({ left: Math.abs(pointer.x) })
|
||||
}
|
||||
if (height < 0) {
|
||||
rect.set({ top: Math.abs(pointer.y) })
|
||||
}
|
||||
|
||||
canvas?.renderAll()
|
||||
}
|
||||
})
|
||||
|
||||
addCanvasMouseEventListener('mouse:up', (e) => {
|
||||
if (rect) {
|
||||
const rectPolygon = pointsToTurfPolygon(rectToPolygon(rect))
|
||||
const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface)
|
||||
|
||||
//지붕 밖으로 그렸을때
|
||||
if (!turf.booleanWithin(rectPolygon, selectedSurfacePolygon)) {
|
||||
swalFire({ text: '지붕안에 그리라고요...', icon: 'error' })
|
||||
//일단 지워
|
||||
const deleteTarget = canvas?.getObjects().filter((obj) => obj.name === BATCH_TYPE.OPENING_TEMP || obj.name === BATCH_TYPE.SHADOW_TEMP)
|
||||
canvas?.remove(...deleteTarget)
|
||||
setShowObjectSettingModal(true) //메뉴보이고
|
||||
initEvent() //이벤트 초기화
|
||||
return
|
||||
}
|
||||
|
||||
// if (!isCrossChecked) {
|
||||
// const isCross = preObjectsArray.some((object) => turf.booleanOverlap(pointsToTurfPolygon(rectToPolygon(object), rectPolygon)))
|
||||
|
||||
// console.log(isCross)
|
||||
|
||||
// if (isCross) {
|
||||
// swalFire({ text: '겹치기 불가요...', icon: 'error' })
|
||||
// const deleteTarget = canvas?.getObjects().filter((obj) => obj.name === BATCH_TYPE.OPENING_TEMP || obj.name === BATCH_TYPE.SHADOW_TEMP)
|
||||
// canvas?.remove(...deleteTarget)
|
||||
// setShowObjectSettingModal(true) //메뉴보이고
|
||||
// initEvent() //이벤트 초기화
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
|
||||
isDown = false
|
||||
const complateName = buttonAct === 1 ? BATCH_TYPE.OPENING : BATCH_TYPE.SHADOW
|
||||
rect.set({ name: complateName })
|
||||
rect.setCoords()
|
||||
|
||||
preObjectsArray.push(rect)
|
||||
|
||||
console.log('preObjectsArray', preObjectsArray)
|
||||
setPreObjects(preObjectsArray)
|
||||
|
||||
setShowObjectSettingModal(true) //메뉴보이고
|
||||
initEvent()
|
||||
}
|
||||
})
|
||||
}
|
||||
applyOpeningAndShadow(objectPlacement, buttonAct, surfaceShapePolygons, setShowObjectSettingModal)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,23 +1,45 @@
|
||||
import { forwardRef } from 'react'
|
||||
import { forwardRef, useState, useEffect } from 'react'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { INPUT_TYPE } from '@/common/common'
|
||||
|
||||
const OpenSpace = forwardRef((props, refs) => {
|
||||
const { getMessage } = useMessage()
|
||||
const [selectedType, setSelectedType] = useState(INPUT_TYPE.FREE)
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedType === INPUT_TYPE.FREE) {
|
||||
refs.widthRef.current.value = 0
|
||||
refs.heightRef.current.value = 0
|
||||
}
|
||||
}, [selectedType])
|
||||
|
||||
//체크하면 값바꿈
|
||||
|
||||
return (
|
||||
<div className="discrimination-box mb10">
|
||||
<div className="mb-box">
|
||||
<div className="d-check-radio pop">
|
||||
<input type="radio" name="radio01" id="ra01" value={INPUT_TYPE.FREE} defaultChecked ref={(el) => (refs.typeRef.current[0] = el)} />
|
||||
<input
|
||||
type="radio"
|
||||
name="radio01"
|
||||
id="ra01"
|
||||
value={INPUT_TYPE.FREE}
|
||||
defaultChecked
|
||||
ref={(el) => (refs.typeRef.current[0] = el)}
|
||||
onClick={() => setSelectedType(INPUT_TYPE.FREE)}
|
||||
/>
|
||||
<label htmlFor="ra01">{getMessage('modal.object.setting.free.input')}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-box">
|
||||
<div className="d-check-radio pop">
|
||||
<input type="radio" name="radio01" id="ra02" value={INPUT_TYPE.DIMENSION} ref={(el) => (refs.typeRef.current[1] = el)} />
|
||||
<input
|
||||
type="radio"
|
||||
name="radio01"
|
||||
id="ra02"
|
||||
value={INPUT_TYPE.DIMENSION}
|
||||
ref={(el) => (refs.typeRef.current[1] = el)}
|
||||
onClick={() => setSelectedType(INPUT_TYPE.DIMENSION)}
|
||||
/>
|
||||
<label htmlFor="ra02">{getMessage('modal.object.setting.size.input')}</label>
|
||||
</div>
|
||||
</div>
|
||||
@ -29,7 +51,13 @@ const OpenSpace = forwardRef((props, refs) => {
|
||||
<div className="eaves-keraba-td">
|
||||
<div className="outline-form">
|
||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||
<input type="text" className="input-origin block" placeholder={0} ref={refs.widthRef} />
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
placeholder={0}
|
||||
ref={refs.widthRef}
|
||||
disabled={selectedType !== INPUT_TYPE.DIMENSION}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
</div>
|
||||
@ -40,7 +68,13 @@ const OpenSpace = forwardRef((props, refs) => {
|
||||
<div className="eaves-keraba-td">
|
||||
<div className="outline-form">
|
||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||
<input type="text" className="input-origin block" placeholder={0} ref={refs.heightRef} />
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
placeholder={0}
|
||||
ref={refs.heightRef}
|
||||
disabled={selectedType !== INPUT_TYPE.DIMENSION}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
</div>
|
||||
|
||||
@ -1,20 +1,45 @@
|
||||
import { forwardRef } from 'react'
|
||||
import { forwardRef, useState, useEffect } from 'react'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { INPUT_TYPE } from '@/common/common'
|
||||
|
||||
const Shadow = forwardRef((props, refs) => {
|
||||
const { getMessage } = useMessage()
|
||||
|
||||
const [selectedType, setSelectedType] = useState(INPUT_TYPE.FREE)
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedType === INPUT_TYPE.FREE) {
|
||||
refs.widthRef.current.value = 0
|
||||
refs.heightRef.current.value = 0
|
||||
}
|
||||
}, [selectedType])
|
||||
|
||||
return (
|
||||
<div className="discrimination-box mb10">
|
||||
<div className="mb-box">
|
||||
<div className="d-check-radio pop">
|
||||
<input type="radio" name="radio01" id="ra01" value={INPUT_TYPE.FREE} defaultChecked ref={(el) => (refs.typeRef.current[0] = el)} />
|
||||
<input
|
||||
type="radio"
|
||||
name="radio01"
|
||||
id="ra01"
|
||||
value={INPUT_TYPE.FREE}
|
||||
defaultChecked
|
||||
ref={(el) => (refs.typeRef.current[0] = el)}
|
||||
onClick={() => setSelectedType(INPUT_TYPE.FREE)}
|
||||
/>
|
||||
<label htmlFor="ra01">{getMessage('modal.object.setting.free.input')}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-box">
|
||||
<div className="d-check-radio pop">
|
||||
<input type="radio" name="radio01" id="ra02" value={INPUT_TYPE.DIMENSION} ref={(el) => (refs.typeRef.current[1] = el)} />
|
||||
<input
|
||||
type="radio"
|
||||
name="radio01"
|
||||
id="ra02"
|
||||
value={INPUT_TYPE.DIMENSION}
|
||||
ref={(el) => (refs.typeRef.current[1] = el)}
|
||||
onClick={() => setSelectedType(INPUT_TYPE.DIMENSION)}
|
||||
/>
|
||||
<label htmlFor="ra02">{getMessage('modal.object.setting.size.input')}</label>
|
||||
</div>
|
||||
</div>
|
||||
@ -26,7 +51,13 @@ const Shadow = forwardRef((props, refs) => {
|
||||
<div className="eaves-keraba-td">
|
||||
<div className="outline-form">
|
||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||
<input type="text" className="input-origin block" placeholder={0} ref={refs.widthRef} />
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
placeholder={0}
|
||||
ref={refs.widthRef}
|
||||
disabled={selectedType !== INPUT_TYPE.DIMENSION}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
</div>
|
||||
@ -37,7 +68,13 @@ const Shadow = forwardRef((props, refs) => {
|
||||
<div className="eaves-keraba-td">
|
||||
<div className="outline-form">
|
||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||
<input type="text" className="input-origin block" placeholder={0} ref={refs.heightRef} />
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
placeholder={0}
|
||||
ref={refs.heightRef}
|
||||
disabled={selectedType !== INPUT_TYPE.DIMENSION}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
</div>
|
||||
|
||||
@ -53,10 +53,8 @@ export default function Stuff() {
|
||||
const onDoubleClick = (e) => {
|
||||
let objectNo = e.target.innerText
|
||||
if (objectNo.substring(0, 1) === 'R') {
|
||||
console.log('진짜')
|
||||
router.push(`${pathname}/detail?objectNo=${objectNo.toString()}`)
|
||||
} else {
|
||||
console.log('임시')
|
||||
router.push(`${pathname}/tempdetail?objectNo=${objectNo.toString()}`)
|
||||
}
|
||||
}
|
||||
@ -87,7 +85,7 @@ export default function Stuff() {
|
||||
},
|
||||
{
|
||||
field: 'objectNo',
|
||||
width: '180px',
|
||||
minWidth: 230,
|
||||
headerName: getMessage('stuff.gridHeader.objectNo'),
|
||||
cellRenderer: function (params) {
|
||||
if (params.data.objectNo) {
|
||||
@ -122,7 +120,7 @@ export default function Stuff() {
|
||||
headerName: getMessage('stuff.gridHeader.saleStoreId'),
|
||||
cellStyle: { textAlign: 'left' },
|
||||
},
|
||||
{ field: 'saleStoreName', headerName: getMessage('stuff.gridHeader.saleStoreName'), cellStyle: { textAlign: 'left' } },
|
||||
{ field: 'saleStoreName', minWidth: 300, headerName: getMessage('stuff.gridHeader.saleStoreName'), cellStyle: { textAlign: 'left' } },
|
||||
{ field: 'address', headerName: getMessage('stuff.gridHeader.address'), cellStyle: { textAlign: 'left' } },
|
||||
{ field: 'dispCompanyName', headerName: getMessage('stuff.gridHeader.dispCompanyName'), cellStyle: { textAlign: 'left' } },
|
||||
{ field: 'receiveUser', headerName: getMessage('stuff.gridHeader.receiveUser'), cellStyle: { textAlign: 'left' } },
|
||||
@ -159,14 +157,11 @@ export default function Stuff() {
|
||||
if (event.column.colId === 'objectNo') {
|
||||
return
|
||||
} else {
|
||||
console.log(' 상세이동::::::::', event.data)
|
||||
//T 면 임시 R은 진짜
|
||||
if (event.data.objectNo) {
|
||||
if (event.data.objectNo.substring(0, 1) === 'R') {
|
||||
console.log('진짜:::::::::')
|
||||
router.push(`${pathname}/detail?objectNo=${event.data.objectNo.toString()}`)
|
||||
} else {
|
||||
console.log('임시:::::::::::::::::')
|
||||
router.push(`${pathname}/tempdetail?objectNo=${event.data.objectNo.toString()}`)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import React, { useState, useEffect, useRef } from 'react'
|
||||
import { useRouter, useSearchParams } from 'next/navigation'
|
||||
import { Button } from '@nextui-org/react'
|
||||
import Select from 'react-dropdown-select'
|
||||
import Link from 'next/link'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { globalLocaleStore } from '@/store/localeAtom'
|
||||
import { isEmptyArray } from '@/util/common-utils'
|
||||
import { isEmptyArray, isObjectNotEmpty } from '@/util/common-utils'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { sessionStore } from '@/store/commonAtom'
|
||||
import FindAddressPop from './popup/FindAddressPop'
|
||||
import DesignRequestPop from './popup/DesignRequestPop'
|
||||
import PlanRequestPop from './popup/PlanRequestPop'
|
||||
export default function StuffDetail() {
|
||||
const sessionState = useRecoilValue(sessionStore)
|
||||
|
||||
@ -21,7 +21,7 @@ export default function StuffDetail() {
|
||||
const searchParams = useSearchParams()
|
||||
const { getMessage } = useMessage()
|
||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||
|
||||
const ref = useRef()
|
||||
const { get, post, del } = useAxios(globalLocaleState)
|
||||
//form
|
||||
const formInitValue = {
|
||||
@ -31,10 +31,12 @@ export default function StuffDetail() {
|
||||
objectName: '', //물건명
|
||||
objectNameOmit: '', //경칭선택
|
||||
objectNameKana: '', //물건명 후리가나
|
||||
saleStoreId: '', //판매점ID
|
||||
saleStoreName: '', //판매점명
|
||||
otherSaleStoreId: '',
|
||||
otherSaleStoreName: '',
|
||||
saleStoreLevel: '', //1차점스토어레벨
|
||||
saleStoreId: '', //1차점판매점ID
|
||||
saleStoreName: '', //1차점판매점명
|
||||
otherSaleStoreId: '', //1차점 외 판매점ID
|
||||
otherSaleStoreName: '', //1차점 외 판매점명
|
||||
otherSaleStoreLevel: '', //1차점 외 스토어레벨
|
||||
zipNo: '', //우편번호
|
||||
prefId: '', //도도부현
|
||||
prefName: '',
|
||||
@ -67,18 +69,19 @@ export default function StuffDetail() {
|
||||
|
||||
const [windSpeedList, setWindSpeedList] = useState([]) //기준풍속 리스트
|
||||
const [isFormValid, setIsFormValid] = useState(false) //임시저장, 진짜저장 버튼 컨트롤
|
||||
const [showButtonValid, setShowButtonValid] = useState(false) //주소검색 활성화 컨트롤
|
||||
const [showAddressButtonValid, setShowAddressButtonValid] = useState(false) //주소검색팝업 활성화 컨트롤
|
||||
const [showDesignRequestButtonValid, setShowDesignRequestButtonValid] = useState(false) //설계의뢰팝업 활성화 컨트롤
|
||||
const objectNo = searchParams.get('objectNo') //url에서 물건번호 꺼내서 바로 set
|
||||
|
||||
// const [] //1차판매점 자동완성 선택값
|
||||
// const [] //2차판매점 자동완성 선택값
|
||||
|
||||
const [editMode, setEditMode] = useState('NEW')
|
||||
const [detailData, setDetailData] = useState({})
|
||||
|
||||
const [tempDetailData, setTempDetailData] = useState({})
|
||||
|
||||
useEffect(() => {
|
||||
console.log('objectNo::', objectNo)
|
||||
if (objectNo) {
|
||||
//console.log('수정화면')
|
||||
console.log('수정화면')
|
||||
setEditMode('EDIT')
|
||||
|
||||
if (objectNo.substring(0, 1) === 'R') {
|
||||
@ -86,38 +89,15 @@ export default function StuffDetail() {
|
||||
setIsFormValid(true)
|
||||
}
|
||||
get({ url: `/api/object/${objectNo}/detail` }).then((res) => {
|
||||
// console.log('물건번호로 상세 API 호출')
|
||||
console.log('물건번호로 상세 API 호출')
|
||||
if (res != null) {
|
||||
setDetailData(res)
|
||||
|
||||
// 신규 상세 공통APi
|
||||
// 도도부현API
|
||||
get({ url: '/api/object/prefecture/list' }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
// console.log('도도부현API 결과:::', res)
|
||||
setPrefCodeList(res)
|
||||
}
|
||||
})
|
||||
// 임시 1차점 판매점코드 saleStoreId=201TES01
|
||||
// T01
|
||||
//1차점 : X167
|
||||
// get({ url: `/api/object/saleStore/X167/list` }).then((res) => {
|
||||
get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
// console.log('판매점 결과:::::', res)
|
||||
setSaleStoreList(res)
|
||||
//1차 판매점 자동완성 값 셋팅
|
||||
form.setValue('saleStoreId', res[0].saleStoreId)
|
||||
//1차 판매점 번호 셋팅
|
||||
form.setValue('saleStoreName', res[0].saleStoreId)
|
||||
setOtherSaleStoreList([])
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// 신규 상세 공통APi
|
||||
// 도도부현API
|
||||
console.log('신규화면')
|
||||
get({ url: '/api/object/prefecture/list' }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
// console.log('신규화면 도도부현API 결과:::', res)
|
||||
@ -135,28 +115,57 @@ export default function StuffDetail() {
|
||||
|
||||
//1차점 셀렉트박스
|
||||
setSaleStoreList(firstList)
|
||||
//1차 판매점 자동완성 값 셋팅
|
||||
//form.setValue('saleStoreId', firstList[0].saleStoreId)
|
||||
//1차 판매점 번호 셋팅
|
||||
form.setValue('saleStoreName', firstList[0]?.saleStoreId)
|
||||
|
||||
//1차점 아닌 판매점 셀렉트박스
|
||||
setOriginOtherSaleStoreList(otherList)
|
||||
setOtherSaleStoreList(otherList)
|
||||
// form.setValue('otherSaleStoreId', otherList[0].saleStoreId)
|
||||
form.setValue('otherSaleStoreName', otherList[0]?.saleStoreId)
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [objectNo])
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(detailData)) {
|
||||
console.log('상세데이타:::::::', detailData)
|
||||
// 도도부현API
|
||||
get({ url: '/api/object/prefecture/list' }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
// console.log('도도부현API 결과:::', res)
|
||||
setPrefCodeList(res)
|
||||
}
|
||||
})
|
||||
|
||||
//상세정보로 1차점 목록등 셋팅??
|
||||
// 임시 1차점 판매점코드 saleStoreId=201TES01
|
||||
// T01
|
||||
//1차점 : X167
|
||||
// get({ url: `/api/object/saleStore/X167/list` }).then((res) => {
|
||||
// get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => {
|
||||
// if (!isEmptyArray(res)) {
|
||||
// // console.log('판매점 결과:::::', res)
|
||||
// setSaleStoreList(res)
|
||||
// //1차 판매점 자동완성 값 셋팅
|
||||
// form.setValue('saleStoreId', res[0].saleStoreId)
|
||||
// //1차 판매점 번호 셋팅
|
||||
// form.setValue('saleStoreName', res[0].saleStoreId)
|
||||
// setOtherSaleStoreList([])
|
||||
// }
|
||||
// })
|
||||
}
|
||||
}, [detailData])
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(tempDetailData)) {
|
||||
console.log('임시저장하고 새로고침했을때:::::::::', tempDetailData)
|
||||
}
|
||||
}, [tempDetailData])
|
||||
|
||||
//1차점 변경 이벤트
|
||||
const onSelectionChange = (key) => {
|
||||
if (!isEmptyArray(key)) {
|
||||
setOtherSaleStoreList(otherSaleStoreList)
|
||||
form.setValue('saleStoreId', key[0].saleStoreId)
|
||||
form.setValue('saleStoreName', key[0].saleStoreId)
|
||||
|
||||
form.setValue('saleStoreName', key[0].saleStoreName)
|
||||
form.setValue('saleStoreLevel', key[0].saleStoreLevel)
|
||||
//선택한 1차점 정보로 2차점 list 추리기
|
||||
//長府工産株式会社 大阪支社
|
||||
let newOtherSaleStoreList = originOtherSaleStoreList.filter((row) => row.firstAgentId === key[0].saleStoreId)
|
||||
@ -165,7 +174,13 @@ export default function StuffDetail() {
|
||||
//X누름
|
||||
form.setValue('saleStoreId', '')
|
||||
form.setValue('saleStoreName', '')
|
||||
form.setValue('saleStoreLevel', '')
|
||||
form.setValue('otherSaleStoreId', '')
|
||||
form.setValue('otherSaleStoreName', '')
|
||||
form.setValue('otherSaleStoreLevel', '')
|
||||
setOtherSaleStoreList(originOtherSaleStoreList)
|
||||
//1차점 지웠을때 2차점 자동완성 초기화
|
||||
handleClear()
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,60 +188,32 @@ export default function StuffDetail() {
|
||||
const onSelectionChange2 = (key) => {
|
||||
if (!isEmptyArray(key)) {
|
||||
form.setValue('otherSaleStoreId', key[0].saleStoreId)
|
||||
form.setValue('otherSaleStoreId', key[0].saleStoreId)
|
||||
form.setValue('otherSaleStoreName', key[0].saleStoreName)
|
||||
form.setValue('otherSaleStoreLevel', key[0].saleStoreLevel)
|
||||
} else {
|
||||
form.setValue('otherSaleStoreId', '')
|
||||
form.setValue('otherSaleStoreId', '')
|
||||
form.setValue('otherSaleStoreName', '')
|
||||
form.setValue('otherSaleStoreLevel', '')
|
||||
}
|
||||
}
|
||||
// 우편번호 숫자만 체크
|
||||
const _zipNo = watch('zipNo')
|
||||
useEffect(() => {
|
||||
if (_zipNo !== '' && _zipNo.length === 7 && !_zipNo.match(/\D/g)) {
|
||||
//setButtonValid(true)
|
||||
|
||||
//1차점 지웠을때 2차점 자동완성 초기화
|
||||
const handleClear = () => {
|
||||
if (ref.current.state.dropDown) {
|
||||
ref.current.methods.dropDown()
|
||||
} else {
|
||||
//setButtonValid(false)
|
||||
ref.current.state.values = []
|
||||
}
|
||||
}, [_zipNo])
|
||||
}
|
||||
|
||||
//팝업에서 넘어온 우편정보
|
||||
const setZipInfo = (info) => {
|
||||
console.log('팝업에서 넘어온 데이타::::::::', info)
|
||||
|
||||
// const params = {
|
||||
// zipcode: _zipNo,
|
||||
// }
|
||||
|
||||
// get({ url: `https://zipcloud.ibsnet.co.jp/api/search?${queryStringFormatter(params)}` }).then((res) => {
|
||||
// //7830060
|
||||
// //9302226
|
||||
// //0790177 3개짜리
|
||||
// if (res.status === 200) {
|
||||
// if (res.results != null) {
|
||||
// console.log('주소검색::', res.results)
|
||||
// // console.log('prefcode::', res.results[0].prefcode)
|
||||
// // console.log('address::', res.results[0].address2 + res.results[0].address3)
|
||||
// setPrefValue(res.results[0].prefcode)
|
||||
// form.setValue('prefId', res.results[0].prefcode)
|
||||
// form.setValue('prefName', res.results[0].address1)
|
||||
// form.setValue('address', res.results[0].address2 + res.results[0].address3)
|
||||
// } else {
|
||||
// alert('등록된 우편번호에서 주소를 찾을 수 없습니다. 다시 입력해주세요.')
|
||||
// form.setValue('prefId', '')
|
||||
// form.setValue('prefName', '')
|
||||
// form.setValue('address', '')
|
||||
// form.setValue('zipNo', '')
|
||||
// setPrefValue('')
|
||||
// setAreaIdList([])
|
||||
// form.setValue('areaId', '')
|
||||
// // form.setValue('areaName', '')
|
||||
// setWindSpeedList([])
|
||||
// form.setValue('windSpeed', '')
|
||||
// }
|
||||
// } else {
|
||||
// alert(res.message)
|
||||
// }
|
||||
// })
|
||||
// console.log('팝업에서 넘어온 데이타::::::::', info)
|
||||
setPrefValue(info.prefId)
|
||||
form.setValue('prefId', info.prefId)
|
||||
form.setValue('prefName', info.address1)
|
||||
form.setValue('address', info.address2 + info.address3)
|
||||
form.setValue('zipNo', info.zipNo)
|
||||
}
|
||||
|
||||
//임시저장 저장 버튼 컨트롤
|
||||
@ -251,7 +238,7 @@ export default function StuffDetail() {
|
||||
const _objectName = watch('objectName')
|
||||
const _objectNameOmit = watch('objectNameOmit')
|
||||
const _saleStoreId = watch('saleStoreId')
|
||||
const _otherSaleStoreId = watch('otherSaleStoreId')
|
||||
const _saleStoreLevel = watch('saleStoreLevel')
|
||||
const _prefId = watch('prefId')
|
||||
const _address = watch('address')
|
||||
const _areaId = watch('areaId') //new
|
||||
@ -260,68 +247,56 @@ export default function StuffDetail() {
|
||||
const _installHeight = watch('installHeight')
|
||||
|
||||
useEffect(() => {
|
||||
console.log('mode:::::', editMode)
|
||||
if (editMode === 'NEW') {
|
||||
const formData = form.getValues()
|
||||
console.log('폼::::::::::::', formData)
|
||||
// console.log('임시저장폼::::::::::::', formData)
|
||||
let errors = {}
|
||||
if (!_dispCompanyName || _dispCompanyName.trim().length === 0) {
|
||||
if (!formData.dispCompanyName || formData.dispCompanyName.trim().length === 0) {
|
||||
errors.dispCompanyName = true
|
||||
}
|
||||
if (!_objectName || _objectName.trim().length === 0) {
|
||||
if (!formData.objectName || formData.objectName.trim().length === 0) {
|
||||
errors.objectName = true
|
||||
}
|
||||
if (!_objectNameOmit) {
|
||||
if (!formData.objectNameOmit) {
|
||||
errors.objectNameOmit = true
|
||||
}
|
||||
if (!_saleStoreId) {
|
||||
if (!formData.saleStoreId) {
|
||||
errors.saleStoreId = true
|
||||
}
|
||||
|
||||
// if (!_otherSaleStoreId) {
|
||||
// errors.otherSaleStoreId = true
|
||||
// }
|
||||
|
||||
if (!_zipNo || _zipNo.length != 7) {
|
||||
errors.zipCode = true
|
||||
}
|
||||
|
||||
if (!_prefId) {
|
||||
if (!formData.prefId) {
|
||||
errors.prefId = true
|
||||
}
|
||||
|
||||
if (!_address.trim().length === 0) {
|
||||
errors.address = true
|
||||
}
|
||||
|
||||
if (!_areaId) {
|
||||
if (!formData.areaId) {
|
||||
errors.areaId = true
|
||||
}
|
||||
|
||||
if (!_windSpeed) {
|
||||
if (!formData.windSpeed) {
|
||||
errors.windSpeed = true
|
||||
}
|
||||
|
||||
if (!_verticalSnowCover) {
|
||||
if (!formData.verticalSnowCover) {
|
||||
errors.verticalSnowCover = true
|
||||
}
|
||||
|
||||
if (!_installHeight) {
|
||||
if (!formData.installHeight) {
|
||||
errors.installHeight = true
|
||||
}
|
||||
|
||||
console.log('errors::', errors)
|
||||
// console.log('임시저장용::', errors)
|
||||
setIsFormValid(Object.keys(errors).length === 0)
|
||||
} else {
|
||||
// console.log('상세일때 폼체크')
|
||||
console.log('상세일때 폼체크')
|
||||
}
|
||||
}, [
|
||||
_dispCompanyName,
|
||||
_objectName,
|
||||
_objectNameOmit,
|
||||
_saleStoreId,
|
||||
_saleStoreLevel,
|
||||
// _otherSaleStoreId,
|
||||
_zipNo,
|
||||
// _otherSaleStoreLevel,
|
||||
_prefId,
|
||||
_address,
|
||||
_areaId,
|
||||
@ -330,24 +305,23 @@ export default function StuffDetail() {
|
||||
_installHeight,
|
||||
])
|
||||
|
||||
// 주소검색 API
|
||||
const onSearchPostNumber = () => {
|
||||
console.log('주소검색클릭!!')
|
||||
// 주소검색 팝업오픈
|
||||
const onSearchPostNumberPopOpen = () => {
|
||||
setShowAddressButtonValid(true)
|
||||
}
|
||||
|
||||
setShowButtonValid(true)
|
||||
//설계의뢰 팝업 오픈
|
||||
const onSearchDesignRequestPopOpen = () => {
|
||||
setShowDesignRequestButtonValid(true)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (prefValue !== '') {
|
||||
console.log('우편번호검색해서 값이왔어:::::::::::', prefValue)
|
||||
// 발전량시뮬레이션 지역 목록
|
||||
// /api/object/prefecture/도도부현코드/list
|
||||
get({ url: `/api/object/prefecture/${prefValue}/list` }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
console.log('발전량 시뮬레이션::::::::', res)
|
||||
//res에 areaId추가됨
|
||||
// form.setValue('areaId', res[0].areaId)
|
||||
form.setValue('areaId', res[0].prefId)
|
||||
// console.log('발전량 시뮬레이션::::::::', res)
|
||||
form.setValue('areaId', res[0].areaId)
|
||||
form.setValue('areaName', res[0].prefName)
|
||||
setAreaIdList(res)
|
||||
}
|
||||
@ -362,13 +336,11 @@ export default function StuffDetail() {
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEmptyArray(areaIdList)) {
|
||||
//도도부현넘기는지 발전량시뮬레이션지역 넘기는지 ->도도부현넘기기
|
||||
console.log('prefName::', form.watch('prefName'))
|
||||
let _prefName = form.watch('prefName')
|
||||
//http://localhost:8080/api/object/windSpeed/兵庫県/list
|
||||
// console.log('기준풍속 가져오는 API', _prefName)
|
||||
get({ url: `/api/object/windSpeed/${_prefName}/list` }).then((res) => {
|
||||
// console.log('res::', res)
|
||||
if (!isEmptyArray(res)) {
|
||||
// console.log('기준풍속결과:::::::::', res)
|
||||
setWindSpeedList(res)
|
||||
}
|
||||
})
|
||||
@ -409,10 +381,11 @@ export default function StuffDetail() {
|
||||
// 임시저장
|
||||
const onTempSave = async () => {
|
||||
const formData = form.getValues()
|
||||
|
||||
// console.log('formData::', formData)
|
||||
const params = {
|
||||
saleStoreId: formData.saleStoreId,
|
||||
saleStoreName: formData.saleStoreName,
|
||||
saleStoreId: formData.otherSaleStoreId ? formData.otherSaleStoreId : formData.saleStoreId,
|
||||
saleStoreName: formData.otherSaleStoreName ? formData.otherSaleStoreName : formData.saleStoreName,
|
||||
saleStoreLevel: formData.otherSaleStoreLevel ? formData.otherSaleStoreLevel : formData.saleStoreLevel,
|
||||
objectStatusId: formData.objectStatusId,
|
||||
objectName: formData.objectName,
|
||||
objectNameOmit: formData.objectNameOmit,
|
||||
@ -434,10 +407,19 @@ export default function StuffDetail() {
|
||||
workNo: null,
|
||||
workName: null,
|
||||
}
|
||||
//1차점 or 2차점 안고르고 임시저장하면
|
||||
if (params.saleStoreId == '') {
|
||||
params.saleStoreId = sessionState.storeId
|
||||
params.saleStoreLevel = sessionState.storeLevel
|
||||
}
|
||||
console.log('임시저장params::', params)
|
||||
// return
|
||||
await post({ url: '/api/object/save-object', data: params }).then((res) => {
|
||||
console.log('res::::::', res)
|
||||
if (res) {
|
||||
console.log('임시저장res::::::', res)
|
||||
setTempDetailData(res)
|
||||
alert('임시저장 되었습니다. 물건번호를 획득하려면 필수 항목을 모두 입력해 주십시오.')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -462,7 +444,8 @@ export default function StuffDetail() {
|
||||
<form onSubmit={handleSubmit(onValid)}>
|
||||
<div className="sub-table-box">
|
||||
<div className="promise-gudie">
|
||||
<span className="important">*</span> 필수 입력항목
|
||||
<span className="important">*</span>
|
||||
{getMessage('stuff.detail.required')}
|
||||
</div>
|
||||
<div className="infomation-table">
|
||||
<table>
|
||||
@ -471,9 +454,20 @@ export default function StuffDetail() {
|
||||
<col />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{getMessage('stuff.detail.designNo')}</th>
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
<div className="input-wrap mr5" style={{ width: '200px' }}></div>
|
||||
<button className="btn-origin grey" onClick={onSearchDesignRequestPopOpen}>
|
||||
{getMessage('stuff.planReqPopup.title')}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
담당자 <span className="important">*</span>
|
||||
{getMessage('stuff.detail.dispCompanyName')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '500px' }}>
|
||||
@ -489,18 +483,18 @@ export default function StuffDetail() {
|
||||
<div className="flx-box">
|
||||
<div className="d-check-radio light mr10">
|
||||
<input type="radio" name="objectStatusId" value="0" id="objectStatus0" {...form.register('objectStatusId')} />
|
||||
<label htmlFor="objectStatus0">신축</label>
|
||||
<label htmlFor="objectStatus0">{getMessage('stuff.detail.objectStatus0')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio light mr10">
|
||||
<input type="radio" name="objectStatusId" value="1" id="objectStatus1" {...form.register('objectStatusId')} />
|
||||
<label htmlFor="objectStatus0">기축</label>
|
||||
<label htmlFor="objectStatus1">{getMessage('stuff.detail.objectStatus1')}</label>
|
||||
</div>
|
||||
<div className="input-wrap mr5" style={{ width: '545px' }}>
|
||||
<input type="text" className="input-light" {...form.register('objectName')} />
|
||||
</div>
|
||||
<div className="select-wrap" style={{ width: '120px' }}>
|
||||
<select className="select-light" name="objectNameOmit" {...register('objectNameOmit')}>
|
||||
<option value="">경칭공통코드선택</option>
|
||||
<option value="">경칭선택</option>
|
||||
<option value="11">경칭11</option>
|
||||
<option value="22">경칭22</option>
|
||||
<option value="33">경칭33</option>
|
||||
@ -510,7 +504,7 @@ export default function StuffDetail() {
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>물건명 후리가나</th>
|
||||
<th>{getMessage('stuff.detail.objectNameKana')}</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '789px' }}>
|
||||
<input type="text" className="input-light" {...form.register('objectNameKana')} />
|
||||
@ -521,7 +515,7 @@ export default function StuffDetail() {
|
||||
<th>
|
||||
<div className="flx-box">
|
||||
<div className="title">
|
||||
1차 판매점명 / ID
|
||||
{getMessage('stuff.detail.saleStoreId')}
|
||||
<span className="important">*</span>
|
||||
</div>
|
||||
<div className="tooltips"></div>
|
||||
@ -549,7 +543,7 @@ export default function StuffDetail() {
|
||||
<tr>
|
||||
<th>
|
||||
<div className="flx-box">
|
||||
<div className="title">2차 판매점명 / ID</div>
|
||||
<div className="title">{getMessage('stuff.detail.otherSaleStoreId')}</div>
|
||||
<div className="tooltips"></div>
|
||||
</div>
|
||||
</th>
|
||||
@ -565,6 +559,8 @@ export default function StuffDetail() {
|
||||
clearable={true}
|
||||
onChange={onSelectionChange2}
|
||||
disabled={form.watch('saleStoreId') !== '' ? false : true}
|
||||
onClearAll={handleClear}
|
||||
ref={ref}
|
||||
></Select>
|
||||
</div>
|
||||
<div className="input-wrap" style={{ width: '216px' }}>
|
||||
@ -581,23 +577,24 @@ export default function StuffDetail() {
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
우편번호 <span className="important">*</span>
|
||||
{getMessage('stuff.detail.zipNo')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
<div className="input-wrap mr5" style={{ width: '200px' }}>
|
||||
<input type="text" className="input-light" disabled />
|
||||
<input type="text" className="input-light" disabled value={form.watch('zipNo')} />
|
||||
</div>
|
||||
<Button className="btn-origin grey" onClick={onSearchPostNumber}>
|
||||
주소검색
|
||||
<Button className="btn-origin grey" onClick={onSearchPostNumberPopOpen}>
|
||||
{getMessage('stuff.detail.btn.addressPop')}
|
||||
</Button>
|
||||
<div className="guide">*주소검색 버튼을 클릭한 후, 도도부현 정보를 선택해주십시오.</div>
|
||||
<div className="guide">{getMessage('stuff.detail.btn.addressPop.guide')}</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
도도부현 / 주소 <span className="important">*</span>
|
||||
{getMessage('stuff.detail.prefId')}
|
||||
<span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
@ -620,17 +617,15 @@ export default function StuffDetail() {
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
발전량시뮬레이션지역 <span className="important">*</span>
|
||||
{getMessage('stuff.detail.areaId')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="select-wrap" style={{ width: '200px' }}>
|
||||
<select
|
||||
className="select-light"
|
||||
name="areaId"
|
||||
onChange={(e) => {
|
||||
form.setValue('areaId', e.target.value)
|
||||
}}
|
||||
disabled={areaIdList?.length > 0 ? false : true}
|
||||
onChange={handleAreaIdOnChange}
|
||||
>
|
||||
{areaIdList.map((row) => {
|
||||
return (
|
||||
@ -645,7 +640,7 @@ export default function StuffDetail() {
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
기준풍속 <span className="important">*</span>
|
||||
{getMessage('stuff.detail.windSpeed')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
@ -660,14 +655,14 @@ export default function StuffDetail() {
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
<span className="mr10">m/s이하</span>
|
||||
<button className="btn-origin grey">풍속선택</button>
|
||||
<span className="mr10">{getMessage('stuff.detail.windSpeedSpan')}</span>
|
||||
<button className="btn-origin grey">{getMessage('stuff.detail.btn.windSpeedPop')}</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
수직적설량 <span className="important">*</span>
|
||||
{getMessage('stuff.detail.verticalSnowCover')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
@ -681,14 +676,14 @@ export default function StuffDetail() {
|
||||
<span className="mr10">cm</span>
|
||||
<div className="d-check-box light">
|
||||
<input type="checkbox" id="coldRegionFlg" {...form.register('coldRegionFlg')} />
|
||||
<label htmlFor="coldRegionFlg">한랭지대책시행</label>
|
||||
<label htmlFor="coldRegionFlg">{getMessage('stuff.detail.coldRegionFlg')}</label>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
면조도구분 <span className="important">*</span>
|
||||
{getMessage('stuff.detail.surfaceType')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
@ -702,7 +697,7 @@ export default function StuffDetail() {
|
||||
</div>
|
||||
<div className="d-check-box light mr5">
|
||||
<input type="checkbox" id="saltAreaFlg" {...form.register('saltAreaFlg')} />
|
||||
<label htmlFor="saltAreaFlg">염해지역용아이템사용</label>
|
||||
<label htmlFor="saltAreaFlg">{getMessage('stuff.detail.saltAreaFlg')}</label>
|
||||
</div>
|
||||
<div className="tooltips"></div>
|
||||
</div>
|
||||
@ -710,7 +705,7 @@ export default function StuffDetail() {
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
설치높이 <span className="important">*</span>
|
||||
{getMessage('stuff.detail.installHeight')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
@ -727,25 +722,25 @@ export default function StuffDetail() {
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>계약조건</th>
|
||||
<th>{getMessage('stuff.detail.conType')}</th>
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
<div className="d-check-radio light mr10">
|
||||
<input type="radio" name="conType" value="0" id="conType0" {...form.register('conType')} />
|
||||
<label htmlFor="conType0">잉여</label>
|
||||
<label htmlFor="conType0">{getMessage('stuff.detail.conType0')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio light mr10">
|
||||
<input type="radio" name="conType" value="1" id="conType1" {...form.register('conType')} />
|
||||
<label htmlFor="conType1">전량</label>
|
||||
<label htmlFor="conType1">{getMessage('stuff.detail.conType1')}</label>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>메모</th>
|
||||
<th>{getMessage('stuff.detail.remarks')}</th>
|
||||
<td>
|
||||
<div className="input-wrap">
|
||||
<input type="text" className="input-light" />
|
||||
<input type="text" className="input-light" {...form.register('remarks')} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -772,6 +767,21 @@ export default function StuffDetail() {
|
||||
</form>
|
||||
)) || (
|
||||
<>
|
||||
<form onSubmit={handleSubmit(onValid)}>
|
||||
<div className="sub-table-box">
|
||||
<div className="promise-gudie">
|
||||
<span className="important">*</span> 필수 입력항목
|
||||
</div>
|
||||
<div className="infomation-table">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style={{ width: '200px' }} />
|
||||
<col />
|
||||
</colgroup>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{objectNo.substring(0, 1) === 'R' ? (
|
||||
<>
|
||||
<Link href="/management/stuff">
|
||||
@ -788,20 +798,26 @@ export default function StuffDetail() {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{!isFormValid ? (
|
||||
<button type="submit" className="btn-origin navy mr5" onClick={onTempSave}>
|
||||
TEMP상세:임시저장
|
||||
</button>
|
||||
) : (
|
||||
<button type="submit" className="btn-origin navy mr5">
|
||||
TEMP상세:저장
|
||||
</button>
|
||||
)}
|
||||
<Link href="/management/stuff">
|
||||
<button type="button" className="btn-origin grey">
|
||||
T상세:물건목록
|
||||
</button>
|
||||
</Link>
|
||||
<button type="submit" className="btn-origin navy mr5">
|
||||
T상세:저장
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{showButtonValid && <FindAddressPop setShowButtonValid={setShowButtonValid} zipInfo={setZipInfo} />}
|
||||
<DesignRequestPop />
|
||||
{showAddressButtonValid && <FindAddressPop setShowAddressButtonValid={setShowAddressButtonValid} zipInfo={setZipInfo} />}
|
||||
{showDesignRequestButtonValid && <PlanRequestPop setShowDesignRequestButtonValid={setShowDesignRequestButtonValid} />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ export default function StuffQGrid(props) {
|
||||
flex: 1,
|
||||
sortable: false,
|
||||
suppressMovable: true,
|
||||
resizable: false,
|
||||
resizable: true,
|
||||
suppressSizeToFit: false,
|
||||
}
|
||||
}, [])
|
||||
@ -69,18 +69,12 @@ export default function StuffQGrid(props) {
|
||||
props.getCellDoubleClicked(event)
|
||||
}, [])
|
||||
|
||||
//컨텐츠에 따라 컬럼넓이 자동조절
|
||||
const autoSizeStrategy = useMemo(() => {
|
||||
return {
|
||||
type: 'fitCellContents',
|
||||
}
|
||||
}, [])
|
||||
|
||||
const onGridReady = useCallback((event) => {
|
||||
// 헤더 사이즈 조정 컬럼에 width값으로 계산
|
||||
event.api.sizeColumnsToFit()
|
||||
}, [])
|
||||
|
||||
// Fetch data & update rowData state
|
||||
useEffect(() => {
|
||||
gridData ? setRowData(gridData) : ''
|
||||
@ -97,7 +91,6 @@ export default function StuffQGrid(props) {
|
||||
<div className="ag-theme-quartz" style={{ height: 500 }}>
|
||||
<AgGridReact
|
||||
ref={gridRef}
|
||||
onGridReady={onGridReady}
|
||||
rowBuffer={rowBuffer}
|
||||
rowData={rowData}
|
||||
columnDefs={colDefs}
|
||||
@ -108,10 +101,9 @@ export default function StuffQGrid(props) {
|
||||
onSelectionChanged={onSelectionChanged}
|
||||
onCellDoubleClicked={onCellDoubleClicked}
|
||||
pagination={isPageable}
|
||||
autoSizeStrategy={autoSizeStrategy}
|
||||
overlayNoRowsTemplate={'<span className="ag-overlay-loading-center">물건 목록이 없습니다.</span>'}
|
||||
// getRowStyle={getRowStyle}
|
||||
getRowClass={getRowClass}
|
||||
autoSizeAllColumns={true}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -110,7 +110,6 @@ export default function StuffSearchCondition() {
|
||||
|
||||
//초기화 눌렀을 때 자동완성도..
|
||||
const handleClear = () => {
|
||||
// console.log('ref::', ref.current.state.values)
|
||||
if (ref.current.state.dropDown) {
|
||||
ref.current.methods.dropDown()
|
||||
} else {
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
import React from 'react'
|
||||
|
||||
export default function DesignRequestPop() {
|
||||
return <div></div>
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState, useRef } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { queryStringFormatter } from '@/util/common-utils'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
@ -6,7 +6,7 @@ import { globalLocaleStore } from '@/store/localeAtom'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import FindAddressPopQGrid from './FindAddressPopQGrid'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
|
||||
import { isNotEmptyArray } from '@/util/common-utils'
|
||||
export default function FindAddressPop(props) {
|
||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||
|
||||
@ -14,17 +14,37 @@ export default function FindAddressPop(props) {
|
||||
|
||||
const { getMessage } = useMessage()
|
||||
|
||||
const [prefId, setPrefId] = useState('')
|
||||
const [address1, setAddress1] = useState('')
|
||||
const [address2, setAddress2] = useState('')
|
||||
const [address3, setAddress3] = useState('')
|
||||
const gridRef = useRef()
|
||||
const [prefId, setPrefId] = useState(null)
|
||||
const [zipNo, setZipNo] = useState(null)
|
||||
const [address1, setAddress1] = useState(null)
|
||||
const [address2, setAddress2] = useState(null)
|
||||
const [address3, setAddress3] = useState(null)
|
||||
|
||||
const [gridProps, setGridProps] = useState({
|
||||
gridData: [],
|
||||
isPageable: false,
|
||||
gridColumns: [],
|
||||
gridColumns: [
|
||||
{
|
||||
field: 'address1',
|
||||
headerName: getMessage('stuff.addressPopup.gridHeader.address1'),
|
||||
minWidth: 150,
|
||||
checkboxSelection: true,
|
||||
showDisabledCheckboxes: true,
|
||||
},
|
||||
{
|
||||
field: 'address2',
|
||||
headerName: getMessage('stuff.addressPopup.gridHeader.address2'),
|
||||
minWidth: 150,
|
||||
},
|
||||
{
|
||||
field: 'address3',
|
||||
headerName: getMessage('stuff.addressPopup.gridHeader.address3'),
|
||||
minWidth: 150,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
//검색필드
|
||||
const formInitValue = {
|
||||
zipNo: '',
|
||||
}
|
||||
@ -33,38 +53,46 @@ export default function FindAddressPop(props) {
|
||||
})
|
||||
|
||||
const form = { register, setValue, getValues, handleSubmit, resetField, control, watch }
|
||||
|
||||
//우편번호 검색
|
||||
const searchPostNum = () => {
|
||||
// //7830060
|
||||
// //9302226
|
||||
// //0790177 3개짜리
|
||||
console.log(watch('zipNo'))
|
||||
const params = {
|
||||
zipcode: watch('zipNo'),
|
||||
}
|
||||
|
||||
get({ url: `https://zipcloud.ibsnet.co.jp/api/search?${queryStringFormatter(params)}` }).then((res) => {
|
||||
console.log('우편조회 API결과:::::', res)
|
||||
if (res.status === 200) {
|
||||
if (isNotEmptyArray(res.results)) {
|
||||
setGridProps({ ...gridProps, gridData: res.results })
|
||||
} else {
|
||||
setGridProps({ ...gridProps, gridData: [] })
|
||||
}
|
||||
} else {
|
||||
alert('등록된 우편번호에서 주소를 찾을 수 없습니다. 다시 입력해주세요.')
|
||||
alert(getMessage('stuff.addressPopup.error.message1'))
|
||||
setGridProps({ ...gridProps, gridData: [] })
|
||||
}
|
||||
})
|
||||
}
|
||||
// 주소적용 클릭
|
||||
const zipInfo = () => {
|
||||
console.log('주소적용 클릭:::::::::')
|
||||
// setAddress3('3333')
|
||||
// setAddress3('4444')
|
||||
// setAddress3('5555')
|
||||
props.zipInfo({
|
||||
zipNo: '3434343',
|
||||
address1: '3333',
|
||||
address2: '4444',
|
||||
address3: '5555',
|
||||
})
|
||||
const applyAddress = () => {
|
||||
// console.log('주소적용 클릭:::::::::', prefId, address1, address2, address3, zipNo)
|
||||
if (prefId == null) {
|
||||
alert('stuff.addressPopup.error.message2')
|
||||
} else {
|
||||
props.zipInfo({
|
||||
zipNo: zipNo,
|
||||
address1: address1,
|
||||
address2: address2,
|
||||
address3: address3,
|
||||
prefId: prefId,
|
||||
})
|
||||
|
||||
props.setShowButtonValid(false)
|
||||
//팝업닫기
|
||||
props.setShowAddressButtonValid(false)
|
||||
}
|
||||
}
|
||||
|
||||
//숫자만
|
||||
@ -72,13 +100,31 @@ export default function FindAddressPop(props) {
|
||||
let input = e.target
|
||||
input.value = input.value.replace(/[^0-9]/g, '')
|
||||
}
|
||||
|
||||
//그리드에서 선택한 우편정보
|
||||
const getSelectedRowdata = (data) => {
|
||||
if (isNotEmptyArray(data)) {
|
||||
setAddress1(data[0].address1)
|
||||
setAddress2(data[0].address2)
|
||||
setAddress3(data[0].address3)
|
||||
setPrefId(data[0].prefcode)
|
||||
setZipNo(data[0].zipcode)
|
||||
} else {
|
||||
setAddress1(null)
|
||||
setAddress2(null)
|
||||
setAddress3(null)
|
||||
setPrefId(null)
|
||||
setZipNo(null)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="modal-popup">
|
||||
<div className="modal-dialog middle">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h1 className="title">{getMessage('stuff.addressPopup.title')}</h1>
|
||||
<button className="modal-close" onClick={() => props.setShowButtonValid(false)}>
|
||||
<button className="modal-close" onClick={() => props.setShowAddressButtonValid(false)}>
|
||||
닫기
|
||||
</button>
|
||||
</div>
|
||||
@ -96,14 +142,14 @@ export default function FindAddressPop(props) {
|
||||
<button className="search-btn" onClick={searchPostNum}></button>
|
||||
</div>
|
||||
<div className="address-grid">
|
||||
<FindAddressPopQGrid {...gridProps} gridRef={gridRef} />
|
||||
<FindAddressPopQGrid {...gridProps} getSelectedRowdata={getSelectedRowdata} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer-btn-wrap">
|
||||
<button className="btn-origin grey mr5" onClick={() => props.setShowButtonValid(false)}>
|
||||
<button className="btn-origin grey mr5" onClick={() => props.setShowAddressButtonValid(false)}>
|
||||
{getMessage('stuff.addressPopup.btn1')}
|
||||
</button>
|
||||
<button className="btn-origin navy " onClick={zipInfo}>
|
||||
<button className="btn-origin navy " onClick={applyAddress}>
|
||||
{getMessage('stuff.addressPopup.btn2')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,66 @@
|
||||
import React from 'react'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { AgGridReact } from 'ag-grid-react'
|
||||
|
||||
import 'ag-grid-community/styles/ag-grid.css'
|
||||
import 'ag-grid-community/styles/ag-theme-quartz.css'
|
||||
|
||||
export default function FindAddressPopGrid(props) {
|
||||
const { gridData, gridColumns, isPageable = true, gridRef } = props
|
||||
return <div></div>
|
||||
const { gridData, gridColumns, isPageable = true } = props
|
||||
|
||||
const [rowData, setRowData] = useState(null)
|
||||
|
||||
const [gridApi, setGridApi] = useState(null)
|
||||
|
||||
const [colDefs, setColDefs] = useState(gridColumns)
|
||||
|
||||
const defaultColDef = useMemo(() => {
|
||||
return {
|
||||
flex: 1,
|
||||
minWidth: 100,
|
||||
sortable: false,
|
||||
suppressMovable: false,
|
||||
resizable: false,
|
||||
suppressSizeToFit: false,
|
||||
}
|
||||
}, [])
|
||||
|
||||
const rowBuffer = 100
|
||||
|
||||
useEffect(() => {
|
||||
gridData ? setRowData(gridData) : ''
|
||||
}, [gridData])
|
||||
|
||||
const rowSelection = useMemo(() => {
|
||||
return { mode: 'singleRow', enableClickSelection: true }
|
||||
}, [])
|
||||
|
||||
const onGridReady = useCallback(
|
||||
(params) => {
|
||||
setGridApi(params.api)
|
||||
gridData ? setRowData(gridData) : ''
|
||||
},
|
||||
[gridData],
|
||||
)
|
||||
|
||||
//부모로 선택한 우편정보 보내기
|
||||
const onSelectionChanged = () => {
|
||||
const selectedData = gridApi.getSelectedRows()
|
||||
props.getSelectedRowdata(selectedData)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ag-theme-quartz" style={{ height: 500 }}>
|
||||
<AgGridReact
|
||||
onGridReady={onGridReady}
|
||||
rowBuffer={rowBuffer}
|
||||
rowData={rowData}
|
||||
columnDefs={colDefs}
|
||||
defaultColDef={defaultColDef}
|
||||
rowSelection={rowSelection}
|
||||
pagination={isPageable}
|
||||
onSelectionChanged={onSelectionChanged}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
169
src/components/management/popup/PlanRequestPop.jsx
Normal file
169
src/components/management/popup/PlanRequestPop.jsx
Normal file
@ -0,0 +1,169 @@
|
||||
import React, { useState } from 'react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { queryStringFormatter } from '@/util/common-utils'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { globalLocaleStore } from '@/store/localeAtom'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import FindAddressPopQGrid from './FindAddressPopQGrid'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { isNotEmptyArray } from '@/util/common-utils'
|
||||
import SingleDatePicker from '@/components/common/datepicker/SingleDatePicker'
|
||||
import dayjs from 'dayjs'
|
||||
export default function PlanRequestPop(props) {
|
||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||
|
||||
const { get } = useAxios(globalLocaleState)
|
||||
|
||||
const { getMessage } = useMessage()
|
||||
// 검색조건 달력 셋팅
|
||||
const [startDate, setStartDate] = useState(dayjs(new Date()).add(-3, 'month').format('YYYY-MM-DD'))
|
||||
const [endDate, setEndDate] = useState(dayjs(new Date()).format('YYYY-MM-DD'))
|
||||
|
||||
const rangeDatePickerProps1 = {
|
||||
startDate, //시작일
|
||||
setStartDate,
|
||||
}
|
||||
|
||||
const rangeDatePickerProps2 = {
|
||||
startDate: endDate, //종료일
|
||||
setStartDate: setEndDate,
|
||||
}
|
||||
|
||||
const [gridProps, setGridProps] = useState({
|
||||
gridData: [],
|
||||
isPageable: false,
|
||||
gridColumns: [
|
||||
{
|
||||
field: 'address1',
|
||||
headerName: getMessage('stuff.addressPopup.gridHeader.address1'),
|
||||
minWidth: 150,
|
||||
checkboxSelection: true,
|
||||
showDisabledCheckboxes: true,
|
||||
},
|
||||
{
|
||||
field: 'address2',
|
||||
headerName: getMessage('stuff.addressPopup.gridHeader.address2'),
|
||||
minWidth: 150,
|
||||
},
|
||||
{
|
||||
field: 'address3',
|
||||
headerName: getMessage('stuff.addressPopup.gridHeader.address3'),
|
||||
minWidth: 150,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
//검색필드
|
||||
const formInitValue = {
|
||||
//zipNo: '',
|
||||
}
|
||||
|
||||
const { register, setValue, getValues, handleSubmit, resetField, control, watch } = useForm({
|
||||
defaultValues: formInitValue,
|
||||
})
|
||||
|
||||
const form = { register, setValue, getValues, handleSubmit, resetField, control, watch }
|
||||
|
||||
return (
|
||||
<div className="modal-popup">
|
||||
<div className="modal-dialog big">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h1 className="title">{getMessage('stuff.planReqPopup.title')}</h1>
|
||||
<button className="modal-close" onClick={() => props.setShowDesignRequestButtonValid(false)}>
|
||||
닫기
|
||||
</button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<div className="modal-body-inner">
|
||||
<div className="design-request-table">
|
||||
<div className="common-table">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style={{ width: '160px' }} />
|
||||
<col />
|
||||
<col style={{ width: '160px' }} />
|
||||
<col />
|
||||
<col style={{ width: '160px' }} />
|
||||
<col />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>설계의뢰번호 / 設計依頼番号</th>
|
||||
<td>
|
||||
<div className="input-wrap">
|
||||
<input type="text" className="input-light" />
|
||||
</div>
|
||||
</td>
|
||||
<th>안건명 / 案件名</th>
|
||||
<td>
|
||||
<div className="input-wrap">
|
||||
<input type="text" className="input-light" />
|
||||
</div>
|
||||
</td>
|
||||
<th>도도부현 / 都道府県</th>
|
||||
<td>
|
||||
<div className="input-wrap">
|
||||
<input type="text" className="input-light" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>판매대리점명 / 販売代理店名</th>
|
||||
<td>
|
||||
<div className="input-wrap">
|
||||
<input type="text" className="input-light" />
|
||||
</div>
|
||||
</td>
|
||||
<th>의뢰자명 / 依頼者名</th>
|
||||
<td>
|
||||
<div className="input-wrap">
|
||||
<input type="text" className="input-light" />
|
||||
</div>
|
||||
</td>
|
||||
<th>상태 / 状態</th>
|
||||
<td>
|
||||
<div className="select-wrap">
|
||||
<select className="select-light" name="" id="">
|
||||
<option>All</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>기간검색 / 期間検索</th>
|
||||
<td colSpan={5}>
|
||||
<div className="form-flex-wrap">
|
||||
<div className="radio-wrap mr10">
|
||||
<div className="d-check-radio light mr10">
|
||||
<input type="radio" name="radio04" id="ra07" />
|
||||
<label htmlFor="ra07">제출일 / 提出日</label>
|
||||
</div>
|
||||
<div className="d-check-radio light">
|
||||
<input type="radio" name="radio04" id="ra08" />
|
||||
<label htmlFor="ra08">접수일 / 受付日</label>
|
||||
</div>
|
||||
<div className="date-picker-wrap">
|
||||
<div className="date-picker" style={{ flex: 1 }}>
|
||||
<SingleDatePicker {...rangeDatePickerProps1} />
|
||||
</div>
|
||||
<span> ~ </span>
|
||||
<div className="date-picker" style={{ flex: 1 }}>
|
||||
<SingleDatePicker {...rangeDatePickerProps2} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -1,6 +1,210 @@
|
||||
'use client'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
import { INPUT_TYPE, BATCH_TYPE } from '@/common/common'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
import { polygonToTurfPolygon, rectToPolygon, pointsToTurfPolygon } from '@/util/canvas-util'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import * as turf from '@turf/turf'
|
||||
|
||||
export function useObjectBatch() {
|
||||
const { getMessage } = useMessage()
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const { addCanvasMouseEventListener, initEvent } = useEvent()
|
||||
const { swalFire } = useSwal()
|
||||
|
||||
const openObjectBatch = () => {}
|
||||
const applyOpeningAndShadow = (objectPlacement, buttonAct, surfaceShapePolygons, setShowObjectSettingModal) => {
|
||||
const selectedType = objectPlacement.typeRef.current.find((radio) => radio.checked).value
|
||||
const isCrossChecked = buttonAct === 1 ? objectPlacement.isCrossRef.current.checked : false
|
||||
const objTempName = buttonAct === 1 ? BATCH_TYPE.OPENING_TEMP : BATCH_TYPE.SHADOW_TEMP
|
||||
const objName = buttonAct === 1 ? BATCH_TYPE.OPENING : BATCH_TYPE.SHADOW
|
||||
|
||||
let rect, isDown, origX, origY
|
||||
let selectedSurface
|
||||
|
||||
//프리입력
|
||||
if (selectedType === INPUT_TYPE.FREE) {
|
||||
addCanvasMouseEventListener('mouse:down', (e) => {
|
||||
isDown = true
|
||||
const pointer = canvas.getPointer(e.e)
|
||||
|
||||
surfaceShapePolygons.forEach((surface) => {
|
||||
if (surface.inPolygon({ x: pointer.x, y: pointer.y })) {
|
||||
selectedSurface = surface
|
||||
}
|
||||
})
|
||||
|
||||
if (!selectedSurface) {
|
||||
swalFire({ text: '지붕안에 그려야해요', icon: 'error' })
|
||||
initEvent() //이벤트 초기화
|
||||
return
|
||||
}
|
||||
|
||||
origX = pointer.x
|
||||
origY = pointer.y
|
||||
|
||||
rect = new fabric.Rect({
|
||||
left: origX,
|
||||
top: origY,
|
||||
originX: 'left',
|
||||
originY: 'top',
|
||||
width: 0,
|
||||
height: 0,
|
||||
angle: 0,
|
||||
stroke: 'black',
|
||||
})
|
||||
|
||||
//개구냐 그림자냐에 따라 변경
|
||||
rect.set({
|
||||
fill: buttonAct === 1 ? 'white' : 'rgba(0, 0, 0, 0.4)',
|
||||
name: objTempName,
|
||||
})
|
||||
|
||||
canvas?.add(rect)
|
||||
})
|
||||
|
||||
addCanvasMouseEventListener('mouse:move', (e) => {
|
||||
if (!isDown) return
|
||||
|
||||
if (selectedSurface) {
|
||||
const pointer = canvas.getPointer(e.e)
|
||||
const width = pointer.x - origX
|
||||
const height = pointer.y - origY
|
||||
|
||||
rect.set({ width: Math.abs(width), height: Math.abs(height) })
|
||||
|
||||
if (width < 0) {
|
||||
rect.set({ left: Math.abs(pointer.x) })
|
||||
}
|
||||
if (height < 0) {
|
||||
rect.set({ top: Math.abs(pointer.y) })
|
||||
}
|
||||
|
||||
canvas?.renderAll()
|
||||
}
|
||||
})
|
||||
|
||||
addCanvasMouseEventListener('mouse:up', (e) => {
|
||||
if (rect) {
|
||||
const rectPolygon = pointsToTurfPolygon(rectToPolygon(rect))
|
||||
const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface)
|
||||
|
||||
//지붕 밖으로 그렸을때
|
||||
if (!turf.booleanWithin(rectPolygon, selectedSurfacePolygon)) {
|
||||
swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' })
|
||||
//일단 지워
|
||||
deleteTempObjects(setShowObjectSettingModal)
|
||||
return
|
||||
}
|
||||
|
||||
if (!isCrossChecked) {
|
||||
const preObjects = canvas?.getObjects().filter((obj) => obj.name === BATCH_TYPE.OPENING || obj.name === BATCH_TYPE.SHADOW)
|
||||
const preObjectsArray = preObjects.map((obj) => rectToPolygon(obj))
|
||||
const isCross = preObjectsArray.some((object) => turf.booleanOverlap(pointsToTurfPolygon(object), rectPolygon))
|
||||
|
||||
if (isCross) {
|
||||
swalFire({ text: '겹치기 불가요...', icon: 'error' })
|
||||
deleteTempObjects(setShowObjectSettingModal)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
isDown = false
|
||||
rect.set({ name: objName })
|
||||
rect.setCoords()
|
||||
initEvent()
|
||||
}
|
||||
})
|
||||
} else if (selectedType === INPUT_TYPE.DIMENSION) {
|
||||
const width = objectPlacement.widthRef.current.value / 10
|
||||
const height = objectPlacement.heightRef.current.value / 10
|
||||
|
||||
if (width === '' || height === '' || width <= 0 || height <= 0) {
|
||||
swalFire({ text: getMessage('common.canvas.validate.size'), icon: 'error' })
|
||||
return
|
||||
}
|
||||
|
||||
// setShowObjectSettingModal(false) //메뉴보이고
|
||||
addCanvasMouseEventListener('mouse:move', (e) => {
|
||||
isDown = true
|
||||
if (!isDown) return
|
||||
|
||||
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === objTempName)) //움직일때 일단 지워가면서 움직임
|
||||
const pointer = canvas.getPointer(e.e)
|
||||
|
||||
surfaceShapePolygons.forEach((surface) => {
|
||||
if (surface.inPolygon({ x: pointer.x, y: pointer.y })) {
|
||||
selectedSurface = surface
|
||||
}
|
||||
})
|
||||
|
||||
rect = new fabric.Rect({
|
||||
fill: 'white',
|
||||
stroke: 'black',
|
||||
strokeWidth: 1,
|
||||
width: width,
|
||||
height: height,
|
||||
left: pointer.x - width / 2,
|
||||
top: pointer.y - height / 2,
|
||||
selectable: true,
|
||||
lockMovementX: true,
|
||||
lockMovementY: true,
|
||||
lockRotation: true,
|
||||
lockScalingX: true,
|
||||
lockScalingY: true,
|
||||
})
|
||||
|
||||
//개구냐 그림자냐에 따라 변경
|
||||
rect.set({
|
||||
fill: buttonAct === 1 ? 'white' : 'rgba(0, 0, 0, 0.4)',
|
||||
name: objTempName,
|
||||
})
|
||||
|
||||
canvas?.add(rect)
|
||||
})
|
||||
|
||||
addCanvasMouseEventListener('mouse:up', (e) => {
|
||||
if (rect) {
|
||||
const rectPolygon = pointsToTurfPolygon(rectToPolygon(rect))
|
||||
const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface)
|
||||
|
||||
//지붕 밖으로 그렸을때
|
||||
if (!turf.booleanWithin(rectPolygon, selectedSurfacePolygon)) {
|
||||
swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' })
|
||||
//일단 지워
|
||||
deleteTempObjects(setShowObjectSettingModal)
|
||||
return
|
||||
}
|
||||
|
||||
if (!isCrossChecked) {
|
||||
const preObjects = canvas?.getObjects().filter((obj) => obj.name === BATCH_TYPE.OPENING || obj.name === BATCH_TYPE.SHADOW)
|
||||
const preObjectsArray = preObjects.map((obj) => rectToPolygon(obj))
|
||||
const isCross = preObjectsArray.some((object) => turf.booleanOverlap(pointsToTurfPolygon(object), rectPolygon))
|
||||
|
||||
if (isCross) {
|
||||
swalFire({ text: '겹치기 불가요...', icon: 'error' })
|
||||
deleteTempObjects(setShowObjectSettingModal)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
isDown = false
|
||||
rect.set({ name: objName })
|
||||
rect.setCoords()
|
||||
initEvent()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const deleteTempObjects = (setShowObjectSettingModal) => {
|
||||
const deleteTarget = canvas?.getObjects().filter((obj) => obj.name === BATCH_TYPE.OPENING_TEMP || obj.name === BATCH_TYPE.SHADOW_TEMP)
|
||||
canvas?.remove(...deleteTarget)
|
||||
initEvent() //이벤트 초기화
|
||||
}
|
||||
|
||||
return {
|
||||
applyOpeningAndShadow,
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
import { MENU } from '@/common/common'
|
||||
import { MENU, BATCH_TYPE } from '@/common/common'
|
||||
import { getIntersectionPoint, setSurfaceShapePattern } from '@/util/canvas-util'
|
||||
import { degreesToRadians } from '@turf/turf'
|
||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||
@ -131,23 +131,23 @@ export function useSurfaceShapeBatch() {
|
||||
|
||||
if (surfaceId === 1) {
|
||||
if (length1 === 0) {
|
||||
swalFire({ text: getMessage('surface.shape.validate.size'), icon: 'error' })
|
||||
swalFire({ text: getMessage('common.canvas.validate.size'), icon: 'error' })
|
||||
check = false
|
||||
}
|
||||
if (length2 === 0) {
|
||||
if (length3 === 0) {
|
||||
swalFire({ text: getMessage('surface.shape.validate.size'), icon: 'error' })
|
||||
swalFire({ text: getMessage('common.canvas.validate.size'), icon: 'error' })
|
||||
check = false
|
||||
}
|
||||
}
|
||||
} else if ([2, 4].includes(surfaceId)) {
|
||||
if (length1 === 0 || length2 === 0) {
|
||||
swalFire({ text: getMessage('surface.shape.validate.size'), icon: 'error' })
|
||||
swalFire({ text: getMessage('common.canvas.validate.size'), icon: 'error' })
|
||||
check = false
|
||||
}
|
||||
} else if ([3, 5, 6, 15, 18].includes(surfaceId)) {
|
||||
if (length1 === 0 || length2 === 0 || length3 === 0) {
|
||||
swalFire({ text: getMessage('surface.shape.validate.size'), icon: 'error' })
|
||||
swalFire({ text: getMessage('common.canvas.validate.size'), icon: 'error' })
|
||||
check = false
|
||||
}
|
||||
if (surfaceId === 3 && length3 > length1) {
|
||||
@ -173,7 +173,7 @@ export function useSurfaceShapeBatch() {
|
||||
}
|
||||
} else if ([8, 12, 13, 16, 17].includes(surfaceId)) {
|
||||
if (length1 === 0 || length2 === 0 || length3 === 0 || length4 === 0) {
|
||||
swalFire({ text: getMessage('surface.shape.validate.size'), icon: 'error' })
|
||||
swalFire({ text: getMessage('common.canvas.validate.size'), icon: 'error' })
|
||||
check = false
|
||||
}
|
||||
|
||||
@ -201,7 +201,7 @@ export function useSurfaceShapeBatch() {
|
||||
}
|
||||
} else if ([7, 9, 10, 11, 14].includes(surfaceId)) {
|
||||
if (length1 === 0 || length2 === 0 || length3 === 0 || length4 === 0 || length5 === 0) {
|
||||
swalFire({ text: getMessage('surface.shape.validate.size'), icon: 'error' })
|
||||
swalFire({ text: getMessage('common.canvas.validate.size'), icon: 'error' })
|
||||
check = false
|
||||
}
|
||||
if (surfaceId === 9 || surfaceId === 10 || surfaceId === 11) {
|
||||
@ -564,7 +564,27 @@ export function useSurfaceShapeBatch() {
|
||||
|
||||
return points
|
||||
}
|
||||
|
||||
const deleteAllSurfacesAndObjects = () => {
|
||||
swalFire({
|
||||
text: '삭제 ㄱㄱ?',
|
||||
type: 'confirm',
|
||||
confirmFn: () => {
|
||||
canvas?.getObjects().forEach((obj) => {
|
||||
if (obj.name === MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH || obj.name === BATCH_TYPE.OPENING || obj.name === BATCH_TYPE.SHADOW) {
|
||||
canvas?.remove(obj)
|
||||
}
|
||||
})
|
||||
swalFire({ text: '삭제 완료 되었습니다.' })
|
||||
},
|
||||
denyFn: () => {
|
||||
swalFire({ text: '취소되었습니다.' })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
applySurfaceShape,
|
||||
deleteAllSurfacesAndObjects,
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,6 +54,7 @@ export function usePlan() {
|
||||
'y2',
|
||||
'attributes',
|
||||
'stickeyPoint',
|
||||
'text',
|
||||
])
|
||||
|
||||
const str = JSON.stringify(objs)
|
||||
@ -76,32 +77,49 @@ export function usePlan() {
|
||||
*/
|
||||
const checkModifiedCanvasPlan = () => {
|
||||
removeMouseLines()
|
||||
const canvasStr = addCanvas()
|
||||
const canvasStatus = dbToCanvasFormat(canvasToDbFormat(canvasStr))
|
||||
const canvasStatus = addCanvas()
|
||||
const initPlanData = initCanvasPlans.find((plan) => plan.id === currentCanvasPlan.id)
|
||||
if (JSON.parse(canvasStr).objects.length === 0 && initPlanData === undefined) {
|
||||
// 저장 안 된 빈 캔버스
|
||||
return false
|
||||
} else if (initPlanData && canvasStatus === initPlanData.canvasStatus) {
|
||||
// 저장 되어있고 변경사항 없는 캔버스
|
||||
return false
|
||||
|
||||
if (!initPlanData) {
|
||||
// 새로운 캔버스
|
||||
return JSON.parse(canvasStatus).objects.length > 0
|
||||
} else {
|
||||
return true
|
||||
// 저장된 캔버스
|
||||
if (canvasStatus === initPlanData.canvasStatus) {
|
||||
return false
|
||||
} else {
|
||||
// 각각 object들의 id 목록을 추출하여 비교
|
||||
const canvasObjsIds = getObjectIds(JSON.parse(canvasStatus).objects)
|
||||
const dbObjsIds = getObjectIds(JSON.parse(initPlanData.canvasStatus).objects)
|
||||
|
||||
return canvasObjsIds.length !== dbObjsIds.length || !canvasObjsIds.every((id, index) => id === dbObjsIds[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
const getObjectIds = (objects) => {
|
||||
return objects
|
||||
.filter((obj) => obj.hasOwnProperty('id'))
|
||||
.map((obj) => obj.id)
|
||||
.sort()
|
||||
}
|
||||
|
||||
/**
|
||||
* DB에 저장된 데이터를 canvas에서 사용할 수 있도록 포맷화
|
||||
*/
|
||||
const dbToCanvasFormat = (cs) => {
|
||||
return JSON.stringify(cs.replace(/##/g, '"').replace(/\\/g, '').slice(1, -1))
|
||||
// return JSON.stringify(cs.replace(/##/g, '"')) //.replace(/\\/g, ''))//.slice(1, -1))
|
||||
// JSON.stringify()를 사용하면 "가 \"로 바뀐다. 따라서, JSON.stringify를 제거
|
||||
// canvasToDbFormat()에서 \\의 상황을 없앴으므로 replace(/\\/g, '')를 제거
|
||||
return cs.replace(/##/g, '"')
|
||||
}
|
||||
|
||||
/**
|
||||
* canvas의 데이터를 DB에 저장할 수 있도록 포맷화
|
||||
*/
|
||||
const canvasToDbFormat = (cs) => {
|
||||
return JSON.stringify(cs).replace(/"/g, '##')
|
||||
// return JSON.stringify(cs).replace(/"/g, '##')
|
||||
// addCanvas()에서 JSON.stringify()를 거쳐서 나오는데, 또 감싸버려서 \가 \\로 된다. 따라서, JSON.stringify를 제거
|
||||
return cs.replace(/"/g, '##')
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,9 +148,7 @@ export function usePlan() {
|
||||
setInitCanvasPlans((initCanvasPlans) =>
|
||||
initCanvasPlans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)),
|
||||
)
|
||||
setPlans((plans) =>
|
||||
plans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)),
|
||||
)
|
||||
setPlans((plans) => plans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)))
|
||||
})
|
||||
.catch((error) => {
|
||||
swalFire({ text: error.message, icon: 'error' })
|
||||
|
||||
@ -383,8 +383,40 @@
|
||||
"stuff.message.periodError": "最大1年間閲覧可能.",
|
||||
"stuff.addressPopup.title": "郵便番号",
|
||||
"stuff.addressPopup.placeholder": "郵便番号の7桁を入力してください。",
|
||||
"stuff.addressPopup.error.message1": "登録された郵便番号に住所が見つかりません。もう一度入力してください。",
|
||||
"stuff.addressPopup.error.message2": "住所を選択してください.",
|
||||
"stuff.addressPopup.gridHeader.address1": "都道府県",
|
||||
"stuff.addressPopup.gridHeader.address2": "市区町村",
|
||||
"stuff.addressPopup.gridHeader.address3": "市区町村 以下",
|
||||
"stuff.addressPopup.btn1": "閉じる",
|
||||
"stuff.addressPopup.btn2": "住所適用",
|
||||
"stuff.planReqPopup.title": "設計依頼のインポート",
|
||||
"stuff.detail.required": "必須入力項目",
|
||||
"stuff.detail.designNo": "設計依頼No.",
|
||||
"stuff.detail.dispCompanyName": "担当者",
|
||||
"stuff.detail.objectStatusId": "物品区分/物件名",
|
||||
"stuff.detail.objectStatus0": "新築",
|
||||
"stuff.detail.objectStatus1": "基軸",
|
||||
"stuff.detail.objectNameKana": "商品名 ふりがな",
|
||||
"stuff.detail.saleStoreId": "一次販売店名/ID",
|
||||
"stuff.detail.otherSaleStoreId": "二次販売店名/ID",
|
||||
"stuff.detail.zipNo": "郵便番号 ",
|
||||
"stuff.detail.btn.addressPop": "住所検索",
|
||||
"stuff.detail.btn.addressPop.guide": "※ 郵便番号7桁を入力した後、アドレス検索ボタンをクリックしてください",
|
||||
"stuff.detail.prefId": "都道府県 / 住所 ",
|
||||
"stuff.detail.areaId": "発電量シミュレーション地域 ",
|
||||
"stuff.detail.windSpeed": "基準風速",
|
||||
"stuff.detail.windSpeedSpan": "m/s以下",
|
||||
"stuff.detail.btn.windSpeedPop": "風速選択",
|
||||
"stuff.detail.verticalSnowCover": "垂直説説",
|
||||
"stuff.detail.coldRegionFlg": "寒冷地対策施行",
|
||||
"stuff.detail.surfaceType": "面調図区分",
|
||||
"stuff.detail.saltAreaFlg": "塩害地域用アイテムの使用",
|
||||
"stuff.detail.installHeight": "設置高さ",
|
||||
"stuff.detail.conType": "契約条件",
|
||||
"stuff.detail.conType0": "余剰",
|
||||
"stuff.detail.conType1": "全量",
|
||||
"stuff.detail.remarks": "メモ",
|
||||
"length": "長さ",
|
||||
"height": "高さ",
|
||||
"output": "出力",
|
||||
@ -438,7 +470,7 @@
|
||||
"main.popup.login.validate1": "入力したパスワードが異なります。",
|
||||
"main.popup.login.validate2": "半角10文字以内で入力してください。",
|
||||
"main.popup.login.success": "パスワードが変更されました。",
|
||||
"surface.shape.validate.size": "寸法を入力してください.",
|
||||
"common.canvas.validate.size": "寸法を入力してください.",
|
||||
"surface.shape.validate.size.1to2": "①길이는 ②보다 큰 값을 넣어주세요.",
|
||||
"surface.shape.validate.size.1to3": "①길이는 ③보다 큰 값을 넣어주세요.",
|
||||
"surface.shape.validate.size.1to23": "①길이는 ②+③보다 큰 값을 넣어주세요.",
|
||||
|
||||
@ -387,8 +387,40 @@
|
||||
"stuff.message.periodError": "최대1년 조회 가능합니다.",
|
||||
"stuff.addressPopup.title": "우편번호",
|
||||
"stuff.addressPopup.placeholder": "우편번호의 7자리를 입력하세요.",
|
||||
"stuff.addressPopup.error.message1": "등록된 우편번호에서 주소를 찾을 수 없습니다. 다시 입력해주세요.",
|
||||
"stuff.addressPopup.error.message2": "주소를 선택해주세요.",
|
||||
"stuff.addressPopup.gridHeader.address1": "도도부현",
|
||||
"stuff.addressPopup.gridHeader.address2": "시구정촌",
|
||||
"stuff.addressPopup.gridHeader.address3": "시구정촌 이하",
|
||||
"stuff.addressPopup.btn1": "닫기",
|
||||
"stuff.addressPopup.btn2": "주소적용",
|
||||
"stuff.planReqPopup.title": "설계의뢰 불러오기",
|
||||
"stuff.detail.required": "필수 입력항목",
|
||||
"stuff.detail.designNo": "설계의뢰No.",
|
||||
"stuff.detail.dispCompanyName": "담당자",
|
||||
"stuff.detail.objectStatusId": "물건구분/물건명",
|
||||
"stuff.detail.objectStatus0": "신축",
|
||||
"stuff.detail.objectStatus1": "기축",
|
||||
"stuff.detail.objectNameKana": "물건명 후리가나",
|
||||
"stuff.detail.saleStoreId": "1차 판매점명 / ID",
|
||||
"stuff.detail.otherSaleStoreId": "2차 판매점명 / ID",
|
||||
"stuff.detail.zipNo": "우편번호",
|
||||
"stuff.detail.btn.addressPop": "주소검색",
|
||||
"stuff.detail.btn.addressPop.guide": "※ 주소검색 버튼을 클릭한 후, 도도부현 정보를 선택해주십시오.",
|
||||
"stuff.detail.prefId": "도도부현 / 주소",
|
||||
"stuff.detail.areaId": "발전량시뮬레이션지역",
|
||||
"stuff.detail.windSpeed": "기준풍속",
|
||||
"stuff.detail.windSpeedSpan": "m/s이하",
|
||||
"stuff.detail.btn.windSpeedPop": "풍속선택",
|
||||
"stuff.detail.verticalSnowCover": "수직적설량",
|
||||
"stuff.detail.coldRegionFlg": "한랭지대책시행",
|
||||
"stuff.detail.surfaceType": "면조도구분",
|
||||
"stuff.detail.saltAreaFlg": "염해지역용아이템사용",
|
||||
"stuff.detail.installHeight": "설치높이",
|
||||
"stuff.detail.conType": "계약조건",
|
||||
"stuff.detail.conType0": "잉여",
|
||||
"stuff.detail.conType1": "전량",
|
||||
"stuff.detail.remarks": "메모",
|
||||
"length": "길이",
|
||||
"height": "높이",
|
||||
"output": "출력",
|
||||
@ -442,7 +474,7 @@
|
||||
"main.popup.login.validate1": "입력한 패스워드가 다릅니다.",
|
||||
"main.popup.login.validate2": "반각 10자 이내로 입력해주세요.",
|
||||
"main.popup.login.success": "비밀번호가 변경되었습니다.",
|
||||
"surface.shape.validate.size": "사이즈를 입력해 주세요.",
|
||||
"common.canvas.validate.size": "사이즈를 입력해 주세요.",
|
||||
"surface.shape.validate.size.1to2": "①길이는 ②보다 큰 값을 넣어주세요.",
|
||||
"surface.shape.validate.size.1to3": "①길이는 ③보다 큰 값을 넣어주세요.",
|
||||
"surface.shape.validate.size.1to23": "①길이는 ②+③보다 큰 값을 넣어주세요.",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user