create-einja-app 0.1.2 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -0
- package/dist/cli.js +852 -21
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/templates/default/CLAUDE.md +27 -0
- package/templates/default/README.md +150 -45
- package/templates/default/apps/web/server/presentation/routes/userRoutes.ts +2 -5
- package/templates/default/apps/web/src/app/(authenticated)/data/_components/UserTable.tsx +110 -113
- package/templates/default/apps/web/src/app/(authenticated)/data/_components/UserTableContainer.tsx +5 -17
- package/templates/default/apps/web/src/app/(authenticated)/data/page.tsx +9 -7
- package/templates/default/apps/web/src/app/api/rpc/[[...route]]/route.ts +1 -1
- package/templates/default/apps/web/src/hooks/api/prefetch-users.ts +63 -0
- package/templates/default/apps/web/src/hooks/{use-users.ts → api/use-users.ts} +11 -46
- package/templates/default/apps/web/src/lib/api/parse-response.ts +114 -0
- package/templates/default/apps/web/src/shared/schemas/user.ts +36 -0
- package/templates/default/middleware.ts +0 -32
- package/templates/default/apps/web/src/lib/{api-client.ts → api/client.ts} +1 -1
|
@@ -1,8 +1,108 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Einja Management Template
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Turborepo + Next.js 15 + Auth.js + Prisma 構成のプロジェクトテンプレートと、Claude Code用のATDDワークフロー設定を提供します。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## パッケージ利用者向け
|
|
8
|
+
|
|
9
|
+
### create-einja-app - 新規プロジェクト作成
|
|
10
|
+
|
|
11
|
+
新しいプロジェクトを作成したい場合に使用します。
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx create-einja-app my-project
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**何が起きるか:**
|
|
18
|
+
|
|
19
|
+
1. `my-project/` ディレクトリが作成される
|
|
20
|
+
2. Turborepo + Next.js 15 + Prisma のモノレポ構成が展開される
|
|
21
|
+
3. `.claude/` ディレクトリ(Claude Code設定)が自動セットアップされる
|
|
22
|
+
4. 依存関係がインストールされる
|
|
23
|
+
5. Gitリポジトリが初期化される
|
|
24
|
+
|
|
25
|
+
**作成後の開始手順:**
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cd my-project
|
|
29
|
+
docker-compose up -d postgres # PostgreSQL起動
|
|
30
|
+
pnpm dev # 開発サーバー起動
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
ブラウザで http://localhost:3000 にアクセス
|
|
34
|
+
|
|
35
|
+
**オプション:**
|
|
36
|
+
|
|
37
|
+
| オプション | 説明 |
|
|
38
|
+
|-----------|------|
|
|
39
|
+
| `--yes` | 対話プロンプトをスキップ(デフォルト値使用) |
|
|
40
|
+
| `--skip-git` | Git初期化をスキップ |
|
|
41
|
+
| `--skip-install` | 依存関係インストールをスキップ |
|
|
42
|
+
|
|
43
|
+
📖 詳細: [packages/create-einja-app/README.md](./packages/create-einja-app/README.md)
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
### @einja/dev-cli - 既存プロジェクトにClaude Code設定を追加
|
|
48
|
+
|
|
49
|
+
既存のプロジェクトにClaude Code用のATDDワークフロー設定を追加したい場合に使用します。
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
cd your-existing-project
|
|
53
|
+
npx @einja/dev-cli init
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**何が起きるか:**
|
|
57
|
+
|
|
58
|
+
1. `.claude/` ディレクトリが作成される
|
|
59
|
+
- `agents/` - タスク実行、仕様書生成、フロントエンド開発用サブエージェント
|
|
60
|
+
- `commands/` - `/spec-create`, `/task-exec` などのスラッシュコマンド
|
|
61
|
+
- `skills/` - コーディング規約、コンポーネント設計ガイド
|
|
62
|
+
- `hooks/` - Biomeフォーマット、型チェックなどのGit Hooks
|
|
63
|
+
- `settings.json` - MCPサーバー設定(GitHub, Playwright, Serena等)
|
|
64
|
+
2. `docs/einja/` ディレクトリが作成される
|
|
65
|
+
- `steering/` - コミットルール、テスト戦略、レビューガイドライン
|
|
66
|
+
- `templates/` - 仕様書テンプレート
|
|
67
|
+
3. `CLAUDE.md` テンプレートが作成される
|
|
68
|
+
4. `package.json` にスクリプトが追加される
|
|
69
|
+
|
|
70
|
+
**追加されるnpm scripts:**
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pnpm task:loop 123 # GitHub Issue #123のタスクを自動実行
|
|
74
|
+
pnpm einja:sync # テンプレートから最新設定を同期
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**その他のコマンド:**
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# テンプレートから設定を同期(更新があった場合)
|
|
81
|
+
npx @einja/dev-cli sync
|
|
82
|
+
|
|
83
|
+
# 特定カテゴリのみ同期
|
|
84
|
+
npx @einja/dev-cli sync --only commands,agents
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
📖 詳細: [packages/cli/README.md](./packages/cli/README.md)
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### 使い分けガイド
|
|
92
|
+
|
|
93
|
+
| やりたいこと | 使うパッケージ |
|
|
94
|
+
|-------------|---------------|
|
|
95
|
+
| 新規プロジェクトを作成したい | `npx create-einja-app my-project` |
|
|
96
|
+
| 既存プロジェクトにClaude設定を追加したい | `npx @einja/dev-cli init` |
|
|
97
|
+
| Claude設定を最新に更新したい | `npx @einja/dev-cli sync` |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## パッケージ開発者向け
|
|
102
|
+
|
|
103
|
+
以下は、このリポジトリ自体を開発する場合の情報です。
|
|
104
|
+
|
|
105
|
+
### プロジェクト構成
|
|
6
106
|
|
|
7
107
|
このプロジェクトは**Turborepo**を使用したモノレポ構成です。
|
|
8
108
|
|
|
@@ -19,6 +119,8 @@ einja-management-template/
|
|
|
19
119
|
│ ├── package.json
|
|
20
120
|
│ └── tsconfig.json
|
|
21
121
|
├── packages/
|
|
122
|
+
│ ├── cli/ # @einja/dev-cli
|
|
123
|
+
│ ├── create-einja-app/ # create-einja-app
|
|
22
124
|
│ ├── config/ # 共通設定(Biome, TypeScript, Panda CSS)
|
|
23
125
|
│ ├── front-core/ # フロントエンド共通層
|
|
24
126
|
│ │ └── src/
|
|
@@ -38,7 +140,7 @@ einja-management-template/
|
|
|
38
140
|
└── package.json # ルートpackage.json
|
|
39
141
|
```
|
|
40
142
|
|
|
41
|
-
|
|
143
|
+
### 技術スタック
|
|
42
144
|
|
|
43
145
|
- **モノレポ**: Turborepo + pnpm workspaces
|
|
44
146
|
- **フレームワーク**: Next.js 15 (App Router)
|
|
@@ -52,9 +154,9 @@ einja-management-template/
|
|
|
52
154
|
- **Linter/Formatter**: Biome
|
|
53
155
|
- **Git Hooks**: Husky + lint-staged
|
|
54
156
|
|
|
55
|
-
|
|
157
|
+
### 開発環境セットアップ
|
|
56
158
|
|
|
57
|
-
|
|
159
|
+
#### 初回セットアップ(初めての方)
|
|
58
160
|
|
|
59
161
|
```bash
|
|
60
162
|
# 1. リポジトリをクローン
|
|
@@ -79,7 +181,7 @@ pnpm dev:bg
|
|
|
79
181
|
|
|
80
182
|
---
|
|
81
183
|
|
|
82
|
-
|
|
184
|
+
#### コマンドの役割
|
|
83
185
|
|
|
84
186
|
| コマンド | タイミング | 内容 |
|
|
85
187
|
|---------|-----------|------|
|
|
@@ -90,9 +192,9 @@ pnpm dev:bg
|
|
|
90
192
|
| `pnpm dev:stop` | 随時 | 開発サーバーを停止 |
|
|
91
193
|
| `pnpm env:update` | 随時 | 環境変数の設定・変更(対話式ウィザード) |
|
|
92
194
|
|
|
93
|
-
|
|
195
|
+
### 主要コマンド
|
|
94
196
|
|
|
95
|
-
|
|
197
|
+
#### 開発
|
|
96
198
|
|
|
97
199
|
```bash
|
|
98
200
|
pnpm dev:bg # 開発サーバーをバックグラウンドで起動(推奨)
|
|
@@ -104,7 +206,7 @@ pnpm build # 全アプリのプロダクションビルド
|
|
|
104
206
|
pnpm start # プロダクションサーバーを起動
|
|
105
207
|
```
|
|
106
208
|
|
|
107
|
-
|
|
209
|
+
#### 環境変数の管理
|
|
108
210
|
|
|
109
211
|
対話式ウィザードで環境変数を設定・変更できます:
|
|
110
212
|
|
|
@@ -112,13 +214,13 @@ pnpm start # プロダクションサーバーを起動
|
|
|
112
214
|
pnpm env:update
|
|
113
215
|
```
|
|
114
216
|
|
|
115
|
-
|
|
217
|
+
##### メニュー
|
|
116
218
|
|
|
117
219
|
1. **個人トークンを設定** - `GITHUB_TOKEN` 等の個人用トークンを `.env.personal` に設定
|
|
118
220
|
2. **環境設定を変更** - 各環境の暗号化された設定ファイルを編集
|
|
119
221
|
3. **現在の状態を確認** - 環境変数の設定状況を表示
|
|
120
222
|
|
|
121
|
-
|
|
223
|
+
##### 対応環境
|
|
122
224
|
|
|
123
225
|
| 環境 | ファイル | 用途 |
|
|
124
226
|
|------|----------|------|
|
|
@@ -130,7 +232,7 @@ pnpm env:update
|
|
|
130
232
|
|
|
131
233
|
> **Note**: 環境設定の変更には `.env.keys` の秘密鍵が必要です。本番環境の変更時は追加の確認が表示されます。
|
|
132
234
|
|
|
133
|
-
|
|
235
|
+
#### コード品質
|
|
134
236
|
|
|
135
237
|
```bash
|
|
136
238
|
pnpm lint # Biome linterでコードをチェック
|
|
@@ -140,7 +242,7 @@ pnpm format:fix # Biomeでコードを自動フォーマット
|
|
|
140
242
|
pnpm typecheck # TypeScriptの型チェック
|
|
141
243
|
```
|
|
142
244
|
|
|
143
|
-
|
|
245
|
+
#### テスト
|
|
144
246
|
|
|
145
247
|
```bash
|
|
146
248
|
pnpm test # Vitestでテスト実行
|
|
@@ -149,7 +251,7 @@ pnpm test:ui # Vitest UIモード
|
|
|
149
251
|
pnpm test:coverage # カバレッジ付きテスト
|
|
150
252
|
```
|
|
151
253
|
|
|
152
|
-
|
|
254
|
+
#### データベース
|
|
153
255
|
|
|
154
256
|
```bash
|
|
155
257
|
pnpm db:generate # Prismaクライアント生成
|
|
@@ -158,7 +260,7 @@ pnpm db:migrate # マイグレーションファイル作成&実行
|
|
|
158
260
|
pnpm db:studio # Prisma Studio起動
|
|
159
261
|
```
|
|
160
262
|
|
|
161
|
-
|
|
263
|
+
#### ワークスペース固有のコマンド
|
|
162
264
|
|
|
163
265
|
```bash
|
|
164
266
|
# 特定のワークスペースでコマンド実行
|
|
@@ -167,9 +269,9 @@ pnpm --filter @repo/web build
|
|
|
167
269
|
pnpm --filter @repo/web panda codegen
|
|
168
270
|
```
|
|
169
271
|
|
|
170
|
-
|
|
272
|
+
### データベース設定
|
|
171
273
|
|
|
172
|
-
|
|
274
|
+
#### Docker Compose サービス
|
|
173
275
|
|
|
174
276
|
- **postgres**: PostgreSQL 15
|
|
175
277
|
- ポート: `${POSTGRES_PORT:-25432}` (ホスト) → 5432 (コンテナ)
|
|
@@ -177,7 +279,7 @@ pnpm --filter @repo/web panda codegen
|
|
|
177
279
|
- ユーザー: `postgres`
|
|
178
280
|
- パスワード: `postgres`
|
|
179
281
|
|
|
180
|
-
|
|
282
|
+
#### 便利なコマンド
|
|
181
283
|
|
|
182
284
|
```bash
|
|
183
285
|
# ログを確認
|
|
@@ -195,9 +297,9 @@ pnpm db:push
|
|
|
195
297
|
pnpm db:studio
|
|
196
298
|
```
|
|
197
299
|
|
|
198
|
-
|
|
300
|
+
### ディレクトリ構造の詳細
|
|
199
301
|
|
|
200
|
-
|
|
302
|
+
#### apps/web
|
|
201
303
|
|
|
202
304
|
メイン管理画面アプリケーション
|
|
203
305
|
|
|
@@ -207,37 +309,38 @@ pnpm db:studio
|
|
|
207
309
|
- `shared/`: 共通コンポーネント(Header, Sidebarなど)
|
|
208
310
|
- **src/lib**: ユーティリティ、認証設定など
|
|
209
311
|
|
|
210
|
-
|
|
312
|
+
#### packages
|
|
211
313
|
|
|
314
|
+
- **@einja/dev-cli**: Claude Code設定配布CLI([詳細](./packages/cli/README.md))
|
|
315
|
+
- **create-einja-app**: プロジェクト作成CLI([詳細](./packages/create-einja-app/README.md))
|
|
212
316
|
- **@repo/config**: Biome, TypeScript, Panda CSSの共通設定
|
|
213
317
|
- **@repo/front-core**: フロントエンド共通層(認証共通設定、hooks、utils、context)
|
|
214
318
|
- **@repo/server-core**: バックエンド共通層(Prismaクライアント・スキーマ、ドメインロジック)
|
|
215
319
|
- **@repo/ui**: 共通UIコンポーネント(shadcn/ui)
|
|
216
|
-
- **@einja/dev-cli**: Claude Code設定配布CLI([詳細](./packages/cli/README.md))
|
|
217
320
|
|
|
218
|
-
|
|
321
|
+
### CLIパッケージの開発
|
|
219
322
|
|
|
220
|
-
|
|
323
|
+
#### @einja/dev-cli
|
|
221
324
|
|
|
222
325
|
```bash
|
|
223
|
-
|
|
224
|
-
|
|
326
|
+
cd packages/cli
|
|
327
|
+
pnpm build # ビルド
|
|
328
|
+
pnpm test # テスト
|
|
329
|
+
pnpm typecheck # 型チェック
|
|
225
330
|
```
|
|
226
331
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
- `.claude/` - エージェント、コマンド、スキル、hooks
|
|
230
|
-
- `docs/einja/` - テンプレート、ステアリングドキュメント
|
|
231
|
-
- `CLAUDE.md` - プロジェクト設定テンプレート
|
|
332
|
+
📖 [ビルドプロセス](./packages/cli/docs/BUILD.md) | [NPM公開手順](./packages/cli/docs/PUBLISHING.md) | [リリース手順](./packages/cli/RELEASING.md)
|
|
232
333
|
|
|
233
|
-
|
|
334
|
+
#### create-einja-app
|
|
234
335
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
336
|
+
```bash
|
|
337
|
+
cd packages/create-einja-app
|
|
338
|
+
pnpm build # ビルド(テンプレート更新含む)
|
|
339
|
+
pnpm test # テスト
|
|
340
|
+
pnpm typecheck # 型チェック
|
|
341
|
+
```
|
|
239
342
|
|
|
240
|
-
|
|
343
|
+
### 開発ワークフロー
|
|
241
344
|
|
|
242
345
|
1. ブランチを作成
|
|
243
346
|
2. コードを変更
|
|
@@ -247,9 +350,9 @@ npx @einja/dev-cli init
|
|
|
247
350
|
6. コミット前に自動的にlint-stagedが実行される
|
|
248
351
|
7. プルリクエストを作成
|
|
249
352
|
|
|
250
|
-
|
|
353
|
+
### トラブルシューティング
|
|
251
354
|
|
|
252
|
-
|
|
355
|
+
#### Volta関連エラー
|
|
253
356
|
|
|
254
357
|
**`zsh: command not found: volta`**
|
|
255
358
|
|
|
@@ -272,14 +375,14 @@ pnpmがインストールされていません:
|
|
|
272
375
|
volta install pnpm@10.14.0
|
|
273
376
|
```
|
|
274
377
|
|
|
275
|
-
|
|
378
|
+
#### Panda CSS関連エラー
|
|
276
379
|
|
|
277
380
|
```bash
|
|
278
381
|
# styled-systemを再生成
|
|
279
382
|
pnpm --filter @repo/web panda codegen
|
|
280
383
|
```
|
|
281
384
|
|
|
282
|
-
|
|
385
|
+
#### Prisma関連エラー
|
|
283
386
|
|
|
284
387
|
```bash
|
|
285
388
|
# Prismaクライアントを再生成
|
|
@@ -291,7 +394,7 @@ docker-compose up -d postgres
|
|
|
291
394
|
pnpm db:push
|
|
292
395
|
```
|
|
293
396
|
|
|
294
|
-
|
|
397
|
+
#### 依存関係の問題
|
|
295
398
|
|
|
296
399
|
```bash
|
|
297
400
|
# node_modulesをクリーンアップ
|
|
@@ -300,14 +403,14 @@ rm pnpm-lock.yaml
|
|
|
300
403
|
pnpm install
|
|
301
404
|
```
|
|
302
405
|
|
|
303
|
-
|
|
406
|
+
#### Turborepoキャッシュのクリア
|
|
304
407
|
|
|
305
408
|
```bash
|
|
306
409
|
# .turboディレクトリを削除
|
|
307
410
|
rm -rf .turbo apps/*/.turbo packages/*/.turbo
|
|
308
411
|
```
|
|
309
412
|
|
|
310
|
-
|
|
413
|
+
### コーディング規約
|
|
311
414
|
|
|
312
415
|
詳細は以下のドキュメントを参照してください:
|
|
313
416
|
|
|
@@ -317,6 +420,8 @@ rm -rf .turbo apps/*/.turbo packages/*/.turbo
|
|
|
317
420
|
- [コードレビューガイドライン](./docs/einja/steering/development/review-guidelines.md)
|
|
318
421
|
- [コミットルール](./docs/einja/steering/commit-rules.md)
|
|
319
422
|
|
|
423
|
+
---
|
|
424
|
+
|
|
320
425
|
## ライセンス
|
|
321
426
|
|
|
322
427
|
Proprietary
|
|
@@ -5,13 +5,10 @@
|
|
|
5
5
|
* ユーザー一覧・詳細取得エンドポイント
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { Hono } from "hono";
|
|
9
8
|
import { zValidator } from "@hono/zod-validator";
|
|
10
|
-
import {
|
|
11
|
-
userListQuerySchema,
|
|
12
|
-
userIdParamSchema,
|
|
13
|
-
} from "{{packageName}}/server-core/domain/validators/user";
|
|
9
|
+
import { userIdParamSchema, userListQuerySchema } from "{{packageName}}/server-core/domain/validators/user";
|
|
14
10
|
import { userUseCases } from "@web/application/use-cases/UserUseCases";
|
|
11
|
+
import { Hono } from "hono";
|
|
15
12
|
|
|
16
13
|
/**
|
|
17
14
|
* ユーザーAPI ルート
|
|
@@ -63,127 +63,124 @@ function createColumns(
|
|
|
63
63
|
onDelete?: (userId: string) => void
|
|
64
64
|
): ColumnDef<UserListItem>[] {
|
|
65
65
|
return [
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
66
|
+
{
|
|
67
|
+
accessorKey: "name",
|
|
68
|
+
header: ({ column }) => {
|
|
69
|
+
return (
|
|
70
|
+
<Button
|
|
71
|
+
variant="ghost"
|
|
72
|
+
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
|
73
|
+
>
|
|
74
|
+
名前
|
|
75
|
+
<ArrowUpDown className="ml-2 h-4 w-4" />
|
|
76
|
+
</Button>
|
|
77
|
+
);
|
|
78
|
+
},
|
|
79
|
+
cell: ({ row }) => {
|
|
80
|
+
const name = row.getValue("name") as string;
|
|
81
|
+
return <div className="font-medium">{name || "-"}</div>;
|
|
82
|
+
},
|
|
78
83
|
},
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
{
|
|
85
|
+
accessorKey: "email",
|
|
86
|
+
header: ({ column }) => {
|
|
87
|
+
return (
|
|
88
|
+
<Button
|
|
89
|
+
variant="ghost"
|
|
90
|
+
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
|
91
|
+
>
|
|
92
|
+
メールアドレス
|
|
93
|
+
<ArrowUpDown className="ml-2 h-4 w-4" />
|
|
94
|
+
</Button>
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
cell: ({ row }) => {
|
|
98
|
+
return <div className="text-muted-foreground">{row.getValue("email")}</div>;
|
|
99
|
+
},
|
|
82
100
|
},
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
|
91
|
-
>
|
|
92
|
-
メールアドレス
|
|
93
|
-
<ArrowUpDown className="ml-2 h-4 w-4" />
|
|
94
|
-
</Button>
|
|
95
|
-
);
|
|
101
|
+
{
|
|
102
|
+
accessorKey: "status",
|
|
103
|
+
header: "ステータス",
|
|
104
|
+
cell: ({ row }) => {
|
|
105
|
+
const status = row.getValue("status") as UserListItem["status"];
|
|
106
|
+
return getStatusBadge(status);
|
|
107
|
+
},
|
|
96
108
|
},
|
|
97
|
-
|
|
98
|
-
|
|
109
|
+
{
|
|
110
|
+
accessorKey: "role",
|
|
111
|
+
header: "ロール",
|
|
112
|
+
cell: ({ row }) => {
|
|
113
|
+
const role = row.getValue("role") as UserListItem["role"];
|
|
114
|
+
return getRoleBadge(role);
|
|
115
|
+
},
|
|
99
116
|
},
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
117
|
+
{
|
|
118
|
+
accessorKey: "createdAt",
|
|
119
|
+
header: ({ column }) => {
|
|
120
|
+
return (
|
|
121
|
+
<Button
|
|
122
|
+
variant="ghost"
|
|
123
|
+
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
|
124
|
+
>
|
|
125
|
+
作成日
|
|
126
|
+
<ArrowUpDown className="ml-2 h-4 w-4" />
|
|
127
|
+
</Button>
|
|
128
|
+
);
|
|
129
|
+
},
|
|
130
|
+
cell: ({ row }) => {
|
|
131
|
+
return <div>{formatDate(row.getValue("createdAt"))}</div>;
|
|
132
|
+
},
|
|
107
133
|
},
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
134
|
+
{
|
|
135
|
+
accessorKey: "lastLogin",
|
|
136
|
+
header: ({ column }) => {
|
|
137
|
+
return (
|
|
138
|
+
<Button
|
|
139
|
+
variant="ghost"
|
|
140
|
+
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
|
141
|
+
>
|
|
142
|
+
最終ログイン
|
|
143
|
+
<ArrowUpDown className="ml-2 h-4 w-4" />
|
|
144
|
+
</Button>
|
|
145
|
+
);
|
|
146
|
+
},
|
|
147
|
+
cell: ({ row }) => {
|
|
148
|
+
return <div>{formatDate(row.getValue("lastLogin"))}</div>;
|
|
149
|
+
},
|
|
115
150
|
},
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
variant="ghost"
|
|
123
|
-
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
|
124
|
-
>
|
|
125
|
-
作成日
|
|
126
|
-
<ArrowUpDown className="ml-2 h-4 w-4" />
|
|
127
|
-
</Button>
|
|
128
|
-
);
|
|
129
|
-
},
|
|
130
|
-
cell: ({ row }) => {
|
|
131
|
-
return <div>{formatDate(row.getValue("createdAt"))}</div>;
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
accessorKey: "lastLogin",
|
|
136
|
-
header: ({ column }) => {
|
|
137
|
-
return (
|
|
138
|
-
<Button
|
|
139
|
-
variant="ghost"
|
|
140
|
-
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
|
141
|
-
>
|
|
142
|
-
最終ログイン
|
|
143
|
-
<ArrowUpDown className="ml-2 h-4 w-4" />
|
|
144
|
-
</Button>
|
|
145
|
-
);
|
|
146
|
-
},
|
|
147
|
-
cell: ({ row }) => {
|
|
148
|
-
return <div>{formatDate(row.getValue("lastLogin"))}</div>;
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
id: "actions",
|
|
153
|
-
header: "操作",
|
|
154
|
-
enableHiding: false,
|
|
155
|
-
cell: ({ row }) => {
|
|
156
|
-
const user = row.original;
|
|
151
|
+
{
|
|
152
|
+
id: "actions",
|
|
153
|
+
header: "操作",
|
|
154
|
+
enableHiding: false,
|
|
155
|
+
cell: ({ row }) => {
|
|
156
|
+
const user = row.original;
|
|
157
157
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
</DropdownMenu>
|
|
184
|
-
);
|
|
158
|
+
return (
|
|
159
|
+
<DropdownMenu>
|
|
160
|
+
<DropdownMenuTrigger asChild>
|
|
161
|
+
<Button variant="ghost" className="h-8 w-8 p-0">
|
|
162
|
+
<span className="sr-only">メニューを開く</span>
|
|
163
|
+
<MoreHorizontal className="h-4 w-4" />
|
|
164
|
+
</Button>
|
|
165
|
+
</DropdownMenuTrigger>
|
|
166
|
+
<DropdownMenuContent align="end">
|
|
167
|
+
<DropdownMenuItem onClick={() => onView?.(user.id)}>
|
|
168
|
+
<Eye className="mr-2 h-4 w-4" />
|
|
169
|
+
詳細表示
|
|
170
|
+
</DropdownMenuItem>
|
|
171
|
+
<DropdownMenuItem onClick={() => onEdit?.(user.id)}>
|
|
172
|
+
<Edit className="mr-2 h-4 w-4" />
|
|
173
|
+
編集
|
|
174
|
+
</DropdownMenuItem>
|
|
175
|
+
<DropdownMenuItem onClick={() => onDelete?.(user.id)} className="text-destructive">
|
|
176
|
+
<Trash2 className="mr-2 h-4 w-4" />
|
|
177
|
+
削除
|
|
178
|
+
</DropdownMenuItem>
|
|
179
|
+
</DropdownMenuContent>
|
|
180
|
+
</DropdownMenu>
|
|
181
|
+
);
|
|
182
|
+
},
|
|
185
183
|
},
|
|
186
|
-
},
|
|
187
184
|
];
|
|
188
185
|
}
|
|
189
186
|
|
package/templates/default/apps/web/src/app/(authenticated)/data/_components/UserTableContainer.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import type { PaginatedUserList } from "
|
|
3
|
+
import { type UserFilters, useUsers } from "@/hooks/api/use-users";
|
|
4
|
+
import type { PaginatedUserList } from "@/shared/schemas/user";
|
|
5
5
|
import { UserTable } from "./UserTable";
|
|
6
6
|
|
|
7
7
|
interface UserTableContainerProps {
|
|
@@ -14,10 +14,7 @@ interface UserTableContainerProps {
|
|
|
14
14
|
*
|
|
15
15
|
* Client Component - Tanstack Queryでデータ管理
|
|
16
16
|
*/
|
|
17
|
-
export function UserTableContainer({
|
|
18
|
-
initialData,
|
|
19
|
-
filters = {},
|
|
20
|
-
}: UserTableContainerProps) {
|
|
17
|
+
export function UserTableContainer({ initialData, filters = {} }: UserTableContainerProps) {
|
|
21
18
|
const { data, isLoading, error } = useUsers(filters, initialData);
|
|
22
19
|
|
|
23
20
|
const handleView = (userId: string) => {
|
|
@@ -36,11 +33,7 @@ export function UserTableContainer({
|
|
|
36
33
|
};
|
|
37
34
|
|
|
38
35
|
if (error) {
|
|
39
|
-
return
|
|
40
|
-
<div className="text-destructive">
|
|
41
|
-
エラーが発生しました: {error.message}
|
|
42
|
-
</div>
|
|
43
|
-
);
|
|
36
|
+
return <div className="text-destructive">エラーが発生しました: {error.message}</div>;
|
|
44
37
|
}
|
|
45
38
|
|
|
46
39
|
if (isLoading) {
|
|
@@ -52,11 +45,6 @@ export function UserTableContainer({
|
|
|
52
45
|
}
|
|
53
46
|
|
|
54
47
|
return (
|
|
55
|
-
<UserTable
|
|
56
|
-
users={data.items}
|
|
57
|
-
onView={handleView}
|
|
58
|
-
onEdit={handleEdit}
|
|
59
|
-
onDelete={handleDelete}
|
|
60
|
-
/>
|
|
48
|
+
<UserTable users={data.items} onView={handleView} onEdit={handleEdit} onDelete={handleDelete} />
|
|
61
49
|
);
|
|
62
50
|
}
|