diff --git a/src/app/[locale]/management/stuff/detail/page.jsx b/src/app/[locale]/management/stuff/detail/page.jsx
new file mode 100644
index 00000000..8b84287a
--- /dev/null
+++ b/src/app/[locale]/management/stuff/detail/page.jsx
@@ -0,0 +1,15 @@
+import React from 'react'
+import Hero from '@/components/Hero'
+import StuffDetail from '@/components/management/StuffDetail'
+export default function ManagementStuffDetailPage() {
+ return (
+ <>
+
+
+
+
>
diff --git a/src/components/common/datepicker/RangeDatePicker.jsx b/src/components/common/datepicker/RangeDatePicker.jsx
index ad802f49..de80221f 100644
--- a/src/components/common/datepicker/RangeDatePicker.jsx
+++ b/src/components/common/datepicker/RangeDatePicker.jsx
@@ -14,6 +14,7 @@ export default function RangeDatePicker(props) {
setDateRange(update)
}}
isClearable={true}
+ // showMonthYearPicker={true}
/>
)
}
diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx
index da7b834d..ba463744 100644
--- a/src/components/management/Stuff.jsx
+++ b/src/components/management/Stuff.jsx
@@ -1,7 +1,372 @@
+'use client'
+
+import React, { useEffect, useState, useRef } from 'react'
+import { useRouter, usePathname } from 'next/navigation'
+import { Button } from '@nextui-org/react'
+import { useAxios } from '@/hooks/useAxios'
+import { QToast } from '@/hooks/useToast'
+import StuffQGrid from './StuffQGrid'
+import { useI18n } from '@/locales/client'
+import { useRecoilValue } from 'recoil'
+import { stuffSearchState } from '@/store/stuffAtom'
+import { queryStringFormatter } from '@/util/common-utils'
+import dayjs from 'dayjs'
+import isLeapYear from 'dayjs/plugin/isLeapYear' // 윤년 판단 플러그인
+dayjs.extend(isLeapYear)
+
export default function Stuff() {
+ const stuffSearchParams = useRecoilValue(stuffSearchState)
+
+ const { get, del } = useAxios()
+ const gridRef = useRef()
+ const lang = useI18n()
+
+ const [gridCount, setGridCount] = useState(0)
+ const [selectedRowData, setSelectedRowData] = useState([])
+ const [selectedRowDataCount, setSelectedRowDataCount] = useState(0)
+
+ const router = useRouter()
+ const pathname = usePathname()
+
+ //그리드 내부 복사버튼
+ const copyNo = async (value) => {
+ try {
+ await navigator.clipboard.writeText(value)
+ QToast({
+ message: `${value}물건번호가 복사되었습니다`,
+ type: 'info',
+ })
+ } catch (error) {
+ QToast({
+ message: `클립보드 복사에 실패하였습니다`,
+ type: 'error',
+ })
+ }
+ }
+
+ const [gridProps, setGridProps] = useState({
+ gridData: [],
+ isPageable: false,
+ // sets 10 rows per page (default is 100)
+ paginationPageSize: 100,
+ // allows the user to select the page size from a predefined list of page sizes
+ paginationPageSizeSelector: [100, 200, 300, 400],
+ gridColumns: [
+ {
+ field: 'lastEditDatetime',
+ headerName: lang('stuff.gridHeader.lastEditDatetime'),
+ headerCheckboxSelection: true,
+ headerCheckboxSelectionCurrentPageOnly: true, //페이징시 현재 페이지만 체크되도록
+ checkboxSelection: true,
+ showDisabledCheckboxes: true,
+ // headerClass: 'centered', //_test.scss에 추가 테스트
+ // .centered {
+ // .ag-header-cell-label {
+ // justify-content: center !important;
+ // }
+ // }
+ cellStyle: { textAlign: 'center' },
+ //suppressMovable: true, //헤더 못움직이게
+ // width : 100
+ // minWidth : 100
+ // maxWidth : 100
+ valueFormatter: function (params) {
+ if (params.value) {
+ return dayjs(params?.value).format('YYYY.MM.DD HH:mm:ss')
+ } else {
+ return null
+ }
+ },
+ },
+ {
+ field: 'objectNo',
+ headerName: lang('stuff.gridHeader.objectNo'),
+ // headerClass: 'centered', //_test.scss에 추가 테스트
+ cellRenderer: function (params) {
+ if (params.data.objectNo) {
+ return (
+
+
+ {params.value}
+
+ )
+ }
+ },
+ cellRendererParams: {
+ onPress: copyNo,
+ },
+ },
+ {
+ field: 'planTotCnt',
+ headerName: lang('stuff.gridHeader.planTotCnt'),
+ cellStyle: { textAlign: 'right' },
+ },
+ { field: 'objectName', headerName: lang('stuff.gridHeader.objectName'), cellStyle: { textAlign: 'left' } },
+ {
+ field: 'saleStoreId',
+ headerName: lang('stuff.gridHeader.saleStoreId'),
+ cellStyle: { textAlign: 'left' },
+ },
+ { field: 'saleStoreName', headerName: lang('stuff.gridHeader.saleStoreName'), cellStyle: { textAlign: 'left' } },
+ { field: 'address', headerName: lang('stuff.gridHeader.address'), cellStyle: { textAlign: 'left' } },
+ { field: 'dispCompanyName', headerName: lang('stuff.gridHeader.dispCompanyName'), cellStyle: { textAlign: 'left' } },
+ { field: 'receiveUser', headerName: lang('stuff.gridHeader.receiveUser'), cellStyle: { textAlign: 'left' } },
+ {
+ field: 'specDate',
+ headerName: lang('stuff.gridHeader.specDate'),
+ valueFormatter: function (params) {
+ if (params.value) {
+ return dayjs(params?.value).format('YYYY.MM.DD')
+ } else {
+ return null
+ }
+ },
+ cellStyle: { textAlign: 'center' },
+ },
+ {
+ field: 'createDatetime',
+ headerName: lang('stuff.gridHeader.createDatetime'),
+ valueFormatter: function (params) {
+ if (params.value) {
+ return dayjs(params?.value).format('YYYY.MM.DD')
+ } else {
+ return null
+ }
+ },
+ cellStyle: { textAlign: 'center' },
+ },
+ ],
+ gridCount: 0,
+ })
+
+ //그리드 더블클릭
+ const getCellDoubleClicked = (event) => {
+ if (event.column.colId === 'objectNo') {
+ return
+ } else {
+ console.log(' 상세이동::::::::', event.data)
+ if (event.data.objectNo) {
+ router.push(`${pathname}/detail?objectNo=${event.data.objectNo.toString()}`)
+ } else {
+ QToast({
+ message: '물건정보가 없습니다',
+ type: 'error',
+ })
+ }
+ }
+ }
+
+ //그리드 체크박스 선택시
+ const getSelectedRowdata = (data) => {
+ // console.log('data:::', data)
+ // let delData = data.map((row) => {
+ // return row.objectNo
+ // })
+ // console.log('delData::', delData)
+ setSelectedRowData(data)
+ setSelectedRowDataCount(data.length)
+ }
+
+ //물건삭제
+ const fnDeleteRowData = (data) => {
+ console.log('물건삭제:::::::::::')
+ if (data.length === 0) {
+ QToast({
+ message: '삭제할 데이터를 선택하세요',
+ type: 'error',
+ })
+ return false
+ }
+ let errCount = 0
+ data.forEach((cell) => {
+ if (!cell.objectNo) {
+ // if (errCount === 0) {
+ // QToast({
+ // message: `물건정보가 있는 행만 삭제 됩니다`,
+ // type: 'error',
+ // })
+ // }
+ errCount++
+ }
+ })
+
+ async function fetchDelete(data) {
+ console.log('물건삭제API호출!!!!!!!!!', data)
+ //행추가말고 api데이터만 보냄
+ // let newData = data.filter((item) => item.company != null)
+ // console.log('삭제에 전송되는 데이타::', newData)
+ // await del({ url: '', data:newData })
+ await get({ url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' })
+ // try {
+ // const res = await del({url:'', data:newData})
+
+ // if(!res || res.length === 0) {
+
+ // } else {
+ fetchData()
+ // }
+ // } catch (error) {
+ // console.error('Data Delete error:', error);
+ // }
+ }
+
+ // 삭제API 완료 후 fetchData Api호출
+ async function fetchData() {
+ console.log('물건삭제후 조회API호출!!!!!!!!!!!!!', stuffSearchParams)
+ const data = await get({ url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' })
+ setGridProps({ ...gridProps, gridData: data, count: data.length })
+ setGridCount(data.length)
+ //data.length = 10
+ //setGridProps({ ...gridProps, gridData: data, count: data.length-1})
+ //setGridCount(data.length - 1 )
+ }
+
+ if (errCount === 0) {
+ // console.log('errCount::::::::', errCount)
+ fetchDelete(data)
+ // fetchData()
+ } else {
+ QToast({
+ message: `물건정보가 있는 행만 선택해주세요`,
+ type: 'error',
+ })
+ }
+ }
+
+ //행추가
+ let newCount = 0
+ const addRowItems = () => {
+ // console.log('girdRef::::::', gridRef.current.api)
+ const newItems = [
+ {
+ mission: newCount + 1,
+ successful: true,
+ },
+ ]
+ gridRef.current.api.applyTransaction({
+ add: newItems,
+ addIndex: newCount,
+ })
+ newCount++
+ }
+
+ //행삭제
+ const removeRowItems = () => {
+ // console.log('selectedRowData::', selectedRowData)
+ let errCount = 0
+ selectedRowData.forEach((cell) => {
+ if (!cell.company) {
+ let newSelectedRowData = selectedRowData.filter((item) => item.company == null)
+ gridRef.current.api.applyTransaction({ remove: newSelectedRowData })
+ } else {
+ if (errCount === 0) {
+ QToast({
+ message: `행추가로 추가 한 행만 삭제됩니다.`,
+ type: 'error',
+ })
+ }
+ errCount++
+ }
+ })
+ }
+
+ // 진입시 그리드 데이터 조회
+ useEffect(() => {
+ if (stuffSearchParams?.code === 'S') {
+ const params = {
+ schObjectNo: '',
+ schSaleStoreId: '',
+ schAddress: '',
+ schObjectName: '',
+ schSaleStoreName: '',
+ schSpecDateYn: '',
+ schReceiveUser: '',
+ schDispCompanyName: '',
+ schDateType: 'U',
+ schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
+ schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
+ }
+
+ async function fetchData() {
+ console.log('화면진입:::::::::::::', params)
+ const apiUrl = `/api/object/v1.0/object?saleStoreId=201TES01&${queryStringFormatter(params)}`
+ // console.log('apiUrl::', apiUrl)
+
+ await get({
+ url: apiUrl,
+ }).then((res) => {
+ if (res.length > 0) {
+ console.log('API결과:::::::', res)
+ setGridProps({ ...gridProps, gridData: res, count: res.length })
+ setGridCount(res.length)
+ }
+ })
+ }
+ fetchData()
+ }
+ }, [])
+
+ useEffect(() => {
+ if (stuffSearchParams?.code === 'E') {
+ console.log('조회 눌럿을때 ::::::::::::::', stuffSearchParams)
+ async function fetchData() {
+ const apiUrl = `/api/object/v1.0/object?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}`
+ await get({ url: apiUrl }).then((res) => {
+ console.log('API결과:::::::', res)
+ setGridProps({ ...gridProps, gridData: res, count: res.length })
+ setGridCount(res.length)
+ })
+ }
+ fetchData()
+ }
+ }, [stuffSearchParams])
+
return (
<>
-
Management Stuff
+
+ 물건목록
+
+ 전체 : {gridCount} // 선택 : {selectedRowDataCount}
+
+
+ {/* */}
+ {/*
+ */}
+
+
+
+
+
>
)
}
diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx
new file mode 100644
index 00000000..2f39b066
--- /dev/null
+++ b/src/components/management/StuffDetail.jsx
@@ -0,0 +1,388 @@
+'use client'
+
+import React, { useState, useEffect } from 'react'
+import { useRouter, useSearchParams } from 'next/navigation'
+import { Input, RadioGroup, Radio, Button, Autocomplete, AutocompleteItem, Select, SelectItem, Checkbox, Textarea } from '@nextui-org/react'
+import Link from 'next/link'
+import { get } from '@/lib/Axios'
+import { queryStringFormatter } from '@/util/common-utils'
+import dayjs from 'dayjs'
+export default function StuffDetail() {
+ const router = useRouter()
+ const searchParams = useSearchParams()
+ const [receiveUser, setReceiveUser] = useState('') //담당자
+ const [name2, setName2] = useState('') //물건명
+ const [name3, setName3] = useState('') //물건명후리가나
+ const [zipCode, setZipCode] = useState('') //우편번호
+ const [name5, setName5] = useState('') //수직적설량
+ const [gubun, setGubun] = useState('NEW') //신축 기축
+ const [sel, setSel] = useState('') //경칭선택
+ const [sel2, setSel2] = useState('') //발전량시뮬레이션지역
+ const [sel3, setSel3] = useState('') //기준풍속
+ const [sel4, setSel4] = useState('') //설치높이
+
+ const [errors, setErrors] = useState({})
+ const [isFormValid, setIsFormValid] = useState(false) //임시저장, 진짜저장 버튼 컨트롤
+ const [testSelOption, setTestSelOption] = useState([]) // 테스트용
+ const [autoSelectValue, setAutoSelectValue] = useState('') //판매점명 자동완성
+ const [buttonValid, setButtonValid] = useState(true) //주소검색 활성화 컨트롤
+ const [isSelected, setIsSelected] = useState(false) //한랭지대첵 체크박스
+ const [isSelected2, setIsSelected2] = useState(false) //염해지역용아이템사용 체크박스
+ const [gubun2, setGubun2] = useState('1') //면조도구분 라디오
+ const [gubun3, setGubun3] = useState('A') //계약조건 라디오
+ const [memo, setMemo] = useState('') //메모
+ const objectNo = searchParams.get('objectNo') //url에서 물건번호 꺼내서 바로 set
+
+ const [address1, setAddress1] = useState('') //우편API리턴 도도부현명
+ const [address2, setAddress2] = useState('') //우편API리턴 시구정촌명
+ const [address3, setAddress3] = useState('') //우편API리턴 마을 지역명
+ const [prefcode, setPrefCode] = useState(1) //우편API prefcode
+
+ const [editMode, setEditMode] = useState('NEW')
+ const [detailData, setDetailData] = useState({})
+
+ useEffect(() => {
+ // console.log('상세화면진입:::::::::', searchParams.get('objectNo'))
+ // console.log('물건번호::::', objectNo)
+
+ if (objectNo) {
+ console.log('상세::')
+ setEditMode('EDIT')
+ //http://localhost:8080/api/object/v1.0/object/R201TES01240906007/1
+ //일단 플랜번호 무조건 1로
+ //API 호출
+ get({ url: `/api/object/v1.0/object/${objectNo}/1` }).then((res) => {
+ if (res != null) {
+ // console.log('res:::::::', res)
+ setDetailData(res)
+ //setTestSelOption(res)
+ }
+ })
+ } else {
+ console.log('신규:::')
+ }
+ }, [objectNo])
+
+ useEffect(() => {
+ validateForm()
+ }, [receiveUser, name2, name3, gubun, sel, autoSelectValue, zipCode, sel2, sel3, name5, sel4])
+
+ // 우편번호 숫자만 체크
+ const textTypeHandler = (e) => {
+ //\D 숫자가 아닌것(특수문자포함)과 매치, [^0-9]와 동일
+ if (!e.target.value.match(/\D/g)) {
+ setZipCode(e.target.value)
+ }
+ }
+
+ // 수직적설량 숫자만
+ const textTypeHandler2 = (e) => {
+ if (!e.target.value.match(/[^0-9]/g)) {
+ setName5(e.target.value)
+ }
+ }
+ const validateForm = () => {
+ let errors = {}
+
+ if (!receiveUser || receiveUser.trim().length === 0) {
+ errors.receiveUser = '담당자 is required.'
+ }
+
+ if (!name2 || name2.trim().length === 0) {
+ errors.name2 = '물건명 is required.'
+ }
+
+ if (!name3 || name3.trim().length === 0) {
+ errors.name3 = '물건명후리가나 is required.'
+ }
+
+ if (!sel) {
+ errors.sel = '경칭선택 is required'
+ }
+
+ if (!sel2) {
+ errors.sel2 = '발전량시뮬레이션지역 is required'
+ }
+
+ if (!sel3) {
+ errors.sel3 = '기준풍속 is required'
+ }
+
+ if (!sel4) {
+ errors.sel4 = '설치높이 is required'
+ }
+
+ if (!autoSelectValue) {
+ errors.autoSelectValue = '판매점ID자동완성 is required'
+ }
+
+ if (!zipCode || zipCode.length != 7) {
+ errors.zipCode = '우편번호 is required.'
+ setButtonValid(true)
+ } else {
+ setButtonValid(false)
+ }
+
+ if (!name5) {
+ errors.name5 = '수직적설량 is required.'
+ }
+
+ // console.log('errors::', errors)
+ setErrors(errors)
+ setIsFormValid(Object.keys(errors).length === 0)
+ }
+
+ // 우편번호 API
+ const onSearchPostNumber = () => {
+ if (!zipCode) {
+ return alert('우편번호 입력해')
+ }
+ const params = {
+ zipcode: zipCode,
+ }
+
+ get({ url: `https://zipcloud.ibsnet.co.jp/api/search?${queryStringFormatter(params)}` }).then((res) => {
+ console.log('우편API RES::::::::', res)
+ if (res.status === 200) {
+ if (res.results.length > 0) {
+ setAddress1(res.results[0].address1)
+ setAddress2(res.results[0].address2)
+ setAddress3(res.results[0].address3)
+ setPrefCode(res.results[0].prefcode)
+ } else {
+ alert('등록된 우편번호에서 주소를 찾을 수 없습니다. 다시 입력해주세요.')
+ }
+ } else {
+ alert(res.message)
+ }
+ })
+ }
+
+ const onTempSave = () => {
+ console.log('임시저장::', isFormValid)
+ }
+
+ const onSave = () => {
+ console.log('진짜저장isFormValid:::', isFormValid)
+ }
+
+ const moveList = () => {
+ router.push('/management/stuff')
+ }
+
+ const changeAddress2 = (e) => {
+ console.log('e:::::::', e.target.value)
+ }
+
+ return (
+ <>
+ {(editMode === 'NEW' &&
신규:::::::::::
) ||
상세:::::::::::
}
+
+
+ 물건번호
+ {objectNo}
+
+
+ 사양확정일
+ {detailData?.specDate ? dayjs(detailData.specDate).format('YYYY.MM.DD') : null}
+
+
+ 갱신일시
+
+ {detailData?.lastEditDatetime
+ ? dayjs(detailData.lastEditDatetime).format('YYYY.MM.DD HH:mm:ss')
+ : detailData?.createDatetime
+ ? dayjs(detailData.createDatetime).format('YYYY.MM.DD HH:mm:ss')
+ : null}
+
+
+
+ 등록일
+
+
+
+
(*필수 입력항목)
+
+ 담당자*
+ setReceiveUser(e.target.value)} />
+
+
+
물건구분/물건명 *
+
{
+ setGubun(e.target.value)
+ }}
+ />
+
+
{
+ setGubun(e.target.value)
+ }}
+ />
+
+
+ setName2(e.target.value)} />
+
+
+
+
+
+ 물건명 후리가나
+ setName3(e.target.value)} />
+
+
+
+
판매점명 /ID *
+
+
+ {(option) => {option.name}}
+
+
+
+
+ 우편번호*
+
+
+ *우편번호 7자리를 입력한 후, 주소검색 버튼을 클릭해 주십시오
+
+
+ 도도부현 / 주소*
+ {/* */}
+
+
+
+ 발전량시뮬레이션지역*
+
+
+
+ 기준풍속*
+
+ m/s이하
+
+
+ 수직적설량*
+ cm
+
+ 한랭지대책시행
+
+
+
+ 면조도구분*
+ {
+ setGubun2(e.target.value)
+ }}
+ />
+
+ {
+ setGubun2(e.target.value)
+ }}
+ />
+
+
+ 염해지역용아이템사용
+
+
+
+ 설치높이*
+
+ m
+
+
+ 계약조건
+ {
+ setGubun3(e.target.value)
+ }}
+ />
+
+ {
+ setGubun3(e.target.value)
+ }}
+ />
+
+
+
+ 메모
+
+
+ {!isFormValid ? (
+ <>
+
+ >
+ ) : (
+ <>
+
+ >
+ )}
+
+
+
+ {/*
*/}
+ >
+ )
+}
diff --git a/src/components/management/StuffQGrid.jsx b/src/components/management/StuffQGrid.jsx
new file mode 100644
index 00000000..8139991b
--- /dev/null
+++ b/src/components/management/StuffQGrid.jsx
@@ -0,0 +1,116 @@
+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 StuffQGrid(props) {
+ const { gridData, gridColumns, isPageable = true, count, gridRef } = props
+ /**
+ * 행 데이터를 설정할 때 useState을 사용하여 렌더링 전반에 걸쳐 일관된 배열 참조를 유지하는 것이 좋습니다
+ */
+ const [rowData, setRowData] = useState(null)
+
+ /**
+ * Column Definitions를 설정할 때는 useMemo 또는 useState를 사용하여 렌더 간에 일관된 참조를 유지하십시오.
+ * 응용 프로그램이 Column Definitions를 동적으로 변경하는 경우에도 렌더링 간에 일관된 참조를 유지하려면 useMemo 또는 useState를 사용하십시오.
+ */
+ const [colDefs, setColDefs] = useState(
+ gridColumns ?? [
+ { field: 'mission', filter: true },
+ { field: 'company' },
+ { field: 'location' },
+ { field: 'date' },
+ { field: 'price', valueFormatter: (params) => `₩ ${params.value.toLocaleString()}` },
+ { field: 'successful' },
+ { field: 'rocket' },
+ ],
+ )
+
+ /**
+ * defaultColDef 속성을 제공할 때 이 인라인 또는 구성 요소의 단순 개체로 정의하지 마십시오. 이렇게 하면 모든 렌더링에서 새 인스턴스가 생성됩니다.
+ * 대신 or useState 를 사용하여 useMemo 렌더 간에 일관된 참조가 유지되도록 합니다.
+ */
+ const defaultColDef = useMemo(() => {
+ return {
+ filter: false,
+ flex: 1,
+ sortable: false,
+ suppressMovable: true,
+ resizable: false,
+ suppressSizeToFit: false,
+ headerClass: 'centered', //_test.scss에 추가 테스트
+ }
+ }, [])
+
+ /**
+ * 단순 유형(string, boolean 및 number)의 속성은 렌더링 간에 값으로 비교되므로 후크를 사용할 필요가 없습니다.
+ */
+ const rowBuffer = 100
+
+ /**
+ * 모든 렌더링에서 그리드 상태를 재설정하지 않도록 useCallback을 사용하는 것이 좋습니다.
+ * api데이타 해당 컬럼에 따라 로우 체크박스 체크 가능여부 등 컨트롤
+ */
+ const isRowSelectable = useCallback(
+ (params) => {
+ return !!params.data
+ },
+ [count],
+ )
+
+ // 체크박스 체크시
+ const onSelectionChanged = useCallback((event) => {
+ props.getSelectedRowdata(event.api.getSelectedRows())
+ }, [])
+
+ //더블클릭
+ const onCellDoubleClicked = useCallback((event) => {
+ // if (event.column.colId === 'company') {
+ // return
+ // } else {
+ 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) : ''
+ }, [gridData])
+
+ return (
+
+ )
+}
diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx
new file mode 100644
index 00000000..f0d665d0
--- /dev/null
+++ b/src/components/management/StuffSearchCondition.jsx
@@ -0,0 +1,264 @@
+'use client'
+
+import React, { useEffect } from 'react'
+import { useState } from 'react'
+import { Input, RadioGroup, Radio, Button } from '@nextui-org/react'
+import RangeDatePicker from '@/components/common/datepicker/RangeDatePicker'
+import { useRecoilState, useResetRecoilState } from 'recoil'
+import { stuffSearchState } from '@/store/stuffAtom'
+import dayjs from 'dayjs'
+import isLeapYear from 'dayjs/plugin/isLeapYear' // 윤년 판단 플러그인
+dayjs.extend(isLeapYear)
+import Link from 'next/link'
+export default function StuffSearchCondition() {
+ //달력 props 관련 날짜 셋팅
+ const [dateRange, setDateRange] = useState([dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), dayjs(new Date()).format('YYYY-MM-DD')])
+ const [startRangeDate, endRangeDate] = dateRange
+
+ const rangeDatePickerProps = {
+ startRangeDate, //시작일
+ endRangeDate, //종료일
+ setDateRange,
+ }
+
+ //여기서 선택한 검색조건들을 recoil로 관리
+ const resetStuffRecoil = useResetRecoilState(stuffSearchState)
+ const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState)
+ const [objectNo, setObjectNo] = useState('') //물건번호
+ const [saleStoreId, setSaleStoreId] = useState('') //판매대리점ID
+ const [address, setAddress] = useState('') //물건주소
+ const [objectName, setobjectName] = useState('') //물건명
+ const [saleStoreName, setSaleStoreName] = useState('') //판매대리점명
+ const [specDateYn, setSpecDateYn] = useState('') //사양 확인('', 'Y', 'N')
+ const [receiveUser, setReceiveUser] = useState('') //담당자
+ const [dispCompanyName, setDispCompanyName] = useState('') //견적처
+ const [dateType, setDateType] = useState('U') //갱신일(U)/등록일(R)
+
+ // 조회
+ const onSubmit = () => {
+ let diff = dayjs(endRangeDate).diff(startRangeDate, 'day')
+ if (diff > 366) {
+ return alert('최대1년 조회 가능합니다.')
+ }
+ setStuffSearch({
+ schObjectNo: stuffSearch?.schObjectNo ? stuffSearch.schObjectNo : objectNo,
+ schSaleStoreId: stuffSearch?.schSaleStoreId ? stuffSearch.schSaleStoreId : saleStoreId,
+ schAddress: stuffSearch?.schAddress ? stuffSearch.schAddress : address,
+ schObjectName: stuffSearch?.schObjectName ? stuffSearch.schObjectName : objectName,
+ schSaleStoreName: stuffSearch?.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName,
+ schSpecDateYn: stuffSearch?.schSpecDateYn ? stuffSearch.schSpecDateYn : specDateYn,
+ schReceiveUser: stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser,
+ schDispCompanyName: stuffSearch?.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName,
+ schDateType: stuffSearch?.schDateType ? stuffSearch.schDateType : dateType,
+ schFromDt: dayjs(startRangeDate).format('YYYY-MM-DD'),
+ schToDt: dayjs(endRangeDate).format('YYYY-MM-DD'),
+ code: 'E',
+ })
+ }
+
+ //초기화
+ const resetRecoil = () => {
+ setObjectNo('')
+ setSaleStoreId('')
+ setAddress('')
+ setobjectName('')
+ setSaleStoreName('')
+ setSpecDateYn('')
+ setReceiveUser('')
+ setDispCompanyName('')
+ setDateType('U')
+ setDateRange([dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), dayjs(new Date()).format('YYYY-MM-DD')])
+ resetStuffRecoil()
+ }
+
+ //x로 날짜 비웠을때 기본값으로 셋팅
+ useEffect(() => {
+ if (!startRangeDate && !endRangeDate) {
+ setDateRange([dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), dayjs(new Date()).format('YYYY-MM-DD')])
+ }
+ }, [startRangeDate, endRangeDate])
+
+ useEffect(() => {
+ setDateRange([
+ stuffSearch?.schFromDt ? stuffSearch.schFromDt : dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
+ stuffSearch?.schToDt ? stuffSearch.schToDt : dayjs(new Date()).format('YYYY-MM-DD'),
+ ])
+ }, [stuffSearch])
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+ {Array(4)
+ .fill()
+ .map((_, i) => {
+ if (i === 0) {
+ return (
+
+ {
+ setObjectNo(e.target.value)
+ setStuffSearch({ ...stuffSearch, code: 'S', schObjectNo: e.target.value })
+ }}
+ />
+ {
+ setSaleStoreId(e.target.value)
+ setStuffSearch({ ...stuffSearch, code: 'S', schSaleStoreId: e.target.value })
+ }}
+ />
+ {
+ setAddress(e.target.value)
+ setStuffSearch({ ...stuffSearch, code: 'S', address: e.target.value })
+ }}
+ />
+
+ )
+ } else if (i === 1) {
+ return (
+
+
{
+ setobjectName(e.target.value)
+ setStuffSearch({ ...stuffSearch, code: 'S', schObjectName: e.target.value })
+ }}
+ />
+
{
+ setSaleStoreName(e.target.value)
+ setStuffSearch({ ...stuffSearch, code: 'S', schSaleStoreName: e.target.value })
+ }}
+ />
+
+ {
+ setSpecDateYn(e.target.value)
+ setStuffSearch({ ...stuffSearch, code: 'S', schSpecDateYn: e.target.value })
+ }}
+ />
+
+
+
+ {
+ setSpecDateYn(e.target.value)
+ setStuffSearch({ ...stuffSearch, code: 'S', schSpecDateYn: e.target.value })
+ }}
+ />
+
+
+
+ {
+ setSpecDateYn(e.target.value)
+ setStuffSearch({ ...stuffSearch, code: 'S', schSpecDateYn: e.target.value })
+ }}
+ />
+
+
+
+ )
+ } else if (i === 2) {
+ return (
+
+ {
+ setReceiveUser(e.target.value)
+ setStuffSearch({ ...stuffSearch, code: 'S', schReceiveUser: e.target.value })
+ }}
+ />
+ {
+ setDispCompanyName(e.target.value)
+ setStuffSearch({ ...stuffSearch, code: 'S', schDispCompanyName: e.target.value })
+ }}
+ />
+
+ )
+ } else {
+ return (
+
+
+ {
+ setDateType(e.target.value)
+ setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value })
+ }}
+ />
+
+
+
+ {
+ setDateType(e.target.value)
+ setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value })
+ }}
+ />
+
+
+
+
+ )
+ }
+ })}
+
+ >
+ )
+}
diff --git a/src/locales/ja.js b/src/locales/ja.js
index 2b7df6bd..6b934e61 100644
--- a/src/locales/ja.js
+++ b/src/locales/ja.js
@@ -4,4 +4,15 @@ export default {
hello: 'こんにちは',
welcome: 'こんにちは {name}!',
locale: '現在のロケールは {locale} です。',
+ 'stuff.gridHeader.lastEditDatetime': '갱신일시',
+ 'stuff.gridHeader.objectNo': '물건번호',
+ 'stuff.gridHeader.planTotCnt': '플랜 수',
+ 'stuff.gridHeader.objectName': '물건명',
+ 'stuff.gridHeader.saleStoreId': '대리점ID',
+ 'stuff.gridHeader.saleStoreName': '대리점명',
+ 'stuff.gridHeader.address': '물건주소',
+ 'stuff.gridHeader.dispCompanyName': '견적처',
+ 'stuff.gridHeader.receiveUser': '담당자',
+ 'stuff.gridHeader.specDate': '사양확인',
+ 'stuff.gridHeader.createDatetime': '등록일',
}
diff --git a/src/locales/ko.js b/src/locales/ko.js
index 40e17ba2..ac036335 100644
--- a/src/locales/ko.js
+++ b/src/locales/ko.js
@@ -4,4 +4,15 @@ export default {
hello: '안녕',
welcome: '안녕 {name}!',
locale: '현재 로케일은 {locale}입니다.',
+ 'stuff.gridHeader.lastEditDatetime': '갱신일시',
+ 'stuff.gridHeader.objectNo': '물건번호',
+ 'stuff.gridHeader.planTotCnt': '플랜 수',
+ 'stuff.gridHeader.objectName': '물건명',
+ 'stuff.gridHeader.saleStoreId': '대리점ID',
+ 'stuff.gridHeader.saleStoreName': '대리점명',
+ 'stuff.gridHeader.address': '물건주소',
+ 'stuff.gridHeader.dispCompanyName': '견적처',
+ 'stuff.gridHeader.receiveUser': '담당자',
+ 'stuff.gridHeader.specDate': '사양확인',
+ 'stuff.gridHeader.createDatetime': '등록일',
}
diff --git a/src/store/stuffAtom.js b/src/store/stuffAtom.js
new file mode 100644
index 00000000..a122543c
--- /dev/null
+++ b/src/store/stuffAtom.js
@@ -0,0 +1,22 @@
+import { atom } from 'recoil'
+import dayjs from 'dayjs'
+import isLeapYear from 'dayjs/plugin/isLeapYear' // 윤년 판단 플러그인
+dayjs.extend(isLeapYear)
+export const stuffSearchState = atom({
+ key: 'stuffSearchState',
+ default: {
+ schObjectNo: '', //물건번호
+ schSaleStoreId: '', //판매대리점ID
+ schAddress: '', //물건주소
+ schObjectName: '', //물건명
+ schSaleStoreName: '', //판매대리점명
+ schSpecDateYn: '', //사양타입 ('', 'Y', 'N')
+ schReceiveUser: '', //담당자
+ schDispCompanyName: '', //견적처
+ schDateType: 'U', //갱신일(U)/등록일(R)
+ schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), //시작일
+ schToDt: dayjs(new Date()).format('YYYY-MM-DD'), //종료일
+ code: 'S',
+ },
+ dangerouslyAllowMutability: true,
+})
diff --git a/src/styles/_test.scss b/src/styles/_test.scss
index 55440362..9e542bbd 100644
--- a/src/styles/_test.scss
+++ b/src/styles/_test.scss
@@ -41,7 +41,7 @@
.grid-item {
width: 100%;
height: 100%;
- border: 1px solid black; /* 그리드 외각선 */
+ border: 1px solid black; /* 그리드 외각선 */
text-align: center; /* 그리드 내 가운데 정렬 */
}
@@ -79,3 +79,9 @@
background-color: white;
color: black;
}
+
+.centered {
+ .ag-header-cell-label {
+ justify-content: center !important;
+ }
+}