mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 09:50:01 +00:00
Add ACMCC app source, Supabase backend, and project config
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
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",
|
||||
};
|
||||
|
||||
Deno.serve(async (req) => {
|
||||
if (req.method === "OPTIONS") {
|
||||
return new Response(null, { headers: corsHeaders });
|
||||
}
|
||||
|
||||
try {
|
||||
const supabaseUrl = Deno.env.get("SUPABASE_URL")!;
|
||||
const serviceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!;
|
||||
const supabase = createClient(supabaseUrl, serviceKey);
|
||||
|
||||
const now = new Date();
|
||||
const in24h = new Date(now.getTime() + 24 * 60 * 60 * 1000);
|
||||
|
||||
// Find reminders due within 24 hours that haven't been notified recently
|
||||
const { data: reminders, error } = await supabase
|
||||
.from("reminders")
|
||||
.select("*")
|
||||
.neq("status", "completed")
|
||||
.lte("due_date", in24h.toISOString())
|
||||
.gte("due_date", now.toISOString());
|
||||
|
||||
if (error) throw error;
|
||||
if (!reminders || reminders.length === 0) {
|
||||
return new Response(JSON.stringify({ success: true, processed: 0 }), {
|
||||
headers: { ...corsHeaders, "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
// Filter out recently notified (within last 12 hours)
|
||||
const twelveHoursAgo = new Date(now.getTime() - 12 * 60 * 60 * 1000);
|
||||
const dueReminders = reminders.filter((r: any) => {
|
||||
if (!r.last_notified_at) return true;
|
||||
return new Date(r.last_notified_at) < twelveHoursAgo;
|
||||
});
|
||||
|
||||
// Get active SMTP sender
|
||||
const { data: senders } = await supabase
|
||||
.from("email_senders")
|
||||
.select("*")
|
||||
.eq("is_active", true)
|
||||
.eq("verified", true)
|
||||
.limit(1);
|
||||
|
||||
const sender = senders?.[0];
|
||||
|
||||
let processed = 0;
|
||||
|
||||
for (const reminder of dueReminders) {
|
||||
const userId = reminder.assigned_to || reminder.created_by;
|
||||
if (!userId) continue;
|
||||
|
||||
// Create in-app notification
|
||||
await supabase.rpc("insert_notification", {
|
||||
p_user_id: userId,
|
||||
p_type: "reminder_due",
|
||||
p_title: "Reminder Due Soon",
|
||||
p_message: `"${reminder.title}" is due ${new Date(reminder.due_date).toLocaleString()}.`,
|
||||
p_related_item_type: "reminder",
|
||||
p_link: "/dashboard/settings/reminders",
|
||||
});
|
||||
|
||||
// Send email if SMTP is configured
|
||||
if (sender) {
|
||||
try {
|
||||
const { data: userData } = await supabase.auth.admin.getUserById(userId);
|
||||
if (userData?.user?.email) {
|
||||
const senderFrom = sender.sender_name
|
||||
? `${sender.sender_name} <${sender.email_address}>`
|
||||
: sender.email_address;
|
||||
|
||||
await supabase.functions.invoke("send-smtp-email", {
|
||||
body: {
|
||||
sender: {
|
||||
host: sender.smtp_host,
|
||||
port: sender.smtp_port,
|
||||
username: sender.smtp_username,
|
||||
password: sender.smtp_password,
|
||||
use_tls: sender.use_tls,
|
||||
use_ssl: sender.use_ssl,
|
||||
from: senderFrom,
|
||||
},
|
||||
recipient: [userData.user.email],
|
||||
subject: `Reminder Due: ${reminder.title}`,
|
||||
body: `<h3>Reminder Due Soon</h3><p>Your reminder "<strong>${reminder.title}</strong>" is due on ${new Date(reminder.due_date).toLocaleString()}.</p>${reminder.description ? `<p>${reminder.description}</p>` : ""}<p>Please log in to the portal to manage your reminders.</p>`,
|
||||
html: `<h3>Reminder Due Soon</h3><p>Your reminder "<strong>${reminder.title}</strong>" is due on ${new Date(reminder.due_date).toLocaleString()}.</p>${reminder.description ? `<p>${reminder.description}</p>` : ""}<p>Please log in to the portal to manage your reminders.</p>`,
|
||||
debug: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch (emailErr) {
|
||||
console.error(`Failed to send email for reminder ${reminder.id}:`, emailErr);
|
||||
}
|
||||
}
|
||||
|
||||
// Update last_notified_at
|
||||
await supabase
|
||||
.from("reminders")
|
||||
.update({ last_notified_at: now.toISOString() })
|
||||
.eq("id", reminder.id);
|
||||
|
||||
processed++;
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({ success: true, processed }), {
|
||||
headers: { ...corsHeaders, "Content-Type": "application/json" },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("check-reminder-emails error:", error);
|
||||
return new Response(JSON.stringify({ success: false, error: (error as Error).message }), {
|
||||
status: 500,
|
||||
headers: { ...corsHeaders, "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user