feat: rules engine — priority config UI + worklist scoring

- 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>
This commit is contained in:
2026-04-01 16:51:29 +05:30
parent 462601d0dc
commit b90740e009
14 changed files with 1680 additions and 514 deletions

View File

@@ -0,0 +1,56 @@
import { useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faChevronDown, faChevronRight } from '@fortawesome/pro-duotone-svg-icons';
import { cx } from '@/utils/cx';
interface CollapsibleSectionProps {
title: string;
subtitle?: string;
badge?: string;
badgeColor?: string;
defaultOpen?: boolean;
children: React.ReactNode;
}
export const CollapsibleSection = ({
title,
subtitle,
badge,
badgeColor = 'text-brand-secondary',
defaultOpen = true,
children,
}: CollapsibleSectionProps) => {
const [open, setOpen] = useState(defaultOpen);
return (
<div className="rounded-xl border border-secondary bg-primary overflow-hidden">
<button
onClick={() => setOpen(!open)}
className="flex w-full items-center justify-between px-5 py-3.5 hover:bg-primary_hover transition duration-100 ease-linear"
>
<div className="flex items-center gap-3">
<FontAwesomeIcon
icon={open ? faChevronDown : faChevronRight}
className="size-3 text-fg-quaternary"
/>
<div className="text-left">
<div className="flex items-center gap-2">
<span className="text-sm font-semibold text-primary">{title}</span>
{badge && (
<span className={cx('text-xs font-medium tabular-nums', badgeColor)}>
{badge}
</span>
)}
</div>
{subtitle && <p className="text-xs text-tertiary mt-0.5">{subtitle}</p>}
</div>
</div>
</button>
{open && (
<div className="border-t border-secondary px-5 pb-4">
{children}
</div>
)}
</div>
);
};