b2in/app/Models/CabinetTabletSetting.php
2026-04-10 17:18:17 +02:00

155 lines
5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
class CabinetTabletSetting extends Model
{
/** @use HasFactory<\Database\Factories\CabinetTabletSettingFactory> */
use HasFactory;
protected $fillable = [
'store_status',
'notice_headline',
'notice_subtext',
'override_open_today',
'override_close_today',
'next_appointment_date',
'next_appointment_time',
'hours_monday_open', 'hours_monday_close',
'hours_tuesday_open', 'hours_tuesday_close',
'hours_wednesday_open', 'hours_wednesday_close',
'hours_thursday_open', 'hours_thursday_close',
'hours_friday_open', 'hours_friday_close',
'hours_saturday_open', 'hours_saturday_close',
'hours_sunday_open', 'hours_sunday_close',
'contact_phone',
'contact_email',
];
protected function casts(): array
{
return [
'next_appointment_date' => 'date',
];
}
private const DAYS = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
private const GERMAN_DAY_LABELS = [
'monday' => 'Montag',
'tuesday' => 'Dienstag',
'wednesday' => 'Mittwoch',
'thursday' => 'Donnerstag',
'friday' => 'Freitag',
'saturday' => 'Samstag',
'sunday' => 'Sonntag',
];
/**
* Get or create the singleton settings row.
*/
public static function current(): self
{
return static::firstOrCreate(['id' => 1]);
}
/**
* Get opening hours as display strings for the frontend (e.g. "10:00 18:00" or "Geschlossen").
*
* @return array<string, string>
*/
public function getHoursArray(): array
{
$result = [];
foreach (self::DAYS as $day) {
$open = $this->{"hours_{$day}_open"};
$close = $this->{"hours_{$day}_close"};
$result[$day] = ($open && $close) ? "{$open} {$close}" : 'Geschlossen';
}
return $result;
}
/**
* Compute the effective store status based on opening hours and current Berlin time.
*
* Returns the display status ('open', 'closed', 'notice'), the next opening time when
* closed, and today's closing time when open.
*
* @return array{status: string, today_close: string|null, next_open: array{label: string, time: string}|null}
*/
public function computeStatus(): array
{
if ($this->store_status === 'notice' || $this->store_status === 'warning') {
return ['status' => $this->store_status, 'today_close' => null, 'next_open' => null];
}
if ($this->store_status === 'closed') {
$now = Carbon::now('Europe/Berlin');
return ['status' => 'closed', 'today_close' => null, 'next_open' => $this->findNextOpenTime($now, true)];
}
// Auto mode: compute from opening hours
$now = Carbon::now('Europe/Berlin');
$dayKey = strtolower($now->englishDayOfWeek);
$openTime = $this->override_open_today ?: $this->{"hours_{$dayKey}_open"};
$closeTime = $this->override_close_today ?: $this->{"hours_{$dayKey}_close"};
$currentHHMM = $now->format('H:i');
if ($openTime && $closeTime && $currentHHMM >= $openTime && $currentHHMM < $closeTime) {
return ['status' => 'open', 'today_close' => $closeTime, 'next_open' => null];
}
return ['status' => 'closed', 'today_close' => null, 'next_open' => $this->findNextOpenTime($now, false)];
}
/**
* Find the next upcoming opening time from the given Berlin datetime.
*
* @return array{label: string, time: string}|null
*/
private function findNextOpenTime(Carbon $now, bool $skipToday): ?array
{
// Check if today still has an upcoming opening (we might be before opening time)
if (! $skipToday) {
$dayKey = strtolower($now->englishDayOfWeek);
$todayOpen = $this->override_open_today ?: $this->{"hours_{$dayKey}_open"};
if ($todayOpen && $now->format('H:i') < $todayOpen) {
return ['label' => 'Heute', 'time' => $todayOpen];
}
}
// Look ahead up to 7 days
for ($i = 1; $i <= 7; $i++) {
$checkDate = $now->copy()->addDays($i);
$dayKey = strtolower($checkDate->englishDayOfWeek);
$openTime = $this->{"hours_{$dayKey}_open"};
if ($openTime) {
$label = $i === 1 ? 'Morgen' : self::GERMAN_DAY_LABELS[$dayKey];
return ['label' => $label, 'time' => $openTime];
}
}
return null;
}
/**
* Clear override times (called by midnight scheduler).
*/
public function clearOverrides(): void
{
$this->update([
'override_open_today' => null,
'override_close_today' => null,
]);
}
}