177 lines
6.6 KiB
PHP
177 lines
6.6 KiB
PHP
<?php
|
|
|
|
use App\Models\AdminLog;
|
|
use App\Models\WorkingHour;
|
|
use Carbon\Carbon;
|
|
use Livewire\Volt\Component;
|
|
|
|
new class extends Component {
|
|
public array $schedule = [];
|
|
|
|
public function mount(): void
|
|
{
|
|
for ($day = 0; $day <= 6; $day++) {
|
|
$workingHour = WorkingHour::query()->where('day_of_week', $day)->first();
|
|
|
|
$this->schedule[$day] = [
|
|
'is_active' => $workingHour?->is_active ?? false,
|
|
'start_time' => $workingHour ? Carbon::parse($workingHour->start_time)->format('H:i') : '09:00',
|
|
'end_time' => $workingHour ? Carbon::parse($workingHour->end_time)->format('H:i') : '17:00',
|
|
];
|
|
}
|
|
}
|
|
|
|
public function save(): void
|
|
{
|
|
foreach ($this->schedule as $day => $config) {
|
|
if ($config['is_active'] && $config['end_time'] <= $config['start_time']) {
|
|
$this->addError("schedule.{$day}.end_time", __('validation.end_time_after_start'));
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
$oldValues = WorkingHour::all()->keyBy('day_of_week')->toArray();
|
|
|
|
foreach ($this->schedule as $day => $config) {
|
|
WorkingHour::query()->updateOrCreate(
|
|
['day_of_week' => $day],
|
|
[
|
|
'is_active' => $config['is_active'],
|
|
'start_time' => $config['start_time'],
|
|
'end_time' => $config['end_time'],
|
|
]
|
|
);
|
|
}
|
|
|
|
AdminLog::create([
|
|
'admin_id' => auth()->id(),
|
|
'action' => 'update',
|
|
'target_type' => 'working_hours',
|
|
'old_values' => $oldValues,
|
|
'new_values' => $this->schedule,
|
|
'ip_address' => request()->ip(),
|
|
'created_at' => now(),
|
|
]);
|
|
|
|
session()->flash('success', __('messages.working_hours_saved'));
|
|
}
|
|
|
|
public function getSlotCount(int $day): int
|
|
{
|
|
if (! $this->schedule[$day]['is_active']) {
|
|
return 0;
|
|
}
|
|
|
|
$start = Carbon::parse($this->schedule[$day]['start_time']);
|
|
$end = Carbon::parse($this->schedule[$day]['end_time']);
|
|
|
|
if ($end->lte($start)) {
|
|
return 0;
|
|
}
|
|
|
|
$duration = 60;
|
|
$count = 0;
|
|
|
|
while ($start->copy()->addMinutes($duration)->lte($end)) {
|
|
$count++;
|
|
$start->addMinutes($duration);
|
|
}
|
|
|
|
return $count;
|
|
}
|
|
|
|
public function formatTime(string $time): string
|
|
{
|
|
return Carbon::parse($time)->format('g:i A');
|
|
}
|
|
}; ?>
|
|
|
|
<div>
|
|
<div class="mb-6">
|
|
<flux:heading size="xl">{{ __('admin.working_hours') }}</flux:heading>
|
|
<flux:text class="mt-1 text-zinc-500">
|
|
{{ __('admin.working_hours_description') }}
|
|
</flux:text>
|
|
</div>
|
|
|
|
@if (session('success'))
|
|
<div class="mb-6">
|
|
<flux:callout variant="success" icon="check-circle">
|
|
{{ session('success') }}
|
|
</flux:callout>
|
|
</div>
|
|
@endif
|
|
|
|
<div class="rounded-lg border border-zinc-200 bg-white p-6">
|
|
<form wire:submit="save">
|
|
<div class="space-y-1">
|
|
@foreach (range(0, 6) as $day)
|
|
<div
|
|
wire:key="day-{{ $day }}"
|
|
class="flex flex-col gap-4 border-b border-zinc-200 py-4 last:border-b-0 sm:flex-row sm:items-center"
|
|
>
|
|
<div class="flex items-center gap-4 sm:w-48">
|
|
<flux:switch
|
|
wire:model.live="schedule.{{ $day }}.is_active"
|
|
aria-label="{{ __('admin.working_hours') }} - {{ \App\Models\WorkingHour::getDayName($day) }}"
|
|
/>
|
|
<span class="font-medium text-zinc-900">
|
|
{{ \App\Models\WorkingHour::getDayName($day) }}
|
|
</span>
|
|
</div>
|
|
|
|
@if ($schedule[$day]['is_active'])
|
|
<div class="flex flex-1 flex-wrap items-center gap-3">
|
|
<div class="flex items-center gap-2">
|
|
<flux:input
|
|
type="time"
|
|
wire:model.live="schedule.{{ $day }}.start_time"
|
|
class="w-36"
|
|
/>
|
|
<span class="text-zinc-500">{{ __('admin.to') }}</span>
|
|
<flux:input
|
|
type="time"
|
|
wire:model.live="schedule.{{ $day }}.end_time"
|
|
class="w-36"
|
|
/>
|
|
</div>
|
|
|
|
<div class="flex items-center gap-2 text-sm">
|
|
<span class="text-zinc-500">
|
|
({{ $this->formatTime($schedule[$day]['start_time']) }} - {{ $this->formatTime($schedule[$day]['end_time']) }})
|
|
</span>
|
|
@php($slots = $this->getSlotCount($day))
|
|
@if ($slots > 0)
|
|
<flux:badge color="green" size="sm">
|
|
{{ __('admin.slots_available', ['count' => $slots]) }}
|
|
</flux:badge>
|
|
@else
|
|
<flux:badge color="red" size="sm">
|
|
{{ __('admin.no_slots') }}
|
|
</flux:badge>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
@error("schedule.{$day}.end_time")
|
|
<div class="w-full">
|
|
<flux:text class="text-sm text-red-500">{{ $message }}</flux:text>
|
|
</div>
|
|
@enderror
|
|
@else
|
|
<span class="text-zinc-400">{{ __('admin.closed') }}</span>
|
|
@endif
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
|
|
<div class="mt-6 flex justify-end border-t border-zinc-200 pt-6">
|
|
<flux:button variant="primary" type="submit">
|
|
{{ __('admin.save_working_hours') }}
|
|
</flux:button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|