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();
|
$tracker = Tracker::current();
|
||||||
|
|
||||||
$this->needsOnboarding = $tracker === null;
|
$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
|
public function initialise(): void
|
||||||
|
|
@ -45,7 +47,7 @@ public function initialise(): void
|
||||||
'count' => $this->value,
|
'count' => $this->value,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->count = $tracker->count;
|
$this->syncFrom($tracker);
|
||||||
$this->needsOnboarding = false;
|
$this->needsOnboarding = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,10 +60,8 @@ public function increment(): void
|
||||||
}
|
}
|
||||||
|
|
||||||
$tracker->increment('count');
|
$tracker->increment('count');
|
||||||
$tracker->refresh();
|
|
||||||
|
|
||||||
$this->count = $tracker->count;
|
$this->syncFrom($tracker->refresh());
|
||||||
$this->value = $this->count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit(): void
|
public function edit(): void
|
||||||
|
|
@ -83,7 +83,7 @@ public function save(): void
|
||||||
|
|
||||||
$tracker->update(['count' => $this->value]);
|
$tracker->update(['count' => $this->value]);
|
||||||
|
|
||||||
$this->count = (int) $this->value;
|
$this->syncFrom($tracker);
|
||||||
$this->editing = false;
|
$this->editing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,6 +94,15 @@ public function cancel(): void
|
||||||
$this->editing = false;
|
$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
|
public function render(): View
|
||||||
{
|
{
|
||||||
return view('livewire.counter')->layout('layouts.app');
|
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="min-h-screen flex items-center justify-center p-4">
|
||||||
<div class="w-full max-w-md">
|
<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">
|
<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">
|
<x-counter-form
|
||||||
<label for="starting-value" class="text-red-400 font-mono text-xs uppercase tracking-wider">
|
action="initialise"
|
||||||
> Starting Value
|
label="Starting Value"
|
||||||
</label>
|
submit="[INITIALIZE]"
|
||||||
<input
|
|
||||||
id="starting-value"
|
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>
|
</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)
|
@if ($editing)
|
||||||
<div class="bg-black p-8">
|
<div class="bg-black p-8">
|
||||||
<div class="w-full border-4 border-red-500 p-6 bg-black glow-red">
|
<div class="w-full border-4 border-red-500 p-6 bg-black glow-red">
|
||||||
<form wire:submit="save" class="space-y-4">
|
<x-counter-form
|
||||||
<label for="count" class="text-red-400 font-mono text-xs uppercase tracking-wider">
|
action="save"
|
||||||
> Set Value
|
label="Set Value"
|
||||||
</label>
|
submit="[EXECUTE]"
|
||||||
<input
|
|
||||||
id="count"
|
id="count"
|
||||||
type="number"
|
:cancel="true"
|
||||||
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>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,17 @@ public function test_the_page_renders_the_current_count(): void
|
||||||
->assertSee('42');
|
->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
|
public function test_increment_adds_exactly_one(): void
|
||||||
{
|
{
|
||||||
$tracker = $this->tracker(5);
|
$tracker = $this->tracker(5);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue