mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
- Rules engine spec v2 (priority vs automation rules distinction) - Priority Rules settings page with weight sliders, SLA config, campaign/source weights - Collapsible config sections with dynamic headers - Live worklist preview panel with client-side scoring - AI assistant panel (collapsible) with rules-engine-specific system prompt - Worklist panel: score display with SLA status dots, sort by score - Scoring library (scoring.ts) for client-side preview computation - Sidebar: Rules Engine nav item under Configuration Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
56 lines
2.1 KiB
TypeScript
56 lines
2.1 KiB
TypeScript
import { useMemo } from 'react';
|
|
import { WeightSliderRow } from './weight-slider-row';
|
|
import { CollapsibleSection } from './collapsible-section';
|
|
import { useData } from '@/providers/data-provider';
|
|
import type { PriorityConfig } from '@/lib/scoring';
|
|
|
|
interface CampaignWeightsPanelProps {
|
|
config: PriorityConfig;
|
|
onChange: (config: PriorityConfig) => void;
|
|
}
|
|
|
|
export const CampaignWeightsPanel = ({ config, onChange }: CampaignWeightsPanelProps) => {
|
|
const { campaigns } = useData();
|
|
|
|
const updateCampaign = (campaignId: string, weight: number) => {
|
|
onChange({
|
|
...config,
|
|
campaignWeights: { ...config.campaignWeights, [campaignId]: weight },
|
|
});
|
|
};
|
|
|
|
const badge = useMemo(() => {
|
|
if (!campaigns || campaigns.length === 0) return 'No campaigns';
|
|
const configured = campaigns.filter(c => config.campaignWeights[c.id] != null).length;
|
|
return `${campaigns.length} campaigns · ${configured} configured`;
|
|
}, [campaigns, config.campaignWeights]);
|
|
|
|
if (!campaigns || campaigns.length === 0) {
|
|
return (
|
|
<CollapsibleSection title="Campaign Weights" badge="No campaigns" defaultOpen={false}>
|
|
<p className="text-xs text-tertiary py-2">Campaign weights will apply once campaigns are created.</p>
|
|
</CollapsibleSection>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<CollapsibleSection
|
|
title="Campaign Weights"
|
|
subtitle="Higher-weighted campaigns get their leads called first"
|
|
badge={badge}
|
|
defaultOpen={false}
|
|
>
|
|
<div className="divide-y divide-tertiary">
|
|
{campaigns.map(campaign => (
|
|
<WeightSliderRow
|
|
key={campaign.id}
|
|
label={campaign.campaignName ?? 'Untitled Campaign'}
|
|
weight={config.campaignWeights[campaign.id] ?? 5}
|
|
onWeightChange={(w) => updateCampaign(campaign.id, w)}
|
|
/>
|
|
))}
|
|
</div>
|
|
</CollapsibleSection>
|
|
);
|
|
};
|