Files
meet-hub/supabase/functions/daily-reminders/index.ts
gpt-engineer-app[bot] e569c2cf7e Changes
2025-12-19 16:02:31 +00:00

139 lines
4.2 KiB
TypeScript

import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
};
interface ConsultingSlot {
id: string;
date: string;
start_time: string;
end_time: string;
topic_category: string;
meet_link: string | null;
user_id: string;
profiles: {
full_name: string;
email: string;
};
}
serve(async (req: Request): Promise<Response> => {
if (req.method === "OPTIONS") {
return new Response(null, { headers: corsHeaders });
}
try {
const supabaseUrl = Deno.env.get("SUPABASE_URL")!;
const supabaseKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!;
const supabase = createClient(supabaseUrl, supabaseKey);
// Get tomorrow's date
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const tomorrowStr = tomorrow.toISOString().split('T')[0];
console.log(`Checking consultations for: ${tomorrowStr}`);
// Get confirmed consulting slots for tomorrow
const { data: slots, error } = await supabase
.from("consulting_slots")
.select(`
id,
date,
start_time,
end_time,
topic_category,
meet_link,
user_id,
profiles:user_id (full_name, email)
`)
.eq("date", tomorrowStr)
.eq("status", "confirmed");
if (error) {
console.error("Error fetching slots:", error);
throw error;
}
console.log(`Found ${slots?.length || 0} consultations for tomorrow`);
const results: { email: string; success: boolean; error?: string }[] = [];
// Send reminder to each client
for (const slot of (slots || []) as any[]) {
try {
const profile = slot.profiles;
if (!profile?.email) continue;
// Call send-notification function
const { error: notifyError } = await supabase.functions.invoke("send-notification", {
body: {
template_key: "consultation_reminder",
recipient_email: profile.email,
recipient_name: profile.full_name,
variables: {
consultation_date: new Date(slot.date).toLocaleDateString('id-ID', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
}),
consultation_time: `${slot.start_time.substring(0, 5)} - ${slot.end_time.substring(0, 5)}`,
topic_category: slot.topic_category,
meet_link: slot.meet_link || "Link akan dikirim segera",
},
},
});
results.push({
email: profile.email,
success: !notifyError,
error: notifyError?.message,
});
console.log(`Reminder sent to ${profile.email}: ${notifyError ? 'FAILED' : 'SUCCESS'}`);
} catch (err: any) {
results.push({
email: slot.profiles?.email || "unknown",
success: false,
error: err.message,
});
}
}
// Get platform settings for admin digest
const { data: settings } = await supabase
.from("platform_settings")
.select("smtp_from_email")
.single();
// Send digest to admin if there are consultations
if (slots && slots.length > 0 && settings?.smtp_from_email) {
const slotsList = (slots as any[])
.map(s => `- ${s.start_time?.substring(0, 5)}: ${s.profiles?.full_name || 'N/A'} (${s.topic_category})`)
.join('\n');
console.log(`Admin digest: ${slots.length} consultations tomorrow`);
// Could send admin digest here
}
return new Response(
JSON.stringify({
success: true,
message: `Processed ${results.length} reminders`,
results
}),
{ status: 200, headers: { ...corsHeaders, "Content-Type": "application/json" } }
);
} catch (error: any) {
console.error("Error in daily reminders:", error);
return new Response(
JSON.stringify({ success: false, message: error.message }),
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
);
}
});