212 lines
6.9 KiB
TypeScript
212 lines
6.9 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";
|
|
import { EmailTemplateRenderer } from "../shared/email-template-renderer.ts";
|
|
|
|
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
|
|
// Get notification template and settings to send via send-email-v2
|
|
const { data: template } = await supabase
|
|
.from("notification_templates")
|
|
.select("*")
|
|
.eq("key", "consulting_reminder")
|
|
.eq("is_active", true)
|
|
.single();
|
|
|
|
const { data: emailSettings } = await supabase
|
|
.from("notification_settings")
|
|
.select("*")
|
|
.single();
|
|
|
|
// Get platform settings for brand_name
|
|
const { data: platformSettings } = await supabase
|
|
.from("platform_settings")
|
|
.select("brand_name")
|
|
.single();
|
|
|
|
const brandName = platformSettings?.brand_name || "ACCESS HUB";
|
|
|
|
let notifyError = null;
|
|
|
|
if (template && emailSettings?.api_token) {
|
|
// Build payload with proper shortcode mapping
|
|
const payload = {
|
|
nama: profile.full_name,
|
|
email: profile.email,
|
|
tanggal_konsultasi: new Date(slot.date).toLocaleDateString('id-ID', {
|
|
weekday: 'long',
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric'
|
|
}),
|
|
jam_konsultasi: `${slot.start_time.substring(0, 5)} - ${slot.end_time.substring(0, 5)} WIB`,
|
|
link_meet: slot.meet_link || "Akan diinformasikan",
|
|
jenis_konsultasi: slot.topic_category,
|
|
platform_name: brandName,
|
|
};
|
|
|
|
// Process shortcodes in template
|
|
let emailBody = template.email_body_html || "";
|
|
let emailSubject = template.email_subject || "Reminder Konsultasi";
|
|
|
|
Object.entries(payload).forEach(([key, value]) => {
|
|
const regex = new RegExp(`\\{${key}\\}`, "g");
|
|
emailBody = emailBody.replace(regex, String(value));
|
|
emailSubject = emailSubject.replace(regex, String(value));
|
|
});
|
|
|
|
// Wrap with master template
|
|
const fullHtml = EmailTemplateRenderer.render({
|
|
subject: emailSubject,
|
|
content: emailBody,
|
|
brandName: brandName,
|
|
});
|
|
|
|
// Send via send-email-v2 (Mailketing API)
|
|
const { error: emailError } = await supabase.functions.invoke("send-email-v2", {
|
|
body: {
|
|
recipient: profile.email,
|
|
api_token: emailSettings.api_token,
|
|
from_name: emailSettings.from_name || brandName,
|
|
from_email: emailSettings.from_email || "noreply@with.dwindi.com",
|
|
subject: emailSubject,
|
|
content: fullHtml,
|
|
},
|
|
});
|
|
|
|
notifyError = emailError;
|
|
} else {
|
|
notifyError = { message: "Template not active or email not configured" };
|
|
}
|
|
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" } }
|
|
);
|
|
}
|
|
});
|