mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 08:51:13 -05:00
feat: Enhance notification payloads
This commit is contained in:
@@ -12,7 +12,77 @@ interface RequestBody {
|
|||||||
user_id: string;
|
user_id: string;
|
||||||
submission_type: string;
|
submission_type: string;
|
||||||
status: 'approved' | 'rejected';
|
status: 'approved' | 'rejected';
|
||||||
rejection_reason?: string;
|
reviewer_notes?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function constructEntityURL(
|
||||||
|
supabase: any,
|
||||||
|
submissionType: string,
|
||||||
|
itemData: any
|
||||||
|
): Promise<string> {
|
||||||
|
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) => {
|
serve(async (req) => {
|
||||||
@@ -28,9 +98,9 @@ serve(async (req) => {
|
|||||||
|
|
||||||
const supabase = createClient(supabaseUrl, supabaseServiceKey);
|
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
|
const { data: items, error: itemsError } = await supabase
|
||||||
.from('submission_items')
|
.from('submission_items')
|
||||||
.select('item_data')
|
.select('item_data')
|
||||||
@@ -43,21 +113,40 @@ serve(async (req) => {
|
|||||||
throw new Error(`Failed to fetch submission items: ${itemsError.message}`);
|
throw new Error(`Failed to fetch submission items: ${itemsError.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract entity name from item_data
|
if (!items || !items.item_data) {
|
||||||
const entityName = items?.item_data?.name || 'your submission';
|
throw new Error('No submission items found');
|
||||||
const entityType = submission_type.replace('_', ' ');
|
}
|
||||||
|
|
||||||
// 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 workflowId = status === 'approved' ? 'submission-approved' : 'submission-rejected';
|
||||||
|
|
||||||
const payload: Record<string, string> = {
|
let payload: Record<string, string>;
|
||||||
entityName,
|
|
||||||
entityType,
|
if (status === 'approved') {
|
||||||
submissionId: submission_id,
|
// Approval payload
|
||||||
};
|
payload = {
|
||||||
|
entityType,
|
||||||
if (status === 'rejected' && rejection_reason) {
|
entityName,
|
||||||
payload.rejectionReason = rejection_reason;
|
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:', {
|
console.log('Sending notification to user:', {
|
||||||
|
|||||||
@@ -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$;
|
||||||
Reference in New Issue
Block a user