orderBy('hora_inicio', 'desc'); // Filtros if ($request->filled('estado')) { if ($request->estado === 'activos') { $query->where('activo', true); } elseif ($request->estado === 'inactivos') { $query->where('activo', false); } } if ($request->filled('fecha')) { $query->whereDate('fecha', $request->fecha); } if ($request->filled('fecha_inicio') && $request->filled('fecha_fin')) { $query->whereBetween('fecha', [$request->fecha_inicio, $request->fecha_fin]); } $horarios = $query->paginate(15)->appends($request->query()); return view('admin.horarios-bloqueados.index', compact('horarios')); } /** * Mostrar formulario de creación */ public function create(): View { return view('admin.horarios-bloqueados.create'); } /** * Guardar nuevo horario bloqueado */ public function store(HorarioBloqueadoRequest $request): RedirectResponse { $data = $request->validated(); // Por defecto activo si no se especifica if (! isset($data['activo'])) { $data['activo'] = true; } // Verificar superposición con otros bloques $superpuesto = HorarioBloqueado::whereDate('fecha', $data['fecha']) ->where(function ($query) use ($data) { $query->where(function ($q) use ($data) { $q->whereTime('hora_inicio', '<', $data['hora_fin']) ->whereTime('hora_fin', '>', $data['hora_inicio']); }); }) ->exists(); if ($superpuesto) { return back()->withErrors(['hora_inicio' => 'Ya existe un horario bloqueado en este rango.'])->withInput(); } HorarioBloqueado::create($data); return redirect()->route('admin.horarios-bloqueados.index')->with('success', 'Horario bloqueado creado correctamente.'); } /** * Mostrar detalles de un horario bloqueado */ public function show(HorarioBloqueado $horario_bloqueado): View { return view('admin.horarios-bloqueados.show', compact('horario_bloqueado')); } /** * Mostrar formulario de edición */ public function edit(HorarioBloqueado $horario_bloqueado): View { return view('admin.horarios-bloqueados.edit', compact('horario_bloqueado')); } /** * Actualizar horario bloqueado */ public function update(HorarioBloqueadoRequest $request, HorarioBloqueado $horario_bloqueado): RedirectResponse { $data = $request->validated(); // Verificar superposición con otros bloques (excluyendo el actual) $superpuesto = HorarioBloqueado::where('id', '!=', $horario_bloqueado->id) ->whereDate('fecha', $data['fecha']) ->where(function ($query) use ($data) { $query->where(function ($q) use ($data) { $q->whereTime('hora_inicio', '<', $data['hora_fin']) ->whereTime('hora_fin', '>', $data['hora_inicio']); }); }) ->exists(); if ($superpuesto) { return back()->withErrors(['hora_inicio' => 'Ya existe un horario bloqueado en este rango.'])->withInput(); } $horario_bloqueado->update($data); return redirect()->route('admin.horarios-bloqueados.index')->with('success', 'Horario bloqueado actualizado correctamente.'); } /** * Eliminar horario bloqueado */ public function destroy(HorarioBloqueado $horario_bloqueado): RedirectResponse { $horario_bloqueado->delete(); return redirect()->route('admin.horarios-bloqueados.index')->with('success', 'Horario bloqueado eliminado correctamente.'); } /** * Activar horario bloqueado */ public function activar(HorarioBloqueado $horario_bloqueado): RedirectResponse { $horario_bloqueado->activar(); return back()->with('success', 'Horario bloqueado activado.'); } /** * Desactivar horario bloqueado */ public function desactivar(HorarioBloqueado $horario_bloqueado): RedirectResponse { $horario_bloqueado->desactivar(); return back()->with('success', 'Horario bloqueado desactivado.'); } /** * Verificar si una fecha y hora está bloqueada (API) */ public function verificar(Request $request): JsonResponse { $request->validate([ 'fecha' => ['required', 'date'], 'hora' => ['required', 'date_format:H:i'], ]); $estaBloqueado = HorarioBloqueado::estaBloqueado($request->fecha, $request->hora); return response()->json([ 'bloqueado' => $estaBloqueado, 'mensaje' => $estaBloqueado ? 'El horario está bloqueado.' : 'El horario está disponible.', ]); } /** * Obtener bloques para una fecha específica */ public function porFecha(Request $request): JsonResponse { $request->validate([ 'fecha' => ['required', 'date'], ]); $bloques = HorarioBloqueado::getBloquesPorFecha($request->fecha); return response()->json($bloques); } /** * Crear bloqueo rápido desde el calendario */ public function bloqueoRapido(Request $request): RedirectResponse { $request->validate([ 'fecha' => ['required', 'date'], 'hora_inicio' => ['required', 'date_format:H:i'], 'hora_fin' => ['required', 'date_format:H:i', 'after:hora_inicio'], 'motivo' => ['nullable', 'string', 'max:255'], ]); HorarioBloqueado::create([ 'fecha' => $request->fecha, 'hora_inicio' => $request->hora_inicio, 'hora_fin' => $request->hora_fin, 'motivo' => $request->motivo ?? 'Bloqueo rápido', 'activo' => true, ]); return back()->with('success', 'Horario bloqueado correctamente.'); } }