Smart Punjab — Toxic Craft Hackathon
Completed
Hackathon · Web

Smart Punjab — Toxic Craft Hackathon

2022

Civic-issue reporting platform for Patiala built for the Toxic Craft hackathon: residents register, log complaints across dedicated screens for sewage, water, roads, gas, electrical and garbage plus an emergency-services path, and track them, while authorities work them from a dashboard. A single index.php dispatches on a ?type= parameter and stitches forty-odd HTML partials with Apache virtual() includes — the thing that let four people edit the site at once on a hackathon Saturday — over a MySQL schema shipped as smart_patiala.sql and PHPMailer for verification mail.

Built with
PHPPHP
MySQLMySQL
JavaScriptJavaScript
CSSCSS
PHPMailerPHPMailer
Project Details
RESOURCES

STATUS
Completed
YEAR

2022

TYPE

Hackathon · Web

TAGS
Hackathon
Civic Tech
Smart City

Reporting a broken streetlight or a blocked sewer line in Patiala meant finding the right department and hoping. Smart Punjab was built for the Toxic Craft hackathon around a simpler contract: a resident files one complaint, it lands with the department that owns it, and both sides can see where it stands.

The brief in the repository is broader than that — a platform for governments to deliver services with transparency, accountability and data-driven decisions — and the honest reading of a weekend is that most of those words are ambition. The one that had to be real was accountability, and accountability in this context is a specific technical claim: every complaint has a named owner and a named supervisor from the moment it is filed, and neither the resident nor the department can pretend otherwise afterwards. That is the thing the system is actually built around.

Three roles, one codebase

The system splits into resident, employee and administrator, each with its own dashboard, navigation partial and complaint view. A resident registers, verifies their email, files against a department and tracks it. An employee works a queue for their department and marks items done. An administrator sees everything, creates and edits users, registers officials, and pulls analytics across the whole complaint set.

Departments are first-class rather than a dropdown value — the front end ships dedicated screens for sewage, water, roads, gas, electrical and garbage, plus emergency services, and the team's notes cover pest, stray-animal and general complaints on top of those.

Five tables and a complaint lifecycle

The schema is small and the interesting part is what a complaint row carries. Beyond the department, category, title, description and a resource URL for the attached photograph, it holds an x and y coordinate, a state, a registration date, an assigned employee, a supervisor, a remark plus a remark URL from the employee, a separate supervisor remark, and a user feedback field. That is a complaint's whole life laid out as columns: filed, routed, worked, signed off, and rated by the person who reported it.

Around it sit an officials table with employee code, designation, department, a count of assigned jobs and a type flag separating workers from supervisors; a users table carrying the role, dashboard type, verification flag and address; a verification-email table holding a code with a creation timestamp and a used flag; and a logged_in table storing a session key against an email and the client IP. Every column in all five tables is declared text NOT NULL, there are no foreign keys, and the only index anywhere is the primary key, which is about the level of schema design a hackathon Saturday supports.

Routing a complaint to a person

Filing a complaint is the one flow with real logic behind it. The handler mints a complaint identifier from the first two letters of the department, the first three of the category and a running serial, then picks two officials out of the department: the worker with the fewest currently assigned jobs, and separately the supervisor with the fewest. Both are written onto the complaint row and both have their job count incremented. It is least-loaded assignment, which is the simplest scheduler that is not round robin, and it is what makes the accountability claim above concrete rather than rhetorical.

Email verification is the other flow with real state. A six-digit code is generated and stored with a timestamp, any earlier codes for that address are deleted first so only one is ever live, and the code is accepted only inside a five-minute window and only if it has not already been consumed. Login mints a UUID session key, writes it to the logged_in table with the requesting IP, and sets it as a cookie with a fifteen-day expiry, dumping the dashboard payload into localStorage on the way through so the first paint needs no second request.

What shipped

  • A front controller. index.php dispatches on a ?type= query parameter and stitches each page out of template.html plus a content partial using Apache's virtual() includes.
  • Clean URLs from .htaccess. Named rewrites for /profile, /complaints, /aboutus, /notification, /dashboard and /analytics, and a catch-all that folds anything else into the front controller's type parameter.
  • Referrer-gated verification routes. verify, verify_error and verify_success each check HTTP_REFERER against the expected origin and path; anything else gets a real 403 Forbidden header and the 403 page.
  • Login state as a redirect guard — hitting the login route while already authenticated bounces straight to the dashboard.
  • Email verification built from a code generator, a credentials store and a mailer, with PHPMailer vendored into the repo and separate success and failure landing pages.
  • Field validators for name, email, password and phone number, each returning either 1 or the message to show, with the password rule requiring 8 to 15 characters across four character classes and no whitespace.
  • 24 PHP endpoints covering registration for residents and officials, login and logout, complaint submission and form handling, profile editing, notifications and notification mail, and the three dashboards.
  • 41 HTML partials, including per-department complaint screens, complaint cards, an onboarding flow for both residents and employees, forgot-password, and 403/404 pages.
  • An analytics screen for the admin view, drawing a complaint-status breakdown as a CanvasJS pie across started, in progress, unresolved and resolved.
  • A checked-in schemasmart_patiala.sql ships with the repo, so the whole thing stands up from a clone plus an import.
  • Two recorded walkthroughs in the repo, one for the resident flow and one for the employee flow, which is how it was demoed.

The shape of it

This is 2022 PHP and it looks it — no framework, no router library, no Composer, template composition done by the web server. That was the right call for a hackathon: virtual() includes cost nothing to learn, and four people could edit forty separate HTML partials at once without stepping on each other. The todo.txt still has files assigned by name, which is about as much project management as the weekend allowed.

The choice does have a real cost worth naming. virtual() is a mod_include call, so the whole page assembly is a property of the web server rather than the application; it needs Options +Includes and server-parsed HTML switched on in .htaccess, and the same code will render nothing on a host that does not allow it. A require would have been portable. What virtual() bought was that a partial stays a plain .html file a teammate can open and edit without touching PHP, which on a Saturday with four people was worth more than portability.

What would not survive contact

Plenty, and it is better to list it than to imply otherwise. Passwords are stored as typed — the column is named psw_hash and the seeded row holds the literal string. Every query is built by interpolating request values straight into SQL, so the whole thing is injectable at every endpoint. Database credentials for the shared host it ran on were committed to the repository rather than kept in the environment. The complaint insert names its coordinate columns with underscores while the shipped schema declares them with hyphens, so that write fails against the checked-in dump. The complaint serial is derived by selecting every row and walking to the last one, which is both linear in the table size and a race between two simultaneous filings. And the analytics pie is drawn from four numbers written into the page rather than counted from the complaints table, so the one screen that promised data-driven decisions is the one screen with no data behind it.

Project Details
RESOURCES

STATUS
Completed
YEAR

2022

TYPE

Hackathon · Web

TAGS
Hackathon
Civic Tech
Smart City