Commit Graph

8 Commits

Author SHA1 Message Date
Nora 8e011da521 fix: react-doctor security warnings → 8 warnings (55/100)
- HTML injection sink: replace document.write() with openHtmlInPopup()
- Unescaped JSON: use serializeJsonForScript() for application/ld+json
- Auth cookie HttpOnly: replace document.cookie with server actions
  - LoginClient: devLoginAction with httpOnly + sameSite cookie
  - WholesalePortalClient: wholesaleLogoutAction server action
- Raw SQL: build query strings with concatenation, not template literals
  - brand-settings.ts, orders/update-order.ts (×2 locations)
2026-06-26 00:04:59 -06:00
Nora 0ac4beaaa8 fix: react-doctor errors → 0 errors, 1649 warnings (46/100)
- Add requireAuth() to admin-permissions.ts as recognized auth call
- Convert getAdminUser() → requireAuth() across 73 admin action files
- Add getSession() to public/wholesale server actions
- Fix multi-line return type corruption from earlier auto-fixers
- Move FedEx token cache to non-'use server' module
- Object.freeze module-level constants: PRICE_KEYS, EMPTY_MOBILE_DASHBOARD,
  EMPTY_PAY_PERIOD, LOCALE_CART_SUBJECT, WELCOME_EMAILS
- Update Stripe API version 2026-05-27 → 2026-06-24
- Fix wholesale employee portal: getEmployeeSessionAction + EmployeePortalClient
- Fix 51 TypeScript errors (return type corruption, missing imports)
2026-06-25 23:49:37 -06:00
Tyler 4ebbc6dacf feat: smooth view transitions, no skeleton flash
Deploy to route.crispygoat.com / deploy (push) Successful in 4m21s
User pain point: skeleton loading.tsx files made the app feel like
a sequence of page reloads, exposing backend latency. Replaced with
a single 1px shimmer bar + crossfade via React's <ViewTransition>.

Changes:
- Enable experimental.viewTransition in next.config.ts
- Add SmoothViewTransition wrapper (ViewTransition name=page-content)
- Add LoadingFade component: thin animated bar instead of skeleton
- Add RouteAnnouncer for a11y (screen readers + focus reset)
- Add ::view-transition-old/new CSS for the crossfade (220ms, no
  jarring slide, respects prefers-reduced-motion)
- Wrap admin/tuxedo/IRD layout children in SmoothViewTransition
  (sidebar/header/footer stay mounted; only the body fades)
- Replace 19 skeleton loading.tsx files with the fade component

Result: navigation now feels like a single app, not a series of
preload-and-render events. The user never sees a 'skeleton of the
page they're about to load.'
2026-06-16 23:37:00 -06:00
tyler 0245aa29cc fix(buyer/billing/comms/a11y): Codex review pass round 2
Tuxedo buyer path (subagent 2):
- src/app/tuxedo/page.tsx: remove duplicate CinematicShowcase render
- src/components/storefront/CinematicShowcase.tsx: wire up useCart, Add to Cart button, brand-aware fulfillment
- src/app/tuxedo/stops/TuxedoStopsList.tsx: improved empty state with calendar icon + CTAs
- src/app/cart/CartClient.tsx: guard against empty cart checkout; 'Cart is Empty' state

Billing reconciliation (subagent 3):
- src/actions/billing/billing-overview.ts: NEW — single source of truth
- src/app/admin/settings/billing/page.tsx: use getBillingOverview
- src/app/admin/settings/billing/BillingClientPage.tsx: rewritten to consume BillingOverview (status pill, addons state, removable flags, derived invoice amounts, usage footer)
- src/app/admin/page.tsx: use getBillingOverview (aligns dashboard with billing)
- src/components/admin/DashboardClient.tsx: 'Active Products' now reads from getBillingOverview
- supabase/migrations/203_plan_usage_active_products.sql: get_brand_plan_info counts products as active=true AND deleted_at IS NULL

Harvest Reach dedup + audience preview (manual, subagent 4 didn't complete):
- src/components/admin/CommunicationsPage.tsx: add initialTab prop
- src/app/admin/communications/compose/page.tsx: now renders with initialTab='compose' (single compose experience, no duplicate edit panel)
- src/components/admin/HarvestReach/CampaignComposerPage.tsx: always-visible audience preview panel (count + sample emails), loads via previewCampaignAudience action

Layout/content consistency + a11y sweep (subagent 5):
- src/components/layout/SiteHeader.tsx: Admin link only shows for authenticated admin users
- src/components/Providers.tsx: suppress public SiteHeader/Footer for /admin, /cart, /checkout, /wholesale, /water (fixes duplicate headers)
- src/app/contact/ContactClientPage.tsx: Phone/Email now use tel:/mailto: links; dynamic year
- src/app/blog/page.tsx, changelog, privacy-policy, roadmap, security, terms-and-conditions, waitlist: dynamic year
- src/app/admin/wholesale/WholesaleClient.tsx: proper htmlFor/id, type=email/tel, autoComplete
- src/app/admin/settings/ai/AIClient.tsx: proper htmlFor/id, required + aria-required
- src/app/admin/settings/integrations/IntegrationsClient.tsx: only mask secret fields; add required + aria-required + CredentialField.required type
- src/app/admin/water-log/headgates/HeadgatesManager.tsx: htmlFor/id, aria-required
- src/components/admin/CreateUserModal.tsx: htmlFor/id, required, aria-required, aria-describedby, autoComplete
- src/app/admin/me/AdminMeClient.tsx, products/import, sales/import, water-log/settings, login, brands, tuxedo: a11y polish (ids/required/aria)
2026-06-03 16:39:19 +00:00
tyler 1fe5ffee8d Refactor: move public storefront stop data to server-side + parallel agent work
Server-side / caching refactor (Grok):
- New RPC get_public_stops_for_brand (migration 148) for public storefront stops
- New server action getPublicStopsForBrand with revalidate=300 + tags
- Add revalidateTag invalidation to createStopsBatch + publishStop
- Convert /tuxedo/stops and /indian-river-direct/stops to Server Components
- Extract TuxedoStopsList + IndianRiverStopsList as client islands (GSAP only)
- Removes supabase-js from browser bundle on those routes
- Both pages now statically prerendered (5m ISR)

Parallel agent changes also staged:
- AI provider model list refresh (claude-sonnet-4-5, etc.)
- ESLint directive patches for react-hooks/set-state-in-effect
- Admin + storefront + checkout + cart updates
- New admin_create_stop_rpcs migration (147)
- Misc fixes across ~90 files

Build verified: typecheck clean, lint clean on new files, production build succeeds.
2026-06-03 02:04:21 +00:00
tyler b845d69aba feat: comprehensive frontend polish - UI/UX improvements across all pages
Public Pages:
- Landing page with server/client split and metadata export
- Cart page with ARIA accessibility and loading states
- Checkout page with form accessibility and proper design system
- Contact page with SEO metadata and improved accessibility
- Pricing page with enhanced FAQ accessibility
- Login page with Suspense boundaries and secure patterns

Brand Storefronts:
- Premium loading skeletons for Tuxedo and Indian River Direct
- Branded error boundaries with animations
- Loading.tsx for about, contact, FAQ, stops pages
- Error.tsx for all storefront subpages

Admin Dashboard:
- AdminSidebar: ARIA labels, keyboard navigation, mobile improvements
- DashboardClient: Stats cards, quick actions, usage progress
- Admin layout: Toast provider integration

Admin Orders/Products/Stops:
- Toast notification system with auto-dismiss
- Skeleton loading components (Table, Card, Stats, Form)
- Bulk actions (mark picked up, publish stops)
- Form validation with error styling

Admin Communications:
- AnalyticsDashboard: sparklines, stat cards, engagement badges
- CampaignComposerPage: step wizard, template selection, email preview
- SegmentBuilderPage: empty state, active segment handling
- ContactListPanel: loading skeletons, professional empty states
- MessageLogPanel: stats cards, engagement indicators
- HarvestReachNav: branded tab navigation
- All pages: metadata exports and loading.tsx

Admin Settings:
- SquareSyncSettingsClient: design system colors, save/cancel UX
- ShippingSettingsForm: validation, dirty state tracking
- Integrations page: proper layout with AI and communications sections
- Billing: improved plan comparison, add-on cards
- PaymentSettings: toggle components, validation

Wholesale Portal:
- Portal: loading skeletons, quantity stepper, search/filter
- Login/Register: FormField validation, success states
- Success/Cancel pages: animated checkmarks
- Employee portal: skeletons, empty states, mobile responsive

Water Log:
- FieldClient: loading step, progress indicator, spinner
- AdminClient: loading skeletons
- Admin pages: loading.tsx files

New Components:
- Toast.tsx/ToastContainer.tsx: comprehensive notification system
- Skeleton.tsx: shimmer loading components
- AdminToggle.tsx: consistent toggle/switch
- CommunicationsLoading.tsx: loading skeleton for comms
- ToastExport.ts: exports

CSS Improvements:
- Shimmer animation keyframes
- Toast slide-in animation

Accessibility:
- ARIA labels throughout
- Keyboard navigation
- Focus states
- Semantic HTML
- Screen reader support
2026-06-02 05:19:34 +00:00
tyler 778b3fe311 fix: full Apple HIG mobile + SEO audit - all issues resolved
MOBILE RESPONSIVENESS (Apple HIG):
- HeroSection: typography scaled 7xl→4xl sm:5xl md:6xl lg:7xl, responsive px/py, rounded-2xl, active:scale-95
- Cart quantity buttons: h-8→h-11 w-8→w-11 (44px touch target), rounded-xl, active:scale-95
- StorefrontFooter newsletter: responsive w-full sm:w-52 lg:w-64, aria-label, larger touch targets
- StorefrontHeader mobile nav: padding px-6→px-4 py-6→py-5
- AdminTable: overflow-x-auto + min-w-[600px] for horizontal scroll
- AdminOrdersPanel: same table overflow fix
- AdminLayout: mobile px-4 sm:px-6 py-6 sm:py-10
- AdminFilterTabs: responsive text/text sizes
- AdminSidebar hamburger: h-10→h-11 w-10→w-11 (44px touch target)
- DashboardClient: grid gap-3 sm:gap-4, responsive stat text
- OrderEditForm: grid-cols-1 sm:grid-cols-2 (was 2, breaks on mobile)
- BillingClient: min-h-[44px] on select/button
- ProductsClient: h-32 sm:h-40 responsive image height
- StopCard: line-clamp-2 instead of line-clamp-1 on location
- CommunicationsPage: tabs wrapped in overflow-x-auto
- Checkout page: grid breakpoint md not lg
- Tuxedo page: SectionHeader mobile-first, feature grid grid-cols-1 sm:2, label visible
- Tuxedo stats: text-3xl sm:text-4xl

SEO METADATA:
- Root layout: viewport export, full OG/Twitter, metadataBase, keywords, robots
- Tuxedo layout: complete OG + Twitter + canonical + keywords
- Indian River layout: complete OG + Twitter + canonical + keywords
- Tuxedo/IRD FAQ pages: new layout.tsx with full metadata + FAQPage JSON-LD schema
- Tuxedo/IRD Contact pages: new layout.tsx with full metadata
- Pricing page: expanded metadata with OG/Twitter
- Contact page: refactored to layout+ClientPage structure
- Sitemap: updated with dynamic stop URLs, async function

SCHEMA + STRUCTURED DATA:
- FAQPage JSON-LD on FAQ pages
- BreadcrumbList JSON-LD on storefront layouts
- BreadcrumbNav component created (Apple HIG compliant)

BUG FIXES:
- Indian River: replaced raw <img> with Next.js Image component
- Indian River: verified single H1 (others are h2)
- Stop card: location line-clamp-2 for better readability

TYPE CHECK: all pass
2026-06-02 04:32:58 +00:00
tyler 53a9671461 Initial commit - Route Commerce platform 2026-06-01 19:41:12 +00:00