nhance/public/dev_logs/2026-03-31_ticket_frontend_validation_plan.md

22 KiB

Ticket Frontend Validation Plan (Backend-Aligned)

Date: 2026-03-31
Scope:

  • app/Views/ticket_form_gmc.php
  • app/Views/ticket_form_gpa.php
  • app/Views/ticket_form_motor.php
  • app/Views/ticket_note.php
  • app/Views/ticket_reply.php
  • app/Views/ticket_feedback_form.php

Reference backend:

  • app/Controllers/TicketController.php
    • createTicket()
    • updateTicket()
    • crudNote($action = 2)
    • saveReply()
    • viewClaimFeedbackForm() (current behavior, no server-side field validation)

1) Objective

Implement consistent JavaScript validation in the six target view files so frontend checks match the current backend rules and reduce avoidable 400 responses.
Validation must remain non-breaking with current dynamic field visibility and existing submit/AJAX flows.

Enhance current submit-time validation to real-time validation using oninput / onchange event-driven checks, so users get immediate feedback before submit.


2) Backend Rule Mapping Summary

ticket_form_gmc.php (ticket type 1 / 72)

  • Required: emp_code, emp_name, insured_name, relationship, emp_mobile, emp_mail, client_policy_id, acm_id, claim_status_id, priority, mode_of_intimation, claim_type, hospital_name, doa, dod.
  • Optional with format checks:
    • policy_no: regex + length constraints.
    • tpa_no: regex.
    • emp_personal_mail: email regex.
    • hospital_address, hospital_state, hospital_city, hospital_pin_code, hospital_phone_no.
    • claim_amount, approved_amount, si_amt: numeric.
    • date-format optional fields: registration_date, denial_date, approved_date, settled_date, pay_initiate_date (dd/mm/yyyy).
    • pod_no, claim_number, utr_details.
  • Conditional front-end behavior already present and retained:
    • Claim-status based dynamic required fields (extra_fields_array_for_validate).
    • pod_no required when mode_of_intimation == 2.
    • TPA-specific required fields via handleTPARequired(tpaId).

ticket_form_gpa.php (non-1/72/8 path)

  • Required: emp_code, emp_name, emp_mobile, emp_mail, client_policy_id, acm_id, claim_status_id, claim_type, dob, date_of_intimat, si_amt.
  • Optional with format checks:
    • emp_personal_mail (email regex),
    • approved_amount numeric,
    • approved_date, settled_date, pay_initiate_date (dd/mm/yyyy),
    • utr_details (alpha_numeric_punct compatible),
    • remarks/letters are permit-empty.

ticket_form_motor.php (ticket type 8)

  • Required: client_name (not default value), vehicle_id, client_policy_id, insurer_id, emp_mobile (10 digits numeric), emp_mail (email format), ticket_type_id, claim_status_id, client_id.
  • Current frontend has partial select validation only; needs backend parity for mobile/email and hidden key integrity.

ticket_note.php

  • Required: note.
  • Length: min 3, max 1000.

ticket_reply.php

  • Required: emp_mail valid email.
  • Required: mail_subject min length 5.
  • Content editor (mail_content) currently not backend-required.

ticket_feedback_form.php

  • Current backend behavior: accepts/stores posted payload as JSON without field validation.
  • Frontend should keep current required radio-group checks (Parsley based), aligned to present backend behavior choice from user.

3) Per-File Frontend Implementation Plan

A. ticket_form_gmc.php

  • Added centralized validators in existing <script> block:
    • email/date regex helpers + field format checks.
    • regex checks for emp_code, emp_name, insured_name, policy_no, tpa_no, hospital_*, pod_no, claim_number.
  • Preserved existing dynamic logic and added pre-submit hook (validateBeforeSubmitGmc) before submitClaimForm.
  • Added numeric checks for emp_mobile (10 digits), hospital_pin_code (6 digits), and optional numeric fields.
  • Retained current claim-status UI behavior (no controller-side behavior override on frontend).
  • Added deduplicated aggregate toastr error display.

B. ticket_form_gpa.php

  • Added custom pre-submit validation (validateBeforeSubmitGpa) tied to form submit.
  • Implemented backend-aligned required and format checks for email/mobile/SI/date fields.
  • Kept existing dynamic claim_status section behavior and extra field logic untouched.
  • Added deduplicated validation toast handling.

C. ticket_form_motor.php

  • Extended validateBeforeSubmit(event, form):
    • kept required select checks (0 invalid),
    • added emp_mobile exact 10-digit validation,
    • added emp_mail format validation,
    • added hidden ID integrity checks for client_id and insurer_id.
  • Kept Parsley validation as second layer.
  • Preserved existing submit flow to submitClaimForm.

D. ticket_note.php

  • Added pre-submit note validator:
    • trims value,
    • enforces required,
    • enforces min 3 and max 1000.
  • Prevents AJAX call on invalid note and shows toastr error.
  • Existing backend error handling fallback kept unchanged.

E. ticket_reply.php

  • Added pre-AJAX checks in #ticket_reply_form submit:
    • emp_mail email format,
    • mail_subject required + min length 5.
  • Kept existing backend error handling and Jodit editor flow unchanged.

F. ticket_feedback_form.php

  • Kept current Parsley required checks for radio groups.
  • Added lightweight required-group precheck to block empty submissions with clear message.
  • Did not introduce stricter constraints than current backend contract.

3.2) Real-Time Validation Upgrade Plan (oninput / onchange)

Goal: keep existing pre-submit validation as final guard, and add field-level live validation to improve UX.

Cross-Form Event Strategy

  • Use delegated listeners to avoid inline HTML changes where possible:
    • $(document).on('input', '<text-like selectors>', handler) for typing fields.
    • $(document).on('change', '<select/date/radio selectors>', handler) for selects, date pickers, and radios.
  • Trigger validation for only the changed field; avoid full-form revalidation on each keystroke.
  • Show immediate inline state (is-invalid / is-valid) and small message node near field.
  • Keep toastr only for submit-time aggregate summary; avoid toast spam during typing.
  • Use debouncing (150-250ms) for expensive regex/date checks on large forms.

Field Validation Timing Rules

  • oninput: emp_code, names, email fields, mobile, numeric amount fields, policy_no, tpa_no, pod_no, claim_number, note, reply subject.
  • onchange: select fields (claim_status_id, priority, mode_of_intimation, etc.), datepicker fields, radio groups.
  • Optional fields validate only when non-empty; clearing them should also clear invalid state.
  • Hidden/conditionally shown fields validate only when currently required and visible by active business rule.

A. ticket_form_gmc.php (real-time additions)

  • Add bindGmcRealtimeValidation() called on document ready.
  • Wire input events for mobile/email/pin/regex/numeric fields.
  • Wire change events for claim status, mode of intimation, TPA select, and date fields.
  • Recompute dynamic required set (extra_fields_array_for_validate, pod_no, TPA-required) on relevant change and immediately validate newly required fields.
  • Keep validateBeforeSubmitGmc as final fail-safe.

B. ticket_form_gpa.php (real-time additions)

  • Add bindGpaRealtimeValidation() on ready.
  • input validation for emp_mobile, emp_mail, emp_personal_mail, si_amt, approved_amount, utr_details.
  • change validation for claim_status_id, claim_type, dob, date_of_intimat, optional date fields.
  • Preserve dynamic status behavior; validate extra fields when status switches.
  • Keep validateBeforeSubmitGpa as final fail-safe.

C. ticket_form_motor.php (real-time additions)

  • Add field listeners for emp_mobile (input) and emp_mail (input).
  • Add change listeners for client_name, vehicle_id, client_policy_id, insurer_id, ticket_type_id, claim_status_id.
  • Validate hidden client_id / insurer_id integrity whenever parent selects change.
  • Keep current submit validator + Parsley as final gate.

D. ticket_note.php (real-time additions)

  • Validate note on input with trimmed length checks (required/min/max).
  • Show live character-aware feedback before submit.
  • Keep submit-time block for invalid payload as backup.

E. ticket_reply.php (real-time additions)

  • Validate emp_mail on input (email format).
  • Validate mail_subject on input (required/min length 5).
  • Optionally validate Jodit content non-empty only if future backend makes it required.
  • Keep submit-time checks unchanged as final gate.

F. ticket_feedback_form.php (real-time additions)

  • Validate each required radio group on change.
  • Clear group-level error immediately once a choice is made.
  • Keep existing Parsley and pre-submit required-group checks for reliability.

3.1) Execution Status

  • app/Views/ticket_form_gmc.php updated
  • app/Views/ticket_form_gpa.php updated
  • app/Views/ticket_form_motor.php updated
  • app/Views/ticket_note.php updated
  • app/Views/ticket_reply.php updated
  • app/Views/ticket_feedback_form.php updated

3.3) Real-Time Upgrade Execution Status

  • app/Views/ticket_form_gmc.php event-driven validation added
  • app/Views/ticket_form_gpa.php event-driven validation added
  • app/Views/ticket_form_motor.php event-driven validation added
  • app/Views/ticket_note.php event-driven validation added
  • app/Views/ticket_reply.php event-driven validation added
  • app/Views/ticket_feedback_form.php event-driven validation added

3.4) GMC Additional Documents (Status-Based) Validation Plan

Issue identified from ticket_form_handler.php + ticket_form_gmc.php:

  • The Additional Documents section visibility is status-driven (updateClaimStatusDisplay), and required is toggled broadly by class.
  • Current validation does not explicitly enforce per-status field mapping in one place.
  • Real-time field checks exist for format of some fields, but required checks for status-specific fields are not consistently guaranteed both live and pre-submit.

Status-to-Field Required Matrix (to enforce explicitly)

Base claim flow (ticket type 1):

  • 3 / 4 (.cda_ir): raised_date
  • 5 (.up_cnu): claim_number, registration_date
  • 7 (.up_qdr): query_received_date
  • 8 (.rejected): denial_reason, denial_date
  • 9 (.approved): approved_amount, approved_date, approved_letter (approved_description stays optional)
  • 10 (.payment): pay_initiate_date
  • 11 (.settled): utr_details, settled_date, settle_letter
  • 13 (.canceled): cancel_remark
  • 14 (.returned): return_remark, awb_no_courier_name
  • 1 (.non_id): non_id_reason (conditional, only when tpa_no empty as already implemented)

OPD flow (ticket type 72) status mapping:

  • 69/70 -> .cda_ir
  • 71 -> .up_cnu
  • 72 -> .up_qdr
  • 73 -> .rejected
  • 74 -> .approved
  • 75 -> .payment
  • 76 -> .settled
  • 78 -> .canceled
  • 79 -> .returned
  • 67 -> .non_id

Validation Implementation Plan

  1. Centralize status-required resolver in ticket_form_gmc.php
  • Add getGmcStatusRequiredFields(statusId, ticketTypeId, tpaNo) returning explicit required IDs.
  • Use this resolver in updateClaimStatusDisplay instead of only class-wide required toggling (via getGmcMergedRequiredFields + applyGmcAdditionalDocRequiredState).
  1. Apply required state deterministically
  • Add applyGmcAdditionalDocRequiredState(requiredIds) (plan name: applyGmcRequiredState):
    • clear required from all Additional Documents inputs/selects/textareas,
    • set required only for resolver output,
    • keep approved_description forced optional,
    • keep existing mode-based pod_no requirement and non-id conditional logic.
  1. Real-time status-based validation
  • On #claim_status_id change, call:
    • applyGmcAdditionalDocRequiredState(...)
    • validate each now-required Additional Documents field immediately.
  • On input/change for Additional Documents fields, validate:
    • required non-empty when currently required,
    • existing format rules (date format, numeric, alphanumeric patterns).
  1. Submit-time hard guard parity
  • In validateBeforeSubmitGmc, compute resolver output and enforce required presence for each status field.
  • Ensure submit-time rules exactly match real-time rules to avoid drift.
  1. extra_fields_array_for_validate integration safety
  • Keep current dynamic extra-fields behavior, but avoid mutating hidden JSON to only selected status (current code rewrites payload).
  • Parse once from original source and use selected status key without destructive overwrite (GMC_EXTRA_FIELDS_VALIDATE_SNAPSHOT on load; removed destructive #claim_status_id JSON rewrite).
  1. Error UX consistency
  • For live checks: inline field message + is-invalid.
  • For submit checks: aggregated deduplicated toast + focus first invalid field in Additional Documents section (submit uses existing showGmcValidationErrors; focus-on-first not added separately for GMC—same as prior submit flow).

Verification Checklist (Additional Documents focus)

  • Switching status shows only the expected section and required markers for that status.
  • Required fields block submit when empty for each mapped status in both ticket type 1 and 72.
  • Optional fields in visible sections do not block submit unless mapped as required.
  • Date fields in Additional Documents reject invalid format (dd/mm/yyyy) in real-time and on submit.
  • approved_description remains optional for all statuses.
  • non_id_reason required behavior remains conditional on status + tpa_no emptiness.

Execution Status (new scope)

  • app/Views/ticket_form_gmc.php status-required resolver implemented
  • app/Views/ticket_form_gmc.php Additional Documents real-time required checks implemented
  • app/Views/ticket_form_gmc.php Additional Documents submit-time parity implemented
  • app/Views/ticket_form_handler.php integration-impact reviewed (no direct code change expected)

3.5) Parsley UI Preservation Plan (Do Not Overwrite Parsley Errors)

Observed from current UI behavior (as shown in shared screenshot):

  • Parsley is already rendering required-field messages (This value is required.) and invalid field styles.
  • Custom real-time validation currently adds its own inline messages (field-error-realtime) and is-invalid states.
  • This can duplicate/conflict with Parsley output and produce mixed error UX.

Goal

  • Keep Parsley as the single source of truth for required/empty-state messages and error placement.
  • Use custom JS validators only for non-Parsley checks (regex/date/business rules), without replacing Parsley errors.
  • Ensure only one validation message is shown per field at a time.

Single-Message Rule (Mandatory)

  • For required/empty errors: show only Parsley message (This value is required.), no custom inline duplicate.
  • For custom format/business errors: show one custom message only when Parsley has no active message for that field.
  • Never show Parsley + custom inline message simultaneously on the same field.

Implementation Plan

  1. Preserve Parsley error rendering
  • Do not inject custom inline error nodes for fields that are Parsley-managed required fields.
  • Do not clear/remove Parsley-generated elements (.parsley-errors-list, .parsley-required, etc.).
  • Do not override Parsley error text for required checks.
  • Before rendering custom inline message, detect existing Parsley required condition and skip custom required message.
  1. Separate validation responsibilities
  • Parsley handles: required, basic empty checks, and configured parsley triggers.
  • Custom realtime handles only: format/business checks not covered by Parsley (email regex edge rules, policy formats, status-based requirements, etc.).
  • If a field is currently failing Parsley required, custom validator skips showing its own required message for that field.
  • Keep toast summary deduplicated and avoid repeating inline-required messages already shown by Parsley.
  1. UI state conflict prevention
  • Avoid forcing is-valid / is-invalid classes on Parsley-owned required failures.
  • For custom non-required format errors, use a separate CSS hook/class (e.g., custom-invalid) so Parsley classes remain authoritative.
  • On submit, keep existing aggregated toast for custom/business errors, but do not suppress Parsley native inline messages.
  • Remove any legacy custom .field-error-realtime node for required-state field conflicts.
  1. Event-flow alignment with Parsley
  • After dynamic required updates (status/TPA/mode changes), avoid replacing Parsley messages; required-state errors defer to Parsley.
  • Ensure select2/date fields continue to use change-driven validation flow.
  1. Regression checklist
  • Required fields show only one message (Parsley), no duplicate custom inline required message.
  • Custom format errors still appear for non-empty invalid values.
  • No double red borders/error labels for the same field.
  • Status-based Additional Documents required fields still block submit correctly.
  • Existing toast summary remains for business-rule failures, without masking Parsley output.
  • Screenshot scenario is resolved: each invalid field displays a single message line only.

Execution Status (new scope)

  • GMC realtime validators updated to preserve Parsley UI ownership
  • GPA realtime validators updated to preserve Parsley UI ownership
  • Motor realtime validators updated to preserve Parsley UI ownership
  • Note/Reply/Feedback checked for non-conflicting error rendering

3.6) Optional Field Character Restriction Plan

Requirement:

  • For non-required fields only, do not allow special characters except: space, /, -, _.
  • Allowed set: letters (a-z, A-Z), numbers (0-9), space, /, -, _.
  • Disallowed examples: @, #, $, %, ^, &, *, (, ), +, =, !, ?, ., ,, :, ;, quotes, backslash, pipes, etc.

Validation Rule Definition

  • Shared regex for optional restricted-text fields:
    • ^[a-zA-Z0-9\\s/_-]+$
  • Behavior:
    • if optional field is empty -> valid (no error),
    • if optional field has value and fails regex -> invalid with one inline message,
    • do not apply this rule to email/date/numeric-specific fields that already have dedicated validators.

Scope (initial target fields)

GMC optional text fields:

  • policy_no, tpa_no, pod_no, claim_number, denial_reason, approved_letter, approved_description, utr_details, settle_letter, cancel_remark, return_remark, awb_no_courier_name.

GPA optional text fields:

  • policy_no, utr_details, approved_letter, approved_description, settle_letter, cancel_remark, return_remark, awb_no_courier_name.

Motor optional text fields:

  • policy_no (if editable in flow), any optional free-text field introduced by status section (if/when enabled in motor form variant).

Reply/Note/Feedback:

  • Keep existing domain-specific behavior for now (not part of this restriction unless explicitly requested).

Implementation Plan

  1. Shared helper per form script
  • Add helper isAllowedOptionalChars(value) using ^[a-zA-Z0-9\\s/_-]+$.
  • Add helper validateOptionalRestrictedField(id) that:
    • exits valid for empty values,
    • checks regex for non-empty,
    • shows single inline custom message (non-Parsley conflict-safe).
  1. Bind in realtime validators
  • GMC: apply to listed optional text fields inside validateGmcFieldRealtime.
  • GPA: apply to listed optional text fields inside validateGpaFieldRealtime.
  • Motor: apply where optional free-text fields exist.
  1. Submit-time parity
  • GMC submit validator adds same restriction for optional text fields.
  • GPA submit validator adds same restriction for optional text fields.
  • Motor submit validator adds same restriction for optional text fields (if applicable).
  1. Parsley coexistence
  • Keep restriction messages custom-only for optional non-empty invalid values.
  • Do not replace Parsley required messages.
  • Ensure one message per field (no duplication with Parsley).

Error Message Standard

  • Use one consistent message:
    • Only letters, numbers, spaces, /, -, and _ are allowed.

Verification Checklist

  • Optional empty fields pass validation.
  • Optional fields reject disallowed characters (@ # $ % & * + = ! ? . , etc.).
  • Optional fields accept abc 123 / - _.
  • Required-field Parsley messages remain unaffected.
  • No duplicate messages per field.

Execution Status (new scope)

  • GMC optional-field character restriction implemented
  • GPA optional-field character restriction implemented
  • Motor optional-field character restriction implemented (where applicable)
  • Submit-time parity added for all implemented forms

Create lightweight reusable helper methods inside each view script (or shared JS later):

  • isValidEmail(value)
  • isValidDateDDMMYYYY(value)
  • isDigits(value, length = null)
  • showValidationErrors(errorsArray) with dedupe

This keeps behavior consistent across GMC/GPA/Motor/Reply/Note.


5) UX and Error Handling Standards

  • Use existing toastr pattern for inline consistency.
  • Deduplicate repeated messages in one submit cycle.
  • Focus first invalid field and scroll into view for long forms.
  • Do not block submit for optional fields when empty.
  • Validate optional fields only when they contain non-empty value.

6) Verification Checklist

  • GMC form blocks invalid email/mobile/date/regex mismatches before API call.
  • GPA form enforces required + numeric/date/email parity.
  • Motor form rejects default select values and bad mobile/email.
  • Note form rejects <3 and >1000 chars.
  • Reply form rejects invalid recipient email and short subject.
  • Feedback form continues required radio enforcement and successful submit.
  • Existing edit mode and dynamic status-dependent fields still behave as before.
  • Fields now show validation feedback live during typing/selection.
  • Submit still remains blocked when any invalid state persists.

7) Out of Scope (Current Plan)

  • Backend controller refactor.
  • Converting all pages to one shared validation module file.
  • New validation rules not currently present in backend.
  • Changes to feedback backend validation (explicitly not requested in this run).