Agrego frontend app

This commit is contained in:
Pablo
2026-08-22 19:08:19 -03:00
parent 824e092b29
commit 2d0797e627
254 changed files with 37231 additions and 0 deletions
@@ -0,0 +1,126 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:gimnasio_soma/features/turnos/data/repositories/turnos_repository_impl.dart';
import 'package:gimnasio_soma/features/turnos/domain/entities/turno.dart';
import 'package:gimnasio_soma/features/turnos/domain/repositories/turnos_repository.dart';
String _errorMessage(Object e) {
if (e is PostgrestException) return e.message;
return e.toString().replaceFirst('Exception: ', '');
}
DateTime _normalizeWeekStart(DateTime d) {
final monday = DateTime(d.year, d.month, d.day - (d.weekday - 1));
return monday;
}
final turnosRepositoryProvider = Provider<TurnosRepository>((ref) {
return TurnosRepositoryImpl();
});
final turnosProvider =
StateNotifierProvider<TurnosNotifier, AsyncValue<SemanaTurnos?>>((ref) {
return TurnosNotifier(ref.read(turnosRepositoryProvider));
});
class TurnosNotifier extends StateNotifier<AsyncValue<SemanaTurnos?>> {
final TurnosRepository _repository;
DateTime? _currentWeek;
TurnosNotifier(this._repository) : super(const AsyncValue.data(null));
DateTime? get semanaActual => _currentWeek;
/// Carga la semana que contiene [referencia] (se normaliza al lunes).
/// Si ya estamos en esa semana, no recarga (a menos que [force] sea true).
Future<String?> cargarSemana(
DateTime referencia, {
bool force = false,
}) async {
final weekStart = _normalizeWeekStart(referencia);
if (!force && _currentWeek == weekStart && state.value != null) {
return null;
}
_currentWeek = weekStart;
state = const AsyncValue.loading();
try {
final semana = await _repository.obtenerSemana(weekStart);
if (_currentWeek != weekStart) return null; // semana cambió mientras cargaba
state = AsyncValue.data(semana);
return null;
} catch (e, st) {
if (_currentWeek != weekStart) return null;
state = AsyncValue.error(e, st);
return _errorMessage(e);
}
}
/// Refresca la semana actual en segundo plano, sin parpadeo: mantiene los
/// datos visibles mientras recarga y solo los reemplaza cuando llegan. Evita
/// el "corte" de volver a estado loading, que vaciaría la grilla a un spinner
/// (se nota, por ejemplo, al cerrar el diálogo de inscriptos).
Future<String?> refrescar() async {
final week = _currentWeek;
if (week == null) return null;
try {
final semana = await _repository.obtenerSemana(week);
if (_currentWeek != week) return null; // semana cambió mientras cargaba
state = AsyncValue.data(semana);
return null;
} catch (e) {
if (_currentWeek != week) return null;
// No pisamos los datos visibles con un error: los dejamos en pantalla y
// devolvemos el mensaje para que la pantalla muestre un toast.
return _errorMessage(e);
}
}
Future<String?> crearTurnoManual({
required DateTime fecha,
required int actividadId,
required String horaInicio,
required String horaFin,
required int capacidad,
}) async {
try {
await _repository.crearTurnoManual(
fecha: fecha,
actividadId: actividadId,
horaInicio: horaInicio,
horaFin: horaFin,
capacidad: capacidad,
);
await refrescar();
return null;
} catch (e) {
return _errorMessage(e);
}
}
Future<String?> limpiarAntiguos({int dias = 30}) async {
try {
final result =
await _repository.limpiarTurnosAntiguos(diasAntiguedad: dias);
final eliminados = result['turnos_eliminados'] ?? 0;
return 'Se eliminaron $eliminados turnos antiguos';
} catch (e) {
return _errorMessage(e);
}
}
}
/// Lista de reservas de un turno (incluye canceladas; filtrar en UI).
final inscriptosTurnoProvider =
FutureProvider.autoDispose.family<List<InscriptoTurno>, String>(
(ref, turnoId) =>
ref.read(turnosRepositoryProvider).obtenerInscriptos(turnoId),
);
/// Cupo semanal del cliente para la fecha pedida (usados/disponibles/total).
final estadoCupoProvider = FutureProvider.autoDispose
.family<EstadoCupo, ({String clienteId, DateTime fecha})>(
(ref, params) => ref.read(turnosRepositoryProvider).obtenerEstadoCupo(
clienteId: params.clienteId,
fecha: params.fecha,
),
);