This commit is contained in:
2026-02-10 15:30:56 -05:00
parent 4ef2ebae2c
commit 921d300e31
7 changed files with 151 additions and 41 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -1,16 +1,16 @@
{
"files": {
"main.css": "/static/css/main.6616f3cb.css",
"main.js": "/static/js/main.0e292118.js",
"main.js": "/static/js/main.60ebc889.js",
"static/js/787.c4e7f8f9.chunk.js": "/static/js/787.c4e7f8f9.chunk.js",
"static/media/landing.png": "/static/media/landing.d4c6072db7a67dff6a78.png",
"index.html": "/index.html",
"main.6616f3cb.css.map": "/static/css/main.6616f3cb.css.map",
"main.0e292118.js.map": "/static/js/main.0e292118.js.map",
"main.60ebc889.js.map": "/static/js/main.60ebc889.js.map",
"787.c4e7f8f9.chunk.js.map": "/static/js/787.c4e7f8f9.chunk.js.map"
},
"entrypoints": [
"static/css/main.6616f3cb.css",
"static/js/main.0e292118.js"
"static/js/main.60ebc889.js"
]
}

View File

@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"><link rel="manifest" href="/manifest.json"/><title>Worldshine Transportation</title><script defer="defer" src="/static/js/main.0e292118.js"></script><link href="/static/css/main.6616f3cb.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"><link rel="manifest" href="/manifest.json"/><title>Worldshine Transportation</title><script defer="defer" src="/static/js/main.60ebc889.js"></script><link href="/static/css/main.6616f3cb.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import CircularTable from './CircularTable';
import { Breadcrumb, Tabs, Tab, Dropdown, Modal, Button, Form } from "react-bootstrap";
import { Columns, Download, Filter, PencilSquare, ArrowBarRight, ChevronDown, ChevronRight, FileX, ArrowsFullscreen } from "react-bootstrap-icons";
@@ -114,36 +114,118 @@ const Seating = () => {
const [lunchRecords, setLunchRecords] = useState([]);
const [snackRecords, setSnackRecords] = useState([]);
const [selectedDate, setSelectedDate] = useState(new Date());
const colorsList = ['#AD967A', '#BD816E', '#2B76E5', '#66CCFF', '#0A7E22', '#00C875', '#9CD326', '#FFCB00', '#FF642E', '#FD314D', '#BB3354', '#FF158A', '#9B51E0', '#BDA8F9'];
// Fetch meal records
const fetchMealRecords = () => {
TransRoutesService.getAllBreakfastRecords().then(data => setBreakfastRecords(data?.data || []));
TransRoutesService.getAllLunchRecords().then(data => setLunchRecords(data?.data || []));
TransRoutesService.getAllSnackRecords().then(data => setSnackRecords(data?.data || []));
const isToday = moment(selectedDate).isSame(moment(), 'day');
const goToPreviousDay = () => {
setSelectedDate(prev => {
const d = new Date(prev);
d.setDate(d.getDate() - 1);
return d;
});
};
useEffect(() => {
CustomerService.getAllActiveCustomers().then(data => setCustomers(data?.data));
LabelService.getAll('active').then((data) => {setCurrentLabels(data?.data); setOriginalLabelsList(data?.data)});
SeatingService.getAll(moment().format('MM/DD/YYYY')).then(data => {
const goToNextDay = () => {
if (isToday) return;
setSelectedDate(prev => {
const d = new Date(prev);
d.setDate(d.getDate() + 1);
// Don't go beyond today
const today = new Date();
today.setHours(0,0,0,0);
d.setHours(0,0,0,0);
if (d > today) return prev;
return d;
});
};
const goToToday = () => {
setSelectedDate(new Date());
};
// Fetch meal records for selected date
const fetchMealRecords = useCallback(() => {
const dateStr = moment(selectedDate).format('MM/DD/YYYY');
TransRoutesService.getAllBreakfastRecords(dateStr).then(data => setBreakfastRecords(data?.data || []));
TransRoutesService.getAllLunchRecords(dateStr).then(data => setLunchRecords(data?.data || []));
TransRoutesService.getAllSnackRecords(dateStr).then(data => setSnackRecords(data?.data || []));
}, [selectedDate]);
// Fetch seating + routes data for selected date
const fetchSeatingData = useCallback(() => {
const dateStr = moment(selectedDate).format('MM/DD/YYYY');
SeatingService.getAll(dateStr).then(data => {
const result = data?.data;
if (result?.length > 0) {
setTableLayout(result[0]?.seating_assignment);
setCurrentDateRecord(result[0]);
// OLD ROW-BASED LOGIC - COMMENTED OUT
// setRowCount(result[0]?.seating_assignment?.rows?.length);
// setTableCountsPerRow(result[0]?.seating_assignment?.rows?.map(item => item.tables));
// NEW COLUMN-BASED LOGIC
setColumnCount(result[0]?.seating_assignment?.columns?.length || 1);
setTableCountsPerColumn(result[0]?.seating_assignment?.columns?.map(item => item.tables) || [1]);
} else {
// No record for this date - fetch all records to find the most recent one on or before this date
SeatingService.getAll().then(allData => {
const allRecords = allData?.data || [];
if (allRecords.length > 0) {
const selectedTime = new Date(selectedDate);
selectedTime.setHours(23,59,59,999);
const sorted = allRecords
.filter(r => {
const parts = r?.date?.split('/');
if (!parts || parts.length !== 3) return false;
return new Date(parts[2], parts[0] - 1, parts[1]).getTime() <= selectedTime.getTime();
})
.sort((a, b) => {
const parseDate = (d) => {
const parts = d?.date?.split('/');
if (!parts || parts.length !== 3) return 0;
return new Date(parts[2], parts[0] - 1, parts[1]).getTime();
};
return parseDate(b) - parseDate(a);
});
const latest = sorted[0];
const layout = latest?.seating_assignment;
if (layout) {
setTableLayout(layout);
setColumnCount(layout?.columns?.length || 1);
setTableCountsPerColumn(layout?.columns?.map(item => item.tables) || [1]);
// Only auto-create a record if viewing today
if (moment(selectedDate).isSame(moment(), 'day')) {
SeatingService.createNewSeating({
date: dateStr,
seating_assignment: layout,
create_by: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name,
update_by: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name,
create_date: new Date(),
update_date: new Date()
}).then((newData) => {
setCurrentDateRecord(newData?.data);
});
} else {
setCurrentDateRecord(null);
}
} else {
setTableLayout(initialValue);
setCurrentDateRecord(null);
setColumnCount(1);
setTableCountsPerColumn([1]);
}
} else {
setTableLayout(initialValue);
setCurrentDateRecord(null);
setColumnCount(1);
setTableCountsPerColumn([1]);
}
});
}
});
// Fetch today's inbound routes to check which customers are in-center
TransRoutesService.getAll(moment().format('MM/DD/YYYY')).then(data => {
// Fetch inbound routes for selected date
TransRoutesService.getAll(dateStr).then(data => {
const routes = data?.data || [];
// Filter only inbound routes and get customers who are inCenter
const inboundRoutes = routes.filter(route => route.type === 'inbound');
const inCenterIds = [];
inboundRoutes.forEach(route => {
@@ -155,9 +237,19 @@ const Seating = () => {
});
setInCenterCustomerIds(inCenterIds);
});
// Fetch meal records
}, [selectedDate]);
// Initial load: customers + labels (only once)
useEffect(() => {
CustomerService.getAllActiveCustomers().then(data => setCustomers(data?.data));
LabelService.getAll('active').then((data) => {setCurrentLabels(data?.data); setOriginalLabelsList(data?.data)});
}, []);
// Fetch date-dependent data when selectedDate changes
useEffect(() => {
fetchSeatingData();
fetchMealRecords();
}, [])
}, [fetchSeatingData, fetchMealRecords])
// OLD ROW-BASED LOGIC - COMMENTED OUT
// useEffect(() => {
@@ -379,7 +471,7 @@ const Seating = () => {
SeatingService.updateSeating(currentDateRecord?.id, { seating_assignment: tableLayout, update_by: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name, update_date: new Date() })
} else {
SeatingService.createNewSeating({
date: moment().format('MM/DD/YYYY'),
date: moment(selectedDate).format('MM/DD/YYYY'),
seating_assignment: tableLayout,
create_by: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name,
update_by: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name,
@@ -612,21 +704,21 @@ const Seating = () => {
const hasBreakfast = (customerId) => {
return breakfastRecords.some(record =>
record.customer_id === customerId &&
record.date === moment().format('MM/DD/YYYY')
record.date === moment(selectedDate).format('MM/DD/YYYY')
);
};
const hasLunch = (customerId) => {
return lunchRecords.some(record =>
record.customer_id === customerId &&
record.date === moment().format('MM/DD/YYYY')
record.date === moment(selectedDate).format('MM/DD/YYYY')
);
};
const hasSnack = (customerId) => {
return snackRecords.some(record =>
record.customer_id === customerId &&
record.date === moment().format('MM/DD/YYYY')
record.date === moment(selectedDate).format('MM/DD/YYYY')
);
};
@@ -635,7 +727,7 @@ const Seating = () => {
customer_id: customer?.customerId,
customer_name: customer?.customerName,
has_breakfast: true,
date: moment(new Date()).format('MM/DD/YYYY'),
date: moment(selectedDate).format('MM/DD/YYYY'),
create_by: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name,
create_date: new Date(),
edit_history: [{
@@ -652,7 +744,7 @@ const Seating = () => {
customer_id: customer?.customerId,
customer_name: customer?.customerName,
has_lunch: true,
date: moment(new Date()).format('MM/DD/YYYY'),
date: moment(selectedDate).format('MM/DD/YYYY'),
create_by: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name,
create_date: new Date(),
edit_history: [{
@@ -669,7 +761,7 @@ const Seating = () => {
customer_id: customer?.customerId,
customer_name: customer?.customerName,
has_snack: true,
date: moment(new Date()).format('MM/DD/YYYY'),
date: moment(selectedDate).format('MM/DD/YYYY'),
create_by: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name,
create_date: new Date(),
edit_history: [{
@@ -684,7 +776,7 @@ const Seating = () => {
const removeBreakfast = (customerId) => {
const record = breakfastRecords.find(b =>
b.customer_id === customerId &&
b.date === moment().format('MM/DD/YYYY')
b.date === moment(selectedDate).format('MM/DD/YYYY')
);
if (record) {
TransRoutesService.deleteBreakfastRecords(record.id).then(() => {
@@ -696,7 +788,7 @@ const Seating = () => {
const removeLunch = (customerId) => {
const record = lunchRecords.find(b =>
b.customer_id === customerId &&
b.date === moment().format('MM/DD/YYYY')
b.date === moment(selectedDate).format('MM/DD/YYYY')
);
if (record) {
TransRoutesService.deleteLunchRecords(record.id).then(() => {
@@ -708,7 +800,7 @@ const Seating = () => {
const removeSnack = (customerId) => {
const record = snackRecords.find(b =>
b.customer_id === customerId &&
b.date === moment().format('MM/DD/YYYY')
b.date === moment(selectedDate).format('MM/DD/YYYY')
);
if (record) {
TransRoutesService.deleteSnackRecords(record.id).then(() => {
@@ -801,6 +893,24 @@ const Seating = () => {
<div className="col-md-12 text-primary">
<h4>Seating Chart</h4>
</div>
<div className="col-md-12 d-flex align-items-center" style={{ marginTop: '8px', marginBottom: '8px' }}>
<div className="d-flex align-items-center" style={{ gap: '12px' }}>
<button className="btn btn-outline-secondary btn-sm" onClick={goToPreviousDay} title="Previous day">
<span style={{ fontSize: '18px', lineHeight: 1 }}>&lsaquo;</span>
</button>
<span style={{ fontWeight: 600, fontSize: '16px', minWidth: '160px', textAlign: 'center' }}>
{moment(selectedDate).format('ddd, MMM D, YYYY')}
</span>
<button className="btn btn-outline-secondary btn-sm" onClick={goToNextDay} title="Next day" disabled={isToday}>
<span style={{ fontSize: '18px', lineHeight: 1 }}>&rsaquo;</span>
</button>
{!isToday && (
<button className="btn btn-outline-primary btn-sm" onClick={goToToday}>
Today
</button>
)}
</div>
</div>
<div className="app-main-content-list-container">
<div className="app-main-content-list-func-container">
<Tabs defaultActiveKey="seatingChart" id="seatingTabs">
@@ -842,7 +952,7 @@ const Seating = () => {
<div className="manage-seating-chart-tables-container">
<div className="title">
<strong>Table Layout</strong>
<PencilSquare color="#777" size={16} onClick={() => setShowTableLayoutConfig(true)}/>
<PencilSquare color="#777" size={16} onClick={() => { setShowLabelConfig(false); setShowTableLayoutConfig(true); }}/>
{
showTableLayoutConfig && <div className="seating-popover">
<h6>Manage Table Layout</h6>
@@ -1017,7 +1127,7 @@ const Seating = () => {
}
<div className="title">
<strong>Customer Label</strong>
<PencilSquare color="#777" size={16} onClick={() => setShowLabelConfig(true)}/>
<PencilSquare color="#777" size={16} onClick={() => { setShowTableLayoutConfig(false); setShowLabelConfig(true); }}/>
{
showLabelConfig && <div className="seating-popover">
<h6>Customer Labels</h6>