Update quantity of voucher after given
This commit is contained in:
@@ -63,9 +63,8 @@ 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">
|
||||||
<Button
|
<Button
|
||||||
@@ -86,20 +85,17 @@ 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"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<Card className="h-full w-full">
|
<Card className="h-full w-full">
|
||||||
<div className="flex flex-col h-full">
|
<div className="flex flex-col h-full">
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
Reference in New Issue
Block a user