feat: Implement initial application structure, core pages, UI components, and Supabase backend integration.

This commit is contained in:
Rodrigo Lopes dos Santos
2026-03-16 01:30:28 +00:00
parent 8ece90a37e
commit 0270a6cbdf
49 changed files with 2122 additions and 797 deletions

View 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

View File

@@ -0,0 +1,5 @@
{
"imports": {
"@supabase/functions-js": "jsr:@supabase/functions-js@^2"
}
}

View 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,
});
}
})