schema([ Forms\Components\Grid::make(2) // Dos columnas en el grid principal ->schema([ // Primera columna Forms\Components\Group::make() // Agrupamos componentes para mantener el diseño limpio ->schema([ Forms\Components\TextInput::make('name') ->label('Nombre del evento ') ->required(), Forms\Components\Select::make('users') ->label('Usuarios') ->options(function () { $user = Auth::user(); $business = $user->businesses->first(); if ($business) { // Especificamos explícitamente qué tabla contiene cada columna return $business->users()->select('users.id', 'users.name')->pluck('name', 'id'); } return []; }) ->multiple() ->preload() //->required() // Carga los valores existentes al editar ->afterStateHydrated(function (Forms\Components\Select $component, $state, $record) { if ($record && $record->exists) { $component->state($record->users()->pluck('users.id')->toArray()); } }) ->saveRelationshipsUsing(function ($record, $state) { // Guardamos en la tabla pivot schedule_user $record->users()->sync($state); }), Forms\Components\Select::make('services') ->label('Servicios') ->relationship('services', 'name') ->preload() ->required(), Forms\Components\Toggle::make('is_closed') ->label('¿Está cerrado?') ->default(0) ->dehydrated(true) //->required(), ]), // Segunda columna Forms\Components\Group::make() // Agrupamos el repeater para mantener diseño limpio ->schema([ Forms\Components\Repeater::make('time_ranges') ->label('Rangos de horarios') ->schema([ Forms\Components\CheckboxList::make('apply_to_days') ->label('Aplicar a días') ->options([ 0 => 'Lunes', 1 => 'Martes', 2 => 'Miércoles', 3 => 'Jueves', 4 => 'Viernes', 5 => 'Sábado', 6 => 'Domingo', ]) ->columns(7) ->required(), Forms\Components\Grid::make(2) ->schema([ Forms\Components\Select::make('opening_time') ->label('Hora de inicio') ->options(function () { $options = []; // Horario de 08:00 a 22:00 con incrementos de 30 minutos for ($hour = 8; $hour <= 22; $hour++) { for ($minute = 0; $minute < 60; $minute += 15) { // Si llegamos a la última hora (22:00), solo incluimos el horario exacto if ($hour == 22 && $minute > 0) { break; } $timeValue = sprintf('%02d:%02d:00', $hour, $minute); // HH:MM:SS para guardar $timeLabel = sprintf('%02d:%02d', $hour, $minute); // HH:MM para mostrar $options[$timeValue] = $timeLabel; } } return $options; }) ->searchable() ->required(), Forms\Components\Select::make('closing_time') ->label('Hora de término') ->options(function () { $options = []; // Horario de 08:00 a 22:00 con incrementos de 30 minutos for ($hour = 8; $hour <= 22; $hour++) { for ($minute = 0; $minute < 60; $minute += 15) { // Si llegamos a la última hora (22:00), solo incluimos el horario exacto if ($hour == 22 && $minute > 0) { break; } $timeValue = sprintf('%02d:%02d:00', $hour, $minute); // HH:MM:SS para guardar $timeLabel = sprintf('%02d:%02d', $hour, $minute); // HH:MM para mostrar $options[$timeValue] = $timeLabel; } } return $options; }) ->searchable() ->required(), ]), ]) ->required() ->defaultItems(1) ->collapsible() ->itemLabel(fn (array $state): ?string => isset($state['opening_time'], $state['closing_time']) ? "Horario: {$state['opening_time']} - {$state['closing_time']}" : null ), ]), ]), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('business.name') ->label('Negocio') ->sortable() ->searchable(), Tables\Columns\TextColumn::make('name') ->label('Nombre del evento') ->searchable(), Tables\Columns\TextColumn::make('users.name') ->label('Usuarios asignados') ->listWithLineBreaks() ->bulleted(), Tables\Columns\TextColumn::make('services.name') ->label('Servicios') ->listWithLineBreaks() ->bulleted(), // Columna para días laborables Tables\Columns\TextColumn::make('dias_laborables') ->label('Días Laborables') ->state(function ($record) { // Necesario para crear una columna virtual return $record->id; }) ->formatStateUsing(function ($state, $record) { $timeRanges = $record->time_ranges; if (empty($timeRanges) || ! is_array($timeRanges)) { return 'Sin horarios definidos'; } $diasSemana = [ '0' => 'Lunes', '1' => 'Martes', '2' => 'Miércoles', '3' => 'Jueves', '4' => 'Viernes', ]; $horariosDiasLaborables = []; foreach ($timeRanges as $range) { // Verificar estructura de datos if (! isset($range['apply_to_days']) || ! isset($range['opening_time']) || ! isset($range['closing_time'])) { continue; } $horario = $range['opening_time'].' - '.$range['closing_time']; $diasAplicables = $range['apply_to_days']; // Filtrar solo días laborables $diasLaborables = []; foreach ($diasAplicables as $dia) { if (in_array($dia, ['0', '1', '2', '3', '4'])) { $diasLaborables[] = $diasSemana[$dia]; } } if (! empty($diasLaborables)) { $horariosDiasLaborables[] = [ 'dias' => $diasLaborables, 'horario' => $horario, ]; } } // Construir HTML $html = ''; if (! empty($horariosDiasLaborables)) { foreach ($horariosDiasLaborables as $item) { $html .= '
'; $html .= ''.implode(', ', $item['dias']).': '; $html .= ''.$item['horario'].''; $html .= '
'; } } return empty($html) ? 'Sin horarios en días laborables' : $html; }) ->html() ->alignLeft(), // Columna para fin de semana Tables\Columns\TextColumn::make('fin_de_semana') ->label('Fin de Semana') ->state(function ($record) { // Necesario para crear una columna virtual return $record->id; }) ->formatStateUsing(function ($state, $record) { $timeRanges = $record->time_ranges; if (empty($timeRanges) || ! is_array($timeRanges)) { return 'Sin horarios definidos'; } $diasSemana = [ '5' => 'Sábado', '6' => 'Domingo', ]; $horariosFinesDeSemana = []; foreach ($timeRanges as $range) { // Verificar estructura de datos if (! isset($range['apply_to_days']) || ! isset($range['opening_time']) || ! isset($range['closing_time'])) { continue; } $horario = $range['opening_time'].' - '.$range['closing_time']; $diasAplicables = $range['apply_to_days']; // Filtrar solo días de fin de semana $diasFinDeSemana = []; foreach ($diasAplicables as $dia) { if (in_array($dia, ['5', '6'])) { $diasFinDeSemana[] = $diasSemana[$dia]; } } if (! empty($diasFinDeSemana)) { $horariosFinesDeSemana[] = [ 'dias' => $diasFinDeSemana, 'horario' => $horario, ]; } } // Construir HTML $html = ''; if (! empty($horariosFinesDeSemana)) { foreach ($horariosFinesDeSemana as $item) { $html .= '
'; $html .= ''.implode(', ', $item['dias']).': '; $html .= ''.$item['horario'].''; $html .= '
'; } } return empty($html) ? 'Sin horarios en fin de semana' : $html; }) ->html() ->alignLeft(), Tables\Columns\IconColumn::make('is_closed') ->label('Estado del Evento') ->boolean() ->trueIcon('heroicon-o-x-circle') ->falseIcon('heroicon-o-check-circle') ->trueColor('danger') ->falseColor('success'), ]) ->filters([ // Puedes añadir filtros si lo necesitas ]) ->actions([ Tables\Actions\EditAction::make(), ]) ->bulkActions([ Tables\Actions\BulkActionGroup::make([ // Tables\Actions\DeleteBulkAction::make(), ]), ]); } public static function getRelations(): array { return [ // ]; } public static function getPages(): array { return [ 'index' => Pages\ListSchedules::route('/'), 'create' => Pages\CreateSchedule::route('/create'), 'edit' => Pages\EditSchedule::route('/{record}/edit'), ]; } }