Commit Graph

11 Commits

Author SHA1 Message Date
tyler 1feba25ced chore: commit tour-seed scripts and delete_stop 400 fix from prior work
* inspect_xlsx.py — one-off xlsx dumper used to discover the Stop
  Directory sheet structure (14 lines, kept for reference when the
  tour schedule xlsx is updated next season).
* scripts/seed_tuxedo_tour.py — Python+openpyxl seed script that
  parsed the 3-week Tuxedo Corn 2026 tour schedule and inserted
  269 stops via admin_create_stops_batch. Also linked each stop to
  its Stop Directory venue (address/phone/contact) and self-published
  by flipping status='draft' -> 'active'.
* supabase/migrations/202_delete_stop_orders_guard_fix.sql — fixes a
  400 error on the admin Stop Table delete button. The delete_stop
  RPC referenced o.deleted_at on the orders table, but that column
  doesn't exist, so the SELECT raised 'column does not exist' and
  PostgREST surfaced it as HTTP 400. The fix drops the redundant
  o.deleted_at IS NULL clause (pickup_complete = false is sufficient
  on its own); re-add it here if/when orders grows a deleted_at
  column.
2026-06-04 15:32:16 +00:00
tyler f26d43ac96 fix: re-dedupe locations by (name, city, address) so Tractor Supply splits into 10 per-city venues
The previous backfill grouped by (name, address) only, which collapsed
Tractor Supply in Brighton, CO and Tractor Supply in Canon City, CO
into a single location whenever they shared the same address (or both
had a NULL address). Same problem for Ace Hardware, Murdoch's,
Big Tool Box, and JAX Farm & Ranch.

This migration re-dedupes by (name, city, address), re-links all 269
Tuxedo stops to the new per-city venues, and soft-deletes the 26
over-grouped original locations.

Result: 41 active locations (was 26). 269/269 stops re-linked.
Slug regex also fixed — previous [a-z0-9] stripped uppercase letters;
now uses [[:alnum:]].
2026-06-04 15:30:22 +00:00
tyler 49a9900d15 feat: add locations table + Locations tab in Stops & Routes
* New 'locations' table for reusable venues (Tractor Supply, Boot Barn,
  etc.) — each stop now links via stops.location_id while keeping the
  denormalized location text for backwards compat.
* 6 SECURITY DEFINER RPCs: admin_create_location, admin_create_locations_batch,
  admin_update_location, admin_delete_location, admin_attach_location_to_stop,
  get_locations_for_brand. Plus admin_list_locations for the admin tab.
* Backfill: 26 unique venues extracted from the 269 Tuxedo stops, all linked.
* Stops & Routes page now has tabs (Stops | Locations) via ?tab= query param.
  Locations tab has full CRUD UI: search, status filter, pagination, edit,
  delete, add-venue modal.
* StopsHeaderActions now tab-aware — Upload Schedule / Add Stop only show on
  Stops tab; Locations tab has its own Add Venue button inline.
2026-06-04 15:24:34 +00: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 ba94d755fa chore: improve Supabase migrations via CLI after login and fix compatibility issues
- Update supabase/push-migrations.js:
  - Detect modern Supabase CLI link state (supabase/.temp/project-ref)
  - Prefer `supabase db query --linked --file` (works in this env where direct postgres connections fail with ENOTFOUND/network unreachable)
  - Updated docs/comments for `supabase login` + `supabase link --project-ref wnzkhezyhnfzhkhiflrp` workflow

- Add MEMORY.md capturing the Supabase login/link session, tooling changes, migration patches applied, and gotchas

- Patch migrations for current remote schema (column drift, syntax, idempotency, pre-existing tables):
  - 091_brand_plan_tier.sql: fix extra paren in get_brand_plan_info
  - 145_create_product_images_bucket.sql: allowed_mime_types + DROP POLICY IF EXISTS + safer bucket insert
  - 148_public_stops_rpc.sql: quote reserved "time" column in RETURNS TABLE + SELECT
  - 200_production_features.sql: add ALTER TABLE for user_activity_logs (originated in 036) so policies/indexes validate
  - 201_seed_data.sql: trim demo seeds with outdated column lists (products/stops/etc.); keep only compatible brands insert

- Include 202_fix_admin_create_stop.sql and related stop creation updates (src/actions/stops/create-stop.ts, 147_admin_create_stop_rpcs.sql, ADMIN_CREATE_STOP_FIX.sql)

- Update CLAUDE.md with pointer to MEMORY.md for recent migration work

Applied via the new flow (after supabase login + link): 084, 091, 142–148, 200–202 etc.

Refs: Supabase CLI now linked; use `node supabase/push-migrations.js <prefix>` or `npm run migrate:one NNN`
2026-06-03 15:11:42 +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 7dfaba6e3d feat: complete launch & marketing layer
- Add marketing pages: blog, changelog, roadmap, waitlist, security, maintenance
- Add GDPR cookie consent banner with preference modal
- Add referral system with API routes for code generation/tracking
- Add waitlist API with referral support
- Add PWA support: manifest, service worker, install prompt
- Add onboarding flow with 6-step guided tour
- Add in-app notification center with bell dropdown
- Add admin launch checklist (32 items across 8 categories)
- Update landing page with trust badges
- Add Open Graph image and favicon
- Configure ESLint for PWA install patterns
- Add LAUNCH_CHECKLIST.md with go-to-market guide

Supabase migrations for:
- blog_posts and blog_categories tables
- waitlist_signups table
- roadmap_items table
- launch_checklist_items table
2026-06-02 06:19:56 +00:00
tyler 6ab52a2499 Production upgrade: Clerk auth, Stripe billing, analytics, PWA support
Backend & Auth:
- Add @clerk/nextjs for production authentication
- Create src/proxy.ts with clerkMiddleware() for route protection
- Implement multi-tenant auth with role-based access control
- Add Clerk components (Show, UserButton, SignInButton, SignUpButton)

Billing & Payments:
- Full Stripe integration (subscriptions, add-ons, customer portal)
- Plan tiers: Starter 9/mo, Farm 49/mo, Enterprise 99/mo
- Webhook handling for subscription events
- createSubscription(), createAddonSubscription(), createCustomerPortalSession()

API & Security:
- Rate limiting with @upstash/ratelimit (100 req/min API, 20 req/min checkout)
- Zod validation schemas for all endpoints (orders, products, campaigns, etc.)
- Security headers (CSP, HSTS, X-Frame-Options)
- API routes: /api/v1/ with validated, rate-limited endpoints

Monitoring:
- Sentry error tracking with performance monitoring
- PostHog analytics for feature usage, funnels, cohorts
- User activity logging and breadcrumb tracking

Admin Features:
- Analytics dashboard with revenue charts, customer growth, conversion funnel
- Onboarding flow with 6-step interactive tour
- Referral system with share tracking and reward redemption
- Changelog feed with in-app notifications

PWA & SEO:
- Web app manifest with icons and shortcuts
- Service worker for offline support and caching
- Full SEO metadata, OpenGraph, Twitter cards
- Structured data (JSON-LD) for organization and products

Database:
- Add referral_codes, changelogs, onboarding_progress tables
- Add user_activity_logs, api_keys, notification_preferences
- Comprehensive RLS policies for all new tables
- Seed data for demo brands and products
2026-06-02 05:33:42 +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 15e939ad7e Admin AI Tools page: unified design system styling, provider selector with OpenAI turd emoji, free-text model input with exact ID warning 2026-06-02 02:21:11 +00:00
tyler 53a9671461 Initial commit - Route Commerce platform 2026-06-01 19:41:12 +00:00