'use client'; import { useState } from 'react'; type RuleMatchType = 'HASHTAG' | 'PREFIX' | 'REACTION_EMOJI' | 'INTEREST'; type RuleAction = 'FLAG' | 'AUTO_APPROVE' | 'SKIP' | 'REJECT'; type RuleIntent = 'POSITIVE' | 'NEGATIVE'; interface RuleData { id: string; matchType: RuleMatchType; matchValue: string; action: RuleAction; ruleIntent: RuleIntent; priority: number; isActive: boolean; createdAt: string; updatedAt: string; } const MATCH_TYPE_LABELS: Record = { HASHTAG: 'Hashtag', PREFIX: 'Prefix', REACTION_EMOJI: 'Reaction Emoji', INTEREST: 'Interest', }; const ACTION_LABELS: Record = { FLAG: 'Flag (Pending)', AUTO_APPROVE: 'Auto-approve', SKIP: 'Skip (Silent Drop)', REJECT: 'Reject (Visible)', }; const REACTION_OPTIONS = [ { value: '👍', label: '👍 Thumbs Up' }, { value: '👎', label: '👎 Thumbs Down' }, ]; function getValuePlaceholder(matchType: RuleMatchType): string { if (matchType === 'HASHTAG') return '#important'; if (matchType === 'PREFIX') return '!!'; if (matchType === 'INTEREST') return '#education'; return ''; } export function RuleManager({ initial }: { initial: RuleData[] }) { const [rules, setRules] = useState(initial); const [matchType, setMatchType] = useState('HASHTAG'); const [matchValue, setMatchValue] = useState(''); const [action, setAction] = useState('FLAG'); const [ruleIntent, setRuleIntent] = useState('POSITIVE'); const [priority, setPriority] = useState(0); const [busy, setBusy] = useState(false); const [error, setError] = useState(''); function handleMatchTypeChange(type: RuleMatchType) { setMatchType(type); setMatchValue(''); } async function addRule() { if (!matchValue.trim()) return; setBusy(true); setError(''); try { const res = await fetch('/api/rules', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ matchType, matchValue: matchValue.trim(), action, ruleIntent, priority }), }); if (!res.ok) { const err = await res.json().catch(() => ({ message: 'Failed to create rule' })); setError(err.message ?? 'Failed to create rule'); return; } const created: RuleData = await res.json(); setRules((prev) => [...prev, created].sort((a, b) => a.priority - b.priority)); setMatchValue(''); setAction('FLAG'); setRuleIntent('POSITIVE'); setPriority(0); } finally { setBusy(false); } } async function toggleRule(rule: RuleData) { const res = await fetch(`/api/rules/${rule.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ isActive: !rule.isActive }), }); if (res.ok) { const updated: RuleData = await res.json(); setRules((prev) => prev.map((r) => (r.id === rule.id ? updated : r))); } } async function deleteRule(id: string) { const res = await fetch(`/api/rules/${id}`, { method: 'DELETE' }); if (res.ok) setRules((prev) => prev.filter((r) => r.id !== id)); } return (

Add Rule

{matchType === 'REACTION_EMOJI' ? ( ) : ( setMatchValue(e.target.value)} placeholder={getValuePlaceholder(matchType)} className="border border-gray-300 rounded px-3 py-2 text-sm w-40" /> )} {matchType === 'INTEREST' && ( Helps AI classify content into circles )}
{(['POSITIVE', 'NEGATIVE'] as RuleIntent[]).map((i) => ( ))}
setPriority(Number(e.target.value))} className="border border-gray-300 rounded px-3 py-2 text-sm w-20" />
{error &&

{error}

}

Active Rules

{rules.length === 0 ? (

No rules configured. Assign rules to sync routes to control auto-forwarding.

) : ( {rules.map((rule) => ( ))}
Type Value Intent Action Priority Active
{MATCH_TYPE_LABELS[rule.matchType] ?? rule.matchType} {rule.matchValue} {rule.ruleIntent} {ACTION_LABELS[rule.action] ?? rule.action} {rule.priority}
)}
); }