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,195 @@
enum DiaEstado { cerrado, normal, horarioDiferente }
DiaEstado _parseEstado(String? raw) {
switch (raw) {
case 'cerrado':
return DiaEstado.cerrado;
case 'horario_diferente':
return DiaEstado.horarioDiferente;
default:
return DiaEstado.normal;
}
}
class TurnoActividad {
final int id;
final String nombre;
final bool libre;
const TurnoActividad({
required this.id,
required this.nombre,
required this.libre,
});
factory TurnoActividad.fromMap(Map<String, dynamic> map) {
return TurnoActividad(
id: (map['id'] as num?)?.toInt() ?? 0,
nombre: map['nombre'] as String? ?? '',
libre: map['libre'] as bool? ?? false,
);
}
}
class Turno {
final String id;
final String horaInicio;
final String horaFin;
final int capacidadMaxima;
final int ocupacion;
final TurnoActividad actividad;
const Turno({
required this.id,
required this.horaInicio,
required this.horaFin,
required this.capacidadMaxima,
required this.ocupacion,
required this.actividad,
});
factory Turno.fromMap(Map<String, dynamic> map) {
return Turno(
id: map['id'] as String? ?? '',
horaInicio: map['hora_inicio'] as String? ?? '',
horaFin: map['hora_fin'] as String? ?? '',
capacidadMaxima: (map['capacidad_maxima'] as num?)?.toInt() ?? 0,
ocupacion: (map['ocupacion'] as num?)?.toInt() ?? 0,
actividad: TurnoActividad.fromMap(
(map['actividad'] as Map?)?.cast<String, dynamic>() ?? const {},
),
);
}
int get disponible {
final libre = capacidadMaxima - ocupacion;
return libre < 0 ? 0 : libre;
}
bool get estaLleno => capacidadMaxima > 0 && disponible == 0;
}
class DiaTurnos {
final DateTime fecha;
final int diaSemana;
final DiaEstado estado;
final List<Turno> turnos;
const DiaTurnos({
required this.fecha,
required this.diaSemana,
required this.estado,
required this.turnos,
});
factory DiaTurnos.fromMap(DateTime fecha, Map<String, dynamic> map) {
final lista = (map['turnos'] as List?)
?.map((e) => Turno.fromMap((e as Map).cast<String, dynamic>()))
.toList() ??
const <Turno>[];
return DiaTurnos(
fecha: fecha,
diaSemana: (map['dia_semana'] as num?)?.toInt() ?? fecha.weekday,
estado: _parseEstado(map['estado'] as String?),
turnos: lista,
);
}
}
class SemanaTurnos {
final DateTime weekStart;
final Map<String, DiaTurnos> _byKey;
const SemanaTurnos._(this.weekStart, this._byKey);
factory SemanaTurnos.fromResponse(
DateTime weekStart,
Map<String, dynamic> raw,
) {
final map = <String, DiaTurnos>{};
raw.forEach((dateKey, value) {
if (value is! Map) return;
final fecha = DateTime.tryParse(dateKey);
if (fecha == null) return;
final f = DateTime(fecha.year, fecha.month, fecha.day);
map[_keyFor(f)] =
DiaTurnos.fromMap(f, value.cast<String, dynamic>());
});
return SemanaTurnos._(weekStart, map);
}
static String _keyFor(DateTime d) =>
'${d.year.toString().padLeft(4, '0')}-'
'${d.month.toString().padLeft(2, '0')}-'
'${d.day.toString().padLeft(2, '0')}';
DiaTurnos? diaPara(DateTime fecha) => _byKey[_keyFor(fecha)];
bool contieneFecha(DateTime fecha) => _byKey.containsKey(_keyFor(fecha));
}
class InscriptoTurno {
final String reservaId;
final String clienteId;
final String nombre;
final String? apellido;
final bool cancelada;
const InscriptoTurno({
required this.reservaId,
required this.clienteId,
required this.nombre,
this.apellido,
this.cancelada = false,
});
factory InscriptoTurno.fromMap(Map<String, dynamic> map) {
return InscriptoTurno(
reservaId: map['reserva_id'] as String? ?? '',
clienteId: map['cliente_id'] as String? ?? '',
nombre: map['nombre'] as String? ?? '',
apellido: map['apellido'] as String?,
cancelada: map['cancelada'] as bool? ?? false,
);
}
String get displayName {
if (nombre.isNotEmpty && apellido != null && apellido!.isNotEmpty) {
return '$nombre $apellido';
}
return nombre.isNotEmpty ? nombre : '?';
}
String get initials {
if (nombre.isNotEmpty) {
if (apellido != null && apellido!.isNotEmpty) {
return '${nombre[0]}${apellido![0]}'.toUpperCase();
}
return nombre[0].toUpperCase();
}
return '?';
}
}
class EstadoCupo {
final int usados;
final int disponibles;
final int limiteTotal;
final bool tienePlan;
const EstadoCupo({
required this.usados,
required this.disponibles,
required this.limiteTotal,
required this.tienePlan,
});
factory EstadoCupo.fromMap(Map<String, dynamic> map) {
return EstadoCupo(
usados: (map['usados'] as num?)?.toInt() ?? 0,
disponibles: (map['disponibles'] as num?)?.toInt() ?? 0,
limiteTotal: (map['limite_total'] as num?)?.toInt() ?? 0,
tienePlan: map['tiene_plan'] as bool? ?? false,
);
}
}