Skip to content

Commit

Permalink
Product show and create start
Browse files Browse the repository at this point in the history
  • Loading branch information
jlarm committed Apr 24, 2024
1 parent 1a65aee commit 34f287c
Show file tree
Hide file tree
Showing 20 changed files with 212 additions and 39 deletions.
39 changes: 39 additions & 0 deletions app/Livewire/Product/Create.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Livewire\Product;

use App\Models\Product;
use Illuminate\View\View;
use Livewire\Attributes\Validate;
use Livewire\Component;
use Livewire\WithFileUploads;

class Create extends Component
{
use WithFileUploads;

#[Validate('required|string|max:255')]
public string $name = '';
#[Validate('required|string')]
public string $description = '';
#[Validate('required|numeric')]
public string $price = '';
#[Validate('nullable|image|max:1024')]
public $image = '';

public function create()
{
$this->validate();

Product::create([
'name' => $this->pull('name'),
'description' => $this->pull('description'),
'price' => $this->pull('price'),
// 'image' => $this->pull('image')->store('products'),
]);
}
public function render(): View
{
return view('livewire.product.create')->layout('layouts.app');
}
}
8 changes: 6 additions & 2 deletions app/Livewire/Product/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
namespace App\Livewire\Product;

use App\Models\Product;
use Illuminate\View\View;
use Livewire\Component;
use Livewire\WithPagination;

class Index extends Component
{
public function render()
use WithPagination;

public function render(): View
{
return view('livewire.product.index', [
'products' => Product::all(),
'products' => Product::paginate(5),
]);
}
}
3 changes: 2 additions & 1 deletion app/Livewire/Product/IndexItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
namespace App\Livewire\Product;

use App\Models\Product;
use Illuminate\View\View;
use Livewire\Component;

class IndexItem extends Component
{
public Product $product;

public function render()
public function render(): View
{
return view('livewire.product.index-item');
}
Expand Down
16 changes: 16 additions & 0 deletions app/Livewire/Product/Show.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace App\Livewire\Product;

use App\Models\Product;
use Illuminate\View\View;
use Livewire\Component;

class Show extends Component
{
public Product $product;
public function render(): View
{
return view('livewire.product.show')->layout('layouts.app');
}
}
16 changes: 16 additions & 0 deletions app/Models/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,35 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Number;
use Illuminate\Support\Str;

class Product extends Model
{
use HasFactory, SoftDeletes;

protected $fillable = [
'uuid',
'name',
'slug',
'description',
'price',
'image',
];

protected $casts = [
'price' => 'float',
];

protected static function boot()
{
parent::boot();

static::creating(function ($model) {
$model->uuid = (string) Str::uuid();
$model->slug = Str::slug($model->name);
});
}

public function getPriceAttribute(): string
{
return Number::currency($this->attributes['price']);
Expand Down
35 changes: 18 additions & 17 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions database/factories/ProductFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public function definition(): array
return [
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
'uuid' => \Illuminate\Support\Str::uuid(),
'name' => $this->faker->word(),
'slug' => $this->faker->slug(),
'description' => $this->faker->text(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public function up(): void
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->uuid();
$table->string('name');
$table->string('slug');
$table->string('description');
Expand Down
7 changes: 7 additions & 0 deletions resources/views/components/primary-button-link.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<a
{{ $attributes }}
wire:navigate
class="inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 focus:bg-gray-700 active:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition ease-in-out duration-150"
>
{{ $slot }}
</a>
7 changes: 7 additions & 0 deletions resources/views/components/secondary-button-link.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<a
{{ $attributes }}
wire:navigate
class="inline-flex items-center px-4 py-2 bg-white border border-gray-300 rounded-md font-semibold text-xs text-gray-700 uppercase tracking-widest shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-25 transition ease-in-out duration-150"
>
{{ $slot }}
</a>
2 changes: 1 addition & 1 deletion resources/views/components/text-input.blade.php
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
@props(['disabled' => false])

<input {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm']) !!}>
<input {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md']) !!}>
50 changes: 50 additions & 0 deletions resources/views/livewire/product/create.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<div>
<x-slot name="header">
<div class="w-full flex justify-between items-baseline">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Create New Product') }}
</h2>
<x-secondary-button-link href="{{ route('products.index') }}">Cancel</x-secondary-button-link>
</div>
</x-slot>

<div class="py-12">
<div class="max-w-3xl mx-auto sm:px-6 lg:px-8">
<form wire:submit.prevent="create" class="space-y-6">
<div>
<x-input-label for="name" :value="__('Product Name')" />
<x-text-input wire:model="name" id="create_product_name" name="name" type="text" class="mt-1 block w-full" autocomplete="name" />
<x-input-error :messages="$errors->get('name')" class="mt-2" />
</div>
<div>
<x-input-label for="price" :value="__('Product Price')" />
<x-text-input wire:model="price" id="create_product_price" name="price" type="text" class="mt-1 block w-full" autocomplete="price" />
<x-input-error :messages="$errors->get('price')" class="mt-2" />
</div>
<div>
<x-input-label for="description" :value="__('Product Description')" />
<textarea wire:model="description" rows="4" name="comment" id="comment" class="mt-1 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"></textarea>
<x-input-error :messages="$errors->get('description')" class="mt-2" />
</div>
<div>
<div class="mt-2 flex items-center gap-x-3">
@if($image)
<img src="{{ $image->temporaryUrl() }}" alt="Product Image" class="w-12 h-12 rounded-full">
@else
<svg class="h-12 w-12 text-gray-300" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M18.685 19.097A9.723 9.723 0 0021.75 12c0-5.385-4.365-9.75-9.75-9.75S2.25 6.615 2.25 12a9.723 9.723 0 003.065 7.097A9.716 9.716 0 0012 21.75a9.716 9.716 0 006.685-2.653zm-12.54-1.285A7.486 7.486 0 0112 15a7.486 7.486 0 015.855 2.812A8.224 8.224 0 0112 20.25a8.224 8.224 0 01-5.855-2.438zM15.75 9a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z" clip-rule="evenodd"></path>
</svg>
@endif
<label for="image" class="rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
<span>Change</span>
<input type="file" id="image" name="image" wire:model="image" class="sr-only">
</label>
</div>
<x-input-error :messages="$errors->get('image')" class="mt-2" />
</div>
<x-primary-button>Submit</x-primary-button>
</form>
</div>
</div>

</div>
2 changes: 1 addition & 1 deletion resources/views/livewire/product/index-item.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
<img class="w-12 h-12 rounded-full" src="{{ $product->image }}" alt="">
</td>
<td class="px-5 py-4 text-sm font-medium text-right whitespace-nowrap">
<a class="text-blue-600 hover:text-blue-700" href="#">Edit</a>
<a class="text-blue-600 hover:text-blue-700" href="{{ route('products.show', $product) }}">Edit</a>
</td>
</tr>
5 changes: 4 additions & 1 deletion resources/views/livewire/product/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div class="overflow-x-auto">
<div class="inline-block min-w-full">
<div class="overflow-hidden border rounded-lg">
<table class="min-w-full divide-y divide-neutral-200">
<table class="min-w-full divide-y divide-neutral-200 bg-white">
<thead class="bg-neutral-50">
<tr class="text-neutral-500">
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Name</th>
Expand All @@ -22,4 +22,7 @@
</div>
</div>
</div>
<div class="mt-4">
{{ $products->links() }}
</div>
</div>
8 changes: 8 additions & 0 deletions resources/views/livewire/product/show.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ $product->name }}
</h2>
</x-slot>

</div>
9 changes: 6 additions & 3 deletions resources/views/product/index.blade.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Products') }}
</h2>
<div class="w-full flex justify-between items-baseline">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Products') }}
</h2>
<x-primary-button-link href="{{ route('products.create') }}">New</x-primary-button-link>
</div>
</x-slot>

<div class="py-12">
Expand Down
Loading

0 comments on commit 34f287c

Please sign in to comment.