mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
- Setup wizard: 3-pane layout with right-side live previews, resume banner, edit/copy icons on team step, AI prompt configuration - Forms: employee-create replaces invite-member (no email invites), clinic form with address/hours/payment, doctor form with visit slots - Seed script: aligned to current SDK schema — doctors created as workspace members (HelixEngage Manager role), visitingHours replaced by doctorVisitSlot entity, clinics seeded, portalUserId linked dynamically, SUB/ORIGIN/GQL configurable via env vars - Pages: clinics + doctors CRUD updated for new schema, team settings with temp password + role assignment - New components: time-picker, day-selector, wizard-right-panes, wizard-layout-context, resume-setup-banner - Removed: invite-member-form (replaced by employee-create-form per no-email-invites rule) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
84 lines
3.6 KiB
TypeScript
84 lines
3.6 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
import { faCircleInfo, faXmark, faArrowRight } from '@fortawesome/pro-duotone-svg-icons';
|
|
import { Button } from '@/components/base/buttons/button';
|
|
import { getSetupState, SETUP_STEP_NAMES, type SetupState } from '@/lib/setup-state';
|
|
import { useAuth } from '@/providers/auth-provider';
|
|
|
|
// Dismissible banner shown across the top of authenticated pages when
|
|
// the hospital workspace has incomplete setup steps AND the admin has
|
|
// already dismissed the auto-wizard. This is the "nudge" layer —
|
|
// a persistent reminder that setup is still outstanding, without the
|
|
// intrusion of the full-page wizard.
|
|
//
|
|
// Visibility rules:
|
|
// - Admin users only (other roles can't complete setup)
|
|
// - At least one setup step is still `completed: false`
|
|
// - `setup-state.wizardDismissed === true` (otherwise the wizard
|
|
// auto-shows on next login and this banner would be redundant)
|
|
// - Not dismissed in the current browser session (resets on reload)
|
|
export const ResumeSetupBanner = () => {
|
|
const { isAdmin } = useAuth();
|
|
const [state, setState] = useState<SetupState | null>(null);
|
|
const [dismissed, setDismissed] = useState(
|
|
() => sessionStorage.getItem('helix_resume_setup_dismissed') === '1',
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (!isAdmin || dismissed) return;
|
|
getSetupState()
|
|
.then(setState)
|
|
.catch(() => {
|
|
// Non-fatal — if setup-state isn't reachable, just
|
|
// skip the banner. The wizard still works.
|
|
});
|
|
}, [isAdmin, dismissed]);
|
|
|
|
if (!isAdmin || !state || dismissed) return null;
|
|
|
|
const incompleteCount = SETUP_STEP_NAMES.filter((s) => !state.steps[s].completed).length;
|
|
if (incompleteCount === 0) return null;
|
|
|
|
// If the wizard hasn't been dismissed yet, the first-run redirect
|
|
// in login.tsx handles pushing the admin into /setup — no need
|
|
// for this nudge.
|
|
if (!state.wizardDismissed) return null;
|
|
|
|
const handleDismiss = () => {
|
|
sessionStorage.setItem('helix_resume_setup_dismissed', '1');
|
|
setDismissed(true);
|
|
};
|
|
|
|
return (
|
|
<div className="flex shrink-0 items-center justify-between gap-4 border-b border-brand bg-brand-primary px-4 py-2">
|
|
<div className="flex items-center gap-3">
|
|
<FontAwesomeIcon icon={faCircleInfo} className="size-4 text-brand-primary" />
|
|
<span className="text-sm text-primary">
|
|
<b>Finish setting up your hospital</b> — {incompleteCount} step
|
|
{incompleteCount === 1 ? '' : 's'} still need your attention.
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Button
|
|
size="sm"
|
|
color="primary"
|
|
href="/setup"
|
|
iconTrailing={({ className }: { className?: string }) => (
|
|
<FontAwesomeIcon icon={faArrowRight} className={className} />
|
|
)}
|
|
>
|
|
Resume setup
|
|
</Button>
|
|
<button
|
|
type="button"
|
|
onClick={handleDismiss}
|
|
className="flex size-7 items-center justify-center rounded-md text-fg-quaternary hover:bg-secondary_hover hover:text-fg-secondary transition duration-100 ease-linear"
|
|
title="Dismiss for this session"
|
|
>
|
|
<FontAwesomeIcon icon={faXmark} className="size-3" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|