From 3afa0a5536e94f560208dcee615215d4bf32ad54 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 23:30:06 +0000 Subject: [PATCH] feat: Enhance notification payloads --- .../notify-user-submission-status/index.ts | 119 +++++++++++++++--- ...2_2a846dc3-4852-440a-a09e-469eeb980fff.sql | 48 +++++++ 2 files changed, 152 insertions(+), 15 deletions(-) create mode 100644 supabase/migrations/20251021232852_2a846dc3-4852-440a-a09e-469eeb980fff.sql diff --git a/supabase/functions/notify-user-submission-status/index.ts b/supabase/functions/notify-user-submission-status/index.ts index 110ed256..e93a7351 100644 --- a/supabase/functions/notify-user-submission-status/index.ts +++ b/supabase/functions/notify-user-submission-status/index.ts @@ -12,7 +12,77 @@ interface RequestBody { user_id: string; submission_type: string; status: 'approved' | 'rejected'; - rejection_reason?: string; + reviewer_notes?: string; +} + +async function constructEntityURL( + supabase: any, + submissionType: string, + itemData: any +): Promise { + const baseURL = 'https://www.thrillwiki.com'; + + if (submissionType === 'park') { + const parkSlug = itemData.slug; + return `${baseURL}/parks/${parkSlug}`; + } + + if (submissionType === 'ride') { + const rideSlug = itemData.slug; + const parkId = itemData.park_id; + + if (!parkId) { + return `${baseURL}/rides/${rideSlug}`; + } + + // Fetch park slug + const { data: park } = await supabase + .from('parks') + .select('slug') + .eq('id', parkId) + .maybeSingle(); + + const parkSlug = park?.slug || 'unknown'; + return `${baseURL}/parks/${parkSlug}/rides/${rideSlug}`; + } + + if (submissionType === 'company') { + const companySlug = itemData.slug; + const companyType = itemData.company_type; + + if (companyType === 'manufacturer') { + return `${baseURL}/manufacturers/${companySlug}`; + } else if (companyType === 'operator') { + return `${baseURL}/operators/${companySlug}`; + } else if (companyType === 'property_owner') { + return `${baseURL}/owners/${companySlug}`; + } else if (companyType === 'designer') { + return `${baseURL}/designers/${companySlug}`; + } + return `${baseURL}/companies/${companySlug}`; + } + + if (submissionType === 'ride_model') { + const modelSlug = itemData.slug; + const manufacturerId = itemData.manufacturer_id; + + if (!manufacturerId) { + return `${baseURL}/models/${modelSlug}`; + } + + // Fetch manufacturer slug + const { data: manufacturer } = await supabase + .from('companies') + .select('slug') + .eq('id', manufacturerId) + .eq('company_type', 'manufacturer') + .maybeSingle(); + + const manufacturerSlug = manufacturer?.slug || 'unknown'; + return `${baseURL}/manufacturers/${manufacturerSlug}/models/${modelSlug}`; + } + + return `${baseURL}`; } serve(async (req) => { @@ -28,9 +98,9 @@ serve(async (req) => { const supabase = createClient(supabaseUrl, supabaseServiceKey); - const { submission_id, user_id, submission_type, status, rejection_reason } = await req.json() as RequestBody; + const { submission_id, user_id, submission_type, status, reviewer_notes } = await req.json() as RequestBody; - // Fetch submission items to get entity name + // Fetch submission items to get entity data const { data: items, error: itemsError } = await supabase .from('submission_items') .select('item_data') @@ -43,21 +113,40 @@ serve(async (req) => { throw new Error(`Failed to fetch submission items: ${itemsError.message}`); } - // Extract entity name from item_data - const entityName = items?.item_data?.name || 'your submission'; - const entityType = submission_type.replace('_', ' '); + if (!items || !items.item_data) { + throw new Error('No submission items found'); + } - // Determine workflow and build payload + // Extract entity data + const entityName = items.item_data.name || 'your submission'; + const entityType = submission_type.replace('_', ' '); + + // Construct entity URL + const entityURL = await constructEntityURL(supabase, submission_type, items.item_data); + + // Determine workflow and build payload based on status const workflowId = status === 'approved' ? 'submission-approved' : 'submission-rejected'; - const payload: Record = { - entityName, - entityType, - submissionId: submission_id, - }; - - if (status === 'rejected' && rejection_reason) { - payload.rejectionReason = rejection_reason; + let payload: Record; + + if (status === 'approved') { + // Approval payload + payload = { + entityType, + entityName, + submissionId: submission_id, + entityURL, + moderationNotes: reviewer_notes || '', + }; + } else { + // Rejection payload + payload = { + rejectionReason: reviewer_notes || 'No reason provided', + entityType, + entityName, + entityURL, + actualStatus: 'rejected', + }; } console.log('Sending notification to user:', { diff --git a/supabase/migrations/20251021232852_2a846dc3-4852-440a-a09e-469eeb980fff.sql b/supabase/migrations/20251021232852_2a846dc3-4852-440a-a09e-469eeb980fff.sql new file mode 100644 index 00000000..fe1a6bab --- /dev/null +++ b/supabase/migrations/20251021232852_2a846dc3-4852-440a-a09e-469eeb980fff.sql @@ -0,0 +1,48 @@ +-- Update trigger function to pass reviewer notes properly +CREATE OR REPLACE FUNCTION public.notify_user_on_submission_status_change() +RETURNS TRIGGER +LANGUAGE plpgsql +SECURITY DEFINER +SET search_path TO 'public' +AS $function$ +DECLARE + function_url text; + anon_key text; +BEGIN + -- Only notify on status changes to approved or rejected + IF OLD.status IS DISTINCT FROM NEW.status AND NEW.status IN ('approved', 'rejected') THEN + + -- Build the function URL + function_url := 'https://ydvtmnrszybqnbcqbdcy.supabase.co/functions/v1/notify-user-submission-status'; + + -- Use the public anon key + anon_key := 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InlkdnRtbnJzenlicW5iY3FiZGN5Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTgzMjYzNTYsImV4cCI6MjA3MzkwMjM1Nn0.DM3oyapd_omP5ZzIlrT0H9qBsiQBxBRgw2tYuqgXKX4'; + + -- Call edge function asynchronously with reviewer_notes + PERFORM net.http_post( + url := function_url, + headers := jsonb_build_object( + 'Content-Type', 'application/json', + 'Authorization', 'Bearer ' || anon_key, + 'apikey', anon_key + ), + body := jsonb_build_object( + 'submission_id', NEW.id, + 'user_id', NEW.user_id, + 'submission_type', NEW.submission_type, + 'status', NEW.status, + 'reviewer_notes', COALESCE(NEW.reviewer_notes, '') + ) + ); + + RAISE LOG 'Triggered user notification for submission % with status %', NEW.id, NEW.status; + END IF; + + RETURN NEW; +EXCEPTION + WHEN OTHERS THEN + -- Log error but don't fail the status update + RAISE WARNING 'Failed to notify user about submission status: %', SQLERRM; + RETURN NEW; +END; +$function$; \ No newline at end of file