mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-05-18 20:08:19 +00:00
feat: wizard step indicator, wider dialog, campaigns in admin sidebar, clear leads shortcut
- Import wizard: added step indicator (numbered circles), widened to max-w-5xl - Admin sidebar: added Marketing → Campaigns nav link - Clear campaign leads: Ctrl+Shift+C shortcut with campaign picker modal (test-only) - Test CSV data for all 3 campaigns - Defect fixing plan + CSV import spec docs - Session memory update Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,53 @@ const FileImportIcon: FC<{ className?: string }> = ({ className }) => (
|
||||
|
||||
type ImportStep = 'select-campaign' | 'upload-preview' | 'importing' | 'done';
|
||||
|
||||
const WIZARD_STEPS = [
|
||||
{ key: 'select-campaign', label: 'Select Campaign', number: 1 },
|
||||
{ key: 'upload-preview', label: 'Upload & Map', number: 2 },
|
||||
{ key: 'done', label: 'Import', number: 3 },
|
||||
] as const;
|
||||
|
||||
const StepIndicator = ({ currentStep }: { currentStep: ImportStep }) => {
|
||||
const activeIndex = currentStep === 'importing' ? 2 : WIZARD_STEPS.findIndex(s => s.key === currentStep);
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-center gap-0 px-6 py-3 border-b border-secondary shrink-0">
|
||||
{WIZARD_STEPS.map((step, i) => {
|
||||
const isComplete = i < activeIndex;
|
||||
const isActive = i === activeIndex;
|
||||
const isLast = i === WIZARD_STEPS.length - 1;
|
||||
|
||||
return (
|
||||
<div key={step.key} className="flex items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className={cx(
|
||||
'flex size-7 items-center justify-center rounded-full text-xs font-semibold transition duration-100 ease-linear',
|
||||
isComplete ? 'bg-brand-solid text-white' :
|
||||
isActive ? 'bg-brand-solid text-white ring-4 ring-brand-100' :
|
||||
'bg-secondary text-quaternary',
|
||||
)}>
|
||||
{isComplete ? <FontAwesomeIcon icon={faCheck} className="size-3" /> : step.number}
|
||||
</div>
|
||||
<span className={cx(
|
||||
'text-xs font-medium whitespace-nowrap',
|
||||
isActive ? 'text-brand-secondary' : isComplete ? 'text-primary' : 'text-quaternary',
|
||||
)}>
|
||||
{step.label}
|
||||
</span>
|
||||
</div>
|
||||
{!isLast && (
|
||||
<div className={cx(
|
||||
'mx-3 h-px w-12',
|
||||
i < activeIndex ? 'bg-brand-solid' : 'bg-secondary',
|
||||
)} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
type ImportResult = {
|
||||
created: number;
|
||||
linkedToPatient: number;
|
||||
@@ -152,7 +199,7 @@ export const LeadImportWizard = ({ isOpen, onOpenChange }: LeadImportWizardProps
|
||||
|
||||
return (
|
||||
<ModalOverlay isOpen={isOpen} isDismissable onOpenChange={(open) => { if (!open) handleClose(); }}>
|
||||
<Modal className="sm:max-w-3xl">
|
||||
<Modal className="sm:max-w-5xl">
|
||||
<Dialog>
|
||||
{() => (
|
||||
<div className="flex w-full flex-col rounded-xl bg-primary shadow-xl ring-1 ring-secondary overflow-hidden max-h-[85vh]">
|
||||
@@ -173,6 +220,9 @@ export const LeadImportWizard = ({ isOpen, onOpenChange }: LeadImportWizardProps
|
||||
<button onClick={handleClose} className="text-fg-quaternary hover:text-fg-secondary text-lg">×</button>
|
||||
</div>
|
||||
|
||||
{/* Step indicator */}
|
||||
<StepIndicator currentStep={step} />
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1 overflow-y-auto px-6 py-4 min-h-0">
|
||||
{/* Step 1: Campaign Cards */}
|
||||
|
||||
Reference in New Issue
Block a user