diff --git a/.gitignore b/.gitignore index aff1c6a..17ce8ad 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,4 @@ playwright-report/ .mcp.json .env* public/videos/tuxedo-hero.mp4 +.neon diff --git a/db/migrations/0003_tour_rpc_functions.sql b/db/migrations/0003_tour_rpc_functions.sql new file mode 100644 index 0000000..1f97ad5 --- /dev/null +++ b/db/migrations/0003_tour_rpc_functions.sql @@ -0,0 +1,71 @@ +-- Migration 003: Batch insert RPCs for tour stop / location seeding +-- Required by db/seeds/2026-tuxedo-tour-stops.sql and scripts/import-tuxedo-stops.ts + +BEGIN; + +-- admin_create_locations_batch: insert or update locations from tour seed +-- Payload shape: { name, address, city, state, zip, phone, contact_name, contact_email, notes, active }[] +CREATE OR REPLACE FUNCTION admin_create_locations_batch(p_brand_id UUID, p_locations JSONB) +RETURNS VOID LANGUAGE plpgsql SECURITY DEFINER AS $$ +DECLARE + v_loc JSONB; +BEGIN + FOR v_loc IN SELECT * FROM jsonb_array_elements(p_locations) + LOOP + INSERT INTO locations ( + brand_id, name, address, city, state, zip, + phone, contact_name, contact_email, notes, active + ) VALUES ( + p_brand_id, + v_loc->>'name', + v_loc->>'address', + v_loc->>'city', + v_loc->>'state', + NULLIF(v_loc->>'zip', '')::TEXT, + v_loc->>'phone', + v_loc->>'contact_name', + v_loc->>'contact_email', + v_loc->>'notes', + COALESCE((v_loc->>'active')::BOOLEAN, true) + ) + ON CONFLICT DO NOTHING; + END LOOP; +END; +$$; + +-- admin_create_stops_batch: insert stops from tour seed +-- Payload shape: { city, state, location, date, time, address, zip, cutoff_time, active, notes }[] +-- date format: '2026-07-22 00:00:00+00' โ€” cast to DATE +CREATE OR REPLACE FUNCTION admin_create_stops_batch(p_brand_id UUID, p_stops JSONB) +RETURNS VOID LANGUAGE plpgsql SECURITY DEFINER AS $$ +DECLARE + v_stop JSONB; +BEGIN + FOR v_stop IN SELECT * FROM jsonb_array_elements(p_stops) + LOOP + INSERT INTO stops ( + brand_id, name, location, address, city, state, zip, + date, "time", cutoff_date, status, is_public, notes + ) VALUES ( + p_brand_id, + COALESCE(NULLIF(v_stop->>'name', ''), (v_stop->>'location')::TEXT || ' - ' || (v_stop->>'city')::TEXT || ', ' || (v_stop->>'state')::TEXT), + v_stop->>'location', + v_stop->>'address', + v_stop->>'city', + v_stop->>'state', + NULLIF(v_stop->>'zip', '')::TEXT, + CASE + WHEN v_stop->>'date' IS NULL THEN NULL + ELSE LEFT(v_stop->>'date', 10)::DATE + END, + v_stop->>'time', + NULLIF(v_stop->>'cutoff_time', '')::DATE, + 'active', + COALESCE((v_stop->>'active')::BOOLEAN, true), + v_stop->>'notes' + ); + END LOOP; +END; +$$; + +COMMIT; \ No newline at end of file diff --git a/db/seeds/2026-tuxedo-tour-stops.sql b/db/seeds/2026-tuxedo-tour-stops.sql new file mode 100644 index 0000000..f6003f8 --- /dev/null +++ b/db/seeds/2026-tuxedo-tour-stops.sql @@ -0,0 +1,40 @@ +-- Tuxedo Corn 2026 Tour Data (from ./Tuxedo_Corn_2026_Tour_Schedule-3.xlsx) +-- Stops: 269 | Locations: 40 +-- Preferred: npx tsx scripts/import-tuxedo-stops.ts +-- Manual apply: psql "$DATABASE_URL" -f db/seeds/2026-tuxedo-tour-stops.sql +-- supabase db query --linked --file db/seeds/2026-tuxedo-tour-stops.sql + +BEGIN; + +-- ===== LOCATIONS (Stop Directory master records) ===== +DELETE FROM locations WHERE brand_id = '64294306-5f42-463d-a5e8-2ad6c81a96de'; + +-- 40 unique locations from Stop Directory +SELECT admin_create_locations_batch('64294306-5f42-463d-a5e8-2ad6c81a96de'::uuid, $$[{"name":"Tequila's Mexican Restaurant","address":"9900 Santa Fe Trail","city":"Trinidad","state":"CO","zip":null,"phone":"(719) 846-3514","contact_name":"Hector","contact_email":null,"notes":"โš  Restaurant opens 11 AM โ€” 10 AM setup approved by Hector.","active":true},{"name":"Tractor Supply","address":"13778 E I-25 Frontage Rd","city":"Firestone","state":"CO","zip":null,"phone":"(970) 535-4300","contact_name":"Emily","contact_email":null,"notes":null,"active":true},{"name":"Tractor Supply","address":"1919 E Main St","city":"Canon City","state":"CO","zip":null,"phone":"(719) 275-2116","contact_name":"Britt","contact_email":null,"notes":null,"active":true},{"name":"Jeffco Fairgrounds","address":"15200 W 6th Ave","city":"Golden","state":"CO","zip":null,"phone":"(303) 271-6600","contact_name":"Bailey","contact_email":null,"notes":"Booking confirmed Jul 24/Aug 7/Aug 14/Aug 28/Sep 4.","active":true},{"name":"Big Tool Box","address":"8080 S Holly Street","city":"Centennial","state":"CO","zip":null,"phone":"(303) 779-8822","contact_name":"Bobbi","contact_email":null,"notes":null,"active":true},{"name":"Carpet Mill Outlet","address":"1300 S Abilene Street","city":"Aurora","state":"CO","zip":null,"phone":"(303) 369-8809","contact_name":"Tim","contact_email":null,"notes":"๐Ÿ”ด PRE-SALE LIVE on website.","active":true},{"name":"Big Tool Box","address":"19850 Cockriel Drive S","city":"Parker","state":"CO","zip":null,"phone":"(303) 779-8822","contact_name":"โ€”","contact_email":null,"notes":"๐Ÿ”ด PRE-SALE LIVE on website.","active":true},{"name":"Douglas Co. Fairgrounds","address":"500 Fairgrounds Rd","city":"Castle Rock","state":"CO","zip":null,"phone":"(720) 733-6900","contact_name":"Tori","contact_email":null,"notes":"๐Ÿ”ด PRE-SALE LIVE. 6 dates only โ€” Jul 25 & Aug 1 blocked (Fair & Rodeo). $500/season โ€” confirm payment with Tori.","active":true},{"name":"Murdoch's Ranch & Home","address":"12154 N Dumont Way","city":"Littleton","state":"CO","zip":null,"phone":"(303) 791-7800","contact_name":"โ€”","contact_email":null,"notes":"Alternating Saturdays: Aug 1/15/29, Sep 12.","active":true},{"name":"Aaron's Rent to Own","address":"6750 Camden Blvd","city":"Security","state":"CO","zip":null,"phone":"(719) 391-1515","contact_name":"Tim","contact_email":null,"notes":"๐Ÿ”ด PRE-SALE LIVE. Store opens 10 AM โ€” ARRIVE 9:30 AM for setup.","active":true},{"name":"Tractor Supply","address":"16760 Leather Chaps Dr","city":"Colorado Springs","state":"CO","zip":null,"phone":"(719) 488-8844","contact_name":"Robert/Jen","contact_email":null,"notes":"๐Ÿ”ด PRE-SALE LIVE. Highest volume day.","active":true},{"name":"Bartlett Hay Co.","address":"7090 Old Meridian Road","city":"Falcon","state":"CO","zip":null,"phone":"(719) 495-0774","contact_name":"โ€”","contact_email":null,"notes":"๐Ÿ”ด PRE-SALE LIVE. โš  CLOSES 4 PM SHARP โ€” must be packed and gone by 4:00.","active":true},{"name":"Harbor Freight","address":"705 W Hampden Ave","city":"Englewood","state":"CO","zip":null,"phone":"(719) 442-6414","contact_name":"Store Manager","contact_email":null,"notes":"Same location as T2 Sunday stop.","active":true},{"name":"Hacienda Home Centers","address":"2613 7th Street","city":"Las Vegas","state":"NM","zip":null,"phone":"(505) 425-7569","contact_name":"Ernest","contact_email":null,"notes":"Leave by 1:30 PM sharp โ€” 2.5 hr drive to Pueblo.","active":true},{"name":"Tractor Supply","address":"2140 Kings Royal Blvd","city":"Pueblo","state":"CO","zip":null,"phone":"TBD โ€” str2951@tractorsupply.com","contact_name":"โ€”","contact_email":null,"notes":"Stage overnight in Pueblo. Trinidad is 45 min south for Friday start.","active":true},{"name":"Santa Fe County Fair Board","address":"3229 Rodeo Rd","city":"Santa Fe","state":"NM","zip":null,"phone":"(505) 471-4711","contact_name":"Michelle","contact_email":null,"notes":"Written commitment sent to bethgrayrdsf@gmail.com.","active":true},{"name":"Pioneer Ace Hardware","address":"4100 Sabana Grande Ave SE","city":"Rio Rancho","state":"NM","zip":null,"phone":"(505) 600-3588","contact_name":"โ€”","contact_email":null,"notes":"2 visits only. Driver arrives ABQ area Monday night after Pueblo cross-dock.","active":true},{"name":"Fun Services Colorado","address":"12345 Huron St","city":"Westminster","state":"CO","zip":null,"phone":"(303) 427-7443","contact_name":"โ€”","contact_email":null,"notes":"โœ“ Additional Tuesday visits approved. T2 also uses Wed (4 dates) โ€” back-to-back OK.","active":true},{"name":"Boot Barn","address":"10300 Bannock Street","city":"Thornton","state":"CO","zip":null,"phone":"(303) 450-9999","contact_name":"Russel","contact_email":null,"notes":"T2 also uses Boot Barn on Wednesdays. Confirm back-to-back visits OK with Russel.","active":true},{"name":"JAX Farm & Ranch","address":"1000 N Hwy 287","city":"Fort Collins","state":"CO","zip":null,"phone":"(970) 484-2221","contact_name":"โ€”","contact_email":null,"notes":"End of day. Stage near Cheyenne (~45 min) for WY Wednesday or near Denver for FR Wednesday.","active":true},{"name":"Murdoch's Ranch & Home","address":"3773 E. Lincolnway","city":"Cheyenne","state":"WY","zip":null,"phone":"(307) 632-7888","contact_name":"Kelly","contact_email":null,"notes":"3-hour extended stop. Pre-sales live on website.","active":true},{"name":"Tractor Supply (2nd St NW)","address":"8100 2nd Street NW","city":"Albuquerque","state":"NM","zip":null,"phone":"(505) 897-6800","contact_name":"Chris Miller","contact_email":null,"notes":"3-hour extended stop. Single ABQ stop โ€” Hacienda dropped. Pre-sale customers notified.","active":true},{"name":"Albany Co. Fairgrounds","address":"3510 S 3rd Street","city":"Laramie","state":"WY","zip":null,"phone":"(307) 742-3224","contact_name":"โ€”","contact_email":null,"notes":"Drive ~45 min south from Cheyenne.","active":true},{"name":"Tractor Supply","address":"300 W US Hwy 550","city":"Bernalillo","state":"NM","zip":null,"phone":"(505) 771-0168","contact_name":"โ€”","contact_email":null,"notes":"Stage near Santa Fe after (~30 min north).","active":true},{"name":"Town & Country Liquors","address":"516 S Greeley Hwy","city":"Cheyenne","state":"WY","zip":null,"phone":"(307) 632-8735","contact_name":"โ€”","contact_email":null,"notes":"โš  SEND INSURANCE COPY BEFORE FIRST VISIT (Jul 22).","active":true},{"name":"Ace Hardware","address":"201 South Rollie Ave","city":"Fort Lupton","state":"CO","zip":null,"phone":"(303) 857-1695","contact_name":"Ben","contact_email":null,"notes":"โš  BRING UMBRELLA INSURANCE COPY ON FIRST VISIT.","active":true},{"name":"Highland Park Lanes","address":"1900 59th Ave","city":"Greeley","state":"CO","zip":null,"phone":"(970) 330-2695","contact_name":"Zach/Parker","contact_email":null,"notes":null,"active":true},{"name":"Westeck Rentals","address":"17276 US 34","city":"Fort Morgan","state":"CO","zip":null,"phone":"(970) 542-9380","contact_name":"Matt","contact_email":null,"notes":"5 visits only: Jul 24/31, Aug 14/28, Sep 11. CLOSED Sat & Sun โ€” Friday only.","active":true},{"name":"Ace Hardware","address":"9 S Parish Ave","city":"Johnstown","state":"CO","zip":null,"phone":"(970) 587-4476","contact_name":"Lisa","contact_email":null,"notes":"3 visits: Aug 7 / Aug 21 / Sep 4. Runs on Fridays when Fort Morgan is NOT running.","active":true},{"name":"Bomgaars","address":"4104 Jefferson Ave","city":"Wellington","state":"CO","zip":null,"phone":"(970) 568-0223","contact_name":"Doug Anderson","contact_email":null,"notes":null,"active":true},{"name":"Murdoch's Ranch & Home","address":"2255 Main St","city":"Longmont","state":"CO","zip":null,"phone":"(303) 682-5111","contact_name":"โ€”","contact_email":null,"notes":"Adding Saturday dates to existing Tuesday confirmed stop. Different day โ€” no conflict. Confirm with Murdoch's.","active":true},{"name":"JAX Farm & Ranch","address":"400 W South Boulder Rd","city":"Lafayette","state":"CO","zip":null,"phone":"(303) 665-4900","contact_name":"Chris Miller","contact_email":null,"notes":null,"active":true},{"name":"Ace Hardware","address":"10000 Ralston Road","city":"Arvada","state":"CO","zip":null,"phone":"(720) 612-4248","contact_name":"โ€”","contact_email":null,"notes":"โœ“ Additional Sunday visits approved. Runs every Sunday in addition to every Tuesday.","active":true},{"name":"Brand's Beverage","address":"4355 N Fairgrounds Ave","city":"Windsor","state":"CO","zip":null,"phone":"(970) 617-2698","contact_name":"Nick","contact_email":null,"notes":null,"active":true},{"name":"Tractor Supply","address":"33 NE Frontage Road","city":"Fort Collins","state":"CO","zip":null,"phone":"(970) 221-1104","contact_name":"Cory","contact_email":null,"notes":null,"active":true},{"name":"Tractor Supply","address":"5428 N Garfield Ave","city":"Loveland","state":"CO","zip":null,"phone":"(970) 663-2722","contact_name":"Dylan","contact_email":null,"notes":null,"active":true},{"name":"Tractor Supply","address":"825 US-287","city":"Lafayette","state":"CO","zip":null,"phone":"(303) 665-3050","contact_name":"Brian","contact_email":null,"notes":"Alternating Thursdays: Jul 23 / Aug 6 / Aug 20 / Sep 3.","active":true},{"name":"Wardle Feed & Pet Supply","address":"7610 3 Acre Lane","city":"Wheat Ridge","state":"CO","zip":null,"phone":"(303) 424-6455","contact_name":"โ€”","contact_email":null,"notes":"4 dates: Jul 28 / Aug 11 / Aug 25 / Sep 8.","active":true},{"name":"Tractor Supply","address":"147 Denver Street","city":"Brighton","state":"CO","zip":null,"phone":"(303) 659-6405","contact_name":"โ€”","contact_email":null,"notes":null,"active":true},{"name":"Stockyards Ranch Supply","address":"6990 Vasquez Blvd","city":"Commerce City","state":"CO","zip":null,"phone":"(303) 287-8081","contact_name":"Anna","contact_email":null,"notes":"4 dates only: Jul 22 / Aug 5 / Aug 19 / Sep 2.","active":true}]$$::jsonb); + +-- ===== STOPS (2026 tour schedule) ===== +-- Clear prior 2026 tour stops for brand (date-scoped) +DELETE FROM stops WHERE brand_id = '64294306-5f42-463d-a5e8-2ad6c81a96de' AND date >= '2026-07-01' AND date <= '2026-09-30'; + +-- stops batch 1/6 (50) +SELECT admin_create_stops_batch('64294306-5f42-463d-a5e8-2ad6c81a96de'::uuid, $$[{"city":"Cheyenne","state":"WY","location":"Murdoch's Ranch & Home","date":"2026-07-22 00:00:00+00","time":"10:00 AM - 1:00 PM","address":"3773 E. Lincolnway","zip":null,"cutoff_time":null,"active":true,"notes":"Kelly ยท (307) 632-7888 3-hour extended stop. Pre-sales live on website. | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 632-7888 | Contact: Kelly"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-07-22 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 450-9999 | Contact: Russel"},{"city":"Laramie","state":"WY","location":"Albany Co. Fairgrounds","date":"2026-07-22 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"3510 S 3rd Street","zip":null,"cutoff_time":null,"active":true,"notes":"(307) 742-3224 Drive ~45 min south from Cheyenne. | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 742-3224 | Contact: โ€”"},{"city":"Cheyenne","state":"WY","location":"Town & Country Liquors","date":"2026-07-22 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"516 S Greeley Hwy","zip":null,"cutoff_time":null,"active":true,"notes":"(307) 632-8735 โš  SEND INSURANCE COPY BEFORE FIRST VISIT (Jul 22). | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 632-8735 | Contact: โ€”"},{"city":"Brighton","state":"CO","location":"Tractor Supply","date":"2026-07-22 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 659-6405 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Commerce City","state":"CO","location":"Stockyards Ranch Supply","date":"2026-07-22 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"6990 Vasquez Blvd","zip":null,"cutoff_time":null,"active":true,"notes":"Anna ยท (303) 287-8081 4 dates only: Jul 22 / Aug 5 / Aug 19 / Sep 2. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 287-8081 | Contact: Anna"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-07-23 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 Same location as T2 Sunday stop. | Truck: T1 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Windsor","state":"CO","location":"Brand's Beverage","date":"2026-07-23 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4355 N Fairgrounds Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Nick ยท (970) 617-2698 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 617-2698 | Contact: Nick"},{"city":"Littleton","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-07-23 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"3773 E. Lincolnway","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 791-7800 Adding Thursday dates to existing Saturday confirmed stop. Different day โ€” no conflict. | Truck: T1 | Status: โณ Pending confirm | Phone: (307) 632-7888 | Contact: Kelly"},{"city":"Fort Collins","state":"CO","location":"Tractor Supply","date":"2026-07-23 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Cory ยท (970) 221-1104 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Loveland","state":"CO","location":"Tractor Supply","date":"2026-07-23 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Dylan ยท (970) 663-2722 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Lafayette","state":"CO","location":"Tractor Supply","date":"2026-07-23 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Brian ยท (303) 665-3050 Alternating Thursdays: Jul 23 / Aug 6 / Aug 20 / Sep 3. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Firestone","state":"CO","location":"Tractor Supply","date":"2026-07-24 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Emily ยท (970) 535-4300 | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Fort Lupton","state":"CO","location":"Ace Hardware","date":"2026-07-24 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"Ben ยท (303) 857-1695 โš  BRING UMBRELLA INSURANCE COPY ON FIRST VISIT. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Greeley","state":"CO","location":"Highland Park Lanes","date":"2026-07-24 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"1900 59th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Zach/Parker ยท (970) 330-2695 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 330-2695 | Contact: Zach/Parker"},{"city":"Golden","state":"CO","location":"Jeffco Fairgrounds","date":"2026-07-24 00:00:00+00","time":"1:00 PM - 2:30 PM","address":"15200 W 6th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Bailey ยท (303) 271-6600 Booking confirmed Jul 24/Aug 7/Aug 14/Aug 28/Sep 4. | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 271-6600 | Contact: Bailey"},{"city":"Fort Morgan","state":"CO","location":"Westeck Rentals","date":"2026-07-24 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"17276 US 34","zip":null,"cutoff_time":null,"active":true,"notes":"Matt ยท (970) 542-9380 5 visits only: Jul 24/31, Aug 14/28, Sep 11. CLOSED Sat & Sun โ€” Friday only. | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 542-9380 | Contact: Matt"},{"city":"Centennial","state":"CO","location":"Big Tool Box","date":"2026-07-24 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"Bobbi ยท (303) 779-8822 | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Aurora","state":"CO","location":"Carpet Mill Outlet","date":"2026-07-25 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"1300 S Abilene Street","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (303) 369-8809 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 369-8809 | Contact: Tim"},{"city":"Wellington","state":"CO","location":"Bomgaars","date":"2026-07-25 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4104 Jefferson Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Doug Anderson ยท (970) 568-0223 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 568-0223 | Contact: Doug Anderson"},{"city":"Parker","state":"CO","location":"Big Tool Box","date":"2026-07-25 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 779-8822 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-07-25 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 Adding Saturday dates to existing Tuesday confirmed stop. Different day โ€” no conflict. Confirm with Murdoch's. | Truck: T2 | Status: โณ Pending confirm | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Lafayette","state":"CO","location":"JAX Farm & Ranch","date":"2026-07-25 00:00:00+00","time":"4:00 PM - 5:30 PM","address":"400 W South Boulder Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Chris Miller ยท (303) 665-4900 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 665-4900 | Contact: Chris Miller"},{"city":"Security","state":"CO","location":"Aaron's Rent to Own","date":"2026-07-26 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"6750 Camden Blvd","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (719) 391-1515 ๐Ÿ”ด PRE-SALE LIVE. Store opens 10 AM โ€” ARRIVE 9:30 AM for setup. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 391-1515 | Contact: Tim"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-07-26 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 โœ“ Additional Sunday visits approved. Runs every Sunday in addition to every Tuesday. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Colorado Springs","state":"CO","location":"Tractor Supply","date":"2026-07-26 00:00:00+00","time":"12:00 PM - 1:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Robert/Jen ยท (719) 488-8844 ๐Ÿ”ด PRE-SALE LIVE. Highest volume day. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-07-26 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 โš  LEAVE BY 2:00 PM SHARP โ€” 1 hr 45 min drive to Pueblo. | Truck: T2 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Falcon","state":"CO","location":"Bartlett Hay Co.","date":"2026-07-26 00:00:00+00","time":"2:30 PM - 4:00 PM","address":"7090 Old Meridian Road","zip":null,"cutoff_time":null,"active":true,"notes":"(719) 495-0774 ๐Ÿ”ด PRE-SALE LIVE. โš  CLOSES 4 PM SHARP โ€” must be packed and gone by 4:00. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 495-0774 | Contact: โ€”"},{"city":"Pueblo","state":"CO","location":"Tractor Supply","date":"2026-07-26 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"TBD โ€” str2951@tractorsupply.com Stage overnight in Pueblo. Monday is cross-dock day โ€” drive to Arvada for Tuesday start. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Westminster","state":"CO","location":"Fun Services Colorado","date":"2026-07-28 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"12345 Huron St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 427-7443 โœ“ Additional Tuesday visits approved. T2 also uses Wed (4 dates) โ€” back-to-back OK. | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 427-7443 | Contact: โ€”"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-07-28 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-07-28 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 T2 also uses Boot Barn on Wednesdays. Confirm back-to-back visits OK with Russel. | Truck: T1 | Status: โณ Pending confirm | Phone: (303) 450-9999 | Contact: Russel"},{"city":"Wheat Ridge","state":"CO","location":"Wardle Feed & Pet Supply","date":"2026-07-28 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"7610 3 Acre Lane","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 424-6455 4 dates: Jul 28 / Aug 11 / Aug 25 / Sep 8. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 424-6455 | Contact: โ€”"},{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-07-28 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 5 dates: Jul 28 / Aug 11 / Aug 18 / Sep 1 / Sep 8. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Fort Collins","state":"CO","location":"JAX Farm & Ranch","date":"2026-07-28 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"1000 N Hwy 287","zip":null,"cutoff_time":null,"active":true,"notes":"(970) 484-2221 End of day. Stage near Cheyenne (~45 min) for WY Wednesday or near Denver for FR Wednesday. | Truck: T1 | Status: โœ“ Confirmed | Phone: (970) 484-2221 | Contact: โ€”"},{"city":"Greeley","state":"CO","location":"Highland Park Lanes","date":"2026-07-28 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"1900 59th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Zach/Parker ยท (970) 330-2695 4 dates: Jul 28 / Aug 11 / Aug 25 / Sep 8. In addition to Friday slot. | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 330-2695 | Contact: Zach/Parker"},{"city":"Albuquerque","state":"NM","location":"Tractor Supply (2nd St NW)","date":"2026-07-29 00:00:00+00","time":"10:00 AM - 1:00 PM","address":"8100 2nd Street NW","zip":null,"cutoff_time":null,"active":true,"notes":"Chris Miller ยท (505) 897-6800 3-hour extended stop. Single ABQ stop โ€” Hacienda dropped. Pre-sale customers notified. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 897-6800 | Contact: Chris Miller"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-07-29 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 450-9999 | Contact: Russel"},{"city":"Westminster","state":"CO","location":"Fun Services Colorado","date":"2026-07-29 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"12345 Huron St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 427-7443 4 dates only: Jul 29 / Aug 12 / Aug 26 / Sep 9. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 427-7443 | Contact: โ€”"},{"city":"Bernalillo","state":"NM","location":"Tractor Supply","date":"2026-07-29 00:00:00+00","time":"2:00 PM - 3:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"(505) 771-0168 Stage near Santa Fe after (~30 min north). | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Brighton","state":"CO","location":"Tractor Supply","date":"2026-07-29 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 659-6405 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Windsor","state":"CO","location":"Brand's Beverage","date":"2026-07-30 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4355 N Fairgrounds Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Nick ยท (970) 617-2698 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 617-2698 | Contact: Nick"},{"city":"Las Vegas","state":"NM","location":"Hacienda Home Centers","date":"2026-07-30 00:00:00+00","time":"12:00 PM - 1:30 PM","address":"2613 7th Street","zip":null,"cutoff_time":null,"active":true,"notes":"Ernest ยท (505) 425-7569 Leave by 1:30 PM sharp โ€” 2.5 hr drive to Pueblo. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 425-7569 | Contact: Ernest"},{"city":"Fort Collins","state":"CO","location":"Tractor Supply","date":"2026-07-30 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Cory ยท (970) 221-1104 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Loveland","state":"CO","location":"Tractor Supply","date":"2026-07-30 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Dylan ยท (970) 663-2722 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Pueblo","state":"CO","location":"Tractor Supply","date":"2026-07-30 00:00:00+00","time":"4:00 PM - 5:00 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"TBD โ€” str2951@tractorsupply.com Stage overnight in Pueblo. Trinidad is 45 min south for Friday start. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Santa Fe","state":"NM","location":"Santa Fe County Fair Board","date":"2026-07-30 00:00:00+00","time":"9:00 AM - 10:30 AM","address":"3229 Rodeo Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Michelle ยท (505) 471-4711 Written commitment sent to bethgrayrdsf@gmail.com. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 471-4711 | Contact: Michelle"},{"city":"Trinidad","state":"CO","location":"Tequila's Mexican Restaurant","date":"2026-07-31 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"9900 Santa Fe Trail","zip":null,"cutoff_time":null,"active":true,"notes":"Hector ยท (719) 846-3514 โš  Restaurant opens 11 AM โ€” 10 AM setup approved by Hector. | Truck: T1 | Status: โœ“ Confirmed | Phone: (719) 846-3514 | Contact: Hector"},{"city":"Fort Lupton","state":"CO","location":"Ace Hardware","date":"2026-07-31 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"Ben ยท (303) 857-1695 โš  BRING UMBRELLA INSURANCE COPY ON FIRST VISIT. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Greeley","state":"CO","location":"Highland Park Lanes","date":"2026-07-31 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"1900 59th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Zach/Parker ยท (970) 330-2695 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 330-2695 | Contact: Zach/Parker"}]$$::jsonb); + +-- stops batch 2/6 (50) +SELECT admin_create_stops_batch('64294306-5f42-463d-a5e8-2ad6c81a96de'::uuid, $$[{"city":"Canon City","state":"CO","location":"Tractor Supply","date":"2026-07-31 00:00:00+00","time":"1:00 PM - 2:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Britt ยท (719) 275-2116 | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Fort Morgan","state":"CO","location":"Westeck Rentals","date":"2026-07-31 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"17276 US 34","zip":null,"cutoff_time":null,"active":true,"notes":"Matt ยท (970) 542-9380 5 visits only: Jul 24/31, Aug 14/28, Sep 11. CLOSED Sat & Sun โ€” Friday only. | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 542-9380 | Contact: Matt"},{"city":"Aurora","state":"CO","location":"Carpet Mill Outlet","date":"2026-08-01 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"1300 S Abilene Street","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (303) 369-8809 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 369-8809 | Contact: Tim"},{"city":"Wellington","state":"CO","location":"Bomgaars","date":"2026-08-01 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4104 Jefferson Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Doug Anderson ยท (970) 568-0223 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 568-0223 | Contact: Doug Anderson"},{"city":"Parker","state":"CO","location":"Big Tool Box","date":"2026-08-01 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 779-8822 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-01 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 Adding Saturday dates to existing Tuesday confirmed stop. Different day โ€” no conflict. Confirm with Murdoch's. | Truck: T2 | Status: โณ Pending confirm | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Lafayette","state":"CO","location":"JAX Farm & Ranch","date":"2026-08-01 00:00:00+00","time":"4:00 PM - 5:30 PM","address":"400 W South Boulder Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Chris Miller ยท (303) 665-4900 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 665-4900 | Contact: Chris Miller"},{"city":"Littleton","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-01 00:00:00+00","time":"5:00 PM - 6:30 PM","address":"3773 E. Lincolnway","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 791-7800 Alternating Saturdays: Aug 1/15/29, Sep 12. | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 632-7888 | Contact: Kelly"},{"city":"Security","state":"CO","location":"Aaron's Rent to Own","date":"2026-08-02 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"6750 Camden Blvd","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (719) 391-1515 ๐Ÿ”ด PRE-SALE LIVE. Store opens 10 AM โ€” ARRIVE 9:30 AM for setup. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 391-1515 | Contact: Tim"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-08-02 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 โœ“ Additional Sunday visits approved. Runs every Sunday in addition to every Tuesday. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Colorado Springs","state":"CO","location":"Tractor Supply","date":"2026-08-02 00:00:00+00","time":"12:00 PM - 1:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Robert/Jen ยท (719) 488-8844 ๐Ÿ”ด PRE-SALE LIVE. Highest volume day. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-08-02 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 โš  LEAVE BY 2:00 PM SHARP โ€” 1 hr 45 min drive to Pueblo. | Truck: T2 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Falcon","state":"CO","location":"Bartlett Hay Co.","date":"2026-08-02 00:00:00+00","time":"2:30 PM - 4:00 PM","address":"7090 Old Meridian Road","zip":null,"cutoff_time":null,"active":true,"notes":"(719) 495-0774 ๐Ÿ”ด PRE-SALE LIVE. โš  CLOSES 4 PM SHARP โ€” must be packed and gone by 4:00. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 495-0774 | Contact: โ€”"},{"city":"Pueblo","state":"CO","location":"Tractor Supply","date":"2026-08-02 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"TBD โ€” str2951@tractorsupply.com Stage overnight in Pueblo. Monday is cross-dock day โ€” drive to Arvada for Tuesday start. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Rio Rancho","state":"NM","location":"Pioneer Ace Hardware","date":"2026-08-04 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4100 Sabana Grande Ave SE","zip":null,"cutoff_time":null,"active":true,"notes":"(505) 600-3588 2 visits only. Driver arrives ABQ area Monday night after Pueblo cross-dock. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 600-3588 | Contact: โ€”"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-08-04 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Centennial","state":"CO","location":"Big Tool Box","date":"2026-08-05 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"Bobbi ยท (303) 779-8822 Aug 5 & Aug 26 only (FR weeks). Adding Wednesday dates to existing Friday confirmed stop. Confirm with Bobbi. | Truck: T1 | Status: โณ Pending confirm | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-08-05 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 450-9999 | Contact: Russel"},{"city":"Brighton","state":"CO","location":"Tractor Supply","date":"2026-08-05 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 659-6405 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Commerce City","state":"CO","location":"Stockyards Ranch Supply","date":"2026-08-05 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"6990 Vasquez Blvd","zip":null,"cutoff_time":null,"active":true,"notes":"Anna ยท (303) 287-8081 4 dates only: Jul 22 / Aug 5 / Aug 19 / Sep 2. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 287-8081 | Contact: Anna"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-08-06 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 Same location as T2 Sunday stop. | Truck: T1 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Windsor","state":"CO","location":"Brand's Beverage","date":"2026-08-06 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4355 N Fairgrounds Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Nick ยท (970) 617-2698 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 617-2698 | Contact: Nick"},{"city":"Littleton","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-06 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"3773 E. Lincolnway","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 791-7800 Adding Thursday dates to existing Saturday confirmed stop. Different day โ€” no conflict. | Truck: T1 | Status: โณ Pending confirm | Phone: (307) 632-7888 | Contact: Kelly"},{"city":"Fort Collins","state":"CO","location":"Tractor Supply","date":"2026-08-06 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Cory ยท (970) 221-1104 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Loveland","state":"CO","location":"Tractor Supply","date":"2026-08-06 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Dylan ยท (970) 663-2722 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Lafayette","state":"CO","location":"Tractor Supply","date":"2026-08-06 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Brian ยท (303) 665-3050 Alternating Thursdays: Jul 23 / Aug 6 / Aug 20 / Sep 3. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Firestone","state":"CO","location":"Tractor Supply","date":"2026-08-07 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Emily ยท (970) 535-4300 | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Fort Lupton","state":"CO","location":"Ace Hardware","date":"2026-08-07 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"Ben ยท (303) 857-1695 โš  BRING UMBRELLA INSURANCE COPY ON FIRST VISIT. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Greeley","state":"CO","location":"Highland Park Lanes","date":"2026-08-07 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"1900 59th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Zach/Parker ยท (970) 330-2695 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 330-2695 | Contact: Zach/Parker"},{"city":"Golden","state":"CO","location":"Jeffco Fairgrounds","date":"2026-08-07 00:00:00+00","time":"1:00 PM - 2:30 PM","address":"15200 W 6th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Bailey ยท (303) 271-6600 Booking confirmed Jul 24/Aug 7/Aug 14/Aug 28/Sep 4. | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 271-6600 | Contact: Bailey"},{"city":"Centennial","state":"CO","location":"Big Tool Box","date":"2026-08-07 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"Bobbi ยท (303) 779-8822 | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Johnstown","state":"CO","location":"Ace Hardware","date":"2026-08-07 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"Lisa ยท (970) 587-4476 3 visits: Aug 7 / Aug 21 / Sep 4. Runs on Fridays when Fort Morgan is NOT running. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Aurora","state":"CO","location":"Carpet Mill Outlet","date":"2026-08-08 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"1300 S Abilene Street","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (303) 369-8809 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 369-8809 | Contact: Tim"},{"city":"Wellington","state":"CO","location":"Bomgaars","date":"2026-08-08 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4104 Jefferson Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Doug Anderson ยท (970) 568-0223 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 568-0223 | Contact: Doug Anderson"},{"city":"Parker","state":"CO","location":"Big Tool Box","date":"2026-08-08 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 779-8822 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-08 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 Adding Saturday dates to existing Tuesday confirmed stop. Different day โ€” no conflict. Confirm with Murdoch's. | Truck: T2 | Status: โณ Pending confirm | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Castle Rock","state":"CO","location":"Douglas Co. Fairgrounds","date":"2026-08-08 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"500 Fairgrounds Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Tori ยท (720) 733-6900 ๐Ÿ”ด PRE-SALE LIVE. 6 dates only โ€” Jul 25 & Aug 1 blocked (Fair & Rodeo). $500/season โ€” confirm payment with Tori. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (720) 733-6900 | Contact: Tori"},{"city":"Lafayette","state":"CO","location":"JAX Farm & Ranch","date":"2026-08-08 00:00:00+00","time":"4:00 PM - 5:30 PM","address":"400 W South Boulder Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Chris Miller ยท (303) 665-4900 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 665-4900 | Contact: Chris Miller"},{"city":"Security","state":"CO","location":"Aaron's Rent to Own","date":"2026-08-09 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"6750 Camden Blvd","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (719) 391-1515 ๐Ÿ”ด PRE-SALE LIVE. Store opens 10 AM โ€” ARRIVE 9:30 AM for setup. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 391-1515 | Contact: Tim"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-08-09 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 โœ“ Additional Sunday visits approved. Runs every Sunday in addition to every Tuesday. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Colorado Springs","state":"CO","location":"Tractor Supply","date":"2026-08-09 00:00:00+00","time":"12:00 PM - 1:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Robert/Jen ยท (719) 488-8844 ๐Ÿ”ด PRE-SALE LIVE. Highest volume day. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-08-09 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 โš  LEAVE BY 2:00 PM SHARP โ€” 1 hr 45 min drive to Pueblo. | Truck: T2 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Falcon","state":"CO","location":"Bartlett Hay Co.","date":"2026-08-09 00:00:00+00","time":"2:30 PM - 4:00 PM","address":"7090 Old Meridian Road","zip":null,"cutoff_time":null,"active":true,"notes":"(719) 495-0774 ๐Ÿ”ด PRE-SALE LIVE. โš  CLOSES 4 PM SHARP โ€” must be packed and gone by 4:00. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 495-0774 | Contact: โ€”"},{"city":"Pueblo","state":"CO","location":"Tractor Supply","date":"2026-08-09 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"TBD โ€” str2951@tractorsupply.com Stage overnight in Pueblo. Monday is cross-dock day โ€” drive to Arvada for Tuesday start. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Westminster","state":"CO","location":"Fun Services Colorado","date":"2026-08-11 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"12345 Huron St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 427-7443 โœ“ Additional Tuesday visits approved. T2 also uses Wed (4 dates) โ€” back-to-back OK. | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 427-7443 | Contact: โ€”"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-08-11 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-08-11 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 T2 also uses Boot Barn on Wednesdays. Confirm back-to-back visits OK with Russel. | Truck: T1 | Status: โณ Pending confirm | Phone: (303) 450-9999 | Contact: Russel"},{"city":"Wheat Ridge","state":"CO","location":"Wardle Feed & Pet Supply","date":"2026-08-11 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"7610 3 Acre Lane","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 424-6455 4 dates: Jul 28 / Aug 11 / Aug 25 / Sep 8. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 424-6455 | Contact: โ€”"},{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-11 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 5 dates: Jul 28 / Aug 11 / Aug 18 / Sep 1 / Sep 8. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Fort Collins","state":"CO","location":"JAX Farm & Ranch","date":"2026-08-11 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"1000 N Hwy 287","zip":null,"cutoff_time":null,"active":true,"notes":"(970) 484-2221 End of day. Stage near Cheyenne (~45 min) for WY Wednesday or near Denver for FR Wednesday. | Truck: T1 | Status: โœ“ Confirmed | Phone: (970) 484-2221 | Contact: โ€”"}]$$::jsonb); + +-- stops batch 3/6 (50) +SELECT admin_create_stops_batch('64294306-5f42-463d-a5e8-2ad6c81a96de'::uuid, $$[{"city":"Greeley","state":"CO","location":"Highland Park Lanes","date":"2026-08-11 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"1900 59th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Zach/Parker ยท (970) 330-2695 4 dates: Jul 28 / Aug 11 / Aug 25 / Sep 8. In addition to Friday slot. | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 330-2695 | Contact: Zach/Parker"},{"city":"Cheyenne","state":"WY","location":"Murdoch's Ranch & Home","date":"2026-08-12 00:00:00+00","time":"10:00 AM - 1:00 PM","address":"3773 E. Lincolnway","zip":null,"cutoff_time":null,"active":true,"notes":"Kelly ยท (307) 632-7888 3-hour extended stop. Pre-sales live on website. | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 632-7888 | Contact: Kelly"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-08-12 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 450-9999 | Contact: Russel"},{"city":"Laramie","state":"WY","location":"Albany Co. Fairgrounds","date":"2026-08-12 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"3510 S 3rd Street","zip":null,"cutoff_time":null,"active":true,"notes":"(307) 742-3224 Drive ~45 min south from Cheyenne. | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 742-3224 | Contact: โ€”"},{"city":"Westminster","state":"CO","location":"Fun Services Colorado","date":"2026-08-12 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"12345 Huron St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 427-7443 4 dates only: Jul 29 / Aug 12 / Aug 26 / Sep 9. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 427-7443 | Contact: โ€”"},{"city":"Cheyenne","state":"WY","location":"Town & Country Liquors","date":"2026-08-12 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"516 S Greeley Hwy","zip":null,"cutoff_time":null,"active":true,"notes":"(307) 632-8735 โš  SEND INSURANCE COPY BEFORE FIRST VISIT (Jul 22). | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 632-8735 | Contact: โ€”"},{"city":"Brighton","state":"CO","location":"Tractor Supply","date":"2026-08-12 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 659-6405 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-08-13 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 Same location as T2 Sunday stop. | Truck: T1 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Windsor","state":"CO","location":"Brand's Beverage","date":"2026-08-13 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4355 N Fairgrounds Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Nick ยท (970) 617-2698 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 617-2698 | Contact: Nick"},{"city":"Littleton","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-13 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"3773 E. Lincolnway","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 791-7800 Adding Thursday dates to existing Saturday confirmed stop. Different day โ€” no conflict. | Truck: T1 | Status: โณ Pending confirm | Phone: (307) 632-7888 | Contact: Kelly"},{"city":"Fort Collins","state":"CO","location":"Tractor Supply","date":"2026-08-13 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Cory ยท (970) 221-1104 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Loveland","state":"CO","location":"Tractor Supply","date":"2026-08-13 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Dylan ยท (970) 663-2722 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Firestone","state":"CO","location":"Tractor Supply","date":"2026-08-14 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Emily ยท (970) 535-4300 | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Fort Lupton","state":"CO","location":"Ace Hardware","date":"2026-08-14 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"Ben ยท (303) 857-1695 โš  BRING UMBRELLA INSURANCE COPY ON FIRST VISIT. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Greeley","state":"CO","location":"Highland Park Lanes","date":"2026-08-14 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"1900 59th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Zach/Parker ยท (970) 330-2695 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 330-2695 | Contact: Zach/Parker"},{"city":"Golden","state":"CO","location":"Jeffco Fairgrounds","date":"2026-08-14 00:00:00+00","time":"1:00 PM - 2:30 PM","address":"15200 W 6th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Bailey ยท (303) 271-6600 Booking confirmed Jul 24/Aug 7/Aug 14/Aug 28/Sep 4. | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 271-6600 | Contact: Bailey"},{"city":"Fort Morgan","state":"CO","location":"Westeck Rentals","date":"2026-08-14 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"17276 US 34","zip":null,"cutoff_time":null,"active":true,"notes":"Matt ยท (970) 542-9380 5 visits only: Jul 24/31, Aug 14/28, Sep 11. CLOSED Sat & Sun โ€” Friday only. | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 542-9380 | Contact: Matt"},{"city":"Centennial","state":"CO","location":"Big Tool Box","date":"2026-08-14 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"Bobbi ยท (303) 779-8822 | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Aurora","state":"CO","location":"Carpet Mill Outlet","date":"2026-08-15 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"1300 S Abilene Street","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (303) 369-8809 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 369-8809 | Contact: Tim"},{"city":"Wellington","state":"CO","location":"Bomgaars","date":"2026-08-15 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4104 Jefferson Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Doug Anderson ยท (970) 568-0223 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 568-0223 | Contact: Doug Anderson"},{"city":"Parker","state":"CO","location":"Big Tool Box","date":"2026-08-15 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 779-8822 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-15 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 Adding Saturday dates to existing Tuesday confirmed stop. Different day โ€” no conflict. Confirm with Murdoch's. | Truck: T2 | Status: โณ Pending confirm | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Castle Rock","state":"CO","location":"Douglas Co. Fairgrounds","date":"2026-08-15 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"500 Fairgrounds Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Tori ยท (720) 733-6900 ๐Ÿ”ด PRE-SALE LIVE. 6 dates only โ€” Jul 25 & Aug 1 blocked (Fair & Rodeo). $500/season โ€” confirm payment with Tori. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (720) 733-6900 | Contact: Tori"},{"city":"Lafayette","state":"CO","location":"JAX Farm & Ranch","date":"2026-08-15 00:00:00+00","time":"4:00 PM - 5:30 PM","address":"400 W South Boulder Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Chris Miller ยท (303) 665-4900 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 665-4900 | Contact: Chris Miller"},{"city":"Littleton","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-15 00:00:00+00","time":"5:00 PM - 6:30 PM","address":"3773 E. Lincolnway","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 791-7800 Alternating Saturdays: Aug 1/15/29, Sep 12. | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 632-7888 | Contact: Kelly"},{"city":"Security","state":"CO","location":"Aaron's Rent to Own","date":"2026-08-16 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"6750 Camden Blvd","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (719) 391-1515 ๐Ÿ”ด PRE-SALE LIVE. Store opens 10 AM โ€” ARRIVE 9:30 AM for setup. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 391-1515 | Contact: Tim"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-08-16 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 โœ“ Additional Sunday visits approved. Runs every Sunday in addition to every Tuesday. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Colorado Springs","state":"CO","location":"Tractor Supply","date":"2026-08-16 00:00:00+00","time":"12:00 PM - 1:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Robert/Jen ยท (719) 488-8844 ๐Ÿ”ด PRE-SALE LIVE. Highest volume day. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-08-16 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 โš  LEAVE BY 2:00 PM SHARP โ€” 1 hr 45 min drive to Pueblo. | Truck: T2 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Falcon","state":"CO","location":"Bartlett Hay Co.","date":"2026-08-16 00:00:00+00","time":"2:30 PM - 4:00 PM","address":"7090 Old Meridian Road","zip":null,"cutoff_time":null,"active":true,"notes":"(719) 495-0774 ๐Ÿ”ด PRE-SALE LIVE. โš  CLOSES 4 PM SHARP โ€” must be packed and gone by 4:00. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 495-0774 | Contact: โ€”"},{"city":"Pueblo","state":"CO","location":"Tractor Supply","date":"2026-08-16 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"TBD โ€” str2951@tractorsupply.com Stage overnight in Pueblo. Monday is cross-dock day โ€” drive to Arvada for Tuesday start. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Westminster","state":"CO","location":"Fun Services Colorado","date":"2026-08-18 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"12345 Huron St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 427-7443 โœ“ Additional Tuesday visits approved. T2 also uses Wed (4 dates) โ€” back-to-back OK. | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 427-7443 | Contact: โ€”"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-08-18 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-08-18 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 T2 also uses Boot Barn on Wednesdays. Confirm back-to-back visits OK with Russel. | Truck: T1 | Status: โณ Pending confirm | Phone: (303) 450-9999 | Contact: Russel"},{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-18 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 5 dates: Jul 28 / Aug 11 / Aug 18 / Sep 1 / Sep 8. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Fort Collins","state":"CO","location":"JAX Farm & Ranch","date":"2026-08-18 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"1000 N Hwy 287","zip":null,"cutoff_time":null,"active":true,"notes":"(970) 484-2221 End of day. Stage near Cheyenne (~45 min) for WY Wednesday or near Denver for FR Wednesday. | Truck: T1 | Status: โœ“ Confirmed | Phone: (970) 484-2221 | Contact: โ€”"},{"city":"Albuquerque","state":"NM","location":"Tractor Supply (2nd St NW)","date":"2026-08-19 00:00:00+00","time":"10:00 AM - 1:00 PM","address":"8100 2nd Street NW","zip":null,"cutoff_time":null,"active":true,"notes":"Chris Miller ยท (505) 897-6800 3-hour extended stop. Single ABQ stop โ€” Hacienda dropped. Pre-sale customers notified. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 897-6800 | Contact: Chris Miller"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-08-19 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 450-9999 | Contact: Russel"},{"city":"Bernalillo","state":"NM","location":"Tractor Supply","date":"2026-08-19 00:00:00+00","time":"2:00 PM - 3:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"(505) 771-0168 Stage near Santa Fe after (~30 min north). | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Brighton","state":"CO","location":"Tractor Supply","date":"2026-08-19 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 659-6405 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Commerce City","state":"CO","location":"Stockyards Ranch Supply","date":"2026-08-19 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"6990 Vasquez Blvd","zip":null,"cutoff_time":null,"active":true,"notes":"Anna ยท (303) 287-8081 4 dates only: Jul 22 / Aug 5 / Aug 19 / Sep 2. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 287-8081 | Contact: Anna"},{"city":"Windsor","state":"CO","location":"Brand's Beverage","date":"2026-08-20 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4355 N Fairgrounds Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Nick ยท (970) 617-2698 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 617-2698 | Contact: Nick"},{"city":"Las Vegas","state":"NM","location":"Hacienda Home Centers","date":"2026-08-20 00:00:00+00","time":"12:00 PM - 1:30 PM","address":"2613 7th Street","zip":null,"cutoff_time":null,"active":true,"notes":"Ernest ยท (505) 425-7569 Leave by 1:30 PM sharp โ€” 2.5 hr drive to Pueblo. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 425-7569 | Contact: Ernest"},{"city":"Fort Collins","state":"CO","location":"Tractor Supply","date":"2026-08-20 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Cory ยท (970) 221-1104 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Loveland","state":"CO","location":"Tractor Supply","date":"2026-08-20 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Dylan ยท (970) 663-2722 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Pueblo","state":"CO","location":"Tractor Supply","date":"2026-08-20 00:00:00+00","time":"4:00 PM - 5:00 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"TBD โ€” str2951@tractorsupply.com Stage overnight in Pueblo. Trinidad is 45 min south for Friday start. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Lafayette","state":"CO","location":"Tractor Supply","date":"2026-08-20 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Brian ยท (303) 665-3050 Alternating Thursdays: Jul 23 / Aug 6 / Aug 20 / Sep 3. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Santa Fe","state":"NM","location":"Santa Fe County Fair Board","date":"2026-08-20 00:00:00+00","time":"9:00 AM - 10:30 AM","address":"3229 Rodeo Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Michelle ยท (505) 471-4711 Written commitment sent to bethgrayrdsf@gmail.com. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 471-4711 | Contact: Michelle"},{"city":"Trinidad","state":"CO","location":"Tequila's Mexican Restaurant","date":"2026-08-21 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"9900 Santa Fe Trail","zip":null,"cutoff_time":null,"active":true,"notes":"Hector ยท (719) 846-3514 โš  Restaurant opens 11 AM โ€” 10 AM setup approved by Hector. | Truck: T1 | Status: โœ“ Confirmed | Phone: (719) 846-3514 | Contact: Hector"},{"city":"Fort Lupton","state":"CO","location":"Ace Hardware","date":"2026-08-21 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"Ben ยท (303) 857-1695 โš  BRING UMBRELLA INSURANCE COPY ON FIRST VISIT. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"}]$$::jsonb); + +-- stops batch 4/6 (50) +SELECT admin_create_stops_batch('64294306-5f42-463d-a5e8-2ad6c81a96de'::uuid, $$[{"city":"Greeley","state":"CO","location":"Highland Park Lanes","date":"2026-08-21 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"1900 59th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Zach/Parker ยท (970) 330-2695 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 330-2695 | Contact: Zach/Parker"},{"city":"Canon City","state":"CO","location":"Tractor Supply","date":"2026-08-21 00:00:00+00","time":"1:00 PM - 2:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Britt ยท (719) 275-2116 | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Johnstown","state":"CO","location":"Ace Hardware","date":"2026-08-21 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"Lisa ยท (970) 587-4476 3 visits: Aug 7 / Aug 21 / Sep 4. Runs on Fridays when Fort Morgan is NOT running. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Aurora","state":"CO","location":"Carpet Mill Outlet","date":"2026-08-22 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"1300 S Abilene Street","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (303) 369-8809 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 369-8809 | Contact: Tim"},{"city":"Wellington","state":"CO","location":"Bomgaars","date":"2026-08-22 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4104 Jefferson Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Doug Anderson ยท (970) 568-0223 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 568-0223 | Contact: Doug Anderson"},{"city":"Parker","state":"CO","location":"Big Tool Box","date":"2026-08-22 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 779-8822 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-22 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 Adding Saturday dates to existing Tuesday confirmed stop. Different day โ€” no conflict. Confirm with Murdoch's. | Truck: T2 | Status: โณ Pending confirm | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Castle Rock","state":"CO","location":"Douglas Co. Fairgrounds","date":"2026-08-22 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"500 Fairgrounds Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Tori ยท (720) 733-6900 ๐Ÿ”ด PRE-SALE LIVE. 6 dates only โ€” Jul 25 & Aug 1 blocked (Fair & Rodeo). $500/season โ€” confirm payment with Tori. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (720) 733-6900 | Contact: Tori"},{"city":"Lafayette","state":"CO","location":"JAX Farm & Ranch","date":"2026-08-22 00:00:00+00","time":"4:00 PM - 5:30 PM","address":"400 W South Boulder Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Chris Miller ยท (303) 665-4900 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 665-4900 | Contact: Chris Miller"},{"city":"Security","state":"CO","location":"Aaron's Rent to Own","date":"2026-08-23 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"6750 Camden Blvd","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (719) 391-1515 ๐Ÿ”ด PRE-SALE LIVE. Store opens 10 AM โ€” ARRIVE 9:30 AM for setup. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 391-1515 | Contact: Tim"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-08-23 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 โœ“ Additional Sunday visits approved. Runs every Sunday in addition to every Tuesday. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Colorado Springs","state":"CO","location":"Tractor Supply","date":"2026-08-23 00:00:00+00","time":"12:00 PM - 1:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Robert/Jen ยท (719) 488-8844 ๐Ÿ”ด PRE-SALE LIVE. Highest volume day. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-08-23 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 โš  LEAVE BY 2:00 PM SHARP โ€” 1 hr 45 min drive to Pueblo. | Truck: T2 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Falcon","state":"CO","location":"Bartlett Hay Co.","date":"2026-08-23 00:00:00+00","time":"2:30 PM - 4:00 PM","address":"7090 Old Meridian Road","zip":null,"cutoff_time":null,"active":true,"notes":"(719) 495-0774 ๐Ÿ”ด PRE-SALE LIVE. โš  CLOSES 4 PM SHARP โ€” must be packed and gone by 4:00. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 495-0774 | Contact: โ€”"},{"city":"Pueblo","state":"CO","location":"Tractor Supply","date":"2026-08-23 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"TBD โ€” str2951@tractorsupply.com Stage overnight in Pueblo. Monday is cross-dock day โ€” drive to Arvada for Tuesday start. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Rio Rancho","state":"NM","location":"Pioneer Ace Hardware","date":"2026-08-25 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4100 Sabana Grande Ave SE","zip":null,"cutoff_time":null,"active":true,"notes":"(505) 600-3588 2 visits only. Driver arrives ABQ area Monday night after Pueblo cross-dock. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 600-3588 | Contact: โ€”"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-08-25 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Wheat Ridge","state":"CO","location":"Wardle Feed & Pet Supply","date":"2026-08-25 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"7610 3 Acre Lane","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 424-6455 4 dates: Jul 28 / Aug 11 / Aug 25 / Sep 8. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 424-6455 | Contact: โ€”"},{"city":"Greeley","state":"CO","location":"Highland Park Lanes","date":"2026-08-25 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"1900 59th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Zach/Parker ยท (970) 330-2695 4 dates: Jul 28 / Aug 11 / Aug 25 / Sep 8. In addition to Friday slot. | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 330-2695 | Contact: Zach/Parker"},{"city":"Centennial","state":"CO","location":"Big Tool Box","date":"2026-08-26 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"Bobbi ยท (303) 779-8822 Aug 5 & Aug 26 only (FR weeks). Adding Wednesday dates to existing Friday confirmed stop. Confirm with Bobbi. | Truck: T1 | Status: โณ Pending confirm | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-08-26 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 450-9999 | Contact: Russel"},{"city":"Westminster","state":"CO","location":"Fun Services Colorado","date":"2026-08-26 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"12345 Huron St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 427-7443 4 dates only: Jul 29 / Aug 12 / Aug 26 / Sep 9. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 427-7443 | Contact: โ€”"},{"city":"Brighton","state":"CO","location":"Tractor Supply","date":"2026-08-26 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 659-6405 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-08-27 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 Same location as T2 Sunday stop. | Truck: T1 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Windsor","state":"CO","location":"Brand's Beverage","date":"2026-08-27 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4355 N Fairgrounds Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Nick ยท (970) 617-2698 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 617-2698 | Contact: Nick"},{"city":"Littleton","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-27 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"3773 E. Lincolnway","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 791-7800 Adding Thursday dates to existing Saturday confirmed stop. Different day โ€” no conflict. | Truck: T1 | Status: โณ Pending confirm | Phone: (307) 632-7888 | Contact: Kelly"},{"city":"Fort Collins","state":"CO","location":"Tractor Supply","date":"2026-08-27 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Cory ยท (970) 221-1104 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Loveland","state":"CO","location":"Tractor Supply","date":"2026-08-27 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Dylan ยท (970) 663-2722 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Firestone","state":"CO","location":"Tractor Supply","date":"2026-08-28 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Emily ยท (970) 535-4300 | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Fort Lupton","state":"CO","location":"Ace Hardware","date":"2026-08-28 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"Ben ยท (303) 857-1695 โš  BRING UMBRELLA INSURANCE COPY ON FIRST VISIT. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Greeley","state":"CO","location":"Highland Park Lanes","date":"2026-08-28 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"1900 59th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Zach/Parker ยท (970) 330-2695 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 330-2695 | Contact: Zach/Parker"},{"city":"Golden","state":"CO","location":"Jeffco Fairgrounds","date":"2026-08-28 00:00:00+00","time":"1:00 PM - 2:30 PM","address":"15200 W 6th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Bailey ยท (303) 271-6600 Booking confirmed Jul 24/Aug 7/Aug 14/Aug 28/Sep 4. | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 271-6600 | Contact: Bailey"},{"city":"Fort Morgan","state":"CO","location":"Westeck Rentals","date":"2026-08-28 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"17276 US 34","zip":null,"cutoff_time":null,"active":true,"notes":"Matt ยท (970) 542-9380 5 visits only: Jul 24/31, Aug 14/28, Sep 11. CLOSED Sat & Sun โ€” Friday only. | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 542-9380 | Contact: Matt"},{"city":"Centennial","state":"CO","location":"Big Tool Box","date":"2026-08-28 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"Bobbi ยท (303) 779-8822 | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Aurora","state":"CO","location":"Carpet Mill Outlet","date":"2026-08-29 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"1300 S Abilene Street","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (303) 369-8809 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 369-8809 | Contact: Tim"},{"city":"Wellington","state":"CO","location":"Bomgaars","date":"2026-08-29 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4104 Jefferson Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Doug Anderson ยท (970) 568-0223 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 568-0223 | Contact: Doug Anderson"},{"city":"Parker","state":"CO","location":"Big Tool Box","date":"2026-08-29 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 779-8822 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-29 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 Adding Saturday dates to existing Tuesday confirmed stop. Different day โ€” no conflict. Confirm with Murdoch's. | Truck: T2 | Status: โณ Pending confirm | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Castle Rock","state":"CO","location":"Douglas Co. Fairgrounds","date":"2026-08-29 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"500 Fairgrounds Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Tori ยท (720) 733-6900 ๐Ÿ”ด PRE-SALE LIVE. 6 dates only โ€” Jul 25 & Aug 1 blocked (Fair & Rodeo). $500/season โ€” confirm payment with Tori. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (720) 733-6900 | Contact: Tori"},{"city":"Lafayette","state":"CO","location":"JAX Farm & Ranch","date":"2026-08-29 00:00:00+00","time":"4:00 PM - 5:30 PM","address":"400 W South Boulder Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Chris Miller ยท (303) 665-4900 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 665-4900 | Contact: Chris Miller"},{"city":"Littleton","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-08-29 00:00:00+00","time":"5:00 PM - 6:30 PM","address":"3773 E. Lincolnway","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 791-7800 Alternating Saturdays: Aug 1/15/29, Sep 12. | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 632-7888 | Contact: Kelly"},{"city":"Security","state":"CO","location":"Aaron's Rent to Own","date":"2026-08-30 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"6750 Camden Blvd","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (719) 391-1515 ๐Ÿ”ด PRE-SALE LIVE. Store opens 10 AM โ€” ARRIVE 9:30 AM for setup. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 391-1515 | Contact: Tim"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-08-30 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 โœ“ Additional Sunday visits approved. Runs every Sunday in addition to every Tuesday. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Colorado Springs","state":"CO","location":"Tractor Supply","date":"2026-08-30 00:00:00+00","time":"12:00 PM - 1:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Robert/Jen ยท (719) 488-8844 ๐Ÿ”ด PRE-SALE LIVE. Highest volume day. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-08-30 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 โš  LEAVE BY 2:00 PM SHARP โ€” 1 hr 45 min drive to Pueblo. | Truck: T2 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Falcon","state":"CO","location":"Bartlett Hay Co.","date":"2026-08-30 00:00:00+00","time":"2:30 PM - 4:00 PM","address":"7090 Old Meridian Road","zip":null,"cutoff_time":null,"active":true,"notes":"(719) 495-0774 ๐Ÿ”ด PRE-SALE LIVE. โš  CLOSES 4 PM SHARP โ€” must be packed and gone by 4:00. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 495-0774 | Contact: โ€”"},{"city":"Pueblo","state":"CO","location":"Tractor Supply","date":"2026-08-30 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"TBD โ€” str2951@tractorsupply.com Stage overnight in Pueblo. Monday is cross-dock day โ€” drive to Arvada for Tuesday start. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Westminster","state":"CO","location":"Fun Services Colorado","date":"2026-09-01 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"12345 Huron St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 427-7443 โœ“ Additional Tuesday visits approved. T2 also uses Wed (4 dates) โ€” back-to-back OK. | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 427-7443 | Contact: โ€”"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-09-01 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-09-01 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 T2 also uses Boot Barn on Wednesdays. Confirm back-to-back visits OK with Russel. | Truck: T1 | Status: โณ Pending confirm | Phone: (303) 450-9999 | Contact: Russel"}]$$::jsonb); + +-- stops batch 5/6 (50) +SELECT admin_create_stops_batch('64294306-5f42-463d-a5e8-2ad6c81a96de'::uuid, $$[{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-09-01 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 5 dates: Jul 28 / Aug 11 / Aug 18 / Sep 1 / Sep 8. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Fort Collins","state":"CO","location":"JAX Farm & Ranch","date":"2026-09-01 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"1000 N Hwy 287","zip":null,"cutoff_time":null,"active":true,"notes":"(970) 484-2221 End of day. Stage near Cheyenne (~45 min) for WY Wednesday or near Denver for FR Wednesday. | Truck: T1 | Status: โœ“ Confirmed | Phone: (970) 484-2221 | Contact: โ€”"},{"city":"Cheyenne","state":"WY","location":"Murdoch's Ranch & Home","date":"2026-09-02 00:00:00+00","time":"10:00 AM - 1:00 PM","address":"3773 E. Lincolnway","zip":null,"cutoff_time":null,"active":true,"notes":"Kelly ยท (307) 632-7888 3-hour extended stop. Pre-sales live on website. | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 632-7888 | Contact: Kelly"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-09-02 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 450-9999 | Contact: Russel"},{"city":"Laramie","state":"WY","location":"Albany Co. Fairgrounds","date":"2026-09-02 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"3510 S 3rd Street","zip":null,"cutoff_time":null,"active":true,"notes":"(307) 742-3224 Drive ~45 min south from Cheyenne. | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 742-3224 | Contact: โ€”"},{"city":"Cheyenne","state":"WY","location":"Town & Country Liquors","date":"2026-09-02 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"516 S Greeley Hwy","zip":null,"cutoff_time":null,"active":true,"notes":"(307) 632-8735 โš  SEND INSURANCE COPY BEFORE FIRST VISIT (Jul 22). | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 632-8735 | Contact: โ€”"},{"city":"Brighton","state":"CO","location":"Tractor Supply","date":"2026-09-02 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 659-6405 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Commerce City","state":"CO","location":"Stockyards Ranch Supply","date":"2026-09-02 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"6990 Vasquez Blvd","zip":null,"cutoff_time":null,"active":true,"notes":"Anna ยท (303) 287-8081 4 dates only: Jul 22 / Aug 5 / Aug 19 / Sep 2. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 287-8081 | Contact: Anna"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-09-03 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 Same location as T2 Sunday stop. | Truck: T1 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Windsor","state":"CO","location":"Brand's Beverage","date":"2026-09-03 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4355 N Fairgrounds Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Nick ยท (970) 617-2698 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 617-2698 | Contact: Nick"},{"city":"Littleton","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-09-03 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"3773 E. Lincolnway","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 791-7800 Adding Thursday dates to existing Saturday confirmed stop. Different day โ€” no conflict. | Truck: T1 | Status: โณ Pending confirm | Phone: (307) 632-7888 | Contact: Kelly"},{"city":"Fort Collins","state":"CO","location":"Tractor Supply","date":"2026-09-03 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Cory ยท (970) 221-1104 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Loveland","state":"CO","location":"Tractor Supply","date":"2026-09-03 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Dylan ยท (970) 663-2722 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Lafayette","state":"CO","location":"Tractor Supply","date":"2026-09-03 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Brian ยท (303) 665-3050 Alternating Thursdays: Jul 23 / Aug 6 / Aug 20 / Sep 3. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Firestone","state":"CO","location":"Tractor Supply","date":"2026-09-04 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Emily ยท (970) 535-4300 | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Fort Lupton","state":"CO","location":"Ace Hardware","date":"2026-09-04 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"Ben ยท (303) 857-1695 โš  BRING UMBRELLA INSURANCE COPY ON FIRST VISIT. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Greeley","state":"CO","location":"Highland Park Lanes","date":"2026-09-04 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"1900 59th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Zach/Parker ยท (970) 330-2695 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 330-2695 | Contact: Zach/Parker"},{"city":"Golden","state":"CO","location":"Jeffco Fairgrounds","date":"2026-09-04 00:00:00+00","time":"1:00 PM - 2:30 PM","address":"15200 W 6th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Bailey ยท (303) 271-6600 Booking confirmed Jul 24/Aug 7/Aug 14/Aug 28/Sep 4. | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 271-6600 | Contact: Bailey"},{"city":"Centennial","state":"CO","location":"Big Tool Box","date":"2026-09-04 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"Bobbi ยท (303) 779-8822 | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Johnstown","state":"CO","location":"Ace Hardware","date":"2026-09-04 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"Lisa ยท (970) 587-4476 3 visits: Aug 7 / Aug 21 / Sep 4. Runs on Fridays when Fort Morgan is NOT running. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Aurora","state":"CO","location":"Carpet Mill Outlet","date":"2026-09-05 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"1300 S Abilene Street","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (303) 369-8809 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 369-8809 | Contact: Tim"},{"city":"Wellington","state":"CO","location":"Bomgaars","date":"2026-09-05 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4104 Jefferson Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Doug Anderson ยท (970) 568-0223 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 568-0223 | Contact: Doug Anderson"},{"city":"Parker","state":"CO","location":"Big Tool Box","date":"2026-09-05 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 779-8822 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-09-05 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 Adding Saturday dates to existing Tuesday confirmed stop. Different day โ€” no conflict. Confirm with Murdoch's. | Truck: T2 | Status: โณ Pending confirm | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Castle Rock","state":"CO","location":"Douglas Co. Fairgrounds","date":"2026-09-05 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"500 Fairgrounds Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Tori ยท (720) 733-6900 ๐Ÿ”ด PRE-SALE LIVE. 6 dates only โ€” Jul 25 & Aug 1 blocked (Fair & Rodeo). $500/season โ€” confirm payment with Tori. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (720) 733-6900 | Contact: Tori"},{"city":"Lafayette","state":"CO","location":"JAX Farm & Ranch","date":"2026-09-05 00:00:00+00","time":"4:00 PM - 5:30 PM","address":"400 W South Boulder Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Chris Miller ยท (303) 665-4900 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 665-4900 | Contact: Chris Miller"},{"city":"Security","state":"CO","location":"Aaron's Rent to Own","date":"2026-09-06 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"6750 Camden Blvd","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (719) 391-1515 ๐Ÿ”ด PRE-SALE LIVE. Store opens 10 AM โ€” ARRIVE 9:30 AM for setup. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 391-1515 | Contact: Tim"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-09-06 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 โœ“ Additional Sunday visits approved. Runs every Sunday in addition to every Tuesday. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Colorado Springs","state":"CO","location":"Tractor Supply","date":"2026-09-06 00:00:00+00","time":"12:00 PM - 1:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Robert/Jen ยท (719) 488-8844 ๐Ÿ”ด PRE-SALE LIVE. Highest volume day. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-09-06 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 โš  LEAVE BY 2:00 PM SHARP โ€” 1 hr 45 min drive to Pueblo. | Truck: T2 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Falcon","state":"CO","location":"Bartlett Hay Co.","date":"2026-09-06 00:00:00+00","time":"2:30 PM - 4:00 PM","address":"7090 Old Meridian Road","zip":null,"cutoff_time":null,"active":true,"notes":"(719) 495-0774 ๐Ÿ”ด PRE-SALE LIVE. โš  CLOSES 4 PM SHARP โ€” must be packed and gone by 4:00. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 495-0774 | Contact: โ€”"},{"city":"Pueblo","state":"CO","location":"Tractor Supply","date":"2026-09-06 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"TBD โ€” str2951@tractorsupply.com Stage overnight in Pueblo. Monday is cross-dock day โ€” drive to Arvada for Tuesday start. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Westminster","state":"CO","location":"Fun Services Colorado","date":"2026-09-08 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"12345 Huron St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 427-7443 โœ“ Additional Tuesday visits approved. T2 also uses Wed (4 dates) โ€” back-to-back OK. | Truck: T1 | Status: โœ“ Confirmed | Phone: (303) 427-7443 | Contact: โ€”"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-09-08 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-09-08 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 T2 also uses Boot Barn on Wednesdays. Confirm back-to-back visits OK with Russel. | Truck: T1 | Status: โณ Pending confirm | Phone: (303) 450-9999 | Contact: Russel"},{"city":"Wheat Ridge","state":"CO","location":"Wardle Feed & Pet Supply","date":"2026-09-08 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"7610 3 Acre Lane","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 424-6455 4 dates: Jul 28 / Aug 11 / Aug 25 / Sep 8. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 424-6455 | Contact: โ€”"},{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-09-08 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 5 dates: Jul 28 / Aug 11 / Aug 18 / Sep 1 / Sep 8. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Fort Collins","state":"CO","location":"JAX Farm & Ranch","date":"2026-09-08 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"1000 N Hwy 287","zip":null,"cutoff_time":null,"active":true,"notes":"(970) 484-2221 End of day. Stage near Cheyenne (~45 min) for WY Wednesday or near Denver for FR Wednesday. | Truck: T1 | Status: โœ“ Confirmed | Phone: (970) 484-2221 | Contact: โ€”"},{"city":"Greeley","state":"CO","location":"Highland Park Lanes","date":"2026-09-08 00:00:00+00","time":"5:00 PM - 6:00 PM","address":"1900 59th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Zach/Parker ยท (970) 330-2695 4 dates: Jul 28 / Aug 11 / Aug 25 / Sep 8. In addition to Friday slot. | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 330-2695 | Contact: Zach/Parker"},{"city":"Albuquerque","state":"NM","location":"Tractor Supply (2nd St NW)","date":"2026-09-09 00:00:00+00","time":"10:00 AM - 1:00 PM","address":"8100 2nd Street NW","zip":null,"cutoff_time":null,"active":true,"notes":"Chris Miller ยท (505) 897-6800 3-hour extended stop. Single ABQ stop โ€” Hacienda dropped. Pre-sale customers notified. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 897-6800 | Contact: Chris Miller"},{"city":"Thornton","state":"CO","location":"Boot Barn","date":"2026-09-09 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10300 Bannock Street","zip":null,"cutoff_time":null,"active":true,"notes":"Russel ยท (303) 450-9999 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 450-9999 | Contact: Russel"},{"city":"Westminster","state":"CO","location":"Fun Services Colorado","date":"2026-09-09 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"12345 Huron St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 427-7443 4 dates only: Jul 29 / Aug 12 / Aug 26 / Sep 9. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 427-7443 | Contact: โ€”"},{"city":"Bernalillo","state":"NM","location":"Tractor Supply","date":"2026-09-09 00:00:00+00","time":"2:00 PM - 3:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"(505) 771-0168 Stage near Santa Fe after (~30 min north). | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Brighton","state":"CO","location":"Tractor Supply","date":"2026-09-09 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 659-6405 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Windsor","state":"CO","location":"Brand's Beverage","date":"2026-09-10 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4355 N Fairgrounds Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Nick ยท (970) 617-2698 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 617-2698 | Contact: Nick"},{"city":"Las Vegas","state":"NM","location":"Hacienda Home Centers","date":"2026-09-10 00:00:00+00","time":"12:00 PM - 1:30 PM","address":"2613 7th Street","zip":null,"cutoff_time":null,"active":true,"notes":"Ernest ยท (505) 425-7569 Leave by 1:30 PM sharp โ€” 2.5 hr drive to Pueblo. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 425-7569 | Contact: Ernest"},{"city":"Fort Collins","state":"CO","location":"Tractor Supply","date":"2026-09-10 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Cory ยท (970) 221-1104 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Loveland","state":"CO","location":"Tractor Supply","date":"2026-09-10 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"Dylan ยท (970) 663-2722 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Pueblo","state":"CO","location":"Tractor Supply","date":"2026-09-10 00:00:00+00","time":"4:00 PM - 5:00 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"TBD โ€” str2951@tractorsupply.com Stage overnight in Pueblo. Trinidad is 45 min south for Friday start. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Santa Fe","state":"NM","location":"Santa Fe County Fair Board","date":"2026-09-10 00:00:00+00","time":"9:00 AM - 10:30 AM","address":"3229 Rodeo Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Michelle ยท (505) 471-4711 Written commitment sent to bethgrayrdsf@gmail.com. | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 471-4711 | Contact: Michelle"}]$$::jsonb); + +-- stops batch 6/6 (19) +SELECT admin_create_stops_batch('64294306-5f42-463d-a5e8-2ad6c81a96de'::uuid, $$[{"city":"Trinidad","state":"CO","location":"Tequila's Mexican Restaurant","date":"2026-09-11 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"9900 Santa Fe Trail","zip":null,"cutoff_time":null,"active":true,"notes":"Hector ยท (719) 846-3514 โš  Restaurant opens 11 AM โ€” 10 AM setup approved by Hector. | Truck: T1 | Status: โœ“ Confirmed | Phone: (719) 846-3514 | Contact: Hector"},{"city":"Fort Lupton","state":"CO","location":"Ace Hardware","date":"2026-09-11 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"Ben ยท (303) 857-1695 โš  BRING UMBRELLA INSURANCE COPY ON FIRST VISIT. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Greeley","state":"CO","location":"Highland Park Lanes","date":"2026-09-11 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"1900 59th Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Zach/Parker ยท (970) 330-2695 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 330-2695 | Contact: Zach/Parker"},{"city":"Canon City","state":"CO","location":"Tractor Supply","date":"2026-09-11 00:00:00+00","time":"1:00 PM - 2:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Britt ยท (719) 275-2116 | Truck: T1 | Status: โœ“ Confirmed | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Fort Morgan","state":"CO","location":"Westeck Rentals","date":"2026-09-11 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"17276 US 34","zip":null,"cutoff_time":null,"active":true,"notes":"Matt ยท (970) 542-9380 5 visits only: Jul 24/31, Aug 14/28, Sep 11. CLOSED Sat & Sun โ€” Friday only. | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 542-9380 | Contact: Matt"},{"city":"Aurora","state":"CO","location":"Carpet Mill Outlet","date":"2026-09-12 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"1300 S Abilene Street","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (303) 369-8809 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 369-8809 | Contact: Tim"},{"city":"Wellington","state":"CO","location":"Bomgaars","date":"2026-09-12 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"4104 Jefferson Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Doug Anderson ยท (970) 568-0223 | Truck: T2 | Status: โœ“ Confirmed | Phone: (970) 568-0223 | Contact: Doug Anderson"},{"city":"Parker","state":"CO","location":"Big Tool Box","date":"2026-09-12 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"8080 S Holly Street","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 779-8822 ๐Ÿ”ด PRE-SALE LIVE on website. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (303) 779-8822 | Contact: Bobbi"},{"city":"Longmont","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-09-12 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"2255 Main St","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 682-5111 Adding Saturday dates to existing Tuesday confirmed stop. Different day โ€” no conflict. Confirm with Murdoch's. | Truck: T2 | Status: โณ Pending confirm | Phone: (303) 682-5111 | Contact: โ€”"},{"city":"Castle Rock","state":"CO","location":"Douglas Co. Fairgrounds","date":"2026-09-12 00:00:00+00","time":"3:00 PM - 4:30 PM","address":"500 Fairgrounds Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Tori ยท (720) 733-6900 ๐Ÿ”ด PRE-SALE LIVE. 6 dates only โ€” Jul 25 & Aug 1 blocked (Fair & Rodeo). $500/season โ€” confirm payment with Tori. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (720) 733-6900 | Contact: Tori"},{"city":"Lafayette","state":"CO","location":"JAX Farm & Ranch","date":"2026-09-12 00:00:00+00","time":"4:00 PM - 5:30 PM","address":"400 W South Boulder Rd","zip":null,"cutoff_time":null,"active":true,"notes":"Chris Miller ยท (303) 665-4900 | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 665-4900 | Contact: Chris Miller"},{"city":"Littleton","state":"CO","location":"Murdoch's Ranch & Home","date":"2026-09-12 00:00:00+00","time":"5:00 PM - 6:30 PM","address":"3773 E. Lincolnway","zip":null,"cutoff_time":null,"active":true,"notes":"(303) 791-7800 Alternating Saturdays: Aug 1/15/29, Sep 12. | Truck: T1 | Status: โœ“ Confirmed | Phone: (307) 632-7888 | Contact: Kelly"},{"city":"Security","state":"CO","location":"Aaron's Rent to Own","date":"2026-09-13 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"6750 Camden Blvd","zip":null,"cutoff_time":null,"active":true,"notes":"Tim ยท (719) 391-1515 ๐Ÿ”ด PRE-SALE LIVE. Store opens 10 AM โ€” ARRIVE 9:30 AM for setup. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 391-1515 | Contact: Tim"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-09-13 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 โœ“ Additional Sunday visits approved. Runs every Sunday in addition to every Tuesday. | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"},{"city":"Colorado Springs","state":"CO","location":"Tractor Supply","date":"2026-09-13 00:00:00+00","time":"12:00 PM - 1:30 PM","address":"300 W US Hwy 550","zip":null,"cutoff_time":null,"active":true,"notes":"Robert/Jen ยท (719) 488-8844 ๐Ÿ”ด PRE-SALE LIVE. Highest volume day. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (505) 771-0168 | Contact: โ€”"},{"city":"Englewood","state":"CO","location":"Harbor Freight","date":"2026-09-13 00:00:00+00","time":"12:30 PM - 2:00 PM","address":"705 W Hampden Ave","zip":null,"cutoff_time":null,"active":true,"notes":"Store Manager ยท (719) 442-6414 โš  LEAVE BY 2:00 PM SHARP โ€” 1 hr 45 min drive to Pueblo. | Truck: T2 | Status: โœ“ Confirmed | Phone: (719) 442-6414 | Contact: Store Manager"},{"city":"Falcon","state":"CO","location":"Bartlett Hay Co.","date":"2026-09-13 00:00:00+00","time":"2:30 PM - 4:00 PM","address":"7090 Old Meridian Road","zip":null,"cutoff_time":null,"active":true,"notes":"(719) 495-0774 ๐Ÿ”ด PRE-SALE LIVE. โš  CLOSES 4 PM SHARP โ€” must be packed and gone by 4:00. | Truck: T1 | Status: ๐Ÿ”ด Pre-sale LIVE | Phone: (719) 495-0774 | Contact: โ€”"},{"city":"Pueblo","state":"CO","location":"Tractor Supply","date":"2026-09-13 00:00:00+00","time":"3:30 PM - 5:00 PM","address":"147 Denver Street","zip":null,"cutoff_time":null,"active":true,"notes":"TBD โ€” str2951@tractorsupply.com Stage overnight in Pueblo. Monday is cross-dock day โ€” drive to Arvada for Tuesday start. | Truck: T2 | Status: โœ“ Confirmed | Phone: (303) 659-6405 | Contact: โ€”"},{"city":"Arvada","state":"CO","location":"Ace Hardware","date":"2026-09-15 00:00:00+00","time":"10:00 AM - 11:30 AM","address":"10000 Ralston Road","zip":null,"cutoff_time":null,"active":true,"notes":"(720) 612-4248 | Truck: T2 | Status: โœ“ Confirmed | Phone: (720) 612-4248 | Contact: โ€”"}]$$::jsonb); + +-- Make stops visible (RPC inserts as draft + active=true in payload) +UPDATE stops SET status = 'active' WHERE brand_id = '64294306-5f42-463d-a5e8-2ad6c81a96de' AND date >= '2026-07-01' AND date <= '2026-09-30'; + +COMMIT; diff --git a/package.json b/package.json index b2ed7f5..6e6b78a 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "migrate:one": "node scripts/migrate.js", "db:migrate": "node scripts/migrate.js", "db:seed": "tsx db/seed.ts", + "db:seed:tour": "node scripts/seed-tuxedo-2026.js", "db:reset": "node scripts/db-reset.js", "db:studio": "drizzle-kit studio", "type-check": "npx tsc --noEmit", @@ -29,6 +30,7 @@ "@google/generative-ai": "^0.24.1", "@gsap/react": "^2.1.2", "@neondatabase/auth": "^0.4.2-beta", + "@neondatabase/serverless": "^1.1.0", "@sentry/nextjs": "^10.55.0", "@stripe/react-stripe-js": "^6.6.0", "@stripe/stripe-js": "^9.7.0", diff --git a/scripts/import-tuxedo-stops.ts b/scripts/import-tuxedo-stops.ts new file mode 100644 index 0000000..413807a --- /dev/null +++ b/scripts/import-tuxedo-stops.ts @@ -0,0 +1,448 @@ +// dotenv load temporarily disabled so shell-provided DATABASE_URL wins for this run +// import { config } from "dotenv"; +// config({ path: ".env.local" }); +import { Pool } from "pg"; +import ExcelJS from "exceljs"; +import * as fs from "fs"; + +const TUXEDO_BRAND_ID = "64294306-5f42-463d-a5e8-2ad6c81a96de"; +const YEAR = 2026; + +const MONTH_MAP: Record = { + Jan: "01", Feb: "02", Mar: "03", Apr: "04", May: "05", Jun: "06", + Jul: "07", Aug: "08", Sep: "09", Oct: "10", Nov: "11", Dec: "12", +}; + +interface ParsedStop { + week: string; + region: string; + date: string; + day: string; + city: string; + state: string; + location: string; + time: string; + timeRange: string; + truck: string; + statusText: string; + notes: string; + address: string | null; + phone: string | null; + contact: string | null; +} + +function parseExcelDate(s: unknown): string | null { + if (!s) return null; + const m = /^([A-Za-z]{3})\s+(\d{1,2})$/.exec(String(s).trim()); + if (!m) return null; + const mm = MONTH_MAP[m[1]]; + if (!mm) return null; + return `${YEAR}-${mm}-${parseInt(m[2], 10).toString().padStart(2, "0")}`; +} + +function parseTimeRange(s: unknown): string { + if (!s) return ""; + let c = String(s).replace(/[โ€“โ€”]/g, "-").replace(/\s+/g, " ").trim(); + const m = /^(\d{1,2}:\d{2}\s*[AP]M)/i.exec(c); + // Prefer full range for display (e.g. "10:00 AM โ€“ 1:00 PM"); fall back to start only + return c || (m ? m[1].toUpperCase().replace(" ", " ") : ""); +} + +function splitCityState(s: unknown): [string, string] { + if (!s) return ["", ""]; + const parts = String(s).split(",").map((p) => p.trim()); + if (parts.length === 1) return [parts[0], ""]; + return [parts[0], parts[1]]; +} + +function isWeekHeader(cells: string[]): boolean { + return /^Wk\s/i.test(cells[0] || "") && (cells[3] || "").trim() === ""; +} + +function isOffRow(cells: string[]): boolean { + const d = (cells[3] || "").trim(); + return /OFF|Cross-?Dock/i.test(d); +} + +function isDataRow(cells: string[]): boolean { + const day = (cells[3] || "").trim(); + const city = (cells[4] || "").trim(); + return !!(day && city && city.includes(",")); +} + +function slugify(s: string): string { + let out = (s || "").toLowerCase(); + out = out.replace(/[^a-z0-9]+/g, "-"); + return out.replace(/^-+|-+$/g, ""); +} + +async function loadStops(xlsxPath: string): Promise<{ stops: ParsedStop[]; skipped: Record; dirCount: number }> { + const wb = new ExcelJS.Workbook(); + await wb.xlsx.readFile(xlsxPath); + + const schedule = wb.getWorksheet("Full Schedule"); + const directory = wb.getWorksheet("Stop Directory"); + if (!schedule) throw new Error("Missing 'Full Schedule' sheet"); + + // Build directory lookup for address enrichment: "T1|host lower" -> info + const dirMap = new Map(); + if (directory) { + for (let r = 2; r <= directory.rowCount; r++) { + const row = directory.getRow(r); + const truck = String(row.getCell(1).value || "").trim(); + const host = String(row.getCell(4).value || "").trim().toLowerCase(); + if (!truck || !host) continue; + dirMap.set(`${truck}|${host}`, { + address: String(row.getCell(5).value || "").trim() || null, + phone: String(row.getCell(6).value || "").trim() || null, + contact: String(row.getCell(7).value || "").trim() || null, + state: String(row.getCell(3).value || "").trim(), + }); + } + } + + const stops: ParsedStop[] = []; + const skipped: Record = { weekHeader: 0, off: 0, invalid: 0, noDate: 0 }; + + for (let r = 4; r <= schedule.rowCount; r++) { + const row = schedule.getRow(r); + const cells = Array.from({ length: 10 }, (_, i) => String(row.getCell(i + 1).value ?? "").trim()); + + if (isWeekHeader(cells)) { + skipped.weekHeader++; + continue; + } + if (isOffRow(cells)) { + skipped.off++; + continue; + } + if (!isDataRow(cells)) { + skipped.invalid++; + continue; + } + + const [wk, region, dateText, day, cityState, host, time, truck, status, notes] = cells; + const dateIso = parseExcelDate(dateText); + if (!dateIso) { + skipped.noDate++; + continue; + } + const [city, state] = splitCityState(cityState); + if (!city) { + skipped.invalid++; + continue; + } + + const key = `${truck}|${host.toLowerCase()}`; + const d = dirMap.get(key); + + stops.push({ + week: wk, + region, + date: dateIso, + day, + city, + state: state || (d?.state || ""), + location: host, + time: parseTimeRange(time), + timeRange: time, + truck, + statusText: status, + notes: notes || "", + address: d?.address || null, + phone: d?.phone || null, + contact: d?.contact || null, + }); + } + + return { stops, skipped, dirCount: dirMap.size, locations: loadLocations(directory) }; +} + +export type ParsedLocation = { + name: string; + address: string | null; + city: string; + state: string; + phone: string | null; + contactName: string | null; + notes: string | null; +}; + +function loadLocations(directory: ExcelJS.Worksheet | undefined): ParsedLocation[] { + if (!directory) return []; + const byKey = new Map(); + for (let r = 2; r <= directory.rowCount; r++) { + const row = directory.getRow(r); + const truck = String(row.getCell(1).value || "").trim(); + const city = String(row.getCell(2).value || "").trim(); + const state = String(row.getCell(3).value || "").trim(); + const host = String(row.getCell(4).value || "").trim(); + const address = String(row.getCell(5).value || "").trim() || null; + let phone = String(row.getCell(6).value || "").trim() || null; + const contact = String(row.getCell(7).value || "").trim() || null; + // notes column is 12 + let notes = String(row.getCell(12).value || "").trim() || null; + + if (!host || !city) continue; + + // If phone field contains TBD email, move it to notes + if (phone && /@/.test(phone) && (!notes || notes.length < 10)) { + notes = phone; + phone = null; + } + + const key = `${host.toLowerCase()}|${city.toLowerCase()}|${state.toLowerCase()}`; + if (!byKey.has(key)) { + byKey.set(key, { + name: host, + address, + city, + state, + phone, + contactName: contact || null, + notes, + }); + } + } + return Array.from(byKey.values()); +} + +function toLocationRpcRow(l: ParsedLocation) { + return { + name: l.name, + address: l.address, + city: l.city, + state: l.state, + zip: null, + phone: l.phone, + contact_name: l.contactName, + contact_email: null, + notes: l.notes, + active: true, + }; +} + +function toRpcRow(s: ParsedStop) { + // Date format matches the python seed script expectation for the RPC + const dateWithTz = `${s.date} 00:00:00+00`; + const combinedNotes = [ + s.notes, + s.truck ? `Truck: ${s.truck}` : "", + s.statusText ? `Status: ${s.statusText}` : "", + s.phone ? `Phone: ${s.phone}` : "", + s.contact ? `Contact: ${s.contact}` : "", + ] + .filter(Boolean) + .join(" | "); + + return { + city: s.city, + state: s.state, + location: s.location, + date: dateWithTz, + time: s.time || s.timeRange || "", + address: s.address, + zip: null, + cutoff_time: null, + // active=true makes them visible on the public /tuxedo/stops storefront immediately + active: true, + // forward notes when the RPC supports it (enriched with truck/status/contact) + notes: combinedNotes || null, + }; +} + +async function main() { + const args = process.argv.slice(2); + const dryRun = args.includes("--dry-run") || args.includes("-n"); + let xlsxPath = "./Tuxedo_Corn_2026_Tour_Schedule-3.xlsx"; + const xArg = args.findIndex((a) => a === "--xlsx" || a === "-x"); + if (xArg !== -1 && args[xArg + 1]) xlsxPath = args[xArg + 1]; + const doClean = !args.includes("--no-clean"); + const emitSql = args.includes("--emit-sql") || args.includes("--sql"); + + console.log(`[import-tuxedo-stops] xlsx=${xlsxPath} dryRun=${dryRun} clean=${doClean} emitSql=${emitSql}`); + + const { stops, skipped, dirCount, locations: parsedLocations } = await loadStops(xlsxPath); + + console.log(`\nParsed ${stops.length} stops + ${parsedLocations.length} unique locations`); + console.log(`Skipped: week-headers=${skipped.weekHeader}, off/cross-dock=${skipped.off}, invalid=${skipped.invalid}, no-date=${skipped.noDate}`); + console.log(`Stop Directory raw entries: ${dirCount}\n`); + + if (!stops.length) { + console.error("No stops to insert. Check the xlsx path and filters."); + process.exit(1); + } + + // Show samples + console.log("Sample (first 3):"); + stops.slice(0, 3).forEach((s) => { + console.log(` ${s.date} ${s.time.padEnd(10)} | ${s.city}, ${s.state} | ${s.location.slice(0, 32).padEnd(32)} | ${s.truck} | ${s.statusText}`); + if (s.address) console.log(` addr: ${s.address}`); + }); + console.log("\nSample (last 3):"); + stops.slice(-3).forEach((s) => { + console.log(` ${s.date} ${s.time.padEnd(10)} | ${s.city}, ${s.state} | ${s.location.slice(0, 32).padEnd(32)} | ${s.truck} | ${s.statusText}`); + }); + + // By week/region/truck + const byWeek: Record = {}; + const byRegion: Record = {}; + const byTruck: Record = {}; + for (const s of stops) { + byWeek[s.week] = (byWeek[s.week] || 0) + 1; + byRegion[s.region] = (byRegion[s.region] || 0) + 1; + byTruck[s.truck] = (byTruck[s.truck] || 0) + 1; + } + console.log("\nBy week:", Object.fromEntries(Object.entries(byWeek).sort(([a], [b]) => Number(a) - Number(b)))); + console.log("By region:", byRegion); + console.log("By truck:", byTruck); + + const dates = [...stops.map((s) => s.date)].sort(); + console.log(`\nDate range: ${dates[0]} โ†’ ${dates[dates.length - 1]}`); + + if (emitSql) { + const BATCH = 50; + let sql = `-- Tuxedo Corn 2026 Tour Data (from ${xlsxPath})\n`; + sql += `-- Stops: ${stops.length} | Locations: ${parsedLocations.length}\n`; + sql += `-- Preferred: npx tsx scripts/import-tuxedo-stops.ts\n`; + sql += `-- Manual apply: psql "$DATABASE_URL" -f db/seeds/2026-tuxedo-tour-stops.sql\n`; + sql += `-- supabase db query --linked --file db/seeds/2026-tuxedo-tour-stops.sql\n\n`; + sql += `BEGIN;\n\n`; + + // Locations first (master directory) + if (parsedLocations.length > 0) { + sql += `-- ===== LOCATIONS (Stop Directory master records) =====\n`; + sql += `DELETE FROM locations WHERE brand_id = '${TUXEDO_BRAND_ID}';\n\n`; + const locPayload = parsedLocations.map(toLocationRpcRow); + const locJson = JSON.stringify(locPayload); + sql += `-- ${parsedLocations.length} unique locations from Stop Directory\n`; + sql += `SELECT admin_create_locations_batch('${TUXEDO_BRAND_ID}'::uuid, $$${locJson}$$::jsonb);\n\n`; + } + + // Stops (dated instances) + sql += `-- ===== STOPS (2026 tour schedule) =====\n`; + sql += `-- Clear prior 2026 tour stops for brand (date-scoped)\n`; + sql += `DELETE FROM stops WHERE brand_id = '${TUXEDO_BRAND_ID}' AND date >= '2026-07-01' AND date <= '2026-09-30';\n\n`; + for (let i = 0; i < stops.length; i += BATCH) { + const batchStops = stops.slice(i, i + BATCH); + const payload = batchStops.map(toRpcRow); + const payloadJson = JSON.stringify(payload); + const bnum = Math.floor(i / BATCH) + 1; + sql += `-- stops batch ${bnum}/${Math.ceil(stops.length / BATCH)} (${payload.length})\n`; + sql += `SELECT admin_create_stops_batch('${TUXEDO_BRAND_ID}'::uuid, $$${payloadJson}$$::jsonb);\n\n`; + } + sql += `-- Make stops visible (RPC inserts as draft + active=true in payload)\n`; + sql += `UPDATE stops SET status = 'active' WHERE brand_id = '${TUXEDO_BRAND_ID}' AND date >= '2026-07-01' AND date <= '2026-09-30';\n\n`; + sql += `COMMIT;\n`; + const outPath = "db/seeds/2026-tuxedo-tour-stops.sql"; + fs.writeFileSync(outPath, sql, "utf8"); + console.log(`\nWrote ${outPath} (locations: ${parsedLocations.length}, stops: ${stops.length}).`); + } + + if (dryRun) { + const stopBatches = Math.ceil(stops.length / 50); + console.log(`\n[DRY RUN] Would load for brand:\n - ${parsedLocations.length} locations (full replace)\n - DELETE date-scoped 2026 stops then INSERT ${stops.length} stops in ${stopBatches} batch(es)\n via admin_*_batch RPCs.`); + return; + } + + const pool = new Pool({ + connectionString: + process.env.DATABASE_ADMIN_URL ?? + process.env.DATABASE_URL ?? + "postgres://postgres:postgres@localhost:5432/route_commerce", + }); + + const client = await pool.connect(); + try { + await client.query("BEGIN"); + + if (doClean) { + const del = await client.query( + `DELETE FROM stops WHERE brand_id = $1 AND date >= '2026-07-01' AND date <= '2026-09-30'`, + [TUXEDO_BRAND_ID], + ); + console.log(`\nCleared ${del.rowCount} prior 2026-dated stops for Tuxedo brand.`); + } + + // Locations (from Stop Directory) โ€” full replace for the brand from this xlsx + if (parsedLocations.length > 0) { + const locDel = await client.query( + `DELETE FROM locations WHERE brand_id = $1`, + [TUXEDO_BRAND_ID], + ); + console.log(`Cleared ${locDel.rowCount} previous locations for Tuxedo brand.`); + + const LOC_BATCH = 100; // locations are fewer and smaller + let locTotal = 0; + const locBatches = Math.ceil(parsedLocations.length / LOC_BATCH); + for (let i = 0; i < parsedLocations.length; i += LOC_BATCH) { + const batchLocs = parsedLocations.slice(i, i + LOC_BATCH); + const payload = batchLocs.map(toLocationRpcRow); + const bnum = Math.floor(i / LOC_BATCH) + 1; + process.stdout.write(` Locations batch ${bnum}/${locBatches} (${payload.length}) via admin_create_locations_batch... `); + try { + await client.query( + "SELECT admin_create_locations_batch($1::uuid, $2::jsonb)", + [TUXEDO_BRAND_ID, JSON.stringify(payload)], + ); + locTotal += payload.length; + console.log("OK"); + } catch (e: any) { + console.log("FAIL"); + throw e; + } + } + console.log(` Inserted ${locTotal} locations.`); + } + + const BATCH = 50; + let total = 0; + const batches = Math.ceil(stops.length / BATCH); + + for (let i = 0; i < stops.length; i += BATCH) { + const batchStops = stops.slice(i, i + BATCH); + const payload = batchStops.map(toRpcRow); + const bnum = Math.floor(i / BATCH) + 1; + + process.stdout.write(` Batch ${bnum}/${batches} (${payload.length}) via admin_create_stops_batch... `); + try { + await client.query( + "SELECT admin_create_stops_batch($1::uuid, $2::jsonb)", + [TUXEDO_BRAND_ID, JSON.stringify(payload)], + ); + total += payload.length; + console.log("OK"); + } catch (e: any) { + console.log("FAIL"); + throw e; + } + } + + // RPC inserts with status='draft' (per prior script); flip to active for public visibility. + // Scope by the tour date range so we only touch rows from this import. + if (total > 0) { + const pub = await client.query( + `UPDATE stops SET status = 'active' WHERE brand_id = $1 AND date >= '2026-07-01' AND date <= '2026-09-30'`, + [TUXEDO_BRAND_ID], + ); + console.log(`\nPublished (status=active): ${pub.rowCount} stops.`); + } + + await client.query("COMMIT"); + console.log(`\nDone. Inserted ${parsedLocations.length} locations + ${total} stops for Tuxedo Corn 2026 tour (brand ${TUXEDO_BRAND_ID}).`); + console.log("Locations are the master directory; stops are the dated schedule instances."); + console.log("They should now appear on /tuxedo/stops and in admin locations UI."); + } catch (err) { + await client.query("ROLLBACK"); + console.error("\nInsert failed (rolled back):", err); + process.exitCode = 1; + } finally { + client.release(); + await pool.end(); + } +} + +main().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/scripts/seed-tuxedo-2026.js b/scripts/seed-tuxedo-2026.js new file mode 100644 index 0000000..368dcf7 --- /dev/null +++ b/scripts/seed-tuxedo-2026.js @@ -0,0 +1,192 @@ +#!/usr/bin/env node +/** + * Seed Tuxedo Corn 2026 tour: locations + stops. + * + * Uses sql`...` tagged template from @neondatabase/serverless (WebSocket mode) + * for INSERTs โ€” this is the only Neon serverless API that actually executes writes. + * + * Run with: + * node scripts/seed-tuxedo-2026.js + * + * Requires DATABASE_URL in .env.local (or pass explicitly). + */ +require("dotenv").config({ path: ".env.local" }); +const { neon } = require("@neondatabase/serverless"); +const ExcelJS = require("exceljs"); +const path = require("path"); + +const TUXEDO_BRAND_ID = "64294306-5f42-463d-a5e8-2ad6c81a96de"; +const YEAR = 2026; + +const url = process.env.DATABASE_URL; +if (!url) { + console.error("โŒ DATABASE_URL not set in .env.local"); + process.exit(1); +} + +const cleanUrl = url.replace(/[?&]channel_binding=require/gi, "").trim(); +// Use direct compute endpoint with WebSocket for full DDL + DML support +const directUrl = cleanUrl.replace("-pooler.", "."); +const sql = neon(directUrl, { webSocket: true }); + +const MONTH_MAP = { + Jan: "01", Feb: "02", Mar: "03", Apr: "04", May: "05", Jun: "06", + Jul: "07", Aug: "08", Sep: "09", Oct: "10", Nov: "11", Dec: "12", +}; + +function parseExcelDate(s) { + if (!s) return null; + const m = /^([A-Za-z]{3})\s+(\d{1,2})$/.exec(String(s).trim()); + if (!m) return null; + const mm = MONTH_MAP[m[1]]; + if (!mm) return null; + return `${YEAR}-${mm}-${parseInt(m[2], 10).toString().padStart(2, "0")}`; +} + +function parseTimeRange(s) { + if (!s) return ""; + return String(s).replace(/[โ€“โ€”]/g, "-").replace(/\s+/g, " ").trim(); +} + +async function parseXlsx(xlsxPath) { + const workbook = new ExcelJS.Workbook(); + await workbook.xlsx.readFile(xlsxPath); + + // --- Locations from Stop Directory --- + const locSheet = workbook.getWorksheet("Stop Directory"); + const locations = []; + const seenLoc = new Set(); + + if (locSheet) { + locSheet.eachRow((row, rowNum) => { + if (rowNum === 1) return; + // Column mapping via getCell(): + // col1=Truck, col2=City, col3=State, col4=Host(venue name), col5=Address, col6=Phone, col7=Contact, col12=Notes + const rawCity = String(row.getCell(2).value || "").trim(); + const rawState = String(row.getCell(3).value || "").trim(); + const rawName = String(row.getCell(4).value || "").trim(); + const rawAddress = String(row.getCell(5).value || "").trim(); + if (!rawCity || !rawName) return; + const key = `${rawName}|${rawCity}|${rawState}`; + if (seenLoc.has(key)) return; + seenLoc.add(key); + locations.push({ + name: rawName, + address: rawAddress || null, + city: rawCity, + state: rawState, + zip: null, + phone: String(row.getCell(6).value || "").trim() || null, + contact_name: String(row.getCell(7).value || "").trim() || null, + contact_email: null, + notes: String(row.getCell(12).value || "").trim() || null, + active: true, + }); + }); + } + console.log(`Parsed ${locations.length} locations`); + + // --- Stops from Full Schedule --- + const schedSheet = workbook.getWorksheet("Full Schedule"); + const stops = []; + const venueAddressMap = new Map(); + + if (locSheet) { + locSheet.eachRow((row, rowNum) => { + if (rowNum === 1) return; + const name = String(row.getCell(4).value || "").trim(); + const address = String(row.getCell(5).value || "").trim(); + if (name && address) venueAddressMap.set(name, address); + }); + } + + if (schedSheet) { + schedSheet.eachRow((row) => { + const rowValues = row.values || []; + // Column mapping (1-indexed, col1=null): + // col2=Wk, col3=Type, col4=Date, col5=Day, col6=City/Location, col7=Host/Venue, col8=Time, col9=Truck, col10=Status, col11=Notes + const firstCell = String(rowValues[1] || "").trim(); + // Skip title rows, week headers ("Wk 1"), OFF, Cross-Dock + if (!firstCell || /^Wk\s*\d+/i.test(firstCell) || firstCell === "OFF" || firstCell === "Cross-Dock") return; + + const dateStr = parseExcelDate(rowValues[3]); + if (!dateStr) return; + + const cityStateRaw = String(rowValues[5] || "").trim(); + const cityParts = cityStateRaw.split(",").map((s) => s.trim()); + const city = cityParts[0] || ""; + const state = cityParts[1] || ""; + const location = String(rowValues[6] || "").trim(); + if (!city || !state || !location) return; + + const rawTime = rowValues[7]; + const time = rawTime ? parseTimeRange(rawTime) : ""; + const truck = String(rowValues[8] || "").trim(); + const statusText = String(rowValues[9] || "").trim(); + const notesText = String(rowValues[10] || "").trim(); + + const venueAddress = venueAddressMap.get(location) || null; + const notes = [truck ? `Truck: ${truck}` : "", statusText, notesText].filter(Boolean).join(" | "); + + stops.push({ + name: `${location} - ${city}, ${state}`, + location, + address: venueAddress, + city, + state, + zip: null, + date: dateStr, + time, + cutoff_date: null, + status: "active", + is_public: true, + notes: notes || null, + }); + }); + } + console.log(`Parsed ${stops.length} stops`); + return { locations, stops }; +} + +async function seedLocations(locs) { + if (locs.length === 0) return; + await sql`DELETE FROM locations WHERE brand_id = ${TUXEDO_BRAND_ID}::uuid`; + for (const loc of locs) { + await sql`INSERT INTO locations (brand_id, name, address, city, state, zip, phone, contact_name, contact_email, notes, active) + VALUES (${TUXEDO_BRAND_ID}::uuid, ${loc.name}, ${loc.address}, ${loc.city}, ${loc.state}, ${loc.zip}, ${loc.phone}, ${loc.contact_name}, ${loc.contact_email}, ${loc.notes}, ${loc.active})`; + } + console.log(`Seeded ${locs.length} locations`); +} + +async function seedStops(stops) { + if (stops.length === 0) return; + const minDate = `${YEAR}-07-01`; + const maxDate = `${YEAR}-09-30`; + await sql`DELETE FROM stops WHERE brand_id = ${TUXEDO_BRAND_ID}::uuid AND date >= ${minDate} AND date <= ${maxDate}`; + for (const stop of stops) { + await sql`INSERT INTO stops (brand_id, name, location, address, city, state, zip, date, "time", cutoff_date, status, is_public, notes) + VALUES (${TUXEDO_BRAND_ID}::uuid, ${stop.name}, ${stop.location}, ${stop.address}, ${stop.city}, ${stop.state}, ${stop.zip}, ${stop.date}, ${stop.time}, ${stop.cutoff_date}, ${stop.status}, ${stop.is_public}, ${stop.notes})`; + } + console.log(`Seeded ${stops.length} stops`); +} + +async function main() { + const xlsxPath = path.join(__dirname, "..", "Tuxedo_Corn_2026_Tour_Schedule-3.xlsx"); + console.log("Parsing:", xlsxPath); + const { locations, stops } = await parseXlsx(xlsxPath); + if (locations.length === 0 && stops.length === 0) { + console.error("โŒ No data parsed from xlsx"); + process.exit(1); + } + console.log(`Seeding ${locations.length} locations + ${stops.length} stops for Tuxedo Corn...`); + await seedLocations(locations); + await seedStops(stops); + const locCount = await sql.query(`SELECT COUNT(*) FROM locations WHERE brand_id = '${TUXEDO_BRAND_ID}'`); + const stopCount = await sql.query(`SELECT COUNT(*) FROM stops WHERE brand_id = '${TUXEDO_BRAND_ID}'`); + console.log(`\nโœ… Done โ€” ${locCount[0].count} locations, ${stopCount[0].count} stops in DB`); +} + +main().catch((e) => { + console.error("โŒ Seed failed:", e.message); + process.exit(1); +}); \ No newline at end of file diff --git a/scripts/seed_tuxedo_tour.py b/scripts/seed_tuxedo_tour.py index f486b94..385f2aa 100644 --- a/scripts/seed_tuxedo_tour.py +++ b/scripts/seed_tuxedo_tour.py @@ -38,10 +38,7 @@ MONTH_MAP = { "Sep": "09", "Oct": "10", "Nov": "11", "Dec": "12", } -DEFAULT_XLSX = ( - "/home/coder/dev/x1/kyle/route_commerce-main/" - "Tuxedo_Corn_2026_Tour_Schedule-3.xlsx" -) +DEFAULT_XLSX = "Tuxedo_Corn_2026_Tour_Schedule-3.xlsx" # run from repo root; override with --xlsx /path/to/file.xlsx def parse_excel_date(s): diff --git a/src/app/admin/loading.tsx b/src/app/admin/loading.tsx index 5a4ffb2..f2886ac 100644 --- a/src/app/admin/loading.tsx +++ b/src/app/admin/loading.tsx @@ -1,46 +1,111 @@ -import LoadingSkeleton, { SkeletonCard, SkeletonTable } from "@/components/shared/LoadingSkeleton"; - export default function AdminLoading() { return ( -
-
- {/* Header skeleton */} -
+
+ {/* Header skeleton */} +
+
+
- - +
+
-
+
+
- {/* Stats cards skeleton */} -
- {[1, 2, 3, 4].map((i) => ( -
-
-
-
-
-
+ {/* Stats cards skeleton */} +
+ {[1, 2, 3, 4].map((i) => ( +
+
+
+
+
+
+
+
+
+ ))} +
+ + {/* Quick Actions + Usage skeleton */} +
+
+
+
+
+
+ {[1, 2, 3, 4].map((i) => ( +
+ ))} +
+
+
+
+
+
+
+
+ {[1, 2, 3].map((i) => ( +
+
+
+
+
+
+ ))} +
+
+
+ + {/* Recent orders skeleton */} +
+
+
+
+
+
+ {[1, 2, 3, 4, 5].map((i) => ( +
+
+
+
+
+
+
+
+
+
+
))}
+
- {/* Content cards skeleton */} -
- - - -
+ {/* Filter tabs skeleton */} +
+ {[1, 2, 3, 4].map((i) => ( +
+ ))} +
- {/* Table skeleton */} - + {/* Section cards skeleton */} +
+ {[1, 2, 3, 4, 5, 6].map((i) => ( +
+
+
+
+
+
+
+
+
+
+
+ ))}
); diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 037c6e0..acbb5ed 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -3,6 +3,7 @@ import { getAdminUser } from "@/lib/admin-permissions"; import { getActiveBrandId } from "@/lib/brand-scope"; import { isFeatureEnabled } from "@/lib/feature-flags"; import { getBillingOverview } from "@/actions/billing/billing-overview"; +import { getDashboardStats } from "@/actions/dashboard"; import DashboardClient from "@/components/admin/DashboardClient"; import { pool } from "@/lib/db"; @@ -122,6 +123,10 @@ export default async function AdminPage() { ); } + // Fetch dashboard stats server-side to eliminate client-side waterfall. + // Stats are now available immediately โ€” no "โ€”" placeholder flash. + const stats = await getDashboardStats(); + return ( ); } diff --git a/src/components/admin/DashboardClient.tsx b/src/components/admin/DashboardClient.tsx index 8a84449..bff5d90 100644 --- a/src/components/admin/DashboardClient.tsx +++ b/src/components/admin/DashboardClient.tsx @@ -1,10 +1,16 @@ "use client"; -import { useState, useEffect, type ReactNode } from "react"; +import { useState, type ReactNode } from "react"; import Link from "next/link"; -import UpgradePlanModal from "@/components/admin/UpgradePlanModal"; +import dynamic from "next/dynamic"; import { PageHeader, AdminButton, AdminFilterTabs, AdminBadge } from "@/components/admin/design-system"; -import { getDashboardStats, type DashboardStats } from "@/actions/dashboard"; +import type { DashboardStats } from "@/actions/dashboard"; + +// Lazy-load the upgrade modal โ€” only needed when starter tier + brandId present +const UpgradePlanModal = dynamic( + () => import("@/components/admin/UpgradePlanModal"), + { ssr: false } +); type Section = { title: string; @@ -17,112 +23,21 @@ type Section = { }; const sections: Section[] = [ - { - title: "Orders", - href: "/admin/orders", - description: "View orders, pickup status, fulfillment, and customer details.", - group: "operations", - prominent: true, - }, - { - title: "Products", - href: "/admin/products", - description: "Manage products, pricing, shipping type, and availability.", - group: "operations", - prominent: true, - }, - { - title: "Tours & Stops", - href: "/admin/stops", - description: "Manage routes, pickup locations, dates, and cutoff times.", - group: "fulfillment", - }, - { - title: "Driver Pickup", - href: "/admin/pickup", - description: "Mobile pickup lookup, QR scanning, and completion tools.", - group: "fulfillment", - }, - { - title: "Shipping", - href: "/admin/shipping", - description: "FedEx integration, label creation, and shipment tracking.", - group: "fulfillment", - }, - { - title: "Reports", - href: "/admin/reports", - description: "Sales, route, product, pickup, and customer reports.", - group: "management", - }, - { - title: "Tax Dashboard", - href: "/admin/taxes", - description: "Sales tax collected, breakdown by state, and exportable reports.", - group: "management", - }, - { - title: "Settings", - href: "/admin/settings", - description: "Users, billing, brand, integrations, payments, and shipping.", - group: "management", - }, - { - title: "Harvest Reach", - href: "/admin/communications", - description: "Email campaigns, stop blast, templates, and audience segments.", - group: "tools", - addonKey: "harvest_reach", - upgradeText: "Enable to access email & SMS marketing", - }, - { - title: "Wholesale Portal", - href: "/admin/wholesale", - description: "Standalone B2B portal with custom pricing, credit limits, and net-30.", - group: "tools", - addonKey: "wholesale_portal", - upgradeText: "Enable to unlock B2B buyer portal", - }, - { - title: "Import Center", - href: "/admin/import", - description: "AI-powered import for products, orders, contacts, and stops.", - group: "tools", - addonKey: "ai_tools", - upgradeText: "Enable AI import with smart column mapping", - }, - { - title: "AI Intelligence", - href: "/admin/settings/ai", - description: "Campaign writer, pricing advisor, and report explainer.", - group: "tools", - addonKey: "ai_tools", - upgradeText: "Enable AI tools for marketing and pricing", - }, - { - title: "Time Tracking", - href: "/admin/time-tracking", - description: "Worker clock-in/out, hours tracking, and overtime management.", - group: "tools", - addonKey: "time_tracking", - upgradeText: "Enable for field worker time tracking", - }, - { - title: "Water Log", - href: "/admin/water-log", - description: "Irrigation tracking and water usage reporting.", - group: "tools", - addonKey: "water_log", - upgradeText: "Enable for agricultural water tracking", - }, - { - title: "Route Trace", - href: "/admin/route-trace", - description: "Lot tracking, QR stickers, hauling board, and supply chain traceability.", - group: "tools", - addonKey: "route_trace", - upgradeText: "Enable for field-to-delivery traceability", - }, + { title: "Orders", href: "/admin/orders", description: "View orders, pickup status, fulfillment, and customer details.", group: "operations", prominent: true }, + { title: "Products", href: "/admin/products", description: "Manage products, pricing, shipping type, and availability.", group: "operations", prominent: true }, + { title: "Tours & Stops", href: "/admin/stops", description: "Manage routes, pickup locations, dates, and cutoff times.", group: "fulfillment" }, + { title: "Driver Pickup", href: "/admin/pickup", description: "Mobile pickup lookup, QR scanning, and completion tools.", group: "fulfillment" }, + { title: "Shipping", href: "/admin/shipping", description: "FedEx integration, label creation, and shipment tracking.", group: "fulfillment" }, + { title: "Reports", href: "/admin/reports", description: "Sales, route, product, pickup, and customer reports.", group: "management" }, + { title: "Tax Dashboard", href: "/admin/taxes", description: "Sales tax collected, breakdown by state, and exportable reports.", group: "management" }, + { title: "Settings", href: "/admin/settings", description: "Users, billing, brand, integrations, payments, and shipping.", group: "management" }, + { title: "Harvest Reach", href: "/admin/communications", description: "Email campaigns, stop blast, templates, and audience segments.", group: "tools", addonKey: "harvest_reach", upgradeText: "Enable to access email & SMS marketing" }, + { title: "Wholesale Portal", href: "/admin/wholesale", description: "Standalone B2B portal with custom pricing, credit limits, and net-30.", group: "tools", addonKey: "wholesale_portal", upgradeText: "Enable to unlock B2B buyer portal" }, + { title: "Import Center", href: "/admin/import", description: "AI-powered import for products, orders, contacts, and stops.", group: "tools", addonKey: "ai_tools", upgradeText: "Enable AI import with smart column mapping" }, + { title: "AI Intelligence", href: "/admin/settings/ai", description: "Campaign writer, pricing advisor, and report explainer.", group: "tools", addonKey: "ai_tools", upgradeText: "Enable AI tools for marketing and pricing" }, + { title: "Time Tracking", href: "/admin/time-tracking", description: "Worker clock-in/out, hours tracking, and overtime management.", group: "tools", addonKey: "time_tracking", upgradeText: "Enable for field worker time tracking" }, + { title: "Water Log", href: "/admin/water-log", description: "Irrigation tracking and water usage reporting.", group: "tools", addonKey: "water_log", upgradeText: "Enable for agricultural water tracking" }, + { title: "Route Trace", href: "/admin/route-trace", description: "Lot tracking, QR stickers, hauling board, and supply chain traceability.", group: "tools", addonKey: "route_trace", upgradeText: "Enable for field-to-delivery traceability" }, ]; type Tab = "operations" | "fulfillment" | "management" | "tools"; @@ -132,7 +47,7 @@ const TABS: { id: Tab; label: string; icon: ReactNode }[] = [ id: "operations", label: "Operations", icon: ( - + ), @@ -141,7 +56,7 @@ const TABS: { id: Tab; label: string; icon: ReactNode }[] = [ id: "fulfillment", label: "Fulfillment", icon: ( - + @@ -153,7 +68,7 @@ const TABS: { id: Tab; label: string; icon: ReactNode }[] = [ id: "management", label: "Management", icon: ( - + @@ -163,7 +78,7 @@ const TABS: { id: Tab; label: string; icon: ReactNode }[] = [ id: "tools", label: "Tools", icon: ( - + ), @@ -178,6 +93,7 @@ type Props = { enabledAddons: Record; usage: { users: number; stops_this_month: number; products: number }; limits: { max_users: number; max_stops_monthly: number; max_products: number }; + stats: DashboardStats; }; export default function DashboardClient({ @@ -188,26 +104,13 @@ export default function DashboardClient({ enabledAddons, usage, limits, + stats, }: Props) { const [activeTab, setActiveTab] = useState("operations"); const [isUpgradeOpen, setIsUpgradeOpen] = useState(false); - const [stats, setStats] = useState(null); - const [isLoadingStats, setIsLoadingStats] = useState(true); - useEffect(() => { - const loadStats = async () => { - setIsLoadingStats(true); - try { - const data = await getDashboardStats(); - setStats(data); - } catch (err) { - console.error("Failed to load stats:", err); - } finally { - setIsLoadingStats(false); - } - }; - loadStats(); - }, []); + // Stats are pre-fetched server-side โ€” no loading state needed. + // All values are guaranteed to be present before this component renders. const usagePct = { users: limits.max_users > 0 ? (usage.users / limits.max_users) * 100 : 0, @@ -217,15 +120,10 @@ export default function DashboardClient({ const tabSections = sections.filter((s) => s.group === activeTab); - // Format currency const formatCurrency = (amount: number) => { - return new Intl.NumberFormat("en-US", { - style: "currency", - currency: "USD", - }).format(amount); + return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(amount); }; - // Get status badge color const getStatusBadge = (status: string) => { const styles: Record = { pending: { bg: "var(--admin-warning-light)", text: "var(--admin-warning)" }, @@ -235,7 +133,6 @@ export default function DashboardClient({ return styles[status] || { bg: "var(--admin-bg)", text: "var(--admin-text-secondary)" }; }; - // Quick action buttons const quickActions = [ { label: "New Order", href: "/admin/orders?new=true", icon: "plus" }, { label: "Add Stop", href: "/admin/stops/new", icon: "map" }, @@ -246,10 +143,10 @@ export default function DashboardClient({ return (
{/* Page Header */} -
+
+ @@ -257,17 +154,14 @@ export default function DashboardClient({ } title="Admin Dashboard" - subtitle={`${brandName} Control Center`} + subtitle={brandName} actions={ -
- +
+ Billing โ†’ {planTier === "starter" && brandId && ( - setIsUpgradeOpen(true)} - size="md" - > + setIsUpgradeOpen(true)} size="sm"> Upgrade Plan )} @@ -277,338 +171,226 @@ export default function DashboardClient({ />
- {/* Content */} -
- {/* Stats Cards Row */} -
+ {/* Main Content */} +
+ + {/* โ”€โ”€ Stats Cards Row โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */} +
{/* Today's Orders */} -
-
-
- +
+
+
+
-
-

- Today's Orders -

-

- {isLoadingStats ? "โ€”" : stats?.todayOrders ?? 0} -

+
+ Today's Orders + {stats.todayOrders}
{/* Today's Revenue */} -
-
-
- +
+
+
+
-
-

- Today's Revenue -

-

- {isLoadingStats ? "โ€”" : formatCurrency(stats?.todayRevenue ?? 0)} -

+
+ Today's Revenue + {formatCurrency(stats.todayRevenue)}
{/* Pending Stops */} -
-
-
- +
+
+
+
-
-

- Pending Stops -

-

- {isLoadingStats ? "โ€”" : stats?.pendingStops ?? 0} -

+
+ Pending Stops + {stats.pendingStops}
- {/* Active Products โ€” uses plan-aware usage.products so this card - always matches the "Products 0/25" usage bar below and the - billing page's invoice/usage row. Previously this came from a - separate query (`active=eq.true` only) and could disagree with - the plan limit usage, producing e.g. "1 vs 0/25" in the same - dashboard. */} -
-
-
- + {/* Active Products */} +
+
+
+
-
-

- Active Products -

-

- {/* usage.products comes from the server-rendered prop (via - getBillingOverview), so it's available immediately and - is guaranteed to match the "Products X/25" usage bar - and the billing page. */} - {usage.products} -

+
+ Active Products + {usage.products}
- {/* Quick Actions + Recent Orders Row */} -
+ {/* โ”€โ”€ Quick Actions + Usage Row โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */} +
{/* Quick Actions */} -
-

- Quick Actions -

-
+
+
+ Quick Actions +
+
{quickActions.map((action) => ( -
+
{action.icon === "plus" && ( - + )} {action.icon === "map" && ( - + )} {action.icon === "package" && ( - + )} {action.icon === "mail" && ( - + )}
- - {action.label} - + {action.label} + + + ))}
- {/* Recent Orders */} -
-
-

- Recent Orders -

- - View all โ†’ - + {/* Usage Stats */} +
+
+
+ + {planTier.charAt(0).toUpperCase() + planTier.slice(1)} + + {brandId ? brandName : "All Brands"} +
+ + Manage โ†’ +
-
- {stats?.recentOrders && stats.recentOrders.length > 0 ? ( - stats.recentOrders.map((order) => { - const badge = getStatusBadge(order.status); - return ( -
-
-
- - - -
-
-

- {order.customer_name} -

-

- {order.created_at} -

-
+
+ {[ + { label: "Users", value: `${usage.users}/${limits.max_users}`, pct: usagePct.users, icon: "users" }, + { label: "Stops", value: `${usage.stops_this_month}/${limits.max_stops_monthly}`, pct: usagePct.stops, icon: "map" }, + { label: "Products", value: `${usage.products}/${limits.max_products}`, pct: usagePct.products, icon: "package" }, + ].map(({ label, value, pct }) => ( +
+
+ {label} + {value} +
+
+
90 ? "var(--admin-danger)" : pct > 75 ? "#f59e0b" : "var(--admin-accent)", + }} + /> +
+ {pct > 85 && ( + Near limit + )} +
+ ))} +
+
+
+ + {/* โ”€โ”€ Recent Orders โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */} +
+
+ Recent Orders + + View all โ†’ + +
+ {stats.recentOrders && stats.recentOrders.length > 0 ? ( +
+ {stats.recentOrders.slice(0, 6).map((order) => { + const badge = getStatusBadge(order.status); + return ( + +
+
+ + +
-
- - {formatCurrency(order.total)} - - - {order.status} - +
+ {order.customer_name} + {order.created_at}
- ); - }) - ) : ( -
- - - -

- No recent orders -

- - Create your first order โ†’ +
+ {formatCurrency(order.total)} + + {order.status} + +
-
- )} + ); + })}
-
+ ) : ( +
+ + + +

No recent orders

+ + Create your first order โ†’ + +
+ )}
- {/* Usage stats bar */} -
-
- - {planTier.charAt(0).toUpperCase() + planTier.slice(1)} Plan - - - {brandId ? brandName : "All Brands"} - -
-
- {[ - { label: "Users", value: `${usage.users}/${limits.max_users}`, pct: usagePct.users, icon: "users" }, - { label: "Stops", value: `${usage.stops_this_month}/${limits.max_stops_monthly}`, pct: usagePct.stops, icon: "map" }, - { label: "Products", value: `${usage.products}/${limits.max_products}`, pct: usagePct.products, icon: "package" }, - ].map(({ label, value, pct }) => ( -
-
-
- {label === "Users" && ( - - - - )} - {label === "Stops" && ( - - - - - )} - {label === "Products" && ( - - - - )} - {label} -
- {value} -
-
-
90 ? "var(--admin-danger)" : pct > 75 ? "#f59e0b" : "var(--admin-accent)" - }} - /> -
- {pct > 85 && ( -

- Near limit - consider upgrading -

- )} -
- ))} -
+ {/* โ”€โ”€ Section Navigation Tabs โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */} +
+ setActiveTab(value as Tab)} + tabs={TABS.map((tab) => ({ value: tab.id, label: tab.label, icon: tab.icon }))} + size="md" + showCounts={false} + />
- {/* Tab navigation */} - setActiveTab(value as Tab)} - tabs={TABS.map((tab) => ({ - value: tab.id, - label: tab.label, - icon: tab.icon, - }))} - size="md" - showCounts={false} - /> - - {/* Section Cards Grid */} -
+ {/* โ”€โ”€ Section Cards Grid โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */} +
{tabSections.map((section) => { if (section.title === "Water Log" && !isWaterLogVisible) return null; if (section.title === "Route Trace" && !enabledAddons["route_trace"]) return null; @@ -622,87 +404,64 @@ export default function DashboardClient({ key={section.title} href={section.href} className={[ - "group relative flex flex-col rounded-xl border p-5 transition-all hover:-translate-y-0.5 hover:shadow-md", - isAddon && !isEnabled - ? "border-stone-200 shadow-sm opacity-75 hover:opacity-100" - : isProminent - ? "border-[var(--admin-accent)]/20 shadow-[0_2px_8px_rgba(0,0,0,0.04)]" - : "border-stone-200 shadow-sm", - ].join(" ")} - style={{ backgroundColor: "var(--admin-card-bg)" }} + "admin-section-card", + isAddon && !isEnabled ? "admin-section-card--locked" : "", + isProminent ? "admin-section-card--prominent" : "", + ].filter(Boolean).join(" ")} > -
-
+
+
{section.title === "Orders" && ( - + )} {section.title === "Products" && ( - + )} {section.title === "Tours & Stops" && ( - + )} {section.title === "Driver Pickup" && ( - + )} {!["Orders", "Products", "Tours & Stops", "Driver Pickup"].includes(section.title) && ( - + )}
- {isAddon && !isEnabled && ( - - Add-on - - )} - {isAddon && isEnabled && ( - - Active - - )} - {isProminent && ( - - Core - - )} +
+ {isAddon && !isEnabled && Add-on} + {isAddon && isEnabled && Active} + {isProminent && Core} +
-

- {section.title} -

- -

- {section.description} -

+
+

{section.title}

+

+ {section.description} +

+
{isAddon && !isEnabled && section.upgradeText && ( -

- {section.upgradeText} -

+

{section.upgradeText}

)} - - {/* Arrow indicator */} -
- Open section - + +
+
@@ -712,7 +471,7 @@ export default function DashboardClient({
- {/* Upgrade Modal */} + {/* Upgrade Modal โ€” lazy-loaded via next/dynamic */} {planTier === "starter" && brandId && (