From 857efcf2847fdc277dfc382a06b83f37540aebf8 Mon Sep 17 00:00:00 2001 From: Timotej Date: Wed, 28 Jan 2026 21:02:19 +0100 Subject: [PATCH 1/2] added swagger, logic work --- app/Http/Controllers/ProductController.php | 28 +++++ app/Models/Product.php | 18 ++++ ...026_01_28_134245_create_products_table.php | 26 +++++ database/seeders/DatabaseSeeder.php | 15 +++ database/seeders/ProductSeeder.php | 49 +++++++++ docs/openapi.yaml | 102 ++++++++++++++++++ resources/views/swagger.blade.php | 22 ++++ routes/api.php | 85 ++++----------- 8 files changed, 278 insertions(+), 67 deletions(-) create mode 100644 app/Http/Controllers/ProductController.php create mode 100644 app/Models/Product.php create mode 100644 database/migrations/2026_01_28_134245_create_products_table.php create mode 100644 database/seeders/DatabaseSeeder.php create mode 100644 database/seeders/ProductSeeder.php create mode 100644 docs/openapi.yaml create mode 100644 resources/views/swagger.blade.php diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php new file mode 100644 index 0000000..ed8a6b0 --- /dev/null +++ b/app/Http/Controllers/ProductController.php @@ -0,0 +1,28 @@ +orderByDesc('id') + ->get(); + + return response()->json([ + 'data' => $products, + ]); + } + + public function show(int $id) + { + $product = Product::query()->findOrFail($id); + + return response()->json([ + 'data' => $product, + ]); + } +} \ No newline at end of file diff --git a/app/Models/Product.php b/app/Models/Product.php new file mode 100644 index 0000000..a122968 --- /dev/null +++ b/app/Models/Product.php @@ -0,0 +1,18 @@ + 'integer', + ]; +} \ No newline at end of file diff --git a/database/migrations/2026_01_28_134245_create_products_table.php b/database/migrations/2026_01_28_134245_create_products_table.php new file mode 100644 index 0000000..085b7ec --- /dev/null +++ b/database/migrations/2026_01_28_134245_create_products_table.php @@ -0,0 +1,26 @@ +id(); + $table->string('name', 180); + $table->text('description')->nullable(); + $table->unsignedInteger('price'); + $table->string('image_url', 500)->nullable(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('products'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php new file mode 100644 index 0000000..c77250d --- /dev/null +++ b/database/seeders/DatabaseSeeder.php @@ -0,0 +1,15 @@ +call([ + ProductSeeder::class, + ]); + } +} \ No newline at end of file diff --git a/database/seeders/ProductSeeder.php b/database/seeders/ProductSeeder.php new file mode 100644 index 0000000..a352ffc --- /dev/null +++ b/database/seeders/ProductSeeder.php @@ -0,0 +1,49 @@ + 'CloudShopt Hoodie', + 'description' => 'Comfort hoodie with CloudShopt logo.', + 'price' => 4990, + 'image_url' => null, + ], + [ + 'name' => 'CloudShopt T-Shirt', + 'description' => 'Basic tee for everyday wear.', + 'price' => 1990, + 'image_url' => null, + ], + [ + 'name' => 'Sticker Pack', + 'description' => 'Set of 10 vinyl stickers.', + 'price' => 590, + 'image_url' => null, + ], + [ + 'name' => 'Coffee Mug', + 'description' => 'Ceramic mug 330ml.', + 'price' => 1290, + 'image_url' => null, + ], + [ + 'name' => 'Notebook', + 'description' => 'A5 dotted notebook.', + 'price' => 990, + 'image_url' => null, + ], + ]; + + foreach ($items as $item) { + Product::query()->create($item); + } + } +} \ No newline at end of file diff --git a/docs/openapi.yaml b/docs/openapi.yaml new file mode 100644 index 0000000..7d00ea5 --- /dev/null +++ b/docs/openapi.yaml @@ -0,0 +1,102 @@ +openapi: 3.0.3 +info: + title: CloudShopt Product Service API + version: 0.1.0 + description: API for product catalog +servers: + - url: /api +tags: + - name: meta + - name: products + +paths: + /info: + get: + tags: [meta] + summary: Service info (test endpoint) + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + service: + type: string + example: product-service + status: + type: string + example: ok + + /health: + get: + tags: [meta] + summary: Health check + responses: + "200": + description: Healthy + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + example: true + + /products: + get: + tags: [products] + summary: List products (test placeholder) + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/Product" + "500": + $ref: "#/components/responses/ServerError" + +components: + responses: + ServerError: + description: Server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + + schemas: + Product: + type: object + properties: + id: + type: integer + example: 1 + name: + type: string + example: "T-Shirt" + price: + type: number + format: float + example: 19.99 + + ErrorResponse: + type: object + properties: + message: + type: string + example: "Internal Server Error" + code: + type: string + example: "SERVER_ERROR" + details: + type: object + additionalProperties: true \ No newline at end of file diff --git a/resources/views/swagger.blade.php b/resources/views/swagger.blade.php new file mode 100644 index 0000000..34fe766 --- /dev/null +++ b/resources/views/swagger.blade.php @@ -0,0 +1,22 @@ + + + + + + API Docs + + + +
+ + + + + \ No newline at end of file diff --git a/routes/api.php b/routes/api.php index 8c550d9..f7451d7 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,8 +1,24 @@ file($path, [ + 'Content-Type' => 'application/yaml; charset=utf-8', + 'Cache-Control' => 'no-store', + ]); +}); + +Route::get('/docs', function () { + return response()->view('swagger'); +}); + Route::get('/info', function () { return response()->json([ 'ok11' => true, @@ -40,70 +56,5 @@ -Route::get('/products', function () { - return response()->json([ - [ - 'id' => 1, - 'name' => 'CloudShopt Hoodie', - 'price' => 49.90, - 'currency' => 'EUR', - 'sku' => 'CS-HOODIE-001', - 'in_stock' => true, - ], - [ - 'id' => 2, - 'name' => 'CloudShopt T-Shirt', - 'price' => 19.90, - 'currency' => 'EUR', - 'sku' => 'CS-TSHIRT-001', - 'in_stock' => true, - ], - [ - 'id' => 3, - 'name' => 'CloudShopt Mug', - 'price' => 12.90, - 'currency' => 'EUR', - 'sku' => 'CS-MUG-001', - 'in_stock' => false, - ], - ]); -}); - - -Route::get('/products/{id}', function (string $id) { - $products = [ - 1 => [ - 'id' => 1, - 'name' => 'CloudShopt Hoodie', - 'price' => 49.90, - 'currency' => 'EUR', - 'sku' => 'CS-HOODIE-001', - 'in_stock' => true, - 'description' => 'Warm hoodie for cloud-native builders.', - ], - 2 => [ - 'id' => 2, - 'name' => 'CloudShopt T-Shirt', - 'price' => 19.90, - 'currency' => 'EUR', - 'sku' => 'CS-TSHIRT-001', - 'in_stock' => true, - 'description' => 'Soft cotton tee with CloudShopt logo.', - ], - 3 => [ - 'id' => 3, - 'name' => 'CloudShopt Mug', - 'price' => 12.90, - 'currency' => 'EUR', - 'sku' => 'CS-MUG-001', - 'in_stock' => false, - 'description' => 'Ceramic mug for your morning deploys.', - ], - ]; - - if (!isset($products[(int)$id])) { - return response()->json(['message' => 'Product not found'], 404); - } - - return response()->json($products[(int)$id]); -}); \ No newline at end of file +Route::get('/items', [ProductController::class, 'index']); // /api/products +Route::get('/items/{id}', [ProductController::class, 'show']); // /api/products/{id} \ No newline at end of file From 17dab3eeb4441c47a5ba7fbcafca2552da71a7bd Mon Sep 17 00:00:00 2001 From: Timotej Date: Wed, 28 Jan 2026 21:33:05 +0100 Subject: [PATCH 2/2] cleanup --- routes/api.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/routes/api.php b/routes/api.php index f7451d7..1135c49 100644 --- a/routes/api.php +++ b/routes/api.php @@ -52,9 +52,5 @@ } }); - - - - -Route::get('/items', [ProductController::class, 'index']); // /api/products -Route::get('/items/{id}', [ProductController::class, 'show']); // /api/products/{id} \ No newline at end of file +Route::get('/items', [ProductController::class, 'index']); +Route::get('/items/{id}', [ProductController::class, 'show']); \ No newline at end of file