diff --git a/supabase/functions/send-reminders/index.ts b/supabase/functions/send-reminders/index.ts index b582e3d..226c2b2 100644 --- a/supabase/functions/send-reminders/index.ts +++ b/supabase/functions/send-reminders/index.ts @@ -8,24 +8,21 @@ const corsHeaders = { } serve(async (req) => { - // Gestione CORS per sicurezza if (req.method === 'OPTIONS') { return new Response('ok', { headers: corsHeaders }) } try { - // 1. Inizializziamo il client Supabase con i poteri di Service Role (per scavalcare le RLS) + // 1. Client Supabase (Service Role) const supabaseClient = createClient( Deno.env.get('SUPABASE_URL') ?? '', Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '' ) - // 2. Recuperiamo la chiave di Firebase dai Secrets + // 2. Setup Firebase (Push) const firebaseSecret = Deno.env.get('FIREBASE_SERVICE_ACCOUNT') if (!firebaseSecret) throw new Error('Missing FIREBASE_SERVICE_ACCOUNT secret') const credentials = JSON.parse(firebaseSecret) - - // 3. Prepariamo l'autenticazione OAuth2 per Firebase HTTP v1 const jwtClient = new JWT({ email: credentials.client_email, key: credentials.private_key, @@ -34,68 +31,94 @@ serve(async (req) => { const tokens = await jwtClient.getAccessToken() const fcmAccessToken = tokens.token - // 4. Selezioniamo i reminder da inviare (trigger_at passato e non ancora inviati) + // 3. Setup Resend (Email) + const resendApiKey = Deno.env.get('RESEND_API_KEY') + if (!resendApiKey) throw new Error('Missing RESEND_API_KEY secret') + + // 4. Recupero Promemoria (TUTTI i canali, non ancora inviati) const { data: reminders, error: fetchError } = await supabaseClient .from('task_reminders') - .select('id, task_id, staff_id, channel, tasks(title, description)') - .eq('channel', 'push') + .select(` + id, task_id, staff_id, channel, + tasks(title, description), + staff_members(email, first_name) + `) .eq('is_sent', false) .lte('trigger_at', new Date().toISOString()) if (fetchError) throw fetchError if (!reminders || reminders.length === 0) { - return new Response(JSON.stringify({ message: 'Nessun promemoria push da inviare.' }), { + return new Response(JSON.stringify({ message: 'Nessun promemoria da inviare.' }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 200, }) } - // 5. Ciclo sui promemoria per raccogliere i token ed inviare + // 5. Smistamento ed Invio for (const reminder of reminders) { const taskTitle = reminder.tasks?.title || 'Nuovo Task!'; - const taskBody = reminder.tasks?.description || 'Hai un task da completare.'; + const taskBody = reminder.tasks?.description || 'Hai un task in scadenza.'; + const staffEmail = reminder.staff_members?.email; + const staffName = reminder.staff_members?.first_name || 'Staff'; - // Preleviamo tutti i dispositivi registrati per questo specifico membro dello staff - const { data: devices } = await supabaseClient - .from('staff_devices') - .select('fcm_token') - .eq('staff_id', reminder.staff_id) + if (reminder.channel === 'push') { + // --- LOGICA PUSH --- + const { data: devices } = await supabaseClient + .from('staff_devices') + .select('fcm_token') + .eq('staff_id', reminder.staff_id) - if (devices && devices.length > 0) { - // Spediamo la notifica a OGNI dispositivo associato all'utente - for (const device of devices) { - try { - await fetch( - `https://fcm.googleapis.com/v1/projects/${credentials.project_id}/messages:send`, - { - method: 'POST', - headers: { - 'Authorization': `Bearer ${fcmAccessToken}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - message: { - token: device.fcm_token, - notification: { - title: taskTitle, - body: taskBody, - }, - data: { - click_action: 'FLUTTER_NOTIFICATION_CLICK', - taskId: reminder.task_id, // Fondamentale per far scattare il Deep Link all'apertura! - }, + if (devices && devices.length > 0) { + for (const device of devices) { + try { + await fetch( + `https://fcm.googleapis.com/v1/projects/${credentials.project_id}/messages:send`, + { + method: 'POST', + headers: { + 'Authorization': `Bearer ${fcmAccessToken}`, + 'Content-Type': 'application/json', }, - }), - } - ) - } catch (pushErr) { - console.error(`Errore invio push al token ${device.fcm_token}:`, pushErr) + body: JSON.stringify({ + message: { + token: device.fcm_token, + notification: { title: taskTitle, body: taskBody }, + data: { click_action: 'FLUTTER_NOTIFICATION_CLICK', taskId: reminder.task_id }, + }, + }), + } + ) + } catch (err) { + console.error(`Errore FCM token ${device.fcm_token}:`, err) + } } } + } else if (reminder.channel === 'email' && staffEmail) { + // --- LOGICA EMAIL (RESEND) --- + try { + await fetch('https://api.resend.com/emails', { + method: 'POST', + headers: { + 'Authorization': `Bearer ${resendApiKey}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + from: 'FLUX Reminders ', // Sostituirai con la tua email verificata in futuro + to: staffEmail, + subject: `Promemoria: ${taskTitle}`, + html: `

Ciao ${staffName},

+

Questo รจ un promemoria per il task: ${taskTitle}.

+

Dettagli: ${taskBody}

+


Il team FLUX

`, + }), + }) + } catch (err) { + console.error(`Errore invio Email a ${staffEmail}:`, err) + } } - // 6. Segnamo il reminder come inviato per non riprocessarlo al prossimo giro + // 6. Segna come inviato await supabaseClient .from('task_reminders') .update({ is_sent: true, updated_at: new Date().toISOString() })