Synaplan
Open-source AI platform for companies: self-hosted AI agents, GDPR-compliant chatbot widget, RAG knowledge base, WhatsApp and Outlook AI, MCP, multi-model routing. Docker, Kubernetes or hosted in Germ
翻訳待ち
No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗個別指導塾向けのシフト管理システム。 講師・教室長がスマホ / PC から使える Web アプリです。
UI 仕様書は docs/shift-manager_UI仕様書.pdf にあります。
docs/design/ui-refresh/。| 層 | 採用 |
|---|---|
| フレームワーク | Next.js 16 (App Router, TypeScript, Turbopack) |
| UI | Tailwind CSS v4 + shadcn/ui (new-york) + lucide-react |
| フォーム / バリデーション | react-hook-form + zod |
| 認証 / ストレージ | Supabase (Auth + Storage + Postgres) |
| DB アクセス | Drizzle ORM (postgres-js driver) |
| 確定シフト取り込み | csv-parse / iconv-lite(文字コード変換) |
| 日付 | date-fns / date-fns-tz(JST 固定) |
npm install
Northeast Asia (Tokyo) 推奨)https://<project-ref>.supabase.co
⚠️ 末尾の /rest/v1/ を含めない(含めると Auth が PostgREST に流れて 404 になる)cp .env.local.example .env.local
.env.local を編集して上記 4 つの値を設定。DATABASE_URL のプレースホルダ <project-ref> を実際のプロジェクト ref に、<password> を実際の DB パスワードに置換するのを忘れずに。
Next.js も Drizzle CLI も
.env.localを読みます。.envではないので注意。
# スキーマから SQL を生成(既に generate 済みなら不要)
npm run db:generate
# 適用
npm run db:migrate
Supabase ダッシュボードの SQL Editor で実行:
insert into slot_definitions (slot_number, label, start_time, end_time) values
(1, '1限', '09:30', '10:55'),
(2, '2限', '11:00', '12:25'),
(3, '3限', '12:30', '13:55'),
(4, '4限', '14:00', '15:25'),
(5, '5限', '15:30', '16:55'),
(6, '6限', '17:00', '18:25'),
(7, '7限', '18:30', '19:55'),
(8, '8限', '20:00', '21:25');
admin ユーザーは Authentication > Users > Add user(Auto Confirm User を ON)で作成し、
表示される User UID を控えて profiles に対応行を追加:
-- roles は user_role[] 配列(#111 で旧 role 単一列から移行)。
-- 教室長兼講師にする場合は '{admin,tutor}' のように複数指定する。
insert into profiles (id, display_name, roles, email) values
('<コピーした User UID>', '教室長', '{admin}', '[email protected]');
テスト用に CSV の講師名を一括登録したい場合は
scripts/README.md の seed-stub-tutors.ts を参照。
npm run dev
http://localhost:3000 を開くと /login にリダイレクトされます。
Supabase Auth で作成したユーザーに対し、profiles テーブルへ
roles に 'admin' を含めて手動登録するとダッシュボードに入れます。
src/
├─ app/ # Next.js App Router
│ ├─ login/ # ログイン画面
│ ├─ auth/signout/ # POST /auth/signout でサインアウト
│ ├─ tutor/ # 講師用ページ (layout でガード)
│ │ ├─ fixed-shifts/ # 固定シフト登録
│ │ ├─ training/ # 講習期間の日別希望提出
│ │ ├─ absences/ # 欠勤申請
│ │ ├─ swaps/ # 交代申請
│ │ └─ open-swaps/ # 代講募集・応募
│ └─ admin/ # 教室長用ページ (layout でガード)。/admin = ダッシュボード
│ ├─ periods/ # 講習期間と締切の管理
│ ├─ submission-periods/ # 月別提出期間
│ ├─ regular-periods/ # レギュラー(期)提出期間
│ ├─ fixed-shifts/ # 固定シフト俯瞰
│ ├─ tutors/ # 講師管理・招待・連携
│ ├─ admins/ # 教室長管理
│ ├─ training/ # 講習希望の俯瞰(ヒートマップ)
│ ├─ weekly/ # 週次シフト表
│ ├─ uploads/ # 確定シフト CSV アップロード・公開
│ └─ requests/ # 欠勤・交代申請の承認(Tabs)
├─ components/
│ ├─ admin-shell.tsx # 教室長(PC)シェル: ヘッダー + 横ナビ
│ ├─ tutor-shell.tsx # 講師(スマホ)シェル: ヘッダー + 下部タブ
│ ├─ segmented-nav.tsx # グループ内サブナビ(セグメント)
│ ├─ admin-section-nav.tsx # 教室長グループのサブナビ定義
│ ├─ tutor-requests-nav.tsx # 講師「申請」グループのサブナビ定義
│ └─ ui/ # shadcn/ui プリミティブ
├─ db/
│ ├─ client.ts # Drizzle + postgres-js
│ └─ schema.ts # 全テーブル定義
├─ lib/
│ ├─ auth.ts # requireSession / requireRole(roles contains 判定)
│ ├─ profile-active.ts # 有効/無効切替の共有ガード(最後の admin 保護)
│ ├─ supabase/ # ブラウザ / サーバー / middleware クライアント
│ ├─ week.ts # JST 週・日付ユーティリティ(固定 +9h)
│ ├─ shift-constants.ts # 曜日・コマ定義
│ ├─ slot-meta.ts # コマ定義の取得
│ ├─ tutor-schedule.ts # 講師の確定シフト集計
│ ├─ admin-schedule.ts # 教室長向け週次スケジュール
│ ├─ training.ts # 講習期間・日別希望
│ ├─ training-overview.ts # 講習希望の俯瞰
│ ├─ absences.ts # 欠勤申請ロジック
│ ├─ swaps.ts # 交代・代講ロジック
│ ├─ shift-csv-parser.ts # 確定シフト CSV のパース
│ ├─ upload-commit.ts # 確定シフト CSV の取り込み確定
│ ├─ mapping-validation.ts # CSV 上の講師名 ↔ profiles マッピング検証
│ ├─ period-status.ts # 期間バッジ色・受付状態トークン
│ ├─ avatar.ts # アバター色・頭文字ヘルパ
│ ├─ db-errors.ts # 一意制約違反等の判定
│ └─ utils.ts # cn() ヘルパー
└─ middleware.ts # セッション更新 + 未ログインリダイレクト
profiles.roles(user_role[] = tutor / admin の配列)。
requireRole は「指定ロールを含むか」(contains) で判定するため、{admin,tutor} の兼任が可能(#111)docs/design/dual-role.md(#146 で仕様確定)src/app/{tutor,admin}/layout.tsx 内の requireRole でガードデータアクセスは全て サーバー仲介(Server Component / Server Action が
requireRole で認可 → Drizzle が postgres ロールで実行)。postgres は
BYPASSRLS=true かつ全 public テーブルの owner。一方クライアント側で
公開される anon キーは GoTrue 認証専用で、アプリテーブルを JWT で
直接参照しない。
この構成に対し migration 0007_rls.sql で全 public テーブルに:
ENABLE ROW LEVEL SECURITYREVOKE ALL ... FROM anon, authenticatedを適用。結果:
/rest/v1/...)は
permission denied で完全遮断(公開 anon キー悪用による PII 漏洩を解消)postgres / BYPASSRLS+owner)は無影響auth スキーマ)も無影響This is the beginning of the README. Read the rest at the original. Read the full README ↗