Update quantity of voucher after given

This commit is contained in:
ZacTohZY
2024-08-12 22:59:14 +08:00
parent 878e854be8
commit be61213aaf
8 changed files with 94 additions and 47 deletions

View File

@@ -63,8 +63,7 @@ export default function AdministratorNavigationPanel() {
return ( return (
<div className="h-full"> <div className="h-full">
<div <div
className={`fixed transition-all ${ className={`fixed transition-all ${isScrolled ? "top-2" : "top-10"
isScrolled ? "top-2" : "top-10"
} left-2`} } left-2`}
> >
<div className="bg-white rounded-full z-40"> <div className="bg-white rounded-full z-40">
@@ -86,17 +85,14 @@ export default function AdministratorNavigationPanel() {
{/* Panel */} {/* Panel */}
<div <div
className={`h-full transition-all z-50 ${ className={`h-full transition-all z-50 ${panelVisible
panelVisible
? "scale-100 opacity-100 w-[300px] px-2" ? "scale-100 opacity-100 w-[300px] px-2"
: "w-0 scale-[98%] opacity-0 px-0" : "w-0 scale-[98%] opacity-0 px-0"
}`} }`}
></div> ></div>
<div <div
className={`fixed h-full transition-all z-50 ${ className={`fixed h-full transition-all z-50 ${isScrolled ? "pb-2 -mt-8" : "pb-10"
isScrolled ? "pb-2 -mt-8" : "pb-10" } ${panelVisible
} ${
panelVisible
? "scale-100 opacity-100 w-[300px] p-2" ? "scale-100 opacity-100 w-[300px] p-2"
: "w-0 scale-[98%] opacity-0 p-0" : "w-0 scale-[98%] opacity-0 p-0"
}`} }`}
@@ -184,11 +180,6 @@ export default function AdministratorNavigationPanel() {
icon={<CalendarDaysIcon />} icon={<CalendarDaysIcon />}
onClickRef="schedules" onClickRef="schedules"
/> />
<AdministratorNavigationPanelNavigationButton
text="Transactions"
icon={<ClockIcon />}
onClickRef="#"
/>
</div> </div>
<div> <div>
<p className="text-sm font-bold opacity-50 pb-2">Users</p> <p className="text-sm font-bold opacity-50 pb-2">Users</p>

View File

@@ -22,7 +22,7 @@ const initialValues = {
time: "", time: "",
location: "", location: "",
postalCode: "", postalCode: "",
status: "Up coming" // Set the default status status: "Upcoming" // Set the default status
}; };
@@ -57,7 +57,7 @@ export default function CreateSchedulePage() {
data.dateTime = dateTime.toISOString(); data.dateTime = dateTime.toISOString();
data.location = data.location.trim(); data.location = data.location.trim();
data.postalCode = data.postalCode.trim(); data.postalCode = data.postalCode.trim();
data.status = "Up coming"; // Set status to "Up coming" explicitly data.status = "Upcoming"; // Set status to "Up coming" explicitly
console.log("Data to be sent:", data); console.log("Data to be sent:", data);

View File

@@ -16,7 +16,7 @@ interface Schedule {
const determineStatus = (dateTime: string): string => { const determineStatus = (dateTime: string): string => {
const now = dayjs(); const now = dayjs();
const scheduleDateTime = dayjs(dateTime); const scheduleDateTime = dayjs(dateTime);
return scheduleDateTime.isAfter(now) ? "Up coming" : "Ended"; return scheduleDateTime.isAfter(now) ? "Upcoming" : "Ended";
}; };
export default function ManageSchedulePage() { export default function ManageSchedulePage() {

View File

@@ -215,13 +215,11 @@ export default function Ranking() {
return; return;
} }
// Function to get a random voucher from the available vouchers
const getRandomVouchers = (count: number): Voucher[] => { const getRandomVouchers = (count: number): Voucher[] => {
const shuffled = vouchers.sort(() => 0.5 - Math.random()); const shuffled = vouchers.sort(() => 0.5 - Math.random());
return shuffled.slice(0, count); return shuffled.slice(0, count);
}; };
// Group users by town council
const townCouncilGroups: Record<string, FormDataWithUser[]> = {}; const townCouncilGroups: Record<string, FormDataWithUser[]> = {};
topUsers.forEach(user => { topUsers.forEach(user => {
if (!townCouncilGroups[user.userTownCouncil]) { if (!townCouncilGroups[user.userTownCouncil]) {
@@ -230,9 +228,7 @@ export default function Ranking() {
townCouncilGroups[user.userTownCouncil].push(user); townCouncilGroups[user.userTownCouncil].push(user);
}); });
// Iterate over each town council and assign vouchers
for (const [townCouncil, users] of Object.entries(townCouncilGroups)) { for (const [townCouncil, users] of Object.entries(townCouncilGroups)) {
// Sort users by avgBill and pick top 3
const top3 = users.sort((a, b) => b.avgBill - a.avgBill).slice(0, 3); const top3 = users.sort((a, b) => b.avgBill - a.avgBill).slice(0, 3);
for (let i = 0; i < top3.length; i++) { for (let i = 0; i < top3.length; i++) {
@@ -240,11 +236,11 @@ export default function Ranking() {
let voucherCount = 0; let voucherCount = 0;
if (i === 0) { if (i === 0) {
voucherCount = 3; // Top 1 gets 3 vouchers voucherCount = 3;
} else if (i === 1) { } else if (i === 1) {
voucherCount = 2; // Top 2 gets 2 vouchers voucherCount = 2;
} else if (i === 2) { } else if (i === 2) {
voucherCount = 1; // Top 3 gets 1 voucher voucherCount = 1;
} }
const vouchersToAssign = getRandomVouchers(voucherCount); const vouchersToAssign = getRandomVouchers(voucherCount);
@@ -254,16 +250,30 @@ export default function Ranking() {
userId: user.userId, userId: user.userId,
voucherId: voucher.id, voucherId: voucher.id,
}); });
try {
const voucherId = voucher.id;
const response = await instance.put(`${config.serverAddress}/vouchers/update-quantity/${voucherId}`, {
quantityToSubtract: 1
});
if (response.status !== 200) {
console.error(`Failed to update voucher quantity for voucherId: ${voucher.id}`);
}
} catch (error) {
console.error(`Error updating voucher quantity for voucherId: ${voucher.id}`, error);
throw new Error(`Failed to update voucher quantity for voucherId: ${voucher.id}`);
} }
} }
} }
}
console.log("Vouchers assigned successfully");
} catch (error) { } catch (error) {
console.error("Failed to assign vouchers:", error); console.error("Failed to assign vouchers:", error);
} }
}; };
const handleGiveVouchers = async () => { const handleGiveVouchers = async () => {
try { try {
await assignVouchersToUsers(top3Users); await assignVouchersToUsers(top3Users);
@@ -282,7 +292,6 @@ export default function Ranking() {
label: townCouncil, label: townCouncil,
})); }));
return ( return (
<div className="flex flex-col gap-8 p-8"> <div className="flex flex-col gap-8 p-8">
<div className="flex justify-between items-center gap-5"> <div className="flex justify-between items-center gap-5">
@@ -316,8 +325,6 @@ export default function Ranking() {
<TableHeader> <TableHeader>
<TableColumn>Rank</TableColumn> <TableColumn>Rank</TableColumn>
<TableColumn>User Name</TableColumn> <TableColumn>User Name</TableColumn>
<TableColumn>Electrical Bill</TableColumn>
<TableColumn>Water Bill</TableColumn>
<TableColumn>Total Bill</TableColumn> <TableColumn>Total Bill</TableColumn>
<TableColumn>Dependents</TableColumn> <TableColumn>Dependents</TableColumn>
<TableColumn> <TableColumn>
@@ -332,8 +339,6 @@ export default function Ranking() {
<TableRow key={data.id}> <TableRow key={data.id}>
<TableCell>{index + 1}</TableCell> <TableCell>{index + 1}</TableCell>
<TableCell>{data.userName}</TableCell> <TableCell>{data.userName}</TableCell>
<TableCell>${data.electricalBill.toFixed(2)}</TableCell>
<TableCell>${data.waterBill.toFixed(2)}</TableCell>
<TableCell>${data.totalBill.toFixed(2)}</TableCell> <TableCell>${data.totalBill.toFixed(2)}</TableCell>
<TableCell>{data.noOfDependents}</TableCell> <TableCell>{data.noOfDependents}</TableCell>
<TableCell>${data.avgBill.toFixed(2)}</TableCell> <TableCell>${data.avgBill.toFixed(2)}</TableCell>

View File

@@ -160,13 +160,13 @@ export default function SchedulePage() {
))} ))}
</TableBody> </TableBody>
</Table> </Table>
<div className="flex flex-row gap-4"> {/* Adjust gap size as needed */} <div className="flex flex-row gap-4">
<div className="flex-1 p-4"> {/* Flex 1 for equal sizing and padding */} <div className="flex-1 p-4">
<Card className="h-full bg-gray-50 shadow-lg border border-gray-200"> <Card className="h-full bg-gray-50 border border-gray-200">
<CardBody> <CardBody>
<p className="text-lg font-semibold text-blue-600 mb-2">Paper</p> <p className="text-2xl font-semibold text-blue-600 mb-2">Paper</p>
<p className="text-xl font-bold text-gray-800 mb-4">$0.05 to 0.20/KG</p> <p className="text-xl font-bold text-gray-800 mb-4">$0.05 to 0.20/KG</p>
<ul className="list-disc list-inside pl-4 text-gray-700"> <ul className="list-disc list-inside pl-4 text-gray-700 list-none">
<li>Cardboard ($0.20/kg)</li> <li>Cardboard ($0.20/kg)</li>
<li>Newspaper and B&W ($0.11/kg)</li> <li>Newspaper and B&W ($0.11/kg)</li>
<li>Mix paper ($0.05/kg)</li> <li>Mix paper ($0.05/kg)</li>
@@ -175,11 +175,11 @@ export default function SchedulePage() {
</Card> </Card>
</div> </div>
<div className="flex-1 p-4"> <div className="flex-1 p-4">
<Card className="h-full bg-gray-50 shadow-lg border border-gray-200"> <Card className="h-full bg-gray-50 border border-gray-200">
<CardBody> <CardBody>
<p className="text-lg font-semibold text-green-600 mb-2">Electronics</p> <p className="text-2xl font-semibold text-green-600 mb-2">Electronics</p>
<p className="text-xl font-bold text-gray-800 mb-4">$2 to 50/KG</p> <p className="text-xl font-bold text-gray-800 mb-4">$2 to 50/KG</p>
<ul className="list-disc list-inside pl-4 text-gray-700"> <ul className="list-disc list-inside pl-4 text-gray-700 list-none">
<li>Flat TV ($5++)</li> <li>Flat TV ($5++)</li>
<li>Laptop ($10++)</li> <li>Laptop ($10++)</li>
<li>Smartphone ($10++)</li> <li>Smartphone ($10++)</li>
@@ -188,11 +188,11 @@ export default function SchedulePage() {
</Card> </Card>
</div> </div>
<div className="flex-1 p-4"> <div className="flex-1 p-4">
<Card className="h-full bg-gray-50 shadow-lg border border-gray-200"> <Card className="h-full bg-gray-50 border border-gray-200">
<CardBody> <CardBody>
<p className="text-lg font-semibold text-red-600 mb-2">Clothes</p> <p className="text-2xl font-semibold text-red-600 mb-2">Clothes</p>
<p className="text-xl font-bold text-gray-800 mb-4">$0.20/KG</p> <p className="text-xl font-bold text-gray-800 mb-4">$0.20/KG</p>
<ul className="list-disc list-inside pl-4 text-gray-700"> <ul className="list-disc list-inside pl-4 text-gray-700 list-none">
<li>Shoe</li> <li>Shoe</li>
<li>Jewellery</li> <li>Jewellery</li>
<li>Bag</li> <li>Bag</li>

View File

@@ -222,7 +222,7 @@ export default function UserVoucherPage() {
</div> </div>
</ModalBody> </ModalBody>
<div className="flex justify-end p-4 gap-4"> <div className="flex justify-end p-4 gap-4">
<Button color="danger" variant="light" onClick={handleCancel}>Cancel</Button> <Button variant="light" onClick={handleCancel}>Cancel</Button>
<Button color="danger" onClick={handleConfirm}>Yes</Button> <Button color="danger" onClick={handleConfirm}>Yes</Button>
</div> </div>
</ModalContent> </ModalContent>

View File

@@ -111,13 +111,13 @@ router.patch("/:id/status", async (req, res) => {
const schedule = await Schedule.findByPk(id); const schedule = await Schedule.findByPk(id);
if (!schedule) { if (!schedule) {
return res.status(404).json({ message: 'Schedule not found' }); return res.status(404).json({ message: "Schedule not found" });
} }
const now = dayjs(); const now = dayjs();
const scheduleDateTime = dayjs(schedule.dateTime); const scheduleDateTime = dayjs(schedule.dateTime);
const newStatus = scheduleDateTime.isAfter(now) ? "Up coming" : "Ended"; const newStatus = scheduleDateTime.isAfter(now) ? "Upcoming" : "Ended";
schedule.status = newStatus; schedule.status = newStatus;
await schedule.save(); await schedule.save();

View File

@@ -51,7 +51,6 @@ router.post(
} }
); );
router.get("/", async (req, res) => { router.get("/", async (req, res) => {
let condition = {}; let condition = {};
let search = req.query.search; let search = req.query.search;
@@ -150,5 +149,57 @@ router.delete("/:id", async (req, res) => {
} }
}); });
router.patch("/:id/quantity", async (req, res) => {
const { id } = req.params;
const { decrementBy } = req.body; // Expecting the decrement amount in the request body
try {
const voucher = await Voucher.findById(id);
if (!voucher) {
return res.status(404).send("Voucher not found");
}
voucher.quantityAvailable -= decrementBy;
await voucher.save();
res.send({ message: "Voucher quantity updated", voucher });
} catch (error) {
res.status(500).send("Error updating voucher quantity");
}
});
router.put("/update-quantity/:id", async (req, res) => {
let id = req.params.id;
let vouchers = await Voucher.findByPk(id);
if (!vouchers) {
res.sendStatus(404);
return;
}
try {
let newQuantity = vouchers.quantityAvailable - req.body.quantityToSubtract;
if (newQuantity < 0) newQuantity = 0;
let num = await Voucher.update(
{ quantityAvailable: newQuantity },
{ where: { id: id } }
);
if (num == 1) {
res.json({
message: "Voucher quantity was updated successfully.",
});
} else {
res.status(400).json({
message: `Cannot update voucher with id ${id}.`,
});
}
} catch (err) {
console.error("Error:", err);
res.status(400).json({ errors: err.errors });
}
});
module.exports = router; module.exports = router;