- Add EstimatesPage with Estimates + Templates tabs, KPI strip, search, and filter chips
- Estimate detail drawer with pipeline status tracker (Draft→Sent→Waiting Approval→Approved) and edge statuses (Follow Up Required, Revision Required, Rejected, Expired); clickable nodes update estimate status live
- Share bar: WhatsApp, iMessage, Email, PDF download (jsPDF + autotable, light-mode A4)
- ALL_STATUS_CONFIG as shared status registry across cards, badge, filters, and tracker
- Sort controls: Newest First / Oldest First / By Status
- Date range filter with From/To date inputs and clear button
- Fix unit price discrepancy: Unit Price = clientPrice/qty so Qty × Unit Price = Total
- Fix chatbot overlap: pr-20 on drawer footer keeps grand total visible
- Fix card vs drawer total mismatch: computeGrandTotal extracted to estimateExport.js, used as single source of truth in cards, drawer, PDF, and WhatsApp message
- TemplateEditorModal: Owner CRUD for master templates, duplicate with Save as Copy / Replace Original toggle
- EstimatesPage: tabbed hub with Estimates and Templates tabs, KPI strip, search + filter
- EstimateDetailModal: right-side drawer showing scope of work, computed line items, and financial summary from template + roof area
- TemplateEditorModal: create/edit/duplicate templates with segmented mode toggle
- Owner-only template management (create, edit, duplicate, delete); Admin/FA read-only view
- Duplicate mode: toggle between 'Save as new copy' (default, editable name) and 'Replace original'
- MASTER_TEMPLATES and MOCK_ESTIMATES moved into mockStore with full CRUD helpers
- TemplateSelectionModal now reads from mockStore instead of local stub
- Sidebar nav updated to point to /estimates hub for all roles
- Routes added: /emp/fa/estimates, /admin/estimates, /owner/estimates
- DispatchMapPanel: replace h-full/height:100% with explicit inline px height
on both wrapper div and MapContainer — CollapsePanel uses height:auto which
makes percentage heights resolve to 0 giving Leaflet a zero-size canvas
- DispatchMapPanel: accept mapHeight prop from parent for responsive sizing
- LynkDispatchPage: compute responsive mapHeight state (300px mobile →
380px sm → 460px md → 520px lg tablet) updated on window resize; passed
as prop to DispatchMapPanel on all non-desktop renders
- LynkDispatchPage: add missing reps={effectiveReps} prop on mobile map render
so live rep status cycling is reflected on all breakpoints
- LynkDispatchPage: add missing onQuickAssign={handleAssign} on desktop lead
queue render so Quick Assign button works on desktop
- LynkDispatchPage: add whitespace-nowrap to efficiency badge to prevent
'89% AI-Dispatched' wrapping to two lines in header
- LynkDispatchPage: dispatch synthetic resize event 260ms after map panel
expands on mobile/tablet so Leaflet invalidateSize fires post-animation
- DispatchMapPanel: add second invalidateSize call at 320ms (belt-and-suspenders
alongside 50ms) to cover 220ms CollapsePanel animation on slower devices
- DispatchLeadQueue: enrich DROP_POOL leads with phone, email, source
sub-details and notes so Lead Quick View shows complete data on drop-in leads
- Quick Assign: accent Zap pill on unassigned lead cards; dispatches top AI rec in one tap; 2.2s confirmation state
- LeadQuickViewModal: right-drawer with client contact (copy buttons), property, source sub-details, editable notes with double-gate confirmation
- Rep Status Live Cycling: repStatuses state map overrides DISPATCH_REPS.status; effectiveReps prop passed to map and AI drawer; assign sets rep to en_route, reverts to available after 60s
- Dispatch Efficiency Score: aiCount/totalCount seeded 8/9 (89%); AI assign increments both, manual override increments total only; shown as badge in header
- Efficiency badge label updated to '89% AI-Dispatched' with tooltip explaining the metric
- AI Says block in RecommendationDrawer: rep identity row (avatar, name, status/distance, large score) + italic AI insight quote above recommendations
- Lead aging badges: amber Aging (20+ min), red pulsing Overdue (40+ min) on unassigned leads
- Search bar in Lead Queue: filters by customer name, address, city; combines with active tab filter
- mockStore enrichment: email + notes + source sub-details on all 12 leads; rating/closeRate on all 5 reps; distanceMi/aiInsight/conflictFlag on all recommendations; updateLeadNotes() action; DISPATCH_WEEKLY_STATS export
- LynkDispatchPage wired for Phase 5 KPIs, storm mode, chart modal, log drawer, and all new features
- DispatchWeeklyChart: Recharts ComposedChart (Area + Line), custom dots for storm/today/emergency days, rep leaderboard with animated progress bars
- DispatchChartModal: centered modal (max-w-2xl, 88vh), portaled to document.body, scale+fade animation, ESC and backdrop close
- DispatchLogDrawer: right-side sliding drawer (400px sm+, full-width mobile), portaled, spring animation from right, full-height scrollable log, ESC and backdrop close
- Storm mode styling on both — amber tint on headers and borders
- DISPATCH_WEEKLY_STATS: 7-day mock data (Mon Mar 20 – Sun Mar 26) with per-rep breakdown, storm day Thursday, partial Sunday
- Real Plano TX map using Leaflet with dark/light tile layer filter
- Custom DivIcon rep markers (initials circles, pulsing ring on top AI pick)
- Urgency-colored lead pins with radar rings on selected lead
- Route polyline with stroke-dashoffset draw animation keyed to selected lead
- Travel time chip at route midpoint — solid color background, white text, triple ring shadow
- Storm polygon overlay (NE Plano) with Storm Zone Active badge
- Route Active chip top-right, legend overlay bottom-left (rep status + lead urgency counts)
- Hover tooltips on rep markers (name, status, slots, rating/close%) and lead pins (name, urgency, address, notes snippet)
- invalidateSize() with 50ms defer + window resize listener to fix blank tile area after flex layout settles
- Build DispatchRecommendationDrawer with empty/processing/results/dispatched states
- Structured shimmer skeletons during AI processing with cycling analyze messages
- Rep cards: animated score counter, 5-factor breakdown bars, reason chips, capacity donut
- Top Pick badge, storm-aware weather chips (amber styling)
- Assign button fires Sonner toast + updates lead status to confirmed in queue
- Override button opens rep picker modal with capacity and performance data
- Post-assign dispatched confirmation overlay (2.4s) then drawer resets
- Mobile: tap lead auto-expands AI panel and smooth-scrolls to it
- Fix tab overflow: scrollable tab bar, shortened labels (Open/Risk/Done)
- Cap DROP_POOL to 3 fires, no repeat flooding
- Resizable drag handles on desktop (xl 1280px breakpoint)
- Collapsible panels on mobile/tablet — Map + AI collapsed by default on mobile
- iPad Air + iPad Pro 11" treated as tablet via xl breakpoint
- Fixed lead list heights: 22rem mobile → 72rem xl (8 cards visible)
- PageTransition h-full fix to maintain height chain
- DispatchLeadQueue: 4-tab filter (All / Unassigned / At Risk / Confirmed)
with live counts; AnimatePresence popLayout for smooth card entrance/exit
- LeadCard: urgency badge (EMERGENCY pulse / HIGH / STANDARD), source icon,
customer name, lead type, address, status pill, assigned rep initials, time ago
— colored left border by urgency, blue ring when selected
- Storm mode: emergency leads float to top via sort; PRIORITY badge on
emergency_tarp cards; amber Unassigned pill in storm context
- 20s interval drops new leads from 3-lead pool; NEW badge fades after 5s
- LynkDispatchPage: left panel now renders DispatchLeadQueue; handleSelectLead
triggers 1.2s isProcessing state; right panel shows processing/selected/empty
states ready for Phase 3
- mockStore: add DISPATCH_LEADS (12), DISPATCH_REPS (5), DISPATCH_RECOMMENDATIONS
(pre-baked AI scores + route paths for all 12 leads), dispatchLeads state,
assignDispatchLead() action
- LynkDispatchPage: 3-panel command center shell with storm banner, live badge,
Storm Mode toggle, KPI bar with real unassigned count
- App.jsx: routes /admin/dispatch and /owner/dispatch wired
- Layout.jsx: LynkDispatch (Zap icon) added to ADMIN and OWNER sidebar nav
- AnimatedNumber: add ScrollTrigger so counters animate on scroll-into-view
instead of firing immediately on mount (fixes table rows animating before
the user scrolls to them)
- AnimatedNumber: lock locale to 'en-US' for consistent comma formatting
- LeaderboardPage: lock formatValue locale to 'en-US'
- mockStore: update MOCK_SALES_HISTORY dates from Jan/Feb to March 2026 so
the default "This Month" filter returns data; previous dates caused all
agents to show $0 revenue, making the animation appear broken
- mockStore: replace unrealistic amounts ($250K–$520K) with realistic
residential roofing job values ($12K–$42K per deal)
Save action (CreateLeadPage):
- Validate required fields: first/last name, 10-digit phone, address, city, lead source
- On failure: Sonner error toast + auto-opens first incomplete section
- On success: Sonner success toast with name + address, redirects to /emp/fa/leads
- Desktop save bar with progress % indicator and validation error message
- Back button navigates to /emp/fa/leads instead of browser history
Leads List page (LeadsListPage.jsx):
- Route: /emp/fa/leads (FIELD_AGENT, ADMIN, OWNER)
- Lead cards: name, urgency + status badges, address, phone, lead source, time ago, creator
- Search bar: filters by name, address, city, source, status
- Empty state with CTA when no leads saved yet
- Animated card entrance with staggered spring transitions
mockStore:
- Add leads[] state and addLead() action — prepends new lead with id, createdAt, status: New
Navigation:
- Sidebar "New Lead" replaced with "Leads" (ClipboardList icon) for all roles
- New Lead button lives on the list page header
Author: Satyam Rastogi
Phase 5 — Insurance (purple #8B5CF6):
- Insurance Company custom select, Claim Number + Claim Status (2-col grid)
- Adjuster Name + Adjuster Phone (2-col grid, flex-wrapper with Phone icon + mask)
- Policy Number full-width input, all focus rings use purple accent
Phase 6 — Assignment (cyan #06B6D4):
- Role-aware rep selector: Field Agents see self-assign toggle, Admins/Owners
see scrollable list of all field agents with Unassigned option
- Priority pill selector (Low/Medium/High) with Framer Motion layoutId slide
- Follow-up Date: flex-wrapper with Calendar icon + color-scheme fix
- sectionCompletion wired for both sections
Fix: replace Framer Motion variant inheritance with explicit initial/animate on
each section motion.div — inherited variants from already-animated parent caused
Insurance and Assignment to render stuck at opacity:0 when added dynamically
Author: Satyam Rastogi
- LeadPropertySection: Street Address (with pin icon), City/State/ZIP row (flex layout, ZIP auto-strips non-digits to 5 chars, state defaults to TX), Property Type dropdown and Site Photos (Full Form only, animate in/out)
- Photo upload: dashed zone with Camera + Image icons, hover highlight in emerald, hidden file input with capture=environment (opens camera on mobile), multiple selection allowed
- Thumbnails: 4-col grid, spring scale-in animation, hover overlay with X to remove individual photos
- Focus ring accent changed to emerald to match section color identity (blue=contact, emerald=property)
- CreateLeadPage: propertyPhotos added to INITIAL_FORM, sectionCompletion.property live (address + city required), LeadPropertySection wired into renderSectionContent
- LeadContactSection: First/Last name grid, dynamic phone list, dynamic email list (Full Form only), all with spring height animations and LayoutGroup for coordinated layout shifts
- PhoneEntryRow: phone input with (555) 000-0000 mask, type selector (Mobile/Home/Work/Other), amber star primary toggle, red X remove — type+star hidden in Quick Capture mode
- EmailEntryRow: email input, type selector, star primary toggle, remove button
- Add Phone / Add Email buttons animate in when switching to Full Form; rows slide in/out with spring height collapse
- CreateLeadPage: sectionCompletion.contact now live (firstName + lastName + 10-digit phone), progress bar switched to section-completion-based percentage (completed sections / visible sections)
- UrgencyPillSelector: 3-pill selector (Standard/High/Emergency) with Framer Motion layoutId sliding background, spring physics, color transition on text
- LeadJobSection: full Job Details fields — Lead Source (always), Lead Type / Work Type / Trade Type (Full Form only, each row animates in/out with spring height collapse), Urgency pill (always), Notes textarea (Full Form only)
- Full Form fields use overflow-hidden + height:auto spring animation — no phantom gaps since spacing is managed via pt-4 inside each animated block
- CreateLeadPage: formData state tracking all sections (scaffold for Phase 3-6 fields), updateField handler, sectionCompletion map, GSAP progress bar now driven by real field completion percentage, Job Details section wired up with live data
- CreateLeadPage.jsx: full page shell with Quick Capture / Full Form toggle, Barlow Condensed header, breadcrumb nav, GSAP progress bar stub, mobile sticky save footer
- LeadSectionWrapper.jsx: collapsible section component with Framer Motion height animation, spring chevron rotation, completion dot, dual light/dark header design matching GlassPanel language
- 5 sections wired up: Contact (blue), Property (emerald), Job Details (amber), Insurance (violet), Assignment (cyan) — Quick Capture shows first 3, Full Form shows all 5
- Section indicator pills in header dim gracefully when hidden in Quick Capture mode
- LEAD_FORM_OPTIONS added to mockStore: lead types, sources, work types, trade types, urgency/priority levels, insurance companies, claim statuses, phone/email types, US states
- Route /emp/fa/leads/new added (FIELD_AGENT, ADMIN, OWNER)
- New Lead nav item added to sidebar for all 3 roles
- Add Estimate_Section_Screens_and_Workflows/ to .gitignore (local reference images only)
- Rewrite README to reflect revamp branch: React 19, ProCanvas dual-mode design, EstimateBuilder redesign, Lead Creation and LynkDispatch AI upcoming features
Light mode — Energetic & Clean (Duolingo/fitness app aesthetic):
- GlassPanel rebuilt as function component using useTheme; light mode gets
solid colored header banners per panel (gold=Showdown, fire=Hot Streak,
cyan=Weekly, blue=Stats/Leaderboard, purple=Rewards/Badges) with white
text on color; dark mode keeps existing glass panel + accent glow line
- Page background: zinc-100/80 so white cards float visually
- Event cards (Showdown, Hot Streak, 12 Appointments) promoted to use
GlassPanel title+icon props — each gets its own colored identity banner
- OperatorCard: soft shadow + amber ring in light mode; stays dark (sports
card aesthetic intentional); harsh rgba(0,0,0,0.6) shadow removed
- Live Event Banner: vibrant emerald-600→green-700 gradient in light mode
replacing the always-dark green-900; softer shadow and border
- Log Action buttons: clean bg-white with shadow-sm, removed dark inset
shadow that made them look dirty in light mode
- Neon/cyan on white fixed: #AAFF00→green-600, #00E5FF→sky-500/sky-600
- EnergyBar tracks: bg-zinc-200 in light, bg-black/60 in dark
- Leaderboard, badge cards, reward nodes: all adapted with dark: variants
- XP badge in header: bg-zinc-100/border-zinc-200 in light mode
- Import useTheme added to support GlassPanel and OperatorCard hooks
Dark mode — unchanged; all existing glass panel aesthetics preserved.
The collapsed sidebar was showing '[object Object]' on hover because the
HTML title attribute received a JSX element (ProCanvas uses a JSX label
with styled spans). Removed the native title attribute — the custom
tooltip div already handles collapsed-state label display correctly.
- Complete ProCanvas redesign with retro sports game aesthetic
- Card-game style photo frame with tilt, shimmer, corner star accents
- Daily Missions card with weekly challenge + individual quest progress bars
- Log Action card (Door Knocked, Lead Gained, Appointment Set, Client Meeting)
- Each log action opens themed modal with relevant input fields
- Challenges modal with 6 active challenges and progress tracking
- Achievements modal with all badges, unlock status, descriptions
- Nav bar tabs (Leaderboard, Challenges, Achievements) wired to modals
- Rewards & Checkpoints with named stages (Daily Grind to Legend Run)
- Smoother Hot Streak pulse animation (2.5s float + 3s pulse rings)
- Hit The Map button with smooth pulsing glow animation
- Grid pattern overlay in Leaderboard card
- Light mode support via dark: Tailwind variants throughout
- Top 3 badges displayed on profile card
- Fixed dropdown option visibility in dark mode
- Added visually hidden labels, IDs, and names to form inputs across all key components and pages (modals, directories, chatbots)
- Added tabIndex and onKeyDown handlers to clickable table rows in OwnerProjectDetail for keyboard accessibility
- Validated existing ARIA roles and Escape key bindings on modal components
- Added whitespace-nowrap to all text labels on both Old Way and Our Way sides to prevent inconsistent text wrapping on mobile
- Added opacity fade to Our Way labels based on slider position (fades out as slider moves right)
- Matched symmetric fade behavior: both sides now smoothly fade in/out based on slider position
- Added transition-opacity duration-150 for smooth fade animation
- Rewrote AI chatbot context system with deep role-aware data injection for all 7 roles (Owner, Admin, Field Agent, Contractor, Subcontractor, Vendor, Customer) plus guest fallback
- Added mobile-responsive bottom-sheet modals across all roles (ChangeOrderDrawer, InvoiceDetailModal, FinancialSummaryModal, VendorFinancialSummaryModal, FinancialDetailsModal)
- Converted Owner Project List and Vendor Orders tables to mobile card views with touch-friendly layouts
- Optimized Vendor Management and People Directory with mobile list/detail toggle and back navigation
- Fixed Document Control mobile view: horizontally scrollable filter tabs, proper overflow chain for document visibility
- Added responsive padding, text scaling, and flex-wrap across StatCard, TaskDetailsModal, OwnerSnapshot, OwnerProjectDetail, VendorDashboard, and DocumentManagement
- Expanded mock data store with richer vendor invoices, orders, documents, and compliance records
- Enhanced Owner Snapshot with financial KPI cards, urgent items panel, and Action Center modal
- Built Contractor Dashboard with task management, financial summary, and performance metrics
- Built Subcontractor Dashboard with clock-in tracking, task assignments, and invoice management
- Enhanced Vendor Dashboard with earnings summary, active orders, compliance status, and performance rating
- Added icon-only tab navigation on mobile for OwnerProjectDetail
- Extended attribution signatures across all platform pages
- Add responsive font scaling for heading (3xl to 9xl)
- Add responsive font scaling for subtitle (sm to 2xl)
- Limit CTA button width on mobile (max-w-[260px])
- Limit discount banner width on mobile (max-w-[280px])
- Adjust padding and spacing for all screen sizes
- Fix text overflow issue on 'REVOLUTIONIZED' heading
- Add Owner, Contractor, Vendor, Subcontractor dashboards and role-based routing
- Owner now has superuser access to all Admin pages (dashboard, schedule, leaderboard)
- Redesign landing page mobile menu as slide-in sidebar (replaces broken Framer Motion overlay)
- Add body scroll lock to app sidebar for mobile consistency
- Fix Team Schedule to match Admin Dashboard design language (ambient glows, gradient header, SpotlightCard, zinc palette)
- Fix login page tab overflow — use abbreviated labels and grid layout for 6 role tabs
- Fix Recharts ResponsiveContainer warnings — replace height="100%" with fixed pixel heights
- Fix lightbox image viewer — unified nav bar, touch swipe support, no more overlapping text
- Add AI Assistant page, People/Vendor/Document management for Owner role
- Expand mock data store with contractor, vendor, and subcontractor data
- Created reusable AnimatedNumber component with GSAP
- Integrated animated counters in Dashboard (metrics, weather)
- Integrated animated counters in Leaderboard (podium, table)
- Fixed AdminSchedule dark mode styling with theme-aware classes
- Added responsive columns and functional dropdown to Team Schedule
- Implemented date range and status filters for Team Schedule
- Improved animation smoothness with expo.out easing