作業時間の記録・分析を行う Web アプリ。 後から入力した記録が既存の時間を自動的に上書き・分割する「後出し優先ロジック」が核心機能。 日またぎ(深夜作業など)にも対応し、直近 20 件の記録をタイムラインで一覧できる。
worktrace/
├── backend/
│ ├── main.py # FastAPI アプリ本体(DBモデル・重複処理・全エンドポイント)
│ └── requirements.txt # Python 依存ライブラリ
└── frontend/
├── index.html
├── package.json
├── vite.config.js
├── tailwind.config.js
├── postcss.config.js
└── src/
├── main.jsx
├── index.css
├── App.jsx # メイン UI・状態管理
└── components/
├── Timeline.jsx # タイムライン表示
└── Analytics.jsx # アナリティクスダッシュボード
| レイヤー | 技術 |
|---|---|
| Backend | Python / FastAPI |
| DB | SQLite(SQLAlchemy ORM) |
| Frontend | React 18 / Vite |
| スタイリング | Tailwind CSS |
| グラフ | Recharts |
| HTTP クライアント | Axios |
Debian/Ubuntu 系の Python 3.12 以降は externally-managed-environment のため、
システム全体への pip install が禁止されている。
仮想環境(venv)を作成してからインストールする。
cd backend
# 初回のみ: 仮想環境を作成
python3 -m venv .venv
# 仮想環境を有効化(プロンプトが (.venv) になる)
source .venv/bin/activate
# 依存ライブラリをインストール
pip install -r requirements.txt
# サーバー起動
uvicorn main:app --reload2回目以降は仮想環境の作成・pip install は不要。
source .venv/bin/activateしてからuvicorn main:app --reloadだけでよい。仮想環境を抜けるときは
deactivate。
cd frontend
npm install
npm run devブラウザで http://localhost:5173 を開く。
Vite のプロキシ設定により、フロントエンドからの API リクエストは自動的に localhost:8000 へ転送される。
| フィールド | 内容 |
|---|---|
| 開始日 | デフォルトは日付ナビの選択日。日付ナビ変更時に自動同期 |
| 開始時間 | HH:MM 形式 |
| 終了日 | 開始日〜開始日の翌日まで選択可能(翌日以降は不可) |
| 終了時間 | HH:MM 形式 |
| プロジェクト | 過去の入力履歴をサジェスト(<datalist>) |
| 作業種別 | 過去の入力履歴をサジェスト(デフォルト候補あり) |
| 作業メモ | 任意のメモ。タイムラインにも表示される |
- 日付ナビ(ヘッダーの ← → ボタン)で日付を変えると、開始日・終了日が自動的にその日に合わせて更新される
- 送信時に後出し優先ロジックを自動実行
backend/main.py の resolve_overlaps() 関数が実装している。
新しいエントリ [n_start, n_end] に対し、既存の全エントリを 4 ケースで処理する。
日またぎエントリも含め、datetime 単位で全期間を対象に重複を検出する。
ケース1: 完全内包(既存が新規の中にすっぽり収まる)
既存: [──e──]
新規: [────────────]
→ 既存を削除
ケース2: 完全包含(既存が新規を丸ごと包む)
既存: [──────────────]
新規: [──n──]
→ 既存を前後 2 つに分割
前半: [e_start, n_start]
後半: [n_end, e_end ] ※後半セグメントの date は n_end の実日付
ケース3: 左側重複(既存が左にはみ出す)
既存: [────]
新規: [────────]
→ 既存の終端を n_start に短縮
ケース4: 右側重複(既存が右にはみ出す)
既存: [────]
新規: [────────]
→ 既存の始端を n_end に短縮(date フィールドも n_end の実日付に更新)
処理フロー:
POST /entriesでリクエストを受信- 新エントリを DB に INSERT し ID を確定(
db.flush()) resolve_overlaps()で重複を解決db.commit()で一括確定
- 開始日と終了日を個別に指定できる(例:2/28 22:00 〜 3/1 02:00)
- 終了日は開始日の翌日までに制限(それ以上はフロント・バック両方で弾く)
- タイムラインの 24h バーでは、日またぎエントリの終端を 24:00 でカットして表示
- エントリリストでは日またぎを「翌」ラベルで表示(例:
22:00 – 翌 02:00)
24時間ビジュアルバー(選択日)
- ヘッダーの日付ナビで選択した日のエントリを表示
- 横幅全体 = 24時間(1440分)
- 日またぎエントリは 24:00 でカット
- 未記録の隙間は破線ボーダーで視覚化
直近 20 件リスト
- 全日付を対象に
start_time降順で直近 20 件を表示 - 各エントリに日付(M/D)・時間・期間・プロジェクト・作業種別・メモを表示
- ホバーで「複製」「削除」ボタンが表示される
複製機能
- 「複製」ボタンをクリックすると、そのエントリの内容をフォームに展開する
- 日付は日付ナビの選択日、時間・プロジェクト・種別・メモはそのままセット
- 日またぎエントリは終了日も自動調整(選択日 + 1 日)
- フォームに展開後、内容を確認・修正してから「記録する」で保存
| グラフ | 内容 |
|---|---|
| ドーナツチャート(左) | プロジェクト別合計時間の内訳 |
| ドーナツチャート(右) | 作業種別(設計/実装/MTG…)の比率 |
| 棒グラフ | 日次作業時間のサマリー |
| 稼働率バー | 作業種別ごとのパーセンテージをプログレスバーで表示 |
分析期間は「今日 / 7日間 / 30日間」で切り替え可能。
GET /tagsで過去に使用したプロジェクト名・作業種別を取得- フォームの
<datalist>に反映し、入力補完を提供 - エントリ追加のたびに自動更新
| メソッド | パス | 説明 |
|---|---|---|
GET |
/entries?date=YYYY-MM-DD |
指定日のエントリを時刻順で取得 |
POST |
/entries |
新規エントリ追加(重複自動解決) |
DELETE |
/entries/{id} |
エントリ削除 |
GET |
/entries/recent?limit=20 |
直近 N 件のエントリを新しい順で取得 |
POST |
/entries/{id}/clone |
指定エントリを target_date にクローン |
GET |
/analytics?start_date=...&end_date=... |
期間集計データ取得 |
GET |
/tags |
過去のプロジェクト名・作業種別を取得 |
POST /entries
{
"start_date": "2026-02-28",
"start_time": "09:00",
"end_date": "2026-02-28",
"end_time": "10:30",
"project": "ProjectA",
"task_type": "実装",
"memo": "認証まわりの実装"
}GET /entries レスポンス
[
{
"id": 1,
"start_date": "2026-02-28",
"start_time": "09:00",
"end_date": "2026-02-28",
"end_time": "10:30",
"project": "ProjectA",
"task_type": "実装",
"memo": "認証まわりの実装",
"date": "2026-02-28",
"duration_minutes": 90
}
]POST /entries/{id}/clone
{ "target_date": "2026-03-01" }CREATE TABLE time_entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
start_time DATETIME NOT NULL,
end_time DATETIME NOT NULL,
project VARCHAR NOT NULL,
task_type VARCHAR NOT NULL,
date VARCHAR NOT NULL, -- YYYY-MM-DD(start_time の日付、検索フィルタ用)
memo VARCHAR -- 作業メモ(任意)
);SQLite ファイルは初回起動時に backend/worktrace.db として自動生成される。
memo カラムは起動時に自動マイグレーションで追加されるため、既存 DB への手動変更は不要。
┌─────────────────────────────────────────────┐
│ ヘッダー: workTrace ロゴ ← 日付ナビ → │
├─────────────────────────────────────────────┤
│ 入力フォーム │
│ [開始日][開始時間] [終了日][終了時間] │
│ [プロジェクト] [種別] [記録する] │
│ [作業メモ(任意・全幅)] │
├─────────────────────────────────────────────┤
│ タイムライン 直近 N 件 │
│ 選択日 合計 Xh 隙間 Y箇所 │
│ ████░░░████████░░░░████ ← 24h バー │
│ 00 06 09 12 15 18 21 24 │
│ 2/27 09:00–10:30 90分 ProjectA 実装 │
│ 2/27 翌 22:00–02:00 4h ProjectB 調査 │
│ 2/28 11:00–12:00 60分 ProjectC MTG │
│ ↑ ホバーで [複製] [削除] 表示 │
├─────────────────────────────────────────────┤
│ アナリティクス [今日|7日|30日] │
│ [合計時間] [件数] [平均時間] │
│ ドーナツ(PJ別) ドーナツ(種別) │
│ 日次棒グラフ │
│ 稼働率プログレスバー │
└─────────────────────────────────────────────┘