feat: add license activation system with feature gates

- License key generator tool at ~/Desktop/LicenseGenerator
- Backend validator route (GET /api/license/status, POST /api/license/activate)
- Activation page in sidebar with status, key input, and free/premium feature list
- useLicense hook for frontend license state
- Feature gates: premium eligibility buttons (DDMA, DeltaIns, Tufts, United, CCA) disabled without license
- Feature gates: premium claim buttons (CCA, Delta MA, United, Tufts) and all PreAuth buttons disabled without license
- Free features always active: MassHealth eligibility/claim, Documents, Payments, Backups, Reports
- README: license key generator usage instructions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ff
2026-05-26 21:22:34 -04:00
parent 594df39741
commit 070752380d
11 changed files with 472 additions and 81 deletions

View File

@@ -93,6 +93,7 @@ interface ClaimFormProps {
onHandleForUnitedDHSeleniumClaim: (data: ClaimFormData) => void;
onHandleForTuftsSCOSeleniumClaim: (data: ClaimFormData) => void;
onClose: () => void;
isLicensed?: boolean;
}
export function ClaimForm({
@@ -111,6 +112,7 @@ export function ClaimForm({
onHandleForTuftsSCOSeleniumClaim,
onSubmit,
onClose,
isLicensed = false,
}: ClaimFormProps) {
const { toast } = useToast();
const { user } = useAuth();
@@ -2196,24 +2198,32 @@ export function ClaimForm({
<Button
className="w-32 bg-blue-600 hover:bg-blue-700 text-white"
onClick={() => runWithPriceCheck(handleCCAClaim)}
disabled={!isLicensed}
title={!isLicensed ? "License required" : undefined}
>
CCA Claim
</Button>
<Button
className="w-36 bg-violet-600 hover:bg-violet-700 text-white"
onClick={() => runWithPriceCheck(handleDDMAClaim)}
disabled={!isLicensed}
title={!isLicensed ? "License required" : undefined}
>
Delta MA Claim
</Button>
<Button
className="w-44 bg-orange-600 hover:bg-orange-700 text-white"
onClick={() => runWithPriceCheck(handleUnitedDHClaim)}
disabled={!isLicensed}
title={!isLicensed ? "License required" : undefined}
>
United/DentalHub Claim
</Button>
<Button
className="w-32 bg-teal-600 hover:bg-teal-700 text-white"
onClick={() => runWithPriceCheck(handleTuftsSCOClaim)}
disabled={!isLicensed}
title={!isLicensed ? "License required" : undefined}
>
Tufts Claim
</Button>
@@ -2723,24 +2733,32 @@ export function ClaimForm({
<Button
className="w-32 bg-blue-600 hover:bg-blue-700 text-white"
onClick={() => handleMHPreAuth()}
disabled={!isLicensed}
title={!isLicensed ? "License required" : undefined}
>
MH PreAuth
</Button>
<Button
className="w-32 bg-blue-600 hover:bg-blue-700 text-white"
onClick={handleCCAPreAuth}
disabled={!isLicensed}
title={!isLicensed ? "License required" : undefined}
>
CCA PreAuth
</Button>
<Button
className="w-44"
variant="secondary"
disabled={!isLicensed}
title={!isLicensed ? "License required" : undefined}
>
United/DentalHub PreAuth
</Button>
<Button
className="w-32"
variant="secondary"
disabled={!isLicensed}
title={!isLicensed ? "License required" : undefined}
>
Tufts PreAuth
</Button>

View File

@@ -186,6 +186,12 @@ export function Sidebar() {
},
],
},
{
name: "Activation",
path: "/activation",
icon: <KeyRound className="h-5 w-5 text-amber-500" />,
adminOnly: true,
},
{
name: "Database Management",
path: "/database-management",