riseup-squad18/src/services/api/edgeFunctions.ts

422 lines
12 KiB
TypeScript

/**
* API Client para Edge Functions
* Centraliza todas as chamadas para as Edge Functions do Supabase
*/
import axios from "axios";
import { API_CONFIG } from "./config";
const FUNCTIONS_BASE_URL = `${API_CONFIG.SUPABASE_URL}/functions/v1`;
// Pegar token de autenticação
function getAuthToken(): string | null {
return localStorage.getItem(API_CONFIG.STORAGE_KEYS.ACCESS_TOKEN);
}
// Cliente configurado para Edge Functions
const functionsClient = axios.create({
baseURL: FUNCTIONS_BASE_URL,
headers: {
"Content-Type": "application/json",
apikey: API_CONFIG.SUPABASE_ANON_KEY,
},
});
// Interceptor para adicionar token de auth
functionsClient.interceptors.request.use((config) => {
const token = getAuthToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// Interceptor para tratar erros
functionsClient.interceptors.response.use(
(response) => response,
(error) => {
console.error(
"[EdgeFunctions] Error:",
error.response?.data || error.message
);
return Promise.reject(error);
}
);
/**
* Edge Functions API
*/
export const edgeFunctions = {
// ============ USER ============
user: {
info: () => functionsClient.get("/user-info"),
updatePreferences: (data: {
dark_mode?: boolean;
high_contrast?: boolean;
font_size?: string;
dyslexia_font?: boolean;
language?: string;
}) => functionsClient.post("/user-update-preferences", data),
},
// ============ AVAILABILITY ============
availability: {
list: (params?: { external_doctor_id?: string; day_of_week?: number }) =>
functionsClient.get("/availability-list", { params }),
create: (data: {
external_doctor_id: string;
day_of_week: number;
start_time: string;
end_time: string;
slots_per_hour?: number;
}) => functionsClient.post("/availability-create", data),
update: (data: {
id: string;
start_time?: string;
end_time?: string;
slots_per_hour?: number;
active?: boolean;
}) => functionsClient.post("/availability-update", data),
delete: (data: { id: string }) =>
functionsClient.post("/availability-delete", data),
slots: (data: { external_doctor_id: string; date: string }) =>
functionsClient.post("/availability-slots", data),
},
// ============ EXCEPTIONS ============
exceptions: {
list: (params?: {
external_doctor_id?: string;
date_from?: string;
date_to?: string;
}) => functionsClient.get("/exceptions-list", { params }),
create: (data: {
external_doctor_id: string;
exception_date: string;
reason?: string;
all_day?: boolean;
}) => functionsClient.post("/exceptions-create", data),
delete: (data: { id: string }) =>
functionsClient.post("/exceptions-delete", data),
},
// ============ APPOINTMENTS ============
appointments: {
list: (params?: {
patient_id?: string;
doctor_id?: string;
status?: string;
}) => functionsClient.get("/appointments", { params }),
create: (data: {
doctor_id: string;
patient_id: string;
appointment_date: string;
appointment_time: string;
duration_minutes?: number;
type?: string;
}) => functionsClient.post("/appointments-create", data),
update: (data: {
appointment_id: string;
appointment_date?: string;
appointment_time?: string;
duration_minutes?: number;
type?: string;
status?: string;
}) => functionsClient.post("/appointments-update", data),
cancel: (data: { appointment_id: string; reason?: string }) =>
functionsClient.post("/appointments-cancel", data),
suggestSlot: (data: {
patient_id: string;
doctor_id: string;
preferred_dates?: string[];
preferred_times?: string[];
}) => functionsClient.post("/appointments-suggest-slot", data),
reschedule: (data: {
appointment_id: string;
new_datetime: string;
reason?: string;
}) => functionsClient.post("/appointments-reschedule", data),
confirm: (data: { token: string }) =>
functionsClient.post("/appointments-confirm", data),
checkin: (data: {
appointment_id: string;
check_in_method: "manual" | "qr_code" | "nfc" | "app" | "kiosk";
}) => functionsClient.post("/appointments-checkin", data),
markNoShow: (data: {
appointment_id: string;
reason?: string;
automatic_detection?: boolean;
}) => functionsClient.post("/appointments-no-show", data),
},
// ============ WAITLIST ============
waitlist: {
add: (data: {
patient_id: string;
doctor_id: string;
desired_date?: string;
desired_time?: string;
}) => functionsClient.post("/waitlist", data),
list: (params?: {
doctor_id?: string;
patient_id?: string;
status?: string;
}) => functionsClient.get("/waitlist", { params }),
match: (data: {
external_doctor_id: string;
appointment_date: string;
appointment_time: string;
}) => functionsClient.post("/waitlist-match", data),
remove: (data: { id: string }) =>
functionsClient.post("/waitlist-remove", data),
},
// ============ VIRTUAL QUEUE ============
virtualQueue: {
list: (doctorId: string) =>
functionsClient.get(`/virtual-queue/${doctorId}`),
advance: (data: {
doctor_id: string;
completed: boolean;
duration_minutes?: number;
notes?: string;
}) => functionsClient.post("/virtual-queue-advance", data),
checkin: (data: {
external_patient_id: string;
external_doctor_id?: string;
external_appointment_id: string;
}) => functionsClient.post("/queue-checkin", data),
},
// ============ NOTIFICATIONS ============
notifications: {
send: (data: {
type: "sms" | "email" | "whatsapp" | "push";
recipient_id: string;
template?: string;
data?: Record<string, unknown>;
scheduled_at?: string;
}) => functionsClient.post("/notifications-send", data),
confirm: (data: { notification_id: string; read_at?: string }) =>
functionsClient.post("/notifications-confirm", data),
subscription: (data: {
external_user_id: string;
channel: "sms" | "email" | "whatsapp";
enabled: boolean;
}) => functionsClient.post("/notifications-subscription", data),
},
// ============ ANALYTICS ============
analytics: {
summary: (params?: { start_date?: string; end_date?: string }) =>
functionsClient.get("/analytics", { params }),
heatmap: (data: {
doctor_id?: string;
date_from?: string;
date_to?: string;
}) => functionsClient.post("/analytics-heatmap", data),
demandCurve: (data: { days?: number }) =>
functionsClient.post("/analytics-demand-curve", data),
rankingReasons: () => functionsClient.get("/analytics-ranking-reasons"),
monthlyNoShow: (data: { months?: number }) =>
functionsClient.post("/analytics-monthly-no-show", data),
specialtyHeatmap: () => functionsClient.get("/analytics-specialty-heatmap"),
customReport: (data: {
metrics: string[];
date_from?: string;
date_to?: string;
filters?: Record<string, unknown>;
}) => functionsClient.post("/analytics-custom-report", data),
},
// ============ TELECONSULT ============
teleconsult: {
start: (data: { appointment_id: string; provider?: string }) =>
functionsClient.post("/teleconsult-start", data),
status: (sessionId: string) =>
functionsClient.get(`/teleconsult-status/${sessionId}`),
end: (data: {
session_id: string;
duration_minutes?: number;
recording_url?: string;
}) => functionsClient.post("/teleconsult-end", data),
},
// ============ GAMIFICATION ============
gamification: {
doctorBadges: (doctorId: string) =>
functionsClient.get(`/gamification-doctor-badges/${doctorId}`),
patientStreak: (patientId: string) =>
functionsClient.get(`/gamification-patient-streak/${patientId}`),
addPoints: (data: {
user_id: string;
points: number;
reason: string;
category?: string;
}) => functionsClient.post("/gamification-add-points", data),
},
// ============ USER SYNC ============
userSync: {
sync: (data: {
external_user_id: string;
external_email: string;
external_name?: string;
external_role?: string;
}) => functionsClient.post("/user-sync", data),
},
// ============ REPORTS ============
reports: {
export: (data: {
report_type: string;
format: "csv" | "pdf" | "json" | "xlsx";
filters?: Record<string, unknown>;
}) => functionsClient.post("/reports-export", data),
listExtended: (data: {
patient_id?: string;
doctor_id?: string;
date_from?: string;
date_to?: string;
}) => functionsClient.post("/reports-list-extended", data),
exportCsv: (data: {
patient_id?: string;
date_from?: string;
date_to?: string;
}) => functionsClient.post("/reports-export-csv", data),
integrityCheck: (data: { external_report_id: string; content: string }) =>
functionsClient.post("/reports-integrity-check", data),
},
// ============ DOCTOR ============
doctor: {
summary: (data: { doctor_id: string }) =>
functionsClient.post("/doctor-summary", data),
occupancy: (data: {
external_doctor_id: string;
date_from?: string;
date_to?: string;
}) => functionsClient.post("/doctor-occupancy", data),
delaySuggestion: (data: { external_doctor_id: string }) =>
functionsClient.post("/doctor-delay-suggestion", data),
},
// ============ PATIENTS ============
patients: {
history: (data: { patient_id: string }) =>
functionsClient.post("/patients-history", data),
preferences: (external_patient_id?: string) =>
functionsClient.get("/patients-preferences", {
params: { external_patient_id },
}),
updatePreferences: (data: {
external_patient_id?: string;
preferred_days?: string[];
preferred_times?: string[];
preferred_doctor_id?: string;
communication_channel?: string;
}) => functionsClient.post("/patients-preferences", data),
portal: () => functionsClient.get("/patients-portal"),
},
// ============ PRIVACY (LGPD) ============
privacy: {
request: (action: "access" | "delete" | "export") =>
functionsClient.post("/privacy", { action }),
},
// ============ FEATURE FLAGS ============
flags: {
list: () => functionsClient.get("/flags"),
update: (data: {
key: string;
enabled: boolean;
config?: Record<string, unknown>;
}) => functionsClient.post("/flags", data),
},
// ============ ACCESSIBILITY ============
accessibility: {
preferences: () => functionsClient.get("/accessibility-preferences"),
updatePreferences: (data: {
dark_mode?: boolean;
high_contrast?: boolean;
font_size?: string;
dyslexia_font?: boolean;
}) => functionsClient.post("/accessibility-preferences", data),
},
// ============ AUDIT ============
audit: {
list: (params?: {
entity_type?: string;
entity_id?: string;
action_type?: string;
limit?: number;
}) => functionsClient.get("/audit-list", { params }),
},
// ============ SYSTEM ============
system: {
healthCheck: () => functionsClient.get("/system-health-check"),
cacheRebuild: () => functionsClient.post("/system-cache-rebuild", {}),
cronRunner: (data: { job: string }) =>
functionsClient.post("/system-cron-runner", data),
},
// ============ OFFLINE/PWA ============
offline: {
agendaToday: (doctorId: string) =>
functionsClient.get(`/offline-agenda-today/${doctorId}`),
patientBasic: (patientId: string) =>
functionsClient.get(`/offline-patient-basic/${patientId}`),
},
};
export default edgeFunctions;