208 lines
5.9 KiB
TypeScript
208 lines
5.9 KiB
TypeScript
import { Button } from "@/components/ui/button";
|
|
import {
|
|
Tooltip,
|
|
TooltipContent,
|
|
TooltipTrigger,
|
|
} from "@/components/ui/tooltip";
|
|
import {
|
|
PROCEDURE_COMBOS,
|
|
COMBO_CATEGORIES,
|
|
} from "@/utils/procedureCombos";
|
|
|
|
/* =========================================================
|
|
DIRECT COMBO BUTTONS (TOP SECTION)
|
|
========================================================= */
|
|
|
|
export function DirectComboButtons({
|
|
onDirectCombo,
|
|
}: {
|
|
onDirectCombo: (comboKey: string) => void;
|
|
}) {
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Section Title */}
|
|
<div className="text-sm font-semibold text-muted-foreground">
|
|
Direct Claim Submission Buttons
|
|
</div>
|
|
|
|
<div className="grid gap-6 md:grid-cols-2">
|
|
{/* CHILD RECALL */}
|
|
<DirectGroup
|
|
title="Child Recall"
|
|
combos={[
|
|
"childRecallDirect",
|
|
"childRecallDirect2BW",
|
|
"childRecallDirect4BW",
|
|
"childRecallDirect2PA2BW",
|
|
"childRecallDirect2PA4BW",
|
|
"childRecallDirect3PA2BW",
|
|
"childRecallDirect3PA",
|
|
"childRecallDirect4PA",
|
|
"childRecallDirectPANO",
|
|
]}
|
|
labelMap={{
|
|
childRecallDirect: "Direct",
|
|
childRecallDirect2BW: "Direct 2BW",
|
|
childRecallDirect4BW: "Direct 4BW",
|
|
childRecallDirect2PA2BW: "Direct 2PA 2BW",
|
|
childRecallDirect2PA4BW: "Direct 2PA 4BW",
|
|
childRecallDirect3PA2BW: "Direct 3PA 2BW",
|
|
childRecallDirect3PA: "Direct 3PA",
|
|
childRecallDirect4PA: "Direct 4PA",
|
|
childRecallDirectPANO: "Direct Pano",
|
|
}}
|
|
onSelect={onDirectCombo}
|
|
/>
|
|
|
|
{/* ADULT RECALL */}
|
|
<DirectGroup
|
|
title="Adult Recall"
|
|
combos={[
|
|
"adultRecallDirect",
|
|
"adultRecallDirect2BW",
|
|
"adultRecallDirect4BW",
|
|
"adultRecallDirect2PA2BW",
|
|
"adultRecallDirect2PA4BW",
|
|
"adultRecallDirect4PA",
|
|
"adultRecallDirectPano",
|
|
]}
|
|
labelMap={{
|
|
adultRecallDirect: "Direct",
|
|
adultRecallDirect2BW: "Direct 2BW",
|
|
adultRecallDirect4BW: "Direct 4BW",
|
|
adultRecallDirect2PA2BW: "Direct 2PA 2BW",
|
|
adultRecallDirect2PA4BW: "Direct 2PA 4BW",
|
|
adultRecallDirect4PA: "Direct 4PA",
|
|
adultRecallDirectPano: "Direct Pano",
|
|
}}
|
|
onSelect={onDirectCombo}
|
|
/>
|
|
|
|
{/* ORTH */}
|
|
<DirectGroup
|
|
title="Orth"
|
|
combos={[
|
|
"orthPreExamDirect",
|
|
"orthRecordDirect",
|
|
"orthPerioVisitDirect",
|
|
"orthRetentionDirect",
|
|
]}
|
|
onSelect={onDirectCombo}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
/* =========================================================
|
|
REGULAR COMBO BUTTONS (BOTTOM SECTION)
|
|
========================================================= */
|
|
|
|
export function RegularComboButtons({
|
|
onRegularCombo,
|
|
}: {
|
|
onRegularCombo: (comboKey: string) => void;
|
|
}) {
|
|
return (
|
|
<div className="space-y-4 mt-8">
|
|
{Object.entries(COMBO_CATEGORIES).map(([section, ids]) => (
|
|
<div key={section}>
|
|
<div className="mb-3 text-sm font-semibold opacity-70">
|
|
{section}
|
|
</div>
|
|
|
|
<div className="flex flex-wrap gap-1">
|
|
{ids.map((id) => {
|
|
const b = PROCEDURE_COMBOS[id];
|
|
if (!b) return null;
|
|
|
|
const tooltipText = b.codes
|
|
.map((code, idx) => {
|
|
const tooth = b.toothNumbers?.[idx];
|
|
return tooth ? `${code} (tooth ${tooth})` : code;
|
|
})
|
|
.join(", ");
|
|
|
|
return (
|
|
<Tooltip key={id}>
|
|
<TooltipTrigger asChild>
|
|
<Button
|
|
variant="secondary"
|
|
onClick={() => onRegularCombo(id)}
|
|
aria-label={`${b.label} — codes: ${tooltipText}`}
|
|
>
|
|
{b.label}
|
|
</Button>
|
|
</TooltipTrigger>
|
|
|
|
<TooltipContent side="top" align="center">
|
|
<div className="text-sm max-w-xs break-words">
|
|
{tooltipText}
|
|
</div>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
/* =========================================================
|
|
INTERNAL HELPERS
|
|
========================================================= */
|
|
|
|
function DirectGroup({
|
|
title,
|
|
combos,
|
|
labelMap,
|
|
onSelect,
|
|
}: {
|
|
title: string;
|
|
combos: string[];
|
|
labelMap?: Record<string, string>;
|
|
onSelect: (id: string) => void;
|
|
}) {
|
|
return (
|
|
<div className="space-y-2">
|
|
<div className="text-sm font-medium opacity-80">{title}</div>
|
|
|
|
<div className="flex flex-wrap gap-2">
|
|
{combos.map((id) => {
|
|
const b = PROCEDURE_COMBOS[id];
|
|
if (!b) return null;
|
|
|
|
const tooltipText = b.codes
|
|
.map((code, idx) => {
|
|
const tooth = b.toothNumbers?.[idx];
|
|
return tooth ? `${code} (tooth ${tooth})` : code;
|
|
})
|
|
.join(", ");
|
|
|
|
return (
|
|
<Tooltip key={id}>
|
|
<TooltipTrigger asChild>
|
|
<Button
|
|
variant="secondary"
|
|
onClick={() => onSelect(id)}
|
|
aria-label={`${b.label} — codes: ${tooltipText}`}
|
|
>
|
|
{labelMap?.[id] ?? b.label}
|
|
</Button>
|
|
</TooltipTrigger>
|
|
|
|
<TooltipContent side="top" align="center">
|
|
<div className="text-sm max-w-xs break-words">
|
|
{tooltipText}
|
|
</div>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|