Skip to content

Leads

Inbound inquiries that haven't become customers yet — website form submissions, WhatsApp pings, referrals. Tracked in one list, convertible to a quotation or a booking.

Scope

Only one page in this module: src/pages/leads/Leads.tsx (route /sales/leads). No detail route — the full edit experience is a dialog opened from the list.

Page — Leads.tsx

Route /sales/leads, gated by leads.view (src/App.tsx:159).

List

DataTable filtered by search + status. Columns: lead name + phone, travel type + group size, linked group name, status badge, received date, view action (Leads.tsx:263-319).

Status enum (Leads.tsx:39-45): new, contacted, qualified, converted, closed.

Travel type enum (Leads.tsx:47-52): umrah, hajj, umrah_plus, custom.

Create lead

Header "Add Lead" button — gated by leads.edit (Leads.tsx:255-260). Fields:

  • fullName, phone, email, city.
  • travelType (one of the four above).
  • groupSize — integer.
  • preferredMonth — free text.
  • message — long text.

The form has no file uploader — inbound leads with attachments (from the website widget) are created by the public API and show their files on the detail dialog (Leads.tsx:361-380).

Detail dialog

Opens when "View" is clicked. Shows all captured fields plus any attachments[] that came in with the website submission. Two conversion buttons plus an in-dialog status updater.

Lead → customer / quotation / booking conversion

Two conversion paths, both live on the detail dialog (Leads.tsx:381-389):

Convert to quotation (convertLeadToQuotation, Leads.tsx:201-209)

Service: src/services/leadService.ts. Fields collected on the convert dialog:

  • totalAmount, currency.
  • validUntil (date).
  • notes.
  • discount.

Creates a Quotation row linked to the (newly-created or matched) customer. Permission: quotations.create.

Convert to booking (convertLeadToBooking, Leads.tsx:215-223)

Requires a group selectiongroupId is required (Leads.tsx:211-214). Fields:

  • totalAmount, currency.
  • groupId — the travel group this booking belongs to.
  • paymentPolicypartial or full.
  • paidAmount.
  • notes.

Creates a Booking inside the selected TravelGroup, with an associated customer record. Permission: bookings.create.

Customer creation is implicit during conversion

Converting a lead to a quotation or booking creates (or matches) a Customer row from the lead's contact fields — the lead itself is not a customer until it converts.

Status updates (updateLeadStatus)

The detail dialog has a Select that updates status independently of conversion. Gated by leads.edit (Leads.tsx:391).

Permissions

Canonical reference: docs/PERMISSIONS.md §4.1 and §6.2.

Action Permission
View /sales/leads leads.view
Create lead leads.edit
Update status leads.edit
Convert to quotation quotations.create
Convert to booking bookings.create

No leads.create — creation is gated by leads.edit

The catalog only defines leads.view and leads.edit (PERMISSIONS.md §4.1). Creating a lead and updating its status share the same permission.

Roles holding leads.edit by default: SALES_MANAGER, SALES_EXEC, plus super-admin/admin tier (PERMISSIONS.md §5.2).

  • Customers — created implicitly by convertLeadToBooking / convertLeadToQuotation.
  • Quotations — destination of convertLeadToQuotation.
  • Bookings — destination of convertLeadToBooking.
  • PERMISSIONS.md §6.2 — authoritative action matrix.