'use client'; import { useState } from 'react'; interface RuleData { id: string; matchType: 'HASHTAG' | 'PREFIX' | 'REACTION_EMOJI'; matchValue: string; action: 'FLAG' | 'AUTO_APPROVE' | 'SKIP' | 'REJECT'; priority: number; isActive: boolean; createdAt: string; updatedAt: string; } const MATCH_TYPE_LABELS: Record = { HASHTAG: 'Hashtag', PREFIX: 'Prefix', REACTION_EMOJI: 'Reaction Emoji', }; const ACTION_LABELS: Record = { FLAG: 'Flag (Pending)', AUTO_APPROVE: 'Auto-approve', SKIP: 'Skip (Silent Drop)', REJECT: 'Reject (Visible)', }; export function RuleManager({ initial }: { initial: RuleData[] }) { const [rules, setRules] = useState(initial); const [matchType, setMatchType] = useState<'HASHTAG' | 'PREFIX' | 'REACTION_EMOJI'>('HASHTAG'); const [matchValue, setMatchValue] = useState(''); const [action, setAction] = useState<'FLAG' | 'AUTO_APPROVE' | 'SKIP' | 'REJECT'>('FLAG'); const [priority, setPriority] = useState(0); const [busy, setBusy] = useState(false); const [error, setError] = useState(''); 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, 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'); 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

setMatchValue(e.target.value)} placeholder={matchType === 'REACTION_EMOJI' ? '⭐' : '#important'} className="border border-gray-300 rounded px-3 py-2 text-sm w-40" />
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. Messages without matching rules are ignored.

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