/* 아리 — 자동화 규칙 빌더 페이지 좌측 레일로 하위 화면 전환: 내 규칙 · 새 자동화 · 아리 제안 · 실행 기록 */ const { useState } = React; const I = window.AriShell.Icon; const Topbar = window.AriShell.Topbar; const SubRail = window.AriShell.SubRail; const AU = window.AriAuto; const AU_TONE = { mail: "var(--blue)", cal: "var(--violet)", focus: "var(--coral)", life: "var(--green)" }; const AU_CAT = { mail: "메일", cal: "일정", focus: "집중", life: "라이프" }; function Flow({ p, small }) { return (
트리거{p.trigger} {p.cond && ( 조건{p.cond} )} 동작{p.action}
); } /* ===== 내 규칙 ===== */ function RulesView({ rules, toggle }) { const activeN = rules.filter((r) => r.on).length; return (

내 규칙

켜고 끄는 건 언제든지
{activeN}/{rules.length} 켜짐
{rules.map((r) => (
{r.name} {AU_CAT[r.cat]}
마지막 실행 {r.last} · 이번 주 {r.runs}회
))}

자동화 작동 방식

안심하고 맡기세요
되돌릴 수 있어요모든 자동 실행은 결재함에 기록되고 한 번에 되돌릴 수 있어요.
위험한 건 물어봐요보내기·결제·삭제는 규칙이 있어도 실행 전에 확인받아요.
스스로 배워요반복되는 손길을 발견하면 새 규칙을 먼저 제안해요.
); } /* ===== 새 자동화 (작성 플로우) ===== */ function NewView({ onCreate }) { const [text, setText] = useState(""); const match = AU.examples.find((e) => e.text === text.trim()); return (
새 자동화 만들기

하고 싶은 일을 한 문장으로 적으세요. 트리거·조건·동작은 아리가 찾아요.

setText(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter" && match) onCreate(match); }} placeholder="예: 출장 전날엔 저녁 일정 비워줘" aria-label="새 규칙 문장" autoFocus />
{AU.examples.map((e) => ( ))}
{/* 미리보기 */}

미리보기

{match ? "아리가 이렇게 이해했어요" : "문장을 적으면 여기에 규칙이 그려져요"}
{match && {AU_CAT[match.cat]}}
{match ? (
{match.name}
만든 규칙은 ‘내 규칙’에서 언제든 끄거나 지울 수 있어요.
) : (

예시 문장을 누르거나 직접 적어보세요. 아리가 트리거 → 조건 → 동작으로 나눠 보여드려요.

)}
); } /* ===== 아리 제안 ===== */ function SuggestView({ suggests, accept, dismiss }) { return (

아리 제안

반복 패턴을 발견했어요
{suggests.length}건
{suggests.map((s) => (
{s.pattern}
{s.offer.name}
))} {suggests.length === 0 && (
지금은 새 제안이 없어요. 패턴이 보이면 알려드릴게요.
)}
); } /* ===== 실행 기록 ===== */ function LogView() { return (

실행 기록

규칙이 움직인 순간들
오늘 {AU.log.filter((l) => !l.time.startsWith("어제")).length}건
{AU.log.map((l, i) => (
{l.time}
{l.rule}
{l.text}
))}
); } const AU_RAIL = (suggestN) => [ { id: "rules", icon: "zap", label: "내 규칙" }, { id: "new", icon: "plus", label: "새 자동화" }, { sep: true }, { id: "suggest", icon: "brain", label: "아리 제안", dot: suggestN > 0 }, { id: "log", icon: "clock", label: "실행 기록" }, ]; const AU_HEAD = { rules: { eye: ["규칙으로 굴러가는 하루"], title: "내 규칙", em: "켜두면 알아서 굴러가요" }, new: { eye: ["한 문장이면 충분해요"], title: "새 자동화", em: "말하듯 적으면 규칙이 돼요" }, suggest: { eye: ["아리가 지켜보다 발견한 것"], title: "아리 제안", em: "반복되는 일을 자동으로" }, log: { eye: ["조용히 일한 기록"], title: "실행 기록", em: "규칙이 움직인 순간들" }, }; function App() { const [view, setView] = useState("rules"); const [rules, setRules] = useState(AU.rules); const [suggests, setSuggests] = useState(AU.suggests); const [toast, setToast] = useState(null); const activeN = rules.filter((r) => r.on).length; const toggle = (id) => setRules(rules.map((r) => (r.id === id ? { ...r, on: !r.on } : r))); const addRule = (cat, name, parse) => { setRules((rs) => [ { id: "new-" + Date.now(), on: true, cat, name, trigger: parse.trigger, cond: parse.cond, action: parse.action, last: "방금 만듦", runs: 0, fresh: true }, ...rs, ]); setToast("‘" + name + "’ 규칙을 켰어요."); setView("rules"); setTimeout(() => setToast(null), 3200); }; const createFromExample = (m) => addRule(m.cat, m.name, m.parse); const accept = (s) => { addRule(s.offer.cat, s.offer.name, s.offer); setSuggests((x) => x.filter((y) => y.id !== s.id)); }; const dismiss = (s) => setSuggests((x) => x.filter((y) => y.id !== s.id)); const h = AU_HEAD[view]; return (
활성 규칙 {activeN}개 이번 주 {AU.stats.runsWeek}회 실행 {AU.stats.saved} 아꼈어요

{h.title} {h.em}

{view === "rules" && } {view === "new" && } {view === "suggest" && } {view === "log" && }
{toast &&
{toast}
}
); } ReactDOM.createRoot(document.getElementById("root")).render();