# Story 3.1: Working Hours Configuration ## Epic Reference **Epic 3:** Booking & Consultation System ## User Story As an **admin**, I want **to configure available working hours for each day of the week**, So that **clients can only book consultations during my available times**. ## Story Context ### Existing System Integration - **Integrates with:** working_hours table, availability calendar - **Technology:** Livewire Volt, Flux UI forms - **Follows pattern:** Admin settings pattern - **Touch points:** Booking availability calculation ## Acceptance Criteria ### Working Hours Management - [ ] Set available days (enable/disable each day of week) - [ ] Set start time for each enabled day - [ ] Set end time for each enabled day - [ ] Support different hours for different days - [ ] 15-minute buffer automatically applied between appointments - [ ] 12-hour time format display (AM/PM) ### Configuration Interface - [ ] Visual weekly schedule view - [ ] Toggle for each day (Sunday-Saturday) - [ ] Time pickers for start/end times - [ ] Preview of available slots per day - [ ] Save button with confirmation ### Behavior - [ ] Changes take effect immediately for new bookings - [ ] Existing approved bookings NOT affected by changes - [ ] Warning if changing hours that have pending bookings - [ ] Validation: end time must be after start time ### Quality Requirements - [ ] Bilingual labels and messages - [ ] Default working hours on initial setup - [ ] Audit log entry on changes - [ ] Tests for configuration logic ## Technical Notes ### Database Schema ```php // working_hours table Schema::create('working_hours', function (Blueprint $table) { $table->id(); $table->tinyInteger('day_of_week'); // 0=Sunday, 6=Saturday $table->time('start_time'); $table->time('end_time'); $table->boolean('is_active')->default(true); $table->timestamps(); }); ``` ### Model ```php 'boolean', ]; public static function getDayName(int $dayOfWeek, string $locale = null): string { $locale = $locale ?? app()->getLocale(); $days = [ 'en' => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], 'ar' => ['الأحد', 'الإثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ]; return $days[$locale][$dayOfWeek] ?? $days['en'][$dayOfWeek]; } public function getSlots(int $duration = 60): array { $slots = []; $start = Carbon::parse($this->start_time); $end = Carbon::parse($this->end_time); while ($start->copy()->addMinutes($duration)->lte($end)) { $slots[] = $start->format('H:i'); $start->addMinutes($duration); } return $slots; } } ``` ### Volt Component ```php first(); $this->schedule[$day] = [ 'is_active' => $workingHour?->is_active ?? false, 'start_time' => $workingHour?->start_time ?? '09:00', 'end_time' => $workingHour?->end_time ?? '17:00', ]; } } public function save(): void { foreach ($this->schedule as $day => $config) { WorkingHour::updateOrCreate( ['day_of_week' => $day], [ 'is_active' => $config['is_active'], 'start_time' => $config['start_time'], 'end_time' => $config['end_time'], ] ); } // Log action AdminLog::create([ 'admin_id' => auth()->id(), 'action_type' => 'update', 'target_type' => 'working_hours', 'new_values' => $this->schedule, 'ip_address' => request()->ip(), ]); session()->flash('success', __('messages.working_hours_saved')); } }; ``` ### Blade Template ```blade