CHS Lite - Parking

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:
    1. Slot Name (e.g. P-01, Basement A-12)
    2. Type (represented by icons: 🚗 for 4-wheeler, 🛵 for 2-wheeler)
    3. Status Badge:
      • 🟩 Vacant (Green)
      • 🟥 Occupied (Red) - showing the assigned Member’s Name & Flat No.
    4. Allotted Member: Name of the assigned member.
    5. Flat No: Building/flat information.
    6. Expiry Date: Expiration date of the allotment.
    7. 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.

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 maxLength attribute 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 Members filtered alphabetically by flat number).
    • Allotment Remarks (Text, optional. Character limit: 250 characters).
    • Allotted Until (Date picker).
  • 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 Members table, excluding the current allottee).
    • New Remarks (Text, optional. Character limit: 250 characters).
    • Allotted Until (Date picker).
  • 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


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

  1. Scope Segregation: All queries must filter by chs_id to prevent cross-society visibility.
  2. Input Length Limits: Every UI input is bounded by strict character validations matching database constraints:
    • slot_name maximum length: 50
    • notes maximum length: 250
    • allotment_notes maximum length: 250
  3. 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.”

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