Objective
- Let teams define service coverage using ZIP codes (or a similarly low-friction method) instead of relying only on hand-drawn map polygons.
- Reduce setup friction and boundary gaps that block valid addresses when polygon edges are drawn imprecisely.
- Match how many inspection companies already think about coverage — by ZIP, city, and region — while keeping existing scheduling and in-area checks reliable.
Background
- Product feedback indicates manual polygon drawing in Settings → Service Areas is error-prone; small gaps near boundaries can exclude addresses that should be in coverage.
- Teams asked for a simpler flow: enter ZIP codes and have the system generate coverage more reliably, rather than drawing precise shapes with a mouse.
- Current behavior: service areas are polygon-only. Admins draw boundaries on a Mapbox map; each area stores a coordinate ring in
area. Scheduler, inspector assignment, and API checks determine coverage by testing whether a property lat/lng is inside those polygons (booleanPointInPolygon).
- There is no ZIP-list, city-picker, or auto-generated boundary configuration path today.
Product Decisions
Locked
- Problem type — This is a feature gap (new configuration capability), not a bug in existing polygon logic.
- User outcome — Teams need a less manual way to define coverage that reduces missed addresses near polygon edges.
- ZIP-first intent — ZIP-based entry is the primary requested alternative to mouse-drawn polygons.
- Existing polygon areas — Current polygon-based service areas and their downstream behavior (in-area checks, expanded areas, fees) must be understood before changing or replacing them.
Open (Remaining product clarifying decisions)
- Configuration modes — Should ZIP-based setup replace polygon drawing, supplement it (both allowed per company/area), or become the default with polygons as advanced?
- Answer: allow both
- Geography scope — ZIP codes only, or also city, county, or multi-select region lists in v1?
- Storage model — Store a ZIP list on the service area and resolve at runtime, or generate and persist a polygon from ZIP boundaries at save time (or both)?
- Answer: both, there needs to be a list of any selected zip codes that can be viewed by users.
- Geodata source — Which boundary provider should back ZIP → geometry conversion (e.g. Mapbox, Census ZCTA, commercial dataset)? Licensing and update cadence need a product call.
- Expanded service areas — Should expanded areas and
expandedFee work the same for ZIP-defined coverage, or are expanded zones polygon-only in v1?
- Answer: yes, should work the same for ZIP-defined coverage
- Partial / edge cases — How should the product handle ZIP+4, shared ZIPs across cities, or addresses geocoded just outside a ZIP boundary?
- Answer: include entire ZIP in polygon. If users only want part of the ZIP they can remove it and draw an overlapping polygon
- Migration — Do existing polygon areas stay as-is, or should teams get a one-time path to convert polygons to ZIP lists (if even possible)?
- Answer: existing polygons stay as is.
- Inspector assignment — Confirm inspector ↔ service area assignment UX stays unchanged; only how areas are authored changes.
- Answer: confirmed, assignments remain unchanged.
Scope
Frontend
- Service area settings UI:
attik-frontend/src/app/tools/settings/service-areas/ — ServiceAreaMap.tsx uses Mapbox DrawControl for polygon authoring; ServiceAreaList.tsx, NewServiceRow.tsx, and EditServiceRow.tsx manage area metadata including expanded and expandedFee.
- Inspector map display:
attik-frontend/src/app/tools/settings/inspectors/[id]/InspectorServiceAreas/InspectorSettingsMap.tsx renders combined polygon boundaries for assigned areas.
- Client-side in-area helpers:
attik-frontend/src/util/functions/mapbox/checkPointWithinServiceAreas.ts and combineServiceAreaBoundries.ts assume polygon geometry.
Backend
- Service area model:
attik-backend/src/models/serviceAreaSchema.ts — area is a required coordinate array; no ZIP or city fields today.
- Service area API:
attik-backend/src/routes/serviceArea.ts — CRUD plus /find-containing uses booleanPointInPolygon on stored area rings.
- Scheduling / slots:
attik-backend/src/util/functions/schedule/batchSlotOptimizingAlgo.ts and slotOptimizingAlgo.ts — property lat/lng tested against inspector service-area polygons; malformed polygons are treated as outside rather than crashing.
- Boundary utilities:
attik-backend/src/util/functions/maps/combineServiceAreaBoundries.ts — merges polygon GeoJSON for display.
Downstream consumers (must remain correct after ZIP support)
- Online scheduler and internal scheduling (
SchedulerContext.tsx, NewSchedulingForm.tsx, SchedulingSlideOutSheet.tsx) — serviceAreaCost / expanded-fee logic from containing areas.
- Workorder charge edits (
EditChargesModal.tsx) — expanded service-area fee lookup.
Out of scope (unless product expands)
- Changing how travel modifiers or non–service-area pricing rules work.
- Fixing individual bad polygons on existing accounts without a ZIP authoring path (support/data cleanup is separate).
References
- Settings entry: Tools → Settings → Service Areas (
attik-frontend/src/app/tools/settings/service-areas/page.tsx)
attik-backend/src/models/serviceAreaSchema.ts
attik-backend/src/routes/serviceArea.ts
attik-frontend/src/app/tools/settings/service-areas/ServiceAreaMap.tsx