開発eurekapu-nuxt4

簿記学習用の章ページに「ボタンを押すと仕訳帳に転記され、残高試算表でアニメーションが走る」インタラクティブブロックを純HTML+CSS+JS(IIFE)で組み込んだ。設計は10分で固まったが、実装中に3回つまずき、最後はChrome DevToolsでスクショを撮るまでバグに気づかなかった。

やったこと

cash-3-topics.html というキャッシュ章のページに、仕訳エンジンを埋め込む。要件はこうだ。

  • ユーザーが「仕訳をプッシュ」ボタンを押すと、仕訳帳テーブルに行が追加される
  • 同時に残高試算表の該当勘定の数字が増減し、差分がアニメーションで光る
  • 期間切替(前期/当期)はExcelシート風のタブで切り替える
  • 前期は記帳済み・閲覧専用、当期だけ操作可能

Vue化はまだなので、まずは1ファイルで完結する純HTMLで動かす方針にした。

レイアウトの分割

借方・貸方を縦に並べる愚直な見せ方だと、BS/PLの構造が伝わらない。CSS Gridで4象限に切った。

.tb-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto auto;
  gap: 8px;
}
/* 借方=資産・費用 / 貸方=負債・純資産・収益 */

純資産には繰越利益剰余金(期首)と当期純利益を別行で出し、子要素として2文字インデント。当期純利益は費用区分の末尾にも添えてPLをバランスさせた。これだけで「PLの利益が純資産に積み上がる」感覚が視覚的に伝わるようになった。

帳簿側は黒の角張ったカードで囲み、ヘッダーを黒背景+白文字にした。入力側カードと帳簿側カードの間に「帳簿に反映 ▼」というフロー矢印を1本入れたら、操作の因果がひと目で読めるようになった。

マトリックス形式で出して怒られた

最初、受取時と支払時を縦横の2x2マトリックスで並べて見せたら、ユーザーから「完全に独立した仕訳を縦に並べる形式に直して」と一発で却下された。

確かに、マトリックスは「同じ取引の表裏」を示すには良いが、独立した2つの取引には不向きだった。受取時と支払時で勘定が変わる構造を縮約しすぎていた。例題タブで「① 不一致発覚 / ② 原因判明」をタブ切替にして縦長を圧縮し、各タブの中では仕訳をシンプルに縦並びにした。

リセットボタンも「リセット」のままだと押しづらいという指摘があり、「↺ 一括取消」と動詞ラベルに変えて右上に逃がした。

漫画風の差分吹き出し

仕訳プッシュ後、何がいくら動いたかを可視化したかった。試算表右上のFYタブ行に「現金が +2,000 増加 / 売掛金が −2,000 減少」をマゼンタ薄背景(10% alpha)の吹き出しで出すようにした。

最初は仕訳行の真上に出していたが、「大事な部分が見えなくなる」と指摘されて即座に右上固定に変えた。これも独りよがりな配置だった。

取消後の挙動も悩んだ。新しい吹き出しを作ると「取り消したのに何か出る」状態で混乱を招く。残ったままにして、次のプッシュで上書きされる方針に落ち着けた。

simplifyスキルで踏んだTDZ

ロジックがふくらんできたので simplify スキルで畳み込んだ。

  • preposted展開を applyEntry に統合
  • switchFYJournalswitchFYTbswitchFY に統合
  • アニメーション重複防止に activeRafspendingTimers を導入

ここで applyEntry の宣言順序が崩れて、初期化時にTDZ(Temporal Dead Zone)エラーが出るバグを仕込んだ。エディタで開いてもエラーは出ず、ビルドも通る。「直したつもり」で次のタスクに進みかけた。

ユーザーから「Chrome DevToolsで撮ってみて」と言われ、初めてコンソールに赤いエラーが出ているのを見た。スクショなしで「ファイル更新済み=正常」と判断したのが完全にミスだった。

教訓: ファイル更新だけで「動いた」と言わない

シンプル化のリファクタは、見た目のロジックは正しくても実行順序を壊す。今回もコードを読み返した時点では「変数を上に集めて宣言した」つもりが、関数式の代入が後ろに残っていて、初回呼び出しで参照不能になっていた。

教訓は3つに集約された。

  • ファイルを保存しただけで「動いた」と言わない
  • インタラクティブ要素を触ったら必ずブラウザでスクショを撮る
  • simplify後は特に、初期化パスを通す動作確認が必須

ナレーション化と縦切り検証

cash-3-topics-narration.vue を別途作り、3名話者(ずんだもん他)でVOICEVOX音声を58行生成した。NarrationViewer.vue に line-change emit を追加し、Cash3TopicsExample.vue / Cash3TopicsNarrationViewer.vue を新規作成して、ナレーションの行送りに合わせてインタラクティブ要素のステートが切り替わる作りにした。

縦切り検証で「あるナレーション行に来たら、対応する仕訳が自動でプッシュされる」というイベント同期がきれいに動いた瞬間は、思わずもう一度再生ボタンを押した。

計画書は Codex GPT-5.5 で3ラウンドレビューしてもらい、致命的な指摘13個を全部潰してからOKをもらった。指摘の質が高くて、自分で見直すより速い。

共通化: SVG拡大とモーダル

マウスオーバーでSVGが拡大、クリックでモーダル拡大、ESCで閉じる。この3つは他の章でも使うので _layout.css/_layout.js に共通化した。各章ページは <svg> を置くだけで自動的に拡大UIが効く。

Nuxt/Vue化への移行計画

HTMLだけで全章を展開するのは破綻する。1ファイルが2000行を超え、章をまたいだステート共有もできない。Nuxt/Vue化と並行で進める方針を立てた。

移行計画はM0でTypeScript章メタデータと分類を入れ、仕訳の借方/貸方/金額はTSにせず、章ごとの例題タイトル一覧をマークダウンに残すハイブリッドにした。仕訳データを完全TS化すると編集コストが跳ね上がるためだ。

この計画書も Codex で複数回レビューに回し、5つの致命指摘(ルーティング方針統一、完了条件明確化、マイルストーンの縦切り順)を反映してから本実装に入る。

明日やること

  • M0着手: 章メタデータのTypeScript型を切る
  • 例題タイトル一覧のマークダウン雛形を1章ぶん作る
  • cash-3-topics.html のTDZ修正をユニットテスト相当の手動チェックリスト化
  • simplify後の動作確認手順を .claude/rules/ にメモする