Signal/signal-ui/src/components/CSVExport.jsx
Kisa bcb1a10fe6 feat: demo MVP — 90/60/45 priority tiers, doc state machine, confirm visit workflow
- New CoverageFlag enum: SUPPLY_LAPSED, VISIT_REQUIRED, TRANSFER_PENDING,
  RENEWAL_CRITICAL/ELEVATED/SOON, RESUPPLY_READY, ACTIVE
- Doc state machine: 5-item payer-dependent status per patient (SWO, Visit,
  PECOS, PA, Diagnosis) with cascade chain
- Confirm Visit endpoint: staff enters prescriber-confirmed date, persisted in
  Supabase confirmed_visits table, survives all future CSV imports
- Supabase migration: 001_add_confirmed_visits.sql (run manually in SQL editor)
- Frontend: Badge rebuilt for 8 flags, DocStatusBar 5-dot display,
  ConfirmVisitModal, expandable WorklistTable rows
- Legal: LOI, NDA, BAA drafts at pitch/legal/ for Nixon Law Group review
- Compliance docs: privacy policy, incident response, data handling
- CSV generator: market_data.json + PA/NJ generator scripts
- 15/15 tests passing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 11:29:33 -04:00

66 lines
No EOL
2.2 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",
"Visit Confidence",
];
const rows = records.map((r) => [
r.patient_id,
r.device_display || getDeviceDisplay(r.device_type),
r.payer,
r.status_label || getFlagLabel(r.flag),
r.priority_score ?? r.priority,
r.days_until_coverage_end ?? r.daysUntilEnd,
r.action || getFlagAction(r.flag),
r.coverage_end_date || r.coverageEndDate || "",
r.reason || "",
r.visit_date_confidence || "estimated",
]);
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>
);
}