422 lines
12 KiB
TypeScript
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;
|