The lifecycle is the product
A request moves: raised by a resident, reviewed by an administrator, assigned to a driver, carried out, and paid for. Each transition is where the previous arrangement lost information, so each transition sends a transactional email — request submitted, driver assigned, collection confirmation, payment successful, cancellation, feedback — rendered from EJS templates and delivered over SMTP.
Devices alongside manual requests
The system registers IoT devices and stores the data fetched from them, so device-reported state sits beside the manually raised requests rather than in a separate tool.
Reporting
The administrative dashboard charts request status breakdown, district activity, category distribution, and geographic distribution by city, using Chart.js and Recharts. Reports are generated server-side as PDFs from HTML with Puppeteer, with charts rendered to images so they survive the conversion.
Stack
React with Vite, Redux Toolkit with persistence, React Router, Tailwind CSS and Flowbite on the client; Express with Mongoose over MongoDB on the server; JWT authentication with bcrypt. Google Maps and Places integration handles collection addressing. Unit and integration tests run under Jest.