feat: Implement initial application structure, core pages, UI components, and Supabase backend integration.
This commit is contained in:
3
supabase/functions/send-reminder/.npmrc
Normal file
3
supabase/functions/send-reminder/.npmrc
Normal file
@@ -0,0 +1,3 @@
|
||||
# Configuration for private npm package dependencies
|
||||
# For more information on using private registries with Edge Functions, see:
|
||||
# https://supabase.com/docs/guides/functions/import-maps#importing-from-private-registries
|
||||
5
supabase/functions/send-reminder/deno.json
Normal file
5
supabase/functions/send-reminder/deno.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"imports": {
|
||||
"@supabase/functions-js": "jsr:@supabase/functions-js@^2"
|
||||
}
|
||||
}
|
||||
71
supabase/functions/send-reminder/index.ts
Normal file
71
supabase/functions/send-reminder/index.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
|
||||
|
||||
// URL da API de Push do Expo (não precisa de chaves de servidor para o básico)
|
||||
const EXPO_PUSH_URL = 'https://exp.host/--/api/v2/push/send';
|
||||
|
||||
Deno.serve(async (req) => {
|
||||
// Criar o cliente Supabase com as variáveis de ambiente do sistema
|
||||
const supabase = createClient(
|
||||
Deno.env.get('SUPABASE_URL') ?? '',
|
||||
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
|
||||
)
|
||||
|
||||
try {
|
||||
// 1. Procurar agendamentos pendentes com tokens válidos
|
||||
// Nota: O campo 'fcm_token' na BD irá guardar o 'ExponentPushToken'
|
||||
const { data: appts, error } = await supabase
|
||||
.from('appointments')
|
||||
.select('*, profiles(fcm_token)')
|
||||
.eq('status', 'pendente')
|
||||
.not('profiles.fcm_token', 'is', null);
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
const notifications = [];
|
||||
|
||||
for (const appt of appts) {
|
||||
const expoToken = appt.profiles?.fcm_token;
|
||||
|
||||
// Verifica se é um token válido do Expo
|
||||
if (expoToken && expoToken.startsWith('ExponentPushToken')) {
|
||||
notifications.push({
|
||||
to: expoToken,
|
||||
sound: 'default',
|
||||
title: 'Lembrete Smart Agenda',
|
||||
body: `Olá! Não se esqueça do seu agendamento em breve.`,
|
||||
data: { appointmentId: appt.id },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Enviando ${notifications.length} notificações via Expo...`);
|
||||
|
||||
if (notifications.length > 0) {
|
||||
// 2. Enviar notificações em lote (Batch) via Expo
|
||||
const response = await fetch(EXPO_PUSH_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
},
|
||||
body: JSON.stringify(notifications),
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
console.log('Resultado do Expo:', result);
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({ success: true, sent: notifications.length }), {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
status: 200,
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erro na função send-reminder:', err);
|
||||
return new Response(JSON.stringify({ error: err.message }), {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
status: 500,
|
||||
});
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user