Spaces:
Sleeping
Sleeping
import { useState, useEffect } from 'react'; | |
import { Modal, Button, Container, Row, Col, Tab, Tabs, Form, InputGroup } from 'react-bootstrap'; | |
import MenuItem from '../../molecules/MenuItem'; | |
import BasicTemplate from '../../templates/BasicTemplate'; | |
import DataStorage from '../../organisms/DataStorage'; | |
import CacheStorage from '../../organisms/CacheStorage'; | |
import axios from 'axios'; | |
const categoryMapper = [ | |
{ itemType: 1, category: 'Món chính' }, | |
{ itemType: 2, category: 'Đồ uống' }, | |
{ itemType: 3, category: 'Tráng miệng' }, | |
]; | |
function MenuPage() { | |
const [key, setKey] = useState(0); | |
const [selectedDish, setSelectedDish] = useState(null); | |
const [show, setShow] = useState(false); | |
const [cartAmount, setCartAmount] = useState(0); | |
const [branches, setBranches] = useState([]); | |
const defaultSelectedStore = CacheStorage.get('selectedStore') || ""; | |
const [selectedStore, setSelectedStore] = useState(defaultSelectedStore); | |
const [loadingBranches, setLoadingBranches] = useState(true); | |
const [loading, setLoading] = useState(true); | |
const [menuItems, setMenuItems] = useState({}); | |
function handleClose() { | |
const cart = JSON.parse(DataStorage.get('cart')) || {}; // Đảm bảo cart không null | |
cart[selectedDish.id] = { | |
'name': selectedDish.item_name, | |
'amount': cartAmount, | |
'imageSrc': selectedDish.image_url, | |
'price': selectedDish.price | |
}; | |
for (let id in cart) { | |
if (cart[id].amount === 0) { | |
delete cart[id]; | |
} | |
DataStorage.set('cart', JSON.stringify(cart)); | |
// console.log(JSON.stringify(filteredCart)); | |
setShow(false); | |
} | |
} | |
function notLoggedInClose() { | |
setShow(false); | |
} | |
function handleShow(dish) { | |
if (DataStorage.get('isLoggedIn') !== 'true' || !DataStorage.get('cart')) { | |
setShow(true); | |
return; | |
} else { | |
setSelectedDish(dish); // Đặt selectedDish ngay lập tức | |
// Sau khi cập nhật selectedDish, lấy dữ liệu từ cart theo tên món ăn mới | |
const cart = JSON.parse(DataStorage.get('cart')) || {}; | |
// Kiểm tra số lượng món ăn trong cart | |
const amount = cart[dish.id] !== undefined ? cart[dish.id].amount : 0; | |
setCartAmount(amount); // Cập nhật số lượng | |
setShow(true); // Hiển thị modal | |
} | |
} | |
function setIncrease() { | |
setCartAmount(cartAmount + 1); | |
} | |
function setDecrease() { | |
if (cartAmount > 0) { | |
setCartAmount(cartAmount - 1); | |
} | |
} | |
useEffect(() => { | |
const fetchBranches = async () => { | |
try { | |
const response = await axios.get(process.env.REACT_APP_API_URL + '/branchs'); // Thay 'API_ENDPOINT' bằng URL của API | |
setBranches(response.data); // Lưu dữ liệu vào state | |
setLoadingBranches(false); // Đặt loading thành false khi hoàn tất | |
CacheStorage.set('stores', JSON.stringify(Object(response.data))); | |
} catch (error) { | |
console.error('Error fetching branches:', error); | |
setLoadingBranches(false); // Đặt loading thành false nếu lỗi | |
} | |
}; | |
if (CacheStorage.get('stores')) { | |
setBranches(JSON.parse(CacheStorage.get('stores'))); | |
setLoadingBranches(false); | |
} else { | |
fetchBranches(); | |
} | |
}, []) | |
// useEffect(() => { | |
// const fetchMenuItems = async () => { | |
// try { | |
// const menuItemsByType = {}; | |
// for (const item of categoryMapper) { | |
// // Gọi API để lấy món theo itemType | |
// const response = await axios.get(process.env.REACT_APP_API_URL + `/menu-items?filter.item_type=${item.itemType}`); | |
// // Lưu danh sách món theo itemType | |
// menuItemsByType[item.itemType] = response.data.data; | |
// } | |
// console.log(menuItemsByType); | |
// setMenuItems(menuItemsByType); | |
// setLoading(false); | |
// CacheStorage.set('menuItems',JSON.stringify(menuItemsByType)); | |
// } catch (error) { | |
// console.error('Error fetching menu items:', error); | |
// setLoading(false); | |
// } | |
// }; | |
// if (CacheStorage.get('menuItems')) { | |
// setMenuItems(JSON.parse(CacheStorage.get('menuItems'))); | |
// setLoading(false); | |
// } else { | |
// fetchMenuItems(); | |
// } | |
// }, []); | |
function organizeMenuItemsByType(menuData) { | |
// Lấy ra tất cả menu_item từ array ban đầu | |
const menuItems = menuData.map(item => item.menu_item); | |
// Tạo một object để nhóm menu_item theo item_type, khởi tạo các mảng rỗng cho mỗi item_type từ categoryMapper | |
const organizedItems = categoryMapper.reduce((acc, { itemType }) => { | |
acc[itemType] = []; | |
return acc; | |
}, {}); | |
// Thêm menu_item vào organizedItems theo item_type | |
menuItems.forEach(menuItem => { | |
const type = menuItem.item_type; | |
// Đưa menu_item vào array của item_type tương ứng | |
if (organizedItems[type]) { | |
organizedItems[type].push(menuItem); | |
} | |
}); | |
return organizedItems; | |
} | |
useEffect(() => { | |
const fetchStoreData = async (storeId) => { | |
if (storeId!=="") { | |
try { | |
let menuItemsByType = {}; | |
// Gọi API để lấy món theo itemType | |
const response = await axios.get(process.env.REACT_APP_API_URL + `/branchs/${storeId}/menus?limit=100`); | |
// Lưu danh sách món theo itemType | |
console.log('Response', response.data.data); | |
menuItemsByType = organizeMenuItemsByType(response.data.data); | |
console.log(menuItemsByType); | |
setMenuItems(menuItemsByType); | |
setLoading(false); | |
CacheStorage.set(`store_menu_${storeId}`, JSON.stringify(menuItemsByType)); | |
} catch (error) { | |
console.error('Error fetching menu items:', error); | |
setLoading(false); | |
} | |
} | |
} | |
// Kiểm tra cache thông tin chi nhánh trong sessionStorage | |
const cachedStoreData = CacheStorage.get(`store_menu_${selectedStore}`); | |
if (cachedStoreData) { | |
setMenuItems(JSON.parse(cachedStoreData)); | |
setLoading(false); | |
} else { | |
fetchStoreData(selectedStore); | |
} | |
}, [selectedStore]); | |
const handleSelectStore = (e) => { | |
setSelectedStore(e.target.value); | |
CacheStorage.set('selectedStore',e.target.value); | |
setLoading(true); | |
}; | |
let selectboxContent; | |
if (loadingBranches) { | |
selectboxContent = (<p>Đang tải dữ liệu...</p>) | |
} else { | |
selectboxContent = (<Form> | |
<Form.Group controlId="branchSelect"> | |
<Form.Label>Chọn chi nhánh:</Form.Label> | |
<Form.Control as="select" onChange={handleSelectStore} value={selectedStore}> | |
<option value="">-- Chọn chi nhánh --</option> | |
{branches.map((store) => ( | |
<option key={store.id} value={store.id}> | |
{store.name + ' - ' + store.location} | |
</option> | |
))} | |
</Form.Control> | |
</Form.Group> | |
</Form>); | |
} | |
let modalContent; | |
if (DataStorage.get('isLoggedIn') !== 'true' || !DataStorage.get('cart')) { | |
modalContent = ( | |
<Modal show={show} onHide={notLoggedInClose} className='text-center align-items-center'> | |
<Modal.Header closeButton className='text-center'> | |
<Modal.Title>Bạn chưa đăng nhập</Modal.Title> | |
</Modal.Header> | |
<Modal.Body> | |
Vui lòng đăng nhập để xem chi tiết món và đặt hàng | |
</Modal.Body> | |
<Modal.Footer> | |
<Button variant="primary" as='a' href='/login'> | |
Đăng nhập | |
</Button> | |
<Button variant="secondary" onClick={notLoggedInClose}> | |
Đóng | |
</Button> | |
</Modal.Footer> | |
</Modal> | |
) | |
} | |
else { | |
modalContent = (<Modal show={show} onHide={handleClose} className='text-center'> | |
<Modal.Header closeButton className='text-center'> | |
<Modal.Title >{selectedDish?.item_name}</Modal.Title> {/* Dish name in the title */} | |
</Modal.Header> | |
<Modal.Body> | |
<img src={selectedDish?.image_url} alt={selectedDish?.item_name} style={{ width: '100%' }} /> {/* Dish image */} | |
<p>{selectedDish?.description}</p> {/* Dish description */} | |
<Row className='mb-5'> | |
<Col md={2}></Col> | |
<Col md={8}> | |
<Form.Label>Số lượng</Form.Label> | |
<Row> | |
<InputGroup mb={4} className='mb-3'> | |
<InputGroup.Text as='button' onClick={setDecrease}>-</InputGroup.Text> | |
<Form.Control | |
value={cartAmount} | |
aria-label="Amount" | |
onChange={(e) => setCartAmount(e.target.value)} /> | |
<InputGroup.Text as='button' onClick={setIncrease}>+</InputGroup.Text> | |
</InputGroup> | |
</Row> | |
</Col> | |
<Col md={2}></Col> | |
</Row> | |
</Modal.Body> | |
<Modal.Footer> | |
<Button variant="secondary" onClick={handleClose}> | |
Đóng | |
</Button> | |
</Modal.Footer> | |
</Modal>); | |
} | |
let menuContent; | |
if (loading) { | |
menuContent = (<p>Đang tải thực đơn...</p>); | |
} else { | |
menuContent = (<Tabs | |
id="controlled-tab-example" | |
activeKey={key} | |
onSelect={(k) => setKey(k)} | |
className="mb-3 custom-tab" | |
> | |
{categoryMapper.map((category, index) => ( | |
<Tab eventKey={index} title={category.category}> | |
<Container fluid className='my-5'> | |
<Row md={3} className="g-4"> | |
{menuItems[category.itemType]?.map((item, idx) => ( | |
<Col key={item.id}> | |
<div onClick={() => handleShow(item)} className="text-center"> | |
<MenuItem | |
dishName={item.item_name} | |
description={item.description} | |
imageSrc={item.image_url} | |
/> | |
</div> | |
</Col> | |
))} | |
</Row> | |
</Container> | |
</Tab> | |
))} | |
</Tabs>); | |
} | |
return <BasicTemplate content={( | |
<Container fluid className='d-flex my-5 justify-content-center' style={{ minHeight: '70vh' }}> | |
<div className='align-items-center'> | |
{modalContent} | |
</div> | |
{/* selectbox branches */} | |
<Row style={{ maxWidth: "80vw" }}> | |
<Col xs='12'> | |
{selectboxContent} | |
</Col> | |
<Col xs='12' className='my-5'> | |
<h1 className='text-center'>Thực đơn</h1> | |
</Col> | |
{/* <Col xs={1} md={2}></Col> */} | |
<Col className='text-center'> | |
{menuContent} | |
</Col> | |
{/* <Col xs={1} md={2}></Col> */} | |
</Row> | |
</Container> | |
)} /> | |
} | |
export default MenuPage; |