The sell-car-for-scrap pages allow users to submit their vehicles for scrap and connect with scrapyard suppliers.
src/pages/sell-car-for-scrap.astro - Main landing page with formsrc/pages/sell-car-for-scrap/[region].astro - Region-specific pages (9 provinces)src/pages/sell-car-for-scrap/[city].astro - City-specific pages (100+ cities)src/components/CarSellForm.tsx - Main form for scrap car submissionssrc/components/RecentScrapCarEnquiries.astro - Live feed of recent scrap car leads (enabled on all pages)src/pages/api/sell-car.ts - Handles scrap car form submissions (uses admin Supabase client for RLS bypass)src/pages/api/scrap-car-leads.ts - Fetches paginated scrap car leads for the live feedThe sell-car.ts API uses getAdminSupabase() (service role) for database inserts to bypass RLS policies. This is necessary because server-side API routes don’t have proper anonymous session context for RLS policies.
RLS Policies (Dec 2024): Multiple INSERT policies exist as fallbacks:
public role - covers everyoneauthenticated role - explicit fallbackanon role - anonymous usersservice_role - admin bypassThis belt-and-suspenders approach ensures inserts work regardless of how Vercel/Supabase recognizes the client role.
Photos uploaded via the form go through validation:
Fix (Dec 2024): Email attachments now filter out empty/corrupt images (< 1KB decoded) to prevent empty JPG files appearing in supplier emails.
Fix (Jan 2025): Mobile Browser GC Issue
Photos were arriving as empty attachments on mobile browsers because File objects can lose their blob data if there’s a delay between file selection and form submission (browser garbage collection).
Solution: Photos are now converted to base64 immediately when selected (not at submission time):
StoredPhoto interface: {filename, content, previewUrl}fileToStoredPhoto() helper reads files to base64 on selectionhandleSubmit() uses pre-stored base64 dataConsole logging: Photos now log size on selection:
Successfully stored photo: 1000001744.jpg (847293 base64 chars)
If you see “Skipping empty or invalid attachment” in server logs, the fix isn’t deployed or there’s a different issue.
Added: Dec 2024
iPhones save photos in HEIC/HEIF format by default, which has poor browser/email compatibility. The form now:
.heic, .heif extensionsheic2any library for client-side conversionSupported formats:
Troubleshooting:
The API now matches frontend validation - at least one contact method is required (email OR phone):
| Field | Required | Notes |
|---|---|---|
| Vehicle Make | Yes | Always required |
| No* | Optional if phone provided | |
| Phone | No* | Optional if email provided |
| Full Name | Yes | Required (validated on frontend) |
| City | Yes | Required (validated on frontend) |
*At least ONE contact method must be provided.
Backend behavior when no email:
info@enginefinder.co.za insteademail: nullscrap_car_leadsStores all scrap car enquiries submitted through the form.
Key columns:
id - UUID primary keymake - Vehicle make (required)model - Vehicle modelyear - Vehicle yearcity - Location (required)condition_notes - Description of vehicle conditionphotos - Array of image URLs (stored in Supabase Storage)created_at - Submission timestamp-- Count leads with photos (photos is JSONB)
SELECT COUNT(*) FROM scrap_car_leads
WHERE photos IS NOT NULL AND jsonb_array_length(photos) > 0;
-- Get recent leads with images
SELECT id, make, model, year, city, photos, created_at
FROM scrap_car_leads
WHERE photos IS NOT NULL AND jsonb_array_length(photos) > 0
ORDER BY created_at DESC
LIMIT 12;
-- Check total leads
SELECT COUNT(*) FROM scrap_car_leads;
-- Find leads with broken image URLs (old Supabase project)
SELECT id, make, model, city FROM scrap_car_leads
WHERE photos::text LIKE '%bjywqecxfbuxlachkzia%';
Status: ENABLED (as of Dec 2024)
The RecentScrapCarEnquiries component displays recent scrap car enquiries with:
/logos/large/{make-slug}.png-- Fetch all recent leads (with or without photos)
SELECT * FROM scrap_car_leads
WHERE make IS NOT NULL
AND city IS NOT NULL
AND city NOT ILIKE '%test%'
ORDER BY created_at DESC
LIMIT 12;
The component filters out:
Some older leads may have photos pointing to a previous Supabase project (bjywqecxfbuxlachkzia.supabase.co) instead of the current one (hytuuxolxmlqntgpudcd.supabase.co). These images are inaccessible.
Fix: Clear the photos array for affected leads:
UPDATE scrap_car_leads
SET photos = '[]'::jsonb
WHERE photos::text LIKE '%bjywqecxfbuxlachkzia%';
Updated Dec 2024: Changed from infinite-scroll carousel to a responsive grid to eliminate duplicate display issues.
The page displays a grid of scrapyard suppliers from the suppliers table:
status = 'active', main_category = 'scrapyard', rating >= 3.6The page includes a callout section linking to /scrap-car-leads-service/ for scrapyards wanting to purchase leads.
src/components/supplier-admin/CLAUDE.md - Suppliers view scrap car leads heresupabase/CLAUDE.md - RLS policies for scrap_car_leads tablesrc/pages/admin/CLAUDE.md - Admin tracking and analyticsBefore modifying any files in this feature:
subagent_type: "general-purpose"