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>
49 lines
1.9 KiB
TypeScript
49 lines
1.9 KiB
TypeScript
import { useMemo } from 'react';
|
|
import { WeightSliderRow } from './weight-slider-row';
|
|
import { CollapsibleSection } from './collapsible-section';
|
|
import { SOURCE_LABELS } from '@/lib/scoring';
|
|
import type { PriorityConfig } from '@/lib/scoring';
|
|
|
|
interface SourceWeightsPanelProps {
|
|
config: PriorityConfig;
|
|
onChange: (config: PriorityConfig) => void;
|
|
}
|
|
|
|
const SOURCE_ORDER = ['WHATSAPP', 'PHONE', 'FACEBOOK_AD', 'GOOGLE_AD', 'INSTAGRAM', 'WEBSITE', 'REFERRAL', 'WALK_IN', 'OTHER'];
|
|
|
|
export const SourceWeightsPanel = ({ config, onChange }: SourceWeightsPanelProps) => {
|
|
const updateSource = (source: string, weight: number) => {
|
|
onChange({
|
|
...config,
|
|
sourceWeights: { ...config.sourceWeights, [source]: weight },
|
|
});
|
|
};
|
|
|
|
const badge = useMemo(() => {
|
|
const weights = SOURCE_ORDER.map(s => config.sourceWeights[s] ?? 5);
|
|
const avg = weights.reduce((a, b) => a + b, 0) / weights.length;
|
|
const highest = SOURCE_ORDER.reduce((best, s) => (config.sourceWeights[s] ?? 5) > (config.sourceWeights[best] ?? 5) ? s : best, SOURCE_ORDER[0]);
|
|
return `Avg ${avg.toFixed(1)} · Top: ${SOURCE_LABELS[highest]}`;
|
|
}, [config.sourceWeights]);
|
|
|
|
return (
|
|
<CollapsibleSection
|
|
title="Source Weights"
|
|
subtitle="Leads from higher-weighted sources get priority"
|
|
badge={badge}
|
|
defaultOpen={false}
|
|
>
|
|
<div className="divide-y divide-tertiary">
|
|
{SOURCE_ORDER.map(source => (
|
|
<WeightSliderRow
|
|
key={source}
|
|
label={SOURCE_LABELS[source] ?? source}
|
|
weight={config.sourceWeights[source] ?? 5}
|
|
onWeightChange={(w) => updateSource(source, w)}
|
|
/>
|
|
))}
|
|
</div>
|
|
</CollapsibleSection>
|
|
);
|
|
};
|