first commit
This commit is contained in:
commit
8b790b7601
86 changed files with 6348 additions and 0 deletions
86
ui_kits/web/RulesScreen.jsx
Normal file
86
ui_kits/web/RulesScreen.jsx
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
// RulesScreen — promote-suggested-rules view
|
||||
|
||||
function RuleCard({ rule, checked, onToggle, onApply }) {
|
||||
return (
|
||||
<div className="rule-card">
|
||||
<div className="rule-head">
|
||||
<div className="rule-pattern">
|
||||
<span className="pattern-prefix">payee ~=</span>
|
||||
<code className="ko">"{rule.pattern}"</code>
|
||||
</div>
|
||||
<div className="rule-occ">
|
||||
<span className="rule-num">{rule.occurrences}</span>
|
||||
<span className="rule-occ-lbl">OCCURRENCES · LAST 30d</span>
|
||||
</div>
|
||||
<ConfidenceChip score={rule.score} tier="llm" />
|
||||
</div>
|
||||
<div className="rule-map">
|
||||
<span className="ko">{rule.pattern}</span>
|
||||
<Icon name="arrowRight" size={14} color="var(--fg-muted)" />
|
||||
<span className="rule-target">{rule.target}</span>
|
||||
</div>
|
||||
<div className="rule-examples">
|
||||
<div className="rule-ex-label">MATCHING TRANSACTIONS</div>
|
||||
{rule.examples.map((ex, i) => <div key={i} className="rule-ex">{ex}</div>)}
|
||||
</div>
|
||||
<div className="rule-actions">
|
||||
<label className="rule-promote">
|
||||
<input type="checkbox" checked={checked} onChange={onToggle} />
|
||||
<span>Promote on next run</span>
|
||||
</label>
|
||||
<div style={{ flex: 1 }}></div>
|
||||
<Btn variant="primary" onClick={onApply}>APPLY RULE</Btn>
|
||||
<Btn>DISMISS</Btn>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RulesScreen({ entity }) {
|
||||
const data = window.AKEFIN_DATA.ruleSuggestions;
|
||||
const [promoted, setPromoted] = React.useState(new Set(data.map(r => r.id)));
|
||||
const [applied, setApplied] = React.useState(new Set());
|
||||
|
||||
const toggle = (id) => {
|
||||
setPromoted(prev => {
|
||||
const next = new Set(prev);
|
||||
next.has(id) ? next.delete(id) : next.add(id);
|
||||
return next;
|
||||
});
|
||||
};
|
||||
const apply = (id) => setApplied(prev => new Set([...prev, id]));
|
||||
|
||||
const visible = data.filter(r => !applied.has(r.id));
|
||||
|
||||
return (
|
||||
<div className="rules-screen">
|
||||
<div className="screen-head">
|
||||
<div>
|
||||
<h1 className="screen-title">Rule suggestions</h1>
|
||||
<div className="screen-sub">{visible.length} suggested · {promoted.size} promoted on next run · last AI pass 12 minutes ago</div>
|
||||
</div>
|
||||
<div className="screen-actions">
|
||||
<Btn><Icon name="refresh" size={13} /> RE-RUN AI PASS</Btn>
|
||||
<Btn variant="primary">PROMOTE ALL</Btn>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TermFrame title="AKEFIN — RULE PIPELINE · TIER 1" status="ok">
|
||||
<span className="m">$</span> akefin rules:suggest --entity {entity === "all" ? "*" : entity} --since 30d{"\n"}
|
||||
<span className="m">analysed 1,247 transactions · 5 high-frequency patterns matched ·</span>
|
||||
<span style={{color:"var(--conf-rules)"}}> 218 future rows would auto-categorize</span>
|
||||
</TermFrame>
|
||||
|
||||
<div className="rule-grid">
|
||||
{visible.map(r => (
|
||||
<RuleCard key={r.id} rule={r}
|
||||
checked={promoted.has(r.id)}
|
||||
onToggle={() => toggle(r.id)}
|
||||
onApply={() => apply(r.id)} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Object.assign(window, { RulesScreen });
|
||||
Loading…
Add table
Add a link
Reference in a new issue