-
Notifications
You must be signed in to change notification settings - Fork 0
Dev include bug #2
base: replay-2-base-d7ff49b
Are you sure you want to change the base?
Changes from all commits
0f32688
66d8fb0
99a5f95
546577f
aeb1860
88267db
67e44a3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "extends": "next/core-web-vitals" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
|
||
| # dependencies | ||
| /node_modules | ||
| /.pnp | ||
| .pnp.js | ||
|
|
||
| # testing | ||
| /coverage | ||
|
|
||
| # next.js | ||
| /.next/ | ||
| /out/ | ||
|
|
||
| # production | ||
| /build | ||
|
|
||
| # misc | ||
| .DS_Store | ||
| *.pem | ||
|
|
||
| # debug | ||
| npm-debug.log* | ||
| yarn-debug.log* | ||
| yarn-error.log* | ||
|
|
||
| # local env files | ||
| .env*.local | ||
| .env | ||
|
|
||
| # vercel | ||
| .vercel | ||
|
|
||
| # typescript | ||
| *.tsbuildinfo | ||
| next-env.d.ts | ||
|
|
||
| # prisma | ||
| /prisma/*.db | ||
| /prisma/*.db-journal | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1 +1,97 @@ | ||||||||||||||||||||||||||||||||||||||
| # todo-review-test | ||||||||||||||||||||||||||||||||||||||
| # TODO管理アプリ | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| 簡易的なTODO管理Webアプリケーションです。 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## 技術スタック | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - **フレームワーク**: Next.js 14 (App Router) | ||||||||||||||||||||||||||||||||||||||
| - **言語**: TypeScript | ||||||||||||||||||||||||||||||||||||||
| - **データベース**: SQLite (Prisma ORM) | ||||||||||||||||||||||||||||||||||||||
| - **スタイリング**: Tailwind CSS | ||||||||||||||||||||||||||||||||||||||
| - **テスト**: Vitest + Testing Library | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## 機能 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - TODOの追加 | ||||||||||||||||||||||||||||||||||||||
| - TODOの一覧表示 | ||||||||||||||||||||||||||||||||||||||
| - TODOの完了/未完了の切り替え | ||||||||||||||||||||||||||||||||||||||
| - TODOの削除 | ||||||||||||||||||||||||||||||||||||||
| - 完了済みTODOと未完了TODOの分類表示 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## セットアップ | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### 1. 依存関係のインストール | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||
| npm install | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### 2. 環境変数の設定 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| `.env`ファイルを作成し、以下の内容を追加してください: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
| DATABASE_URL="file:./prisma/dev.db" | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+33
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add language specifier to fenced code block. The static analysis tool flagged this code block as missing a language specifier. Consider adding 📝 Proposed fix-```
+```dotenv
DATABASE_URL="file:./prisma/dev.db"🧰 Tools🪛 markdownlint-cli2 (0.18.1)33-33: Fenced code blocks should have a language specified (MD040, fenced-code-language) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### 3. データベースの初期化 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||
| npm run db:push | ||||||||||||||||||||||||||||||||||||||
| npm run db:generate | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### 4. 開発サーバーの起動 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||
| npm run dev | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ブラウザで [http://localhost:3000](http://localhost:3000) を開いてください。 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## スクリプト | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - `npm run dev` - 開発サーバーを起動 | ||||||||||||||||||||||||||||||||||||||
| - `npm run build` - プロダクションビルド | ||||||||||||||||||||||||||||||||||||||
| - `npm run start` - プロダクションサーバーを起動 | ||||||||||||||||||||||||||||||||||||||
| - `npm run lint` - ESLintでコードをチェック | ||||||||||||||||||||||||||||||||||||||
| - `npm run test` - テストを実行 | ||||||||||||||||||||||||||||||||||||||
| - `npm run test:watch` - ウォッチモードでテストを実行 | ||||||||||||||||||||||||||||||||||||||
| - `npm run db:push` - データベーススキーマをプッシュ | ||||||||||||||||||||||||||||||||||||||
| - `npm run db:generate` - Prismaクライアントを生成 | ||||||||||||||||||||||||||||||||||||||
| - `npm run db:studio` - Prisma Studioを起動 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## プロジェクト構造 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
| todo-review-test/ | ||||||||||||||||||||||||||||||||||||||
| ├── app/ | ||||||||||||||||||||||||||||||||||||||
| │ ├── api/ | ||||||||||||||||||||||||||||||||||||||
| │ │ └── todos/ # TODO APIエンドポイント | ||||||||||||||||||||||||||||||||||||||
| │ ├── globals.css # グローバルスタイル | ||||||||||||||||||||||||||||||||||||||
| │ ├── layout.tsx # ルートレイアウト | ||||||||||||||||||||||||||||||||||||||
| │ └── page.tsx # ホームページ | ||||||||||||||||||||||||||||||||||||||
| ├── components/ | ||||||||||||||||||||||||||||||||||||||
| │ ├── TodoForm.tsx # TODO追加フォーム | ||||||||||||||||||||||||||||||||||||||
| │ ├── TodoList.tsx # TODO一覧 | ||||||||||||||||||||||||||||||||||||||
| │ └── TodoItem.tsx # TODOアイテム | ||||||||||||||||||||||||||||||||||||||
| ├── lib/ | ||||||||||||||||||||||||||||||||||||||
| │ └── prisma.ts # Prismaクライアント | ||||||||||||||||||||||||||||||||||||||
| ├── prisma/ | ||||||||||||||||||||||||||||||||||||||
| │ └── schema.prisma # データベーススキーマ | ||||||||||||||||||||||||||||||||||||||
| └── tests/ # テストファイル | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+66
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add language specifier to fenced code block. The project structure code block is missing a language specifier. Use 📝 Proposed fix-```
+```text
todo-review-test/
├── app/📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.18.1)66-66: Fenced code blocks should have a language specified (MD040, fenced-code-language) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## 拡張性 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| このアプリケーションは以下の点で拡張しやすく設計されています: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - **型安全性**: TypeScriptとPrismaによる完全な型安全性 | ||||||||||||||||||||||||||||||||||||||
| - **モジュール設計**: コンポーネントとAPIルートの分離 | ||||||||||||||||||||||||||||||||||||||
| - **データベース**: SQLiteからPostgreSQLなどへの移行が容易 | ||||||||||||||||||||||||||||||||||||||
| - **テスト**: 包括的なテストカバレッジ | ||||||||||||||||||||||||||||||||||||||
| - **バリデーション**: Zodによる入力検証 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## ライセンス | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| MIT | ||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| import { NextRequest, NextResponse } from 'next/server' | ||
| import { prisma } from '@/lib/prisma' | ||
| import { z } from 'zod' | ||
|
|
||
| const updateTodoSchema = z.object({ | ||
| title: z.string().min(1, 'タイトルは必須です').max(200, 'タイトルは200文字以内で入力してください').optional(), | ||
| description: z.string().max(1000, '説明は1000文字以内で入力してください').optional(), | ||
| completed: z.boolean().optional(), | ||
| }) | ||
|
|
||
| // GET: 特定のTODOを取得 | ||
| export async function GET( | ||
| request: NextRequest, | ||
| { params }: { params: Promise<{ id: string }> } | ||
| ) { | ||
| try { | ||
| const { id } = await params | ||
| const todo = await prisma.todo.findUnique({ | ||
| where: { id }, | ||
| }) | ||
|
|
||
| if (!todo) { | ||
| return NextResponse.json( | ||
| { error: 'TODOが見つかりません' }, | ||
| { status: 404 } | ||
| ) | ||
| } | ||
|
|
||
| return NextResponse.json(todo) | ||
| } catch (error) { | ||
| console.error('Error fetching todo:', error) | ||
| return NextResponse.json( | ||
| { error: 'TODOの取得に失敗しました' }, | ||
| { status: 500 } | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| // PATCH: TODOを更新 | ||
| export async function PATCH( | ||
| request: NextRequest, | ||
| { params }: { params: Promise<{ id: string }> } | ||
| ) { | ||
| try { | ||
| const { id } = await params | ||
| const body = await request.json() | ||
| const validatedData = updateTodoSchema.parse(body) | ||
|
|
||
| const todo = await prisma.todo.update({ | ||
| where: { id }, | ||
| data: validatedData, | ||
| }) | ||
|
|
||
| return NextResponse.json(todo) | ||
| } catch (error) { | ||
| if (error instanceof z.ZodError) { | ||
| return NextResponse.json( | ||
| { error: error.errors[0].message }, | ||
| { status: 400 } | ||
| ) | ||
| } | ||
| if (error instanceof Error && error.message.includes('Record to update not found')) { | ||
| return NextResponse.json( | ||
| { error: 'TODOが見つかりません' }, | ||
| { status: 404 } | ||
| ) | ||
| } | ||
| console.error('Error updating todo:', error) | ||
| return NextResponse.json( | ||
| { error: 'TODOの更新に失敗しました' }, | ||
| { status: 500 } | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| // DELETE: TODOを削除 | ||
| export async function DELETE( | ||
| request: NextRequest, | ||
| { params }: { params: Promise<{ id: string }> } | ||
| ) { | ||
| try { | ||
| const { id } = await params | ||
| await prisma.todo.delete({ | ||
| where: { id }, | ||
| }) | ||
|
|
||
| return NextResponse.json({ message: 'TODOを削除しました' }) | ||
| } catch (error) { | ||
| if (error instanceof Error && error.message.includes('Record to delete does not exist')) { | ||
| return NextResponse.json( | ||
| { error: 'TODOが見つかりません' }, | ||
| { status: 404 } | ||
| ) | ||
| } | ||
| console.error('Error deleting todo:', error) | ||
| return NextResponse.json( | ||
| { error: 'TODOの削除に失敗しました' }, | ||
| { status: 500 } | ||
| ) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| import { NextRequest, NextResponse } from 'next/server' | ||
| import { prisma } from '@/lib/prisma' | ||
| import { z } from 'zod' | ||
|
|
||
| const todoSchema = z.object({ | ||
| title: z.string().min(1, 'タイトルは必須です').max(200, 'タイトルは200文字以内で入力してください'), | ||
| description: z.string().max(1000, '説明は1000文字以内で入力してください').optional(), | ||
| }) | ||
|
|
||
| // GET: すべてのTODOを取得 | ||
| export async function GET() { | ||
| try { | ||
| const todos = await prisma.todo.findMany({ | ||
| orderBy: { | ||
| createdAt: 'desc', | ||
| }, | ||
| }) | ||
| return NextResponse.json(todos) | ||
| } catch (error) { | ||
| console.error('Error fetching todos:', error) | ||
| return NextResponse.json( | ||
| { error: 'TODOの取得に失敗しました' }, | ||
| { status: 500 } | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| // POST: 新しいTODOを作成 | ||
| export async function POST(request: NextRequest) { | ||
| try { | ||
| const body = await request.json() | ||
| const validatedData = todoSchema.parse(body) | ||
|
|
||
| const todo = await prisma.todo.create({ | ||
| data: { | ||
| title: validatedData.title, | ||
| description: validatedData.description, | ||
| }, | ||
| }) | ||
|
|
||
| return NextResponse.json(todo, { status: 201 }) | ||
| } catch (error) { | ||
| if (error instanceof z.ZodError) { | ||
| return NextResponse.json( | ||
| { error: error.errors[0].message }, | ||
| { status: 400 } | ||
| ) | ||
| } | ||
| console.error('Error creating todo:', error) | ||
| return NextResponse.json( | ||
| { error: 'TODOの作成に失敗しました' }, | ||
| { status: 500 } | ||
| ) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| @tailwind base; | ||
| @tailwind components; | ||
| @tailwind utilities; | ||
|
|
||
| :root { | ||
| --background: #ffffff; | ||
| --foreground: #171717; | ||
| } | ||
|
|
||
| @media (prefers-color-scheme: dark) { | ||
| :root { | ||
| --background: #0a0a0a; | ||
| --foreground: #ededed; | ||
| } | ||
| } | ||
|
|
||
| body { | ||
| color: var(--foreground); | ||
| background: var(--background); | ||
| font-family: Arial, Helvetica, sans-serif; | ||
| } | ||
|
|
||
| @layer utilities { | ||
| .text-balance { | ||
| text-wrap: balance; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import type { Metadata } from "next"; | ||
| import "./globals.css"; | ||
|
|
||
| export const metadata: Metadata = { | ||
| title: "TODO管理アプリ", | ||
| description: "簡易的なTODO管理Webアプリケーション", | ||
| }; | ||
|
|
||
| export default function RootLayout({ | ||
| children, | ||
| }: Readonly<{ | ||
| children: React.ReactNode; | ||
| }>) { | ||
| return ( | ||
| <html lang="ja"> | ||
| <body>{children}</body> | ||
| </html> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import TodoList from '@/components/TodoList' | ||
| import TodoForm from '@/components/TodoForm' | ||
|
|
||
| export default function Home() { | ||
| return ( | ||
| <main className="min-h-screen bg-gray-50 py-8"> | ||
| <div className="max-w-2xl mx-auto px-4"> | ||
| <h1 className="text-3xl font-bold text-gray-900 mb-8 text-center"> | ||
| TODO管理アプリ | ||
| </h1> | ||
| <div className="bg-white rounded-lg shadow-md p-6"> | ||
| <TodoForm /> | ||
| <div className="mt-8"> | ||
| <TodoList /> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </main> | ||
| ) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: admin-coderabbit/todo-review-test
Length of output: 284
🏁 Script executed:
Repository: admin-coderabbit/todo-review-test
Length of output: 114
Add a
.env.exampleor.env.templatefile to the repository.The repository correctly ignores
.envfiles for security, but developers need a template showing required environment variables. Add a.env.examplefile with placeholder values for all necessary environment variables.🤖 Prompt for AI Agents