Files
QMS/fe/web/teller-app/src/pages/ShowQueuesForTellerPage/ShowQueuesForTellerPage.jsx
T

212 lines
7.9 KiB
React

import React, { useContext, useEffect, useState } from 'react';
import { Button, Table } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import { useInterval } from '../../hooks/hooks.jsx';
import { fetchData } from '../../fetching/Fetch.js';
import { SERVER_URL } from '../../constants.js';
import { Link, useLocation, useParams } from 'react-router-dom';
import { UserContext } from '../../context/UserContext.jsx';
import { getActiveStation, saveActiveStation } from '../../utils/activeStation.js';
const styles = {
stationRow: {
backgroundColor: '#ADD8E6',
},
};
export default function ShowQueuesForTellerPage() {
const url = `${SERVER_URL}/api/v1/`;
const [tickets, setTickets] = useState([]);
const [usedUndo, setUsedUndo] = useState(false);
const [timedOut, setTimedOut] = useState(false);
const [stationLabel, setStationLabel] = useState(null);
const { stationId } = useParams();
const location = useLocation();
const { user } = useContext(UserContext);
const tenantCode = user?.tenantCode;
useEffect(() => {
fetchTicketsForTellerStation();
}, [stationId]);
useEffect(() => {
const fromNav = location.state;
if (fromNav?.station?.name) {
const next = {
stationId: Number(stationId),
stationName: fromNav.station.name,
branchId: fromNav.branch?.id ?? null,
branchName: fromNav.branch?.name ?? null,
};
saveActiveStation(next);
setStationLabel(next);
return;
}
const fromSession = getActiveStation(stationId);
if (fromSession?.stationName) {
setStationLabel(fromSession);
return;
}
if (!tenantCode) {
setStationLabel({ stationId: Number(stationId), stationName: `Station ${stationId}` });
return;
}
fetchData(`${url}branches/${encodeURIComponent(tenantCode)}`, 'GET')
.then(({ data, success }) => {
if (!success || !Array.isArray(data)) {
setStationLabel({
stationId: Number(stationId),
stationName: `Station ${stationId}`,
});
return;
}
for (const branch of data) {
const station = branch.tellerStations?.find(
(item) => Number(item.id) === Number(stationId)
);
if (station) {
const next = {
stationId: Number(stationId),
stationName: station.name,
branchId: branch.id,
branchName: branch.name,
};
saveActiveStation(next);
setStationLabel(next);
return;
}
}
setStationLabel({
stationId: Number(stationId),
stationName: `Station ${stationId}`,
});
})
.catch(() => {
setStationLabel({
stationId: Number(stationId),
stationName: `Station ${stationId}`,
});
});
}, [stationId, tenantCode, location.state, url]);
useInterval(fetchTicketsForTellerStation, 10000);
function fetchTicketsForTellerStation() {
fetchData(`${url}stations/${stationId}/tickets`, 'GET')
.then((response) => response.data)
.then(setTickets)
.catch(console.error);
}
function advanceQueue() {
fetchData(`${url}teller/advance-queue/${stationId}`, 'POST')
.then(fetchTicketsForTellerStation)
.then(() => setUsedUndo(false))
.then(timeOutTeller)
.catch(console.error);
}
function undoQueue() {
fetchData(`${url}teller/undo-queue/${stationId}`, 'POST')
.then(fetchTicketsForTellerStation)
.then(() => setUsedUndo(true))
.catch(console.error);
}
function timeOutTeller() {
setTimedOut(true);
setTimeout(() => setTimedOut(false), 5000);
// Can't advance more often than every 5 seconds.
}
const hasAssignedTicket = tickets.some((ticket) => ticket.station?.id == stationId);
return (
<div className="text-center mt-5">
<h1>Queues</h1>
{stationLabel ? (
<p className="mb-3" style={{ fontSize: '1.25rem', color: '#334257' }}>
<strong>{stationLabel.stationName}</strong>
{stationLabel.branchName ? (
<span className="text-muted"> · {stationLabel.branchName}</span>
) : null}
</p>
) : null}
<div className="d-flex gap-2 justify-content-center flex-wrap">
<Button
variant="primary"
style={{ backgroundColor: '#548CA8', color: 'white', borderColor: '#548CA8' }}
onClick={advanceQueue}
disabled={timedOut}
>
Nombor Giliran Seterusnya
</Button>
<Button
variant="primary"
style={{ backgroundColor: '#548CA8', color: 'white', borderColor: '#548CA8' }}
onClick={undoQueue}
disabled={usedUndo || !hasAssignedTicket}
>
Patah balik
</Button>
<Button
variant="primary"
style={{ backgroundColor: '#548CA8', color: 'white', borderColor: '#548CA8' }}
onClick={fetchTicketsForTellerStation}
>
Muat semula
</Button>
<Link to={`/display/${stationId}`} target="_blank" rel="noopener noreferrer">
<Button variant="secondary">Tiket semasa</Button>
</Link>
{tenantCode && stationLabel?.branchId ? (
<Link
to={`/display/branch/${encodeURIComponent(tenantCode)}/${stationLabel.branchId}`}
target="_blank"
rel="noopener noreferrer"
>
<Button variant="secondary">Paparan TV</Button>
</Link>
) : null}
</div>
<div style={{ marginTop: '20px' }}>
<Table striped bordered hover>
<thead>
<tr>
<th>Nombor tiket</th>
<th>Perkhidmatan</th>
<th>Dibuat pada</th>
</tr>
</thead>
<tbody>
{tickets.map((ticket, index) => {
const createdAt = new Date(ticket.createdAt);
return (
<tr key={index}>
<td
style={
ticket.station?.id == stationId
? styles.stationRow
: {}
}
>
{ticket.number}
</td>
<td>{ticket.service.name}</td>
<td>{createdAt.toLocaleString()}</td>
</tr>
);
})}
</tbody>
</Table>
</div>
</div>
);
}