products now have an image
This commit is contained in:
@@ -10,5 +10,5 @@ class Product extends Model
|
|||||||
/** @use HasFactory<\Database\Factories\ProductFactory> */
|
/** @use HasFactory<\Database\Factories\ProductFactory> */
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
protected $fillable = ['name', 'description', 'price_cents'];
|
protected $fillable = ['name', 'description', 'price_cents', 'image_url'];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class ProductFactory extends Factory
|
|||||||
'name' => $this->faker->words(3, true),
|
'name' => $this->faker->words(3, true),
|
||||||
'description' => $this->faker->sentence(12),
|
'description' => $this->faker->sentence(12),
|
||||||
'price_cents' => $this->faker->numberBetween(499, 9999),
|
'price_cents' => $this->faker->numberBetween(499, 9999),
|
||||||
|
'image_url' => null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('products', function (Blueprint $table) {
|
||||||
|
$table->string('image_url')->nullable()->after('description');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('products', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('image_url');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -16,29 +16,32 @@ class DatabaseSeeder extends Seeder
|
|||||||
{
|
{
|
||||||
// User::factory(10)->create();
|
// User::factory(10)->create();
|
||||||
|
|
||||||
//User::factory()->create([
|
User::factory()->create([
|
||||||
// 'name' => 'Test User',
|
'name' => 'Test User',
|
||||||
// 'email' => 'test@example.com',
|
'email' => 'test@example.com',
|
||||||
//]);
|
]);
|
||||||
|
|
||||||
Product::create([
|
Product::create([
|
||||||
'name' => 'Ant Spray',
|
'name' => 'Ant Deterrant',
|
||||||
'description' => '',
|
'description' => 'A common problem we can easily take care of!',
|
||||||
'price' => 10000,
|
'price_cents' => 10000,
|
||||||
|
'image_url' => 'https://shopping-cart.test/storage/products/ant.jpg'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
Product::create([
|
Product::create([
|
||||||
'name' => 'Spider Spray',
|
'name' => 'Spider Removal',
|
||||||
'description' => '',
|
'description' => 'More aggressive that just removing the little ones.',
|
||||||
'price' => 25000,
|
'price_cents' => 25000,
|
||||||
|
'image_url' => 'https://shopping-cart.test/storage/products/spider.jpg'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
Product::create([
|
Product::create([
|
||||||
'name' => 'Infestation Spray',
|
'name' => 'Infestation Mitigation',
|
||||||
'description' => '',
|
'description' => 'Time to call in DOOM guy.',
|
||||||
'price' => 50000,
|
'price_cents' => 50000,
|
||||||
|
'image_url' => 'https://shopping-cart.test/storage/products/hydralisk.webp'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ createInertiaApp({
|
|||||||
layout: (name) => {
|
layout: (name) => {
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case name === 'Welcome':
|
case name === 'Welcome':
|
||||||
|
case name === 'Home':
|
||||||
return null;
|
return null;
|
||||||
case name.startsWith('auth/'):
|
case name.startsWith('auth/'):
|
||||||
return AuthLayout;
|
return AuthLayout;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ interface Product {
|
|||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
price_cents: number;
|
price_cents: number;
|
||||||
|
image_url: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@@ -22,23 +23,34 @@ function formatPrice(cents: number): string {
|
|||||||
<link rel="preconnect" href="https://rsms.me/" />
|
<link rel="preconnect" href="https://rsms.me/" />
|
||||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
||||||
</Head>
|
</Head>
|
||||||
<div class="min-h-screen bg-[#FDFDFC] p-6 text-[#1b1b18] dark:bg-[#0a0a0a] lg:p-8">
|
<div class="min-h-screen bg-[#FDFDFC] p-6 text-[#1b1b18] dark:bg-[#0a0a0a] dark:text-[#FDFDFC] lg:p-8">
|
||||||
<header class="mx-auto mb-8 max-w-4xl">
|
<header class="mx-auto mb-8 max-w-4xl">
|
||||||
<h1 class="text-2xl font-semibold">Products</h1>
|
<h1 class="text-2xl font-semibold">Packages</h1>
|
||||||
</header>
|
</header>
|
||||||
<main class="mx-auto max-w-4xl">
|
<main class="mx-auto max-w-4xl">
|
||||||
<p v-if="products.length === 0" class="text-gray-500">No products available.</p>
|
<p v-if="products.length === 0" class="text-gray-500">No packages available.</p>
|
||||||
<div v-else class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
<div v-else class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
<div
|
<div
|
||||||
v-for="product in products"
|
v-for="product in products"
|
||||||
:key="product.id"
|
:key="product.id"
|
||||||
class="rounded-lg border border-gray-200 bg-white p-5 shadow-sm dark:border-gray-700 dark:bg-gray-800"
|
class="overflow-hidden rounded-lg border border-gray-200 bg-white shadow-sm dark:border-gray-700 dark:bg-gray-800"
|
||||||
>
|
>
|
||||||
|
<img
|
||||||
|
v-if="product.image_url"
|
||||||
|
:src="product.image_url"
|
||||||
|
:alt="product.name"
|
||||||
|
class="h-48 w-full object-cover"
|
||||||
|
/>
|
||||||
|
<div v-else class="flex h-48 items-center justify-center bg-gray-100 dark:bg-gray-700">
|
||||||
|
<span class="text-sm text-gray-400">No image</span>
|
||||||
|
</div>
|
||||||
|
<div class="p-5">
|
||||||
<h2 class="mb-1 font-medium capitalize">{{ product.name }}</h2>
|
<h2 class="mb-1 font-medium capitalize">{{ product.name }}</h2>
|
||||||
<p class="mb-4 text-sm text-gray-500 dark:text-gray-400">{{ product.description }}</p>
|
<p class="mb-4 text-sm text-gray-500 dark:text-gray-400">{{ product.description }}</p>
|
||||||
<p class="text-lg font-semibold">{{ formatPrice(product.price_cents) }}</p>
|
<p class="text-lg font-semibold">{{ formatPrice(product.price_cents) }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user