Pink Slips NSW started with one technician. But the business is expanding to six regions. Each technician needs their own calendar view without breaking the drag-and-drop scheduling.
From Single Technician to Multi-Region
Pink Slips NSW is expanding. One calendar showing all technicians creates chaos. We needed multi-technician support without breaking the drag-and-drop scheduling.
Guy Walker has been the sole technician for Pink Slips NSW, operating out of the Sutherland Shire. But the business is growing. New technicians are being onboarded in Gosford, Newcastle, Lismore, Tweed Heads, Dubbo, and Canberra. Each one needs their own calendar view, their own job management, their own schedule.
The existing single-calendar system showed all events overlapping on one view. With multiple technicians, it became completely unusable. You couldn't tell whose job was whose. The visual was a mess of overlapping colored blocks.
Single Calendar Doesn't Scale
One calendar showing all technicians = overlapping events, confusion, unusable
Each technician needs their own filtered view while sharing the same system

The Expansion
6 Regions, 1 System
- ✓
Sydney - Sutherland Shire (Primary)
- ✓
Gosford - Central Coast
- ✓
Newcastle - Hunter Region
- ✓
Tweed Heads - Gold Coast Border
- ✓
Dubbo - Central West NSW
- ✓
Canberra - ACT

The challenge wasn't just adding a filter dropdown. Each technician has different work hours, different home addresses (for travel time calculations), and different capacity limits. We needed a complete technician management system that integrates with the existing calendar and dashboard.
What We Built
Technician Management Page
Full CRUD operations for technicians. Name, email, phone, home address, work hours, max jobs per day, max travel time, active status.
Calendar Filtering
Dropdown to select technician. Events filtered by technicianId. Auto-selects Guy Walker as default. Dropped leads auto-assigned to selected technician.
Dashboard Filtering
Technician dropdown in dashboard header. Filters pipeline stages by calendar event assignments. Shows only leads assigned to selected technician.
Integrated Unscheduled Panel
Moved unscheduled leads inside the calendar card. Compact lead cards with customer name, vehicle, urgency, suburb.
Smart Conflict Detection
Refined overlap detection. Only triggers shift modal for actual time conflicts, not just events later in the day.
Multi-Technician Features
- ✓
Technician management page with full CRUD
- ✓
Calendar filtering by technician
- ✓
Dashboard filtering by technician
- ✓
Auto-assignment on drag-and-drop
- ✓
Smart conflict detection

The technician management page uses the same card-based UI pattern as the rest of the admin interface. Each technician record includes everything needed for intelligent scheduling: home address for travel time calculations, work hours for availability windows, and capacity limits to prevent overbooking.
Technician Record
- Name, email, phone
- Home address (travel calc)
- Work hours (start/end)
- Max jobs per day
- Max travel minutes
- Active/inactive status
Calendar Features
- Dropdown filter in header
- Events filtered by technicianId
- Auto-assign on drag-drop
- Smart conflict detection
- Integrated unscheduled panel
- No more overlap chaos
The Five Bugs We Encountered
Building features is the easy part. Debugging is where the real time goes. 90 minutes of our 4-hour session was spent fixing these five issues.
Google Places Autocomplete Closing Dialogs
What happened:
When adding a new technician, clicking on an address suggestion from the Google Places autocomplete dropdown would close the entire "Add Technician" dialog, losing all entered data.
Why it happened:
The Google Places dropdown (.pac-container) renders outside the dialog's DOM tree, directly on document.body. Radix UI's "click outside to close" behavior was triggered.
Solution:
<DialogContent
onPointerDownOutside={(e) => {
const target = e.target as HTMLElement;
if (target.closest('.pac-container')) {
e.preventDefault();
}
}}
>Dialog Closing on Address Select
Clicking Google Places suggestion closed the entire Add Technician dialog
Added onPointerDownOutside handler to check for .pac-container clicks

This is a common issue with any third-party dropdown that renders to document.bodyrather than inside the parent component. Google Places, date pickers, rich text editors—they all have this problem with modal dialogs. The fix is always the same: intercept the click event and check if it's inside the third-party element.
"Failed to Fetch" When Dropping Leads
What happened:
Dragging an unscheduled lead onto the Newcastle calendar resulted in a "Failed to fetch" error. The event wasn't being created.
Why it happened:
The event creation was sending technicianId: nullwhen no technician was selected. Server-side validation rejected it.
Key insight: Sending field: null is different from not sending the field at all. When optional, omit rather than null.
"Failed to Update Calendar Event" Error
After creating events with technician assignments, updating them (like changing the time) would fail.
The updateCalendarEventSchema in shared/schema.ts didn't include technicianId as an allowed field. We'd added it to the insert schema but forgot the update schema.
Dashboard Technician Filter Not Working
After selecting Sydney in the dashboard filter, no leads appeared even though Sydney has 108 calendar events.
Wrong approach
Checking lead_purchases.assigned_technician_id
All 3,205 leads had NULL in this field
Correct approach
Checking calendar_events.technician_id
This is where the assignment actually lives
Dashboard Filter Not Working
Checking lead_purchases.assigned_technician_id (all NULL)
Checking calendar_events.technician_id (correct data)

Lesson learned: Always verify where data actually lives in the database before building filters. Don't assume based on table names or field names. Check the actual data.
Shift Modal Triggering Unnecessarily
Dropping a lead into an empty slot would still trigger the "Shift events?" confirmation modal if any events existed later in the day.
The original logic was checking if any events started at or after the drop time, rather than checking for actual overlap. So if you dropped at 9am and there was an event at 3pm, it would ask if you wanted to shift.
Solution: Refined conflict detection to check time-based overlap (does the new event's time range intersect with existing events?) and slot-based conflict (does an event already start in the exact slot?).
Database Changes
New Table: technicians
Modified Tables
New Technicians Table
- ✓
name, email, phone - Contact info
- ✓
home_address - For travel calculations
- ✓
work_start_hour, work_end_hour - Availability
- ✓
max_jobs_per_day - Capacity limit
- ✓
max_travel_minutes - Distance constraint

The home_address field is required because it's essential for travel time calculations between jobs. The google_calendar_id field (not shown) is for future Google Calendar sync integration—two-way sync with technicians' personal calendars.
Current Metrics
Sydney region leads with 108 events. System ready to scale to any number.

Lessons Learned
5 Key Takeaways
- Track assignments where they happen - Technician assignment was on calendar_events, not lead_purchases. Always verify where data lives.
- Radix UI + third-party dropdowns need special handling - Use onPointerDownOutside to prevent dialogs closing on external clicks.
- Update ALL schemas when adding fields - Both insert AND update schemas. Missing one causes confusing errors.
- Null vs undefined matters - Sending field: null is different from omitting the field. When optional, omit.
- Test happy paths too - The shift modal bug wasn't caught because testing focused on conflicts. Test the no-conflict scenario.
5 Lessons Learned
- ✓
Track assignments where they happen
- ✓
Radix UI + third-party dropdowns need special handling
- ✓
Update ALL schemas when adding fields
- ✓
Null vs undefined matters in validation
- ✓
Test happy paths, not just edge cases

Time Investment
The bug fixes took the most time (90 minutes for 5 bugs). The Google Places dialog issue alone took about 30 minutes to diagnose.
45m CRUD, 30m calendar filter, 30m dashboard filter, 90m bug fixes, 15m testing.

Ready to Scale
The multi-technician system is now live. Pink Slips NSW can scale to any number of technicians without the calendar becoming unusable. Each technician sees only their jobs, and the drag-and-drop scheduling still works perfectly.
Four hours of development. Five bugs squashed. One business ready to scale.
Get More Pink Slips Updates
Follow the journey as we build AI-powered systems for Pink Slips NSW. Weekly insights on automation, scheduling, and scaling service businesses.
Need a Custom Business System?
We build AI-powered business systems that scale with your growth. Calendar management, lead tracking, technician scheduling—custom-built for your specific workflow.
Frequently Asked Questions
How does the technician filtering work?
Why did the Google Places autocomplete cause issues with dialogs?
What's the difference between sending null vs omitting a field?
{ technicianId: null }, the server receives the field with a null value and may validate it differently than if the field wasn't sent at all. Many validation schemas treat "field is null" differently from "field is missing." For optional fields, it's often safer to omit them entirely rather than sending null.How do you handle travel time between jobs?
Can technicians see each other's calendars?
Social Media Carousel
8 cards • Click to download individually or as ZIP
Building a Multi-Technician Calendar System
Pink Slips NSW Case Study
How we scaled from one technician to many


The Problem
One calendar showing all technicians = overlapping events, confusion, unusable at scale.


The Solution
- 1
Technician selector dropdown
- 2
Filtered calendar views
- 3
Drag-and-drop scheduling
- 4
Auto-assign on drop


From single to multi-technician system


Tech Challenges Solved
- 1
Google Places + Radix Dialog conflict
- 2
Null vs undefined field handling
- 3
Travel time constraints
- 4
Calendar event filtering


Before vs After
Single calendar, manual coordination
Per-technician views, automated assignment


Each technician sees only their jobs. Admin sees everyone. Same database, different views.
— Jordan James


See It Live
Book a Pink Slip and see the multi-tech system in action



Pink Slips NSW
Share This Article
Spread the knowledge