64 - Extract the counter form into a Blade component
This commit is contained in:
parent
181e0cbda5
commit
e5c257d94d
4 changed files with 88 additions and 64 deletions
|
|
@ -31,8 +31,10 @@ public function mount(): void
|
|||
$tracker = Tracker::current();
|
||||
|
||||
$this->needsOnboarding = $tracker === null;
|
||||
$this->count = $tracker === null ? 0 : $tracker->count;
|
||||
$this->value = $this->count;
|
||||
|
||||
if ($tracker !== null) {
|
||||
$this->syncFrom($tracker);
|
||||
}
|
||||
}
|
||||
|
||||
public function initialise(): void
|
||||
|
|
@ -45,7 +47,7 @@ public function initialise(): void
|
|||
'count' => $this->value,
|
||||
]);
|
||||
|
||||
$this->count = $tracker->count;
|
||||
$this->syncFrom($tracker);
|
||||
$this->needsOnboarding = false;
|
||||
}
|
||||
|
||||
|
|
@ -58,10 +60,8 @@ public function increment(): void
|
|||
}
|
||||
|
||||
$tracker->increment('count');
|
||||
$tracker->refresh();
|
||||
|
||||
$this->count = $tracker->count;
|
||||
$this->value = $this->count;
|
||||
$this->syncFrom($tracker->refresh());
|
||||
}
|
||||
|
||||
public function edit(): void
|
||||
|
|
@ -83,7 +83,7 @@ public function save(): void
|
|||
|
||||
$tracker->update(['count' => $this->value]);
|
||||
|
||||
$this->count = (int) $this->value;
|
||||
$this->syncFrom($tracker);
|
||||
$this->editing = false;
|
||||
}
|
||||
|
||||
|
|
@ -94,6 +94,15 @@ public function cancel(): void
|
|||
$this->editing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The tracker is the source of truth; the form input always mirrors it.
|
||||
*/
|
||||
private function syncFrom(Tracker $tracker): void
|
||||
{
|
||||
$this->count = $tracker->count;
|
||||
$this->value = $this->count;
|
||||
}
|
||||
|
||||
public function render(): View
|
||||
{
|
||||
return view('livewire.counter')->layout('layouts.app');
|
||||
|
|
|
|||
48
resources/views/components/counter-form.blade.php
Normal file
48
resources/views/components/counter-form.blade.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
@props([
|
||||
'action',
|
||||
'label',
|
||||
'submit',
|
||||
'id' => 'value',
|
||||
'cancel' => false,
|
||||
])
|
||||
|
||||
<form wire:submit="{{ $action }}" class="space-y-4">
|
||||
<label for="{{ $id }}" class="text-red-400 font-mono text-xs uppercase tracking-wider">
|
||||
> {{ $label }}
|
||||
</label>
|
||||
<input
|
||||
id="{{ $id }}"
|
||||
type="number"
|
||||
min="0"
|
||||
step="1"
|
||||
autofocus
|
||||
wire:model="value"
|
||||
class="w-full bg-black border-red-500 text-red-400 focus:border-red-300 font-mono text-sm rounded-none border-2 focus:ring-0 focus:outline-none placeholder:text-red-400/40 transition-all glow-red px-3 py-2"
|
||||
>
|
||||
@error('value')
|
||||
<p class="text-red-400 font-mono text-xs">{{ $message }}</p>
|
||||
@enderror
|
||||
|
||||
<div @class(['flex gap-3 pt-2' => $cancel])>
|
||||
<button
|
||||
type="submit"
|
||||
@class([
|
||||
'bg-red-500 hover:bg-red-500 text-black font-mono text-sm font-bold border-red-500 rounded-none border-2 uppercase tracking-wider transition-all glow-red px-4 py-2',
|
||||
'flex-1' => $cancel,
|
||||
'w-full' => ! $cancel,
|
||||
])
|
||||
>
|
||||
{{ $submit }}
|
||||
</button>
|
||||
|
||||
@if ($cancel)
|
||||
<button
|
||||
type="button"
|
||||
wire:click="cancel"
|
||||
class="flex-1 bg-black border-red-500 text-red-400 hover:bg-red-950 hover:text-red-300 font-mono text-sm font-bold rounded-none border-2 uppercase tracking-wider transition-all glow-red px-4 py-2"
|
||||
>
|
||||
[ABORT]
|
||||
</button>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -3,30 +3,12 @@
|
|||
<div class="min-h-screen flex items-center justify-center p-4">
|
||||
<div class="w-full max-w-md">
|
||||
<div class="border-2 border-red-500 bg-black shadow-[0_0_20px_rgba(239,68,68,0.3)] p-8">
|
||||
<form wire:submit="initialise" class="space-y-4">
|
||||
<label for="starting-value" class="text-red-400 font-mono text-xs uppercase tracking-wider">
|
||||
> Starting Value
|
||||
</label>
|
||||
<input
|
||||
<x-counter-form
|
||||
action="initialise"
|
||||
label="Starting Value"
|
||||
submit="[INITIALIZE]"
|
||||
id="starting-value"
|
||||
type="number"
|
||||
min="0"
|
||||
step="1"
|
||||
autofocus
|
||||
wire:model="value"
|
||||
class="w-full bg-black border-red-500 text-red-400 focus:border-red-300 font-mono text-sm rounded-none border-2 focus:ring-0 focus:outline-none placeholder:text-red-400/40 transition-all glow-red px-3 py-2"
|
||||
>
|
||||
@error('value')
|
||||
<p class="text-red-400 font-mono text-xs">{{ $message }}</p>
|
||||
@enderror
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="w-full bg-red-500 hover:bg-red-500 text-black font-mono text-sm font-bold border-red-500 rounded-none border-2 uppercase tracking-wider transition-all glow-red px-4 py-2"
|
||||
>
|
||||
[INITIALIZE]
|
||||
</button>
|
||||
</form>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -59,39 +41,13 @@ class="text-red-400/60 hover:text-red-400 font-mono text-xs uppercase tracking-w
|
|||
@if ($editing)
|
||||
<div class="bg-black p-8">
|
||||
<div class="w-full border-4 border-red-500 p-6 bg-black glow-red">
|
||||
<form wire:submit="save" class="space-y-4">
|
||||
<label for="count" class="text-red-400 font-mono text-xs uppercase tracking-wider">
|
||||
> Set Value
|
||||
</label>
|
||||
<input
|
||||
<x-counter-form
|
||||
action="save"
|
||||
label="Set Value"
|
||||
submit="[EXECUTE]"
|
||||
id="count"
|
||||
type="number"
|
||||
min="0"
|
||||
step="1"
|
||||
autofocus
|
||||
wire:model="value"
|
||||
class="w-full bg-black border-red-500 text-red-400 focus:border-red-300 font-mono text-sm rounded-none border-2 focus:ring-0 focus:outline-none placeholder:text-red-400/40 transition-all glow-red px-3 py-2"
|
||||
>
|
||||
@error('value')
|
||||
<p class="text-red-400 font-mono text-xs">{{ $message }}</p>
|
||||
@enderror
|
||||
|
||||
<div class="flex gap-3 pt-2">
|
||||
<button
|
||||
type="submit"
|
||||
class="flex-1 bg-red-500 hover:bg-red-500 text-black font-mono text-sm font-bold border-red-500 rounded-none border-2 uppercase tracking-wider transition-all glow-red px-4 py-2"
|
||||
>
|
||||
[EXECUTE]
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
wire:click="cancel"
|
||||
class="flex-1 bg-black border-red-500 text-red-400 hover:bg-red-950 hover:text-red-300 font-mono text-sm font-bold rounded-none border-2 uppercase tracking-wider transition-all glow-red px-4 py-2"
|
||||
>
|
||||
[ABORT]
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
:cancel="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -29,6 +29,17 @@ public function test_the_page_renders_the_current_count(): void
|
|||
->assertSee('42');
|
||||
}
|
||||
|
||||
public function test_the_edit_form_renders_with_both_actions(): void
|
||||
{
|
||||
$this->tracker(42);
|
||||
|
||||
Livewire::test(Counter::class)
|
||||
->call('edit')
|
||||
->assertSee('Set Value')
|
||||
->assertSee('[EXECUTE]')
|
||||
->assertSee('[ABORT]');
|
||||
}
|
||||
|
||||
public function test_increment_adds_exactly_one(): void
|
||||
{
|
||||
$tracker = $this->tracker(5);
|
||||
|
|
|
|||
Loading…
Reference in a new issue