mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 03:11:12 -05:00
Implement user notifications
This commit is contained in:
128
supabase/functions/notify-user-submission-status/index.ts
Normal file
128
supabase/functions/notify-user-submission-status/index.ts
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
|
||||||
|
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
|
||||||
|
import { startRequest, endRequest } from "../_shared/logger.ts";
|
||||||
|
|
||||||
|
const corsHeaders = {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type, x-request-id',
|
||||||
|
};
|
||||||
|
|
||||||
|
interface RequestBody {
|
||||||
|
submission_id: string;
|
||||||
|
user_id: string;
|
||||||
|
submission_type: string;
|
||||||
|
status: 'approved' | 'rejected';
|
||||||
|
rejection_reason?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
serve(async (req) => {
|
||||||
|
if (req.method === 'OPTIONS') {
|
||||||
|
return new Response(null, { headers: corsHeaders });
|
||||||
|
}
|
||||||
|
|
||||||
|
const tracking = startRequest('notify-user-submission-status');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const supabaseUrl = Deno.env.get('SUPABASE_URL')!;
|
||||||
|
const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
|
||||||
|
|
||||||
|
const supabase = createClient(supabaseUrl, supabaseServiceKey);
|
||||||
|
|
||||||
|
const { submission_id, user_id, submission_type, status, rejection_reason } = await req.json() as RequestBody;
|
||||||
|
|
||||||
|
// Fetch submission items to get entity name
|
||||||
|
const { data: items, error: itemsError } = await supabase
|
||||||
|
.from('submission_items')
|
||||||
|
.select('item_data')
|
||||||
|
.eq('submission_id', submission_id)
|
||||||
|
.order('order_index', { ascending: true })
|
||||||
|
.limit(1)
|
||||||
|
.maybeSingle();
|
||||||
|
|
||||||
|
if (itemsError) {
|
||||||
|
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('_', ' ');
|
||||||
|
|
||||||
|
// Determine workflow and build payload
|
||||||
|
const workflowId = status === 'approved' ? 'submission-approved' : 'submission-rejected';
|
||||||
|
|
||||||
|
const payload: Record<string, string> = {
|
||||||
|
entityName,
|
||||||
|
entityType,
|
||||||
|
submissionId: submission_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (status === 'rejected' && rejection_reason) {
|
||||||
|
payload.rejectionReason = rejection_reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Sending notification to user:', {
|
||||||
|
userId: user_id,
|
||||||
|
workflowId,
|
||||||
|
entityName,
|
||||||
|
status,
|
||||||
|
requestId: tracking.requestId
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call trigger-notification function
|
||||||
|
const { data: notificationResult, error: notificationError } = await supabase.functions.invoke(
|
||||||
|
'trigger-notification',
|
||||||
|
{
|
||||||
|
body: {
|
||||||
|
workflowId,
|
||||||
|
subscriberId: user_id,
|
||||||
|
payload,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (notificationError) {
|
||||||
|
throw new Error(`Failed to trigger notification: ${notificationError.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('User notification sent successfully:', notificationResult);
|
||||||
|
|
||||||
|
endRequest(tracking, 200);
|
||||||
|
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
transactionId: notificationResult?.transactionId,
|
||||||
|
requestId: tracking.requestId
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
...corsHeaders,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Request-ID': tracking.requestId
|
||||||
|
},
|
||||||
|
status: 200,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (error: unknown) {
|
||||||
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
||||||
|
console.error('Error notifying user about submission status:', errorMessage);
|
||||||
|
|
||||||
|
endRequest(tracking, 500, errorMessage);
|
||||||
|
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
success: false,
|
||||||
|
error: errorMessage,
|
||||||
|
requestId: tracking.requestId
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
...corsHeaders,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Request-ID': tracking.requestId
|
||||||
|
},
|
||||||
|
status: 500,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
-- Add notification templates for user submission status notifications
|
||||||
|
INSERT INTO notification_templates (workflow_id, novu_workflow_id, name, description, category, is_active)
|
||||||
|
VALUES
|
||||||
|
('submission-approved', 'submission-approved', 'Submission Approved', 'Notify users when their submission is approved', 'submission', true),
|
||||||
|
('submission-rejected', 'submission-rejected', 'Submission Rejected', 'Notify users when their submission is rejected', 'submission', true)
|
||||||
|
ON CONFLICT (workflow_id) DO NOTHING;
|
||||||
|
|
||||||
|
-- Function to notify users when submission status changes
|
||||||
|
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
|
||||||
|
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,
|
||||||
|
'rejection_reason', 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$;
|
||||||
|
|
||||||
|
-- Create trigger on content_submissions
|
||||||
|
DROP TRIGGER IF EXISTS notify_user_on_submission_status_change_trigger ON content_submissions;
|
||||||
|
CREATE TRIGGER notify_user_on_submission_status_change_trigger
|
||||||
|
AFTER UPDATE ON content_submissions
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION notify_user_on_submission_status_change();
|
||||||
Reference in New Issue
Block a user