Vishal Tyagi
← Projects
Platform Engineering·production

Admin Web Migration

Migrated the administrative web surface incrementally while ops kept working — shared sheet validation, multi-step upload wizards, and dirty-check wrappers replaced duplicated legacy UI plumbing.

Date2026-01
Reading TimeN/A
Statusproduction
StackFlutter Web, Dart, Admin UI+2

Incremental (modules stayed online)

Migration style

[High Confidence]

SheetValidationUtil, CustomStepper, dirty-check wrappers

Shared primitives

[High Confidence]

What it does

Ops teams use the admin web surface for bulk ingestion, allocations, API config, and CRM integrations. Those flows had grown as one-off views: parsing, column mapping, validation, loading states, and error handling were re-implemented per page. Forms lost state on accidental dismissals; wizards re-fetched the same org metadata on every step.

The migration introduced shared components and moved views over one module at a time so the admin shell stayed usable.

Constraints

  • No big-bang cutover — ops depended on the tools daily
  • Large CSV/XLSX uploads needed client-side pre-validation before hitting the API
  • Multi-field mapping forms could not silently discard edits
  • New modules had to reuse the same design and data-grid primitives

Decisions & tradeoffs

  1. Incremental adoption — shared boundaries first; migrate views sequentially
  2. SheetValidationUtil — one place for parse, required fields, and length checks
  3. wrapDialogWithDirtyCheck — navigation/modal guard for unsaved edits
  4. Cached domain adapters — roles/process hierarchies loaded once per wizard instead of per step
flowchart LR
  AdminShell[Admin Core Shell] --> Stepper[CustomStepper Wizard]
  Stepper --> UploadStep[CommonUploadStep]
  UploadStep --> ValidationEngine[SheetValidationUtil]
  ValidationEngine --> SchemaCheck{Schema Validation}
  SchemaCheck -->|Valid| Queue[Ingestion Queue]
  SchemaCheck -->|Invalid| ErrorFeedback[Row/Column Feedback]
  AdminShell --> DialogWrapper[wrapDialogWithDirtyCheck]

Tradeoffs: explicit stateful wizards cost a bit of boilerplate and buy predictable loading/error/partial-submit states. Upfront shared contracts slowed the first integration and sped up later ones (Meta, WhatsApp, HubSpot, Zoho, Salesforce).

What it demonstrates

  • Platform migration under continuous operational use
  • Extracting duplicated admin plumbing into reusable validation and wizard primitives
  • Treating form-state loss as a product bug, not a UX nicety

See also the architecture case study.