feat: group schedule toolbar; add Consent, New Patient Form Link, Consent Templates placeholders
- Schedule page: toolbar grouped into Appointment, Consent, Eligibility, Claim, Communication and Download sections; new Consent button (stub) - Patients page: New Patient Form Link button (stub) - Settings: Consent Templates sidebar entry and placeholder section Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,7 @@ import {
|
||||
KeyRound,
|
||||
Copy,
|
||||
Keyboard,
|
||||
FileSignature,
|
||||
} from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useMemo, useState, useEffect } from "react";
|
||||
@@ -273,6 +274,11 @@ export function Sidebar() {
|
||||
path: "/settings/npi",
|
||||
icon: <Stethoscope className="h-4 w-4 text-gray-400" />,
|
||||
},
|
||||
{
|
||||
name: "Consent Templates",
|
||||
path: "/settings/consenttemplates",
|
||||
icon: <FileSignature className="h-4 w-4 text-gray-400" />,
|
||||
},
|
||||
{
|
||||
name: "Program Bridge",
|
||||
path: "/settings/programs",
|
||||
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
ExternalLink,
|
||||
Bot,
|
||||
UserCheck,
|
||||
FileSignature,
|
||||
} from "lucide-react";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { Calendar } from "@/components/ui/calendar";
|
||||
@@ -1531,6 +1532,11 @@ export default function AppointmentsPage() {
|
||||
}
|
||||
};
|
||||
|
||||
// Consent: logic to be defined later.
|
||||
const handleConsent = () => {
|
||||
toast({ title: "Consent", description: "Consent feature coming soon." });
|
||||
};
|
||||
|
||||
const handleDownloadClaimPdfs = async () => {
|
||||
if (!user) return;
|
||||
setIsDownloadingClaimPdfs(true);
|
||||
@@ -1865,7 +1871,7 @@ export default function AppointmentsPage() {
|
||||
/>
|
||||
|
||||
<div className="container mx-auto">
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<div className="flex flex-col gap-4 mb-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold tracking-tight">
|
||||
Appointment Schedule
|
||||
@@ -1875,7 +1881,13 @@ export default function AppointmentsPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3 flex-wrap">
|
||||
<div className="flex items-start gap-3 flex-wrap">
|
||||
{/* Appointment group */}
|
||||
<div className="flex flex-col gap-1 rounded-lg border border-dashed border-gray-300 bg-gray-50/60 p-2">
|
||||
<span className="px-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
|
||||
Appointment
|
||||
</span>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Button
|
||||
onClick={() => {
|
||||
setEditingAppointment(undefined);
|
||||
@@ -1886,7 +1898,31 @@ export default function AppointmentsPage() {
|
||||
<Plus className="h-4 w-4" />
|
||||
New Appointment
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Consent group */}
|
||||
<div className="flex flex-col gap-1 rounded-lg border border-dashed border-gray-300 bg-gray-50/60 p-2">
|
||||
<span className="px-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
|
||||
Consent
|
||||
</span>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Button
|
||||
onClick={() => handleConsent()}
|
||||
disabled={isLoading}
|
||||
>
|
||||
<FileSignature className="h-4 w-4" />
|
||||
Consent
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Eligibility group */}
|
||||
<div className="flex flex-col gap-1 rounded-lg border border-dashed border-gray-300 bg-gray-50/60 p-2">
|
||||
<span className="px-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
|
||||
Eligibility
|
||||
</span>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{/* Check Eligibility for Column section */}
|
||||
<div className="flex items-center gap-2 border rounded-md px-3 py-2 bg-white shadow-sm">
|
||||
<Button
|
||||
@@ -1923,44 +1959,15 @@ export default function AppointmentsPage() {
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Claim for Column section */}
|
||||
<div className="flex items-center gap-2 border rounded-md px-3 py-2 bg-white shadow-sm">
|
||||
<Button
|
||||
onClick={() => handleClaimForColumn()}
|
||||
disabled={isLoading || isClaimingColumn || selectedClaimColumns.size === 0}
|
||||
size="sm"
|
||||
>
|
||||
{isClaimingColumn ? (
|
||||
<>
|
||||
<LoaderCircleIcon className="h-4 w-4 mr-1 animate-spin" />
|
||||
Submitting...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<FileCheck className="h-4 w-4 mr-1" />
|
||||
Claim for Column
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
{staffMembers.map((staff, index) => (
|
||||
<label
|
||||
key={staff.id}
|
||||
className="flex items-center gap-1 cursor-pointer select-none"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="w-4 h-4 rounded border-gray-400 accent-teal-600"
|
||||
checked={selectedClaimColumns.has(Number(staff.id))}
|
||||
onChange={() => toggleClaimColumn(Number(staff.id))}
|
||||
/>
|
||||
<span className="text-sm font-medium">
|
||||
{columnLabels[String(staff.id)] ?? String.fromCharCode(65 + index)}
|
||||
</span>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Claim group */}
|
||||
<div className="flex flex-col gap-1 rounded-lg border border-dashed border-gray-300 bg-gray-50/60 p-2">
|
||||
<span className="px-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
|
||||
Claim
|
||||
</span>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{/* Claim for Column with AI section */}
|
||||
<div className="flex flex-wrap items-center gap-2 border rounded-md px-3 py-2 bg-white shadow-sm">
|
||||
<Button
|
||||
@@ -2039,6 +2046,51 @@ export default function AppointmentsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Claim for Column section */}
|
||||
<div className="flex items-center gap-2 border rounded-md px-3 py-2 bg-white shadow-sm">
|
||||
<Button
|
||||
onClick={() => handleClaimForColumn()}
|
||||
disabled={isLoading || isClaimingColumn || selectedClaimColumns.size === 0}
|
||||
size="sm"
|
||||
>
|
||||
{isClaimingColumn ? (
|
||||
<>
|
||||
<LoaderCircleIcon className="h-4 w-4 mr-1 animate-spin" />
|
||||
Submitting...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<FileCheck className="h-4 w-4 mr-1" />
|
||||
Claim for Column
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
{staffMembers.map((staff, index) => (
|
||||
<label
|
||||
key={staff.id}
|
||||
className="flex items-center gap-1 cursor-pointer select-none"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="w-4 h-4 rounded border-gray-400 accent-teal-600"
|
||||
checked={selectedClaimColumns.has(Number(staff.id))}
|
||||
onChange={() => toggleClaimColumn(Number(staff.id))}
|
||||
/>
|
||||
<span className="text-sm font-medium">
|
||||
{columnLabels[String(staff.id)] ?? String.fromCharCode(65 + index)}
|
||||
</span>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Communication group */}
|
||||
<div className="flex flex-col gap-1 rounded-lg border border-dashed border-gray-300 bg-gray-50/60 p-2">
|
||||
<span className="px-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
|
||||
Communication
|
||||
</span>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{/* Text Reminder for Column section */}
|
||||
<div className="flex items-center gap-2 border rounded-md px-3 py-2 bg-white shadow-sm">
|
||||
<Button
|
||||
@@ -2140,7 +2192,15 @@ export default function AppointmentsPage() {
|
||||
<span className="text-xs text-gray-600 whitespace-nowrap">AI follow up</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Download group */}
|
||||
<div className="flex flex-col gap-1 rounded-lg border border-dashed border-gray-300 bg-gray-50/60 p-2">
|
||||
<span className="px-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
|
||||
Download
|
||||
</span>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{/* Download Filled Claim/Preauth Form: ADA forms (e.g. BCBS) for the selected date */}
|
||||
<div className="flex items-center gap-2 border rounded-md px-3 py-2 bg-white shadow-sm">
|
||||
<Button
|
||||
@@ -2163,6 +2223,8 @@ export default function AppointmentsPage() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Context Menu */}
|
||||
<Menu id={APPOINTMENT_CONTEXT_MENU_ID} animation="fade">
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
Camera,
|
||||
NotebookPen,
|
||||
FileCheck2,
|
||||
Link2,
|
||||
} from "lucide-react";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import {
|
||||
@@ -398,6 +399,18 @@ export default function PatientsPage() {
|
||||
<Plus className="h-4 w-4" />
|
||||
New Patient
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
// New patient form link: logic to be defined later.
|
||||
toast({ title: "New Patient Form Link", description: "Coming soon." });
|
||||
}}
|
||||
className="gap-1"
|
||||
disabled={isLoading}
|
||||
>
|
||||
<Link2 className="h-4 w-4" />
|
||||
New Patient Form Link
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ type SectionId =
|
||||
| "account"
|
||||
| "credentials"
|
||||
| "npi"
|
||||
| "consenttemplates"
|
||||
| "programs"
|
||||
| "twilio"
|
||||
| "telnyx"
|
||||
@@ -256,6 +257,17 @@ export default function SettingsPage() {
|
||||
case "npi":
|
||||
return <NpiProviderTable />;
|
||||
|
||||
case "consenttemplates":
|
||||
// Consent templates: logic to be defined later.
|
||||
return (
|
||||
<Card>
|
||||
<CardContent className="py-6">
|
||||
<h2 className="text-lg font-semibold text-gray-900">Consent Templates</h2>
|
||||
<p className="text-sm text-gray-500 mt-1">Coming soon.</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
||||
case "programs":
|
||||
return <ProgramBridgeTable />;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user