Backend: JWT middleware validates Clerk tokens on every request, extracts org ID from claims, enforces org-scoped queries via Supabase RLS. Frontend: ClerkProvider wraps the app, auth gate blocks unauthenticated access, UserButton in header, token injected into every API call. Supabase production wired to trust Clerk JWTs via Third-Party Auth integration. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
57 lines
No EOL
1.9 KiB
JavaScript
57 lines
No EOL
1.9 KiB
JavaScript
import { useAuth } from "@clerk/react";
|
|
import { exportFromBackend } from "../lib/api";
|
|
import { getFlagLabel, getFlagAction, getDeviceDisplay } from "../lib/coverage";
|
|
|
|
function downloadBlob(blob, filename) {
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement("a");
|
|
a.href = url;
|
|
a.download = filename;
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
document.body.removeChild(a);
|
|
URL.revokeObjectURL(url);
|
|
}
|
|
|
|
export default function CSVExport({ records, batchId }) {
|
|
const { getToken } = useAuth();
|
|
const today = new Date().toISOString().slice(0, 10);
|
|
const filename = `signal-work-queue-${today}.csv`;
|
|
|
|
const exportCSV = async () => {
|
|
if (!records || records.length === 0) return;
|
|
|
|
if (batchId) {
|
|
const token = await getToken().catch(() => null);
|
|
const blob = await exportFromBackend(records, batchId, token);
|
|
if (blob) {
|
|
downloadBlob(blob, filename);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Fallback: client-side CSV (no batchId or backend unavailable)
|
|
const headers = [
|
|
"Patient ID", "Device", "Payer", "Status", "Priority Score",
|
|
"Days Until Resupply End", "Recommended Action", "Resupply End Date", "Reason",
|
|
];
|
|
const rows = records.map((r) => [
|
|
r.patient_id, getDeviceDisplay(r.device_type), r.payer, getFlagLabel(r.flag),
|
|
r.priority, r.daysUntilEnd, getFlagAction(r.flag), r.coverageEndDate || "", r.reason || "",
|
|
]);
|
|
const csv = [headers, ...rows]
|
|
.map((row) => row.map((v) => `"${String(v).replace(/"/g, '""')}"`).join(","))
|
|
.join("\r\n");
|
|
downloadBlob(new Blob([csv], { type: "text/csv;charset=utf-8;" }), filename);
|
|
};
|
|
|
|
return (
|
|
<button
|
|
onClick={exportCSV}
|
|
className="bg-[var(--brand)] text-warm-white px-4 py-[7px] rounded-md text-[13px] font-medium cursor-pointer transition-colors hover:bg-[var(--brand-hover)] font-body"
|
|
disabled={!records || records.length === 0}
|
|
>
|
|
↓ Export Work Queue
|
|
</button>
|
|
);
|
|
} |