반응형
달력에서 일자 클릭하면
클릭한 일자에 해당하는 유통기한 임박 상품들 재고테이블에서 가져와서 보여준다
근데 유통기한 임박 상품 리스트를 재고관리에서 가져와야해서
재고관리 페이지를 먼저 만들어야함
프론트 ( 리액트 )
1. 데이터를 받아오고 사용할 틀을 만들어준다
import { useState, useEffect } from 'react';
import axios from 'axios';
import stockk from './StockList.module.css';
import ReactPaginate from 'react-paginate';
const Stock = ({ columns }) => {
// 선택된 행의 인덱스를 저장하는 상태
const [selectedRows, setSelectedRows] = useState([]);
// 서버에서 가져온 재고 데이터를 저장하는 상태
const [stock, setStock] = useState([]);
// 현재 정렬 옵션을 저장하는 상태
const [sortOption, setSortOption] = useState('');
// 카테고리 필터 값을 저장하는 상태
const [categoryFilter, setCategoryFilter] = useState('');
// 위치 필터 값을 저장하는 상태
const [locationFilter, setLocationFilter] = useState('');
// 각 정렬 체크박스의 상태를 저장하는 상태
const [sortStates, setSortStates] = useState({
quantity: false,
expiry: false,
stock: false
});
// 현재 페이지 번호를 저장하는 상태
const [currentPage, setCurrentPage] = useState(0);
// 페이지당 항목 수
const itemsPerPage = 10;
//thead는 컬럼명 header
//tbody는 데이터 accessor
// 서버에서 재고 데이터 가져오기
useEffect(() => {
axios.get('http://localhost:8090/traders/stock')
.then(response => {
setStock(response.data);
// console.log(response.data);
})
.catch(error => {
console.error('There was an error fetching the goods!', error);
});
}, []);
// 모든 행을 선택하거나 선택을 해제하는 함수
const handleSelectAll = (event) => {
if (event.target.checked) {
setSelectedRows(stock.map((_, index) => index));
} else {
setSelectedRows([]);
}
};
// 특정 행을 선택하거나 선택을 해제하는 함수
const handleSelectRow = (rowIndex) => {
if (selectedRows.includes(rowIndex)) {
setSelectedRows(selectedRows.filter(index => index !== rowIndex));
} else {
setSelectedRows([...selectedRows, rowIndex]);
}
};
// 정렬 옵션을 변경하는 함수
const handleSortChange = (sortBy) => {
setSortStates(prevState => {
const newSortStates = { ...prevState, [sortBy]: !prevState[sortBy] };
// 체크박스가 해제되면 정렬 옵션을 기본 상태로 설정
if (!newSortStates[sortBy]) {
setSortOption('');
} else {
setSortOption(sortBy);
}
// 한 번에 하나의 정렬만 활성화
for (const key in newSortStates) {
if (key !== sortBy) {
newSortStates[key] = false;
}
}
return newSortStates;
});
};
// 필터링 및 정렬된 재고 데이터를 반환하는 함수
const sortedAndFilteredStock = stock
.filter(item => {
return (categoryFilter ? item.goods.gcategory === categoryFilter : true) &&
(locationFilter ? item.loc2 === locationFilter : true);
})
.sort((a, b) => {
switch (sortOption) {
case 'quantity':
return b.stockquantity - a.stockquantity;
case 'expiry':
return new Date(a.expdate) - new Date(b.expdate);
case 'stock':
return b.stockquantity - a.stockquantity;
default:
return 0;
}
});
// 카테고리 필터 값을 변경하는 함수
const handleCategoryFilterChange = (event) => {
setCategoryFilter(event.target.value);
};
// 위치 필터 값을 변경하는 함수
const handleLocationFilterChange = (event) => {
setLocationFilter(event.target.value);
};
//페이지네이션
// 현재 페이지에 표시할 항목을 반환하는 함수
const displayStock = sortedAndFilteredStock.slice(currentPage * itemsPerPage, (currentPage + 1) * itemsPerPage);
// 총 페이지 수를 계산하는 함수
const pageCount = Math.ceil(sortedAndFilteredStock.length / itemsPerPage);
// 페이지를 변경하는 함수
const handlePageChange = ({ selected }) => {
setCurrentPage(selected);
};
return (
<div className={stockk.tableTop}>
<div className={stockk.tableCon}>
<input type='checkbox' checked={sortStates.quantity} onChange={() => handleSortChange('quantity')} />
<span>판매량</span>
<input type='checkbox' checked={sortStates.expiry} onChange={() => handleSortChange('expiry')} />
<span>유통기한 순</span>
<input type='checkbox' checked={sortStates.stock} onChange={() => handleSortChange('stock')} />
<span>재고량 순</span>
<form className={stockk.cate_Form}>
<select name='category' onChange={handleCategoryFilterChange}>
<option disabled selected>카테고리</option>
<option>간식류</option>
<option>곡류</option>
<option>소스류</option>
</select>
</form>
<form className={stockk.cate_Form}>
<select name='category' onChange={handleLocationFilterChange}>
<option disabled selected>위치</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
</form>
</div>
<table className={stockk.stockT}>
<thead>
<tr>
<th>
<input
type="checkbox"
onChange={handleSelectAll}
checked={selectedRows.length === stock.length}
/>
</th>
{columns.map((column, index) => (
<th key={index}>{column.header}</th>
))}
</tr>
</thead>
<tbody>
{displayStock.map((row, rowIndex) => (
<tr key={rowIndex}>
<td>
<input
type="checkbox"
onChange={() => handleSelectRow(rowIndex)}
checked={selectedRows.includes(rowIndex)}
/>
</td>
{columns.map((column, colIndex) => (
<td key={colIndex}>
{column.render ? column.render(row) : row[column.accessor]}
{/* render는 이미지나 입력필드 같은 특수한 데이터
accessor는 데이터 키값 */}
</td>
))}
</tr>
))}
{displayStock.length < itemsPerPage &&
Array.from({ length: itemsPerPage - displayStock.length }).map((_, index) => (
<tr key={`empty-${index}`}>
<td colSpan={columns.length + 1}> </td>
</tr>
))}
</tbody>
</table>
<hr className={stockk.pageLine} />
<ReactPaginate
previousLabel={"Previous"}
nextLabel={"Next"}
pageCount={pageCount}
onPageChange={handlePageChange}
containerClassName={"paginationBttns"}
previousLinkClassName={"previousBttn"}
nextLinkClassName={"nextBttn"}
disabledClassName={"paginationDisabled"}
activeClassName={"paginationActive"}
className={stockk.page}
/>
<div className={stockk.stockBtn}>
<button>발주하기</button>
<button>삭제하기</button>
</div>
</div>
);
};
export default Stock;
2. 게시판 형태의 페이지가 많아서 재사용하기 위해 컬럼, 키값을 다른 페이지에 적어준다
import Stock from './Stock';
const StockList = () => {
const columns = [
{ header: '재고코드', accessor: 'stockid' },
{ header: '상품코드', accessor: 'goods.gcode', render: (row) => row.goods.gcode },
//stock 테이블의 값은 그냥 키값으로 들고와지는데
//외래키나 조인으로 연결된 goods 테이블의 정보는
//render를 써서 가져와야한다
{ header: "이미지", accessor: 'goods.gimage', render: (row) => <img src={`http://localhost:8090/traders/images/items/${row.goods.gimage}.png`} alt={row.goods.gname} style={{width: '50px', height: '50px'}} /> },
{ header: '카테고리', accessor: 'goods.gcategory', render: (row) => row.goods.gcategory},
{
header: '재고수량',
accessor: 'stockquantity'
},
{ header: '유통기한', accessor: 'expdate' },
{ header: '상품판매가', accessor: 'gprice' },
{ header: '대분류', accessor: 'loc1' },
{ header: '중분류', accessor: 'loc2' },
{ header: '소분류', accessor: 'loc3' },
];
return <Stock columns={columns} />;
};
export default StockList;
백엔드 ( 스프링부트, JPA, MySql )
결과물
기능 정리
1. 정렬기능
handleSortChange로 정렬 옵션기능 만듬, 새로운 변수 만들고 stock에 필터줘서 정렬기능 만듬
// 필터링 및 정렬된 재고 데이터를 반환하는 함수
const sortedAndFilteredStock = stock
.filter(item => {
return (categoryFilter ? item.goods.gcategory === categoryFilter : true) &&
(locationFilter ? item.loc2 === locationFilter : true);
})
.sort((a, b) => {
switch (sortOption) {
case 'quantity':
return b.stockquantity - a.stockquantity;
case 'expiry':
return new Date(a.expdate) - new Date(b.expdate);
case 'stock':
return b.stockquantity - a.stockquantity;
default:
return 0;
}
});
// 정렬 옵션을 변경하는 함수
const handleSortChange = (sortBy) => {
setSortStates(prevState => {
const newSortStates = { ...prevState, [sortBy]: !prevState[sortBy] };
// 체크박스가 해제되면 정렬 옵션을 기본 상태로 설정
if (!newSortStates[sortBy]) {
setSortOption('');
} else {
setSortOption(sortBy);
}
// 한 번에 하나의 정렬만 활성화
for (const key in newSortStates) {
if (key !== sortBy) {
newSortStates[key] = false;
}
}
return newSortStates;
});
};
728x90
반응형
'Final Project 신세계아이앤씨' 카테고리의 다른 글
결제하기 ( 토스페이먼츠 ) (0) | 2024.08.07 |
---|---|
홈페이지 들어가면 달력에 오늘 날짜 보이게하기 (0) | 2024.07.31 |
달력 일자 선택시 7일이내의 유통기한 임박상품 불러오기 ( 리액트, 스프링부트 ) (0) | 2024.07.30 |
캘린더 (react, npm, 커스텀) (0) | 2024.07.23 |
Final 기획 (1) | 2024.07.20 |