CHS Lite - Parking
1. Objective & Scope
The objective is to implement an intuitive, single-screen management system for housing society parking slots in CHS Lite. Admins and managers should be able to configure slots and manage allotments (assignment, vacating, and transferring) with minimal clicks.
2. User Interface Flow
A. Parking Slot Index (Dashboard)
A modern, dense table layout (Row View) optimized for high scaling:
- Grid View Toggle: Removed. The system exclusively presents a clean row/table list representation to allow quick scanning of hundreds of bays.
- Search & Filter: Filter by vehicle type (2-wheeler vs. 4-wheeler) and availability status (All, Vacant, Occupied).
- Create Slot Button: Navigates to the Add Slot page.
- List Columns:
- Slot Name (e.g.
P-01,Basement A-12) - Type (represented by icons: 🚗 for 4-wheeler, 🛵 for 2-wheeler)
- Status Badge:
- 🟩 Vacant (Green)
- 🟥 Occupied (Red) - showing the assigned Member’s Name & Flat No.
- Allotted Member: Name of the assigned member.
- Flat No: Building/flat information.
- Expiry Date: Expiration date of the allotment.
- Actions:
- If Vacant: An Assign Slot button.
- If Occupied: Two buttons: Vacate (to release) and Transfer (to reassign).
- Details & Edit Icons: Quick navigation to view details or edit slot configuration.
- Slot Name (e.g.
B. Action Workflows & Dialogs
graph TD
A[Parking Index] -->|Click Add Slot| B(Add Slot Page)
A -->|If Slot is Vacant: Click Assign| C(Assign Slot Dialog)
A -->|If Slot is Occupied: Click Vacate| D(Vacate Confirmation)
A -->|If Slot is Occupied: Click Transfer| E(Transfer Slot Dialog)1. Add/Edit Parking Slot Form
- Inputs:
- Slot Name (Text, required. Character limit: 50 characters).
- Vehicle Type (Cards: “Four Wheeler”, “Two Wheeler”).
- Location Details / Notes (Textarea, optional. Character limit: 250 characters).
- Validation: Enforced via
maxLengthattribute on HTML input elements to prevent database truncation errors.
2. Assign Slot Dialog
- Trigger: Clicking Assign Slot on any vacant row.
- Inputs:
- Choose Member (Dropdown selection querying existing
Membersfiltered alphabetically by flat number). - Allotment Remarks (Text, optional. Character limit: 250 characters).
- Allotted Until (Date picker).
- Choose Member (Dropdown selection querying existing
- Validation: Enforced via
maxLength={250}on remarks input.
3. Vacant Slot Action
- Trigger: Clicking Vacate on an occupied row.
- Inputs: A confirmation modal asking: “Are you sure you want to vacate Slot [Slot Name]? This will remove the assignment from [Member Name].”
4. Transfer Slot Dialog
- Trigger: Clicking Transfer on an occupied row.
- Inputs:
- Select New Member (Dropdown selection querying the
Memberstable, excluding the current allottee). - New Remarks (Text, optional. Character limit: 250 characters).
- Allotted Until (Date picker).
- Select New Member (Dropdown selection querying the
- Validation: Enforced via
maxLength={250}on remarks input.
3. Database Schema Design (Prisma)
To align with the project’s SQL Server structure, the following model is defined:
model ParkingSlot {
id String @id @db.NVarChar(100)
chs_id String? @db.NVarChar(6)
slot_name String? @db.NVarChar(50)
parking_type String? @db.NVarChar(50) // "TwoWheeler", "FourWheeler"
notes String? @db.NVarChar(250)
is_active Boolean? @default(true)
created_at DateTime? @db.DateTime
// Assignment fields (Null when slot is Vacant)
member_id String? @db.NVarChar(4) // References Members.member_id
assigned_at DateTime? @db.DateTime
allotted_until DateTime? @db.DateTime
allotment_notes String? @db.NVarChar(250)
member Members? @relation("member_parking", fields: [chs_id, member_id], references: [chs_id, member_id], onUpdate: NoAction, onDelete: NoAction)
@@unique([chs_id, slot_name], map: "UQ_parking_slots_Chs_SlotName")
@@map("parking_slots")
}4. Code Implementation Details
Files and Locations
- List Index Page: app/admin/parking/page.tsx
- Add Form Page: app/admin/parking/add/page.tsx
- Edit Form Page: app/admin/parking/edit/[id]/page.tsx
- Details Page: app/admin/parking/details/[id]/page.tsx
- Server Actions: app/actions/parking.ts
Methods and Queries Used
All queries are executed server-side via Server Actions in app/actions/parking.ts:
1. getParkingSlots(chsId: string)
- Purpose: Retrieves all parking slots for the active society dashboard.
- Prisma Query:
await prisma.parkingSlot.findMany({ where: { chs_id: chsId }, include: { member: { select: { first_name: true, last_name: true, bldg_flat: true, member_id: true, } } }, orderBy: { slot_name: 'asc' }, });
2. createParkingSlot(data)
- Purpose: Configures a new parking slot space.
- Prisma Query:
await prisma.parkingSlot.create({ data: { ...data, id: crypto.randomUUID(), is_active: true, created_at: getISTDate(), }, });
3. updateParkingSlot(id, data)
- Purpose: Modifies the base details (name, type, notes) of a parking slot.
- Prisma Query:
await prisma.parkingSlot.update({ where: { id }, data, });
4. assignParkingSlot(id, memberId, allotmentNotes, allottedUntil)
- Purpose: Assigns or transfers a slot to a member.
- Prisma Query:
await prisma.parkingSlot.update({ where: { id }, data: { member_id: memberId, assigned_at: getISTDate(), allotted_until: allottedUntil ? new Date(allottedUntil) : null, allotment_notes: allotmentNotes || null, }, });
5. vacateParkingSlot(id)
- Purpose: Vacates and clears all assignment fields of a slot.
- Prisma Query:
await prisma.parkingSlot.update({ where: { id }, data: { member_id: null, assigned_at: null, allotted_until: null, allotment_notes: null, }, });
6. deleteParkingSlot(id)
- Purpose: Deletes a slot configuration from the system.
- Prisma Query:
await prisma.parkingSlot.delete({ where: { id }, });
7. getParkingSlotById(id)
- Purpose: Retrieves full details of a specific parking slot.
- Prisma Query:
await prisma.parkingSlot.findUnique({ where: { id }, include: { member: { select: { first_name: true, last_name: true, bldg_flat: true, member_id: true, salutation: true, mobile: true, email: true, } } } });
5. Implementation Rules
- Scope Segregation: All queries must filter by
chs_idto prevent cross-society visibility. - Input Length Limits: Every UI input is bounded by strict character validations matching database constraints:
slot_namemaximum length: 50notesmaximum length: 250allotment_notesmaximum length: 250
- Expiration Lockout: If a parking slot’s assignment duration (
allotted_until) has expired, editing, vacating, deleting, or transferring is prohibited. The buttons remain visible, but trying to operate on them displays a warning: “Parking has been expired. You cannot edit this record.”- Enforced Client-side in:
- app/admin/parking/page.tsx (Dashboard table row action buttons: Vacate, Transfer, Edit, Delete).
- app/admin/parking/details/[id]/page.tsx (Details action buttons: Edit, Vacate, Delete).
- app/admin/parking/edit/[id]/page.tsx (Edit submission form
handleSubmit).
- Enforced Server-side in:
- app/actions/parking.ts (In actions:
updateParkingSlot,vacateParkingSlot,deleteParkingSlot).
- app/actions/parking.ts (In actions:
- Enforced Client-side in:
6. Future Plans
- Implementing log for keeping a track which slot was alloted and transfered to whom
- Notify wrong Parking
- Improved UI for Parking, showing in graphics all the vaccant and occupied onces