Add ACMCC app source, Supabase backend, and project config

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 20:19:26 -04:00
parent 313b51b412
commit 183fe0a93c
1422 changed files with 259271 additions and 0 deletions
@@ -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" },
});
}
});