Co-authored-by: Azareth-Tr <Azareth-Tr@users.noreply.github.com> Co-authored-by: eddgranados12 <eddgranados12@users.noreply.github.com> configuracion inicial para supoabase y endpoints
197 lines
6.1 KiB
Dart
197 lines
6.1 KiB
Dart
// ── Usuario ──────────────────────────────────────────────────────────────────
|
|
class UserModel {
|
|
final String id;
|
|
final String nombre;
|
|
final String apellido;
|
|
final String email;
|
|
final String telefono;
|
|
final List<HouseModel> casas;
|
|
|
|
const UserModel({
|
|
required this.id,
|
|
required this.nombre,
|
|
required this.apellido,
|
|
required this.email,
|
|
required this.telefono,
|
|
this.casas = const [],
|
|
});
|
|
|
|
String get nombreCompleto => '$nombre $apellido';
|
|
String get iniciales =>
|
|
'${nombre.isNotEmpty ? nombre[0] : ''}${apellido.isNotEmpty ? apellido[0] : ''}'
|
|
.toUpperCase();
|
|
|
|
UserModel copyWith({
|
|
String? nombre,
|
|
String? apellido,
|
|
String? email,
|
|
String? telefono,
|
|
List<HouseModel>? casas,
|
|
}) {
|
|
return UserModel(
|
|
id: id,
|
|
nombre: nombre ?? this.nombre,
|
|
apellido: apellido ?? this.apellido,
|
|
email: email ?? this.email,
|
|
telefono: telefono ?? this.telefono,
|
|
casas: casas ?? this.casas,
|
|
);
|
|
}
|
|
}
|
|
|
|
// ── Casa ─────────────────────────────────────────────────────────────────────
|
|
class HouseModel {
|
|
final String id;
|
|
final String alias;
|
|
final String calle;
|
|
final String colonia;
|
|
final String codigoPostal;
|
|
final double latitud;
|
|
final double longitud;
|
|
final int radioAlertaMetros;
|
|
final bool alertaCercana;
|
|
final bool alertaMedia;
|
|
final bool recordatorioDiario;
|
|
final bool activa;
|
|
|
|
const HouseModel({
|
|
required this.id,
|
|
this.alias = 'Casa principal',
|
|
required this.calle,
|
|
required this.colonia,
|
|
required this.codigoPostal,
|
|
required this.latitud,
|
|
required this.longitud,
|
|
this.radioAlertaMetros = 200,
|
|
this.alertaCercana = true,
|
|
this.alertaMedia = false,
|
|
this.recordatorioDiario = true,
|
|
this.activa = true,
|
|
});
|
|
|
|
String get direccionCompleta => '$calle, Col. $colonia, C.P. $codigoPostal';
|
|
|
|
HouseModel copyWith({
|
|
String? alias,
|
|
String? calle,
|
|
String? colonia,
|
|
String? codigoPostal,
|
|
double? latitud,
|
|
double? longitud,
|
|
int? radioAlertaMetros,
|
|
bool? alertaCercana,
|
|
bool? alertaMedia,
|
|
bool? recordatorioDiario,
|
|
bool? activa,
|
|
}) {
|
|
return HouseModel(
|
|
id: id,
|
|
alias: alias ?? this.alias,
|
|
calle: calle ?? this.calle,
|
|
colonia: colonia ?? this.colonia,
|
|
codigoPostal: codigoPostal ?? this.codigoPostal,
|
|
latitud: latitud ?? this.latitud,
|
|
longitud: longitud ?? this.longitud,
|
|
radioAlertaMetros: radioAlertaMetros ?? this.radioAlertaMetros,
|
|
alertaCercana: alertaCercana ?? this.alertaCercana,
|
|
alertaMedia: alertaMedia ?? this.alertaMedia,
|
|
recordatorioDiario: recordatorioDiario ?? this.recordatorioDiario,
|
|
activa: activa ?? this.activa,
|
|
);
|
|
}
|
|
}
|
|
|
|
// ── Camión ───────────────────────────────────────────────────────────────────
|
|
class TruckLocation {
|
|
final String id;
|
|
final String ruta;
|
|
final double latitud;
|
|
final double longitud;
|
|
final DateTime ultimaActualizacion;
|
|
final bool enServicio;
|
|
|
|
const TruckLocation({
|
|
required this.id,
|
|
required this.ruta,
|
|
required this.latitud,
|
|
required this.longitud,
|
|
required this.ultimaActualizacion,
|
|
this.enServicio = true,
|
|
});
|
|
|
|
String get tiempoActualizacion {
|
|
final diff = DateTime.now().difference(ultimaActualizacion);
|
|
if (diff.inSeconds < 60) return 'Hace ${diff.inSeconds} s';
|
|
if (diff.inMinutes < 60) return 'Hace ${diff.inMinutes} min';
|
|
return 'Hace ${diff.inHours} h';
|
|
}
|
|
}
|
|
|
|
// ── Alerta ───────────────────────────────────────────────────────────────────
|
|
enum TipoAlerta { cercana, media, recordatorio }
|
|
|
|
class AlertaModel {
|
|
final String id;
|
|
final TipoAlerta tipo;
|
|
final double distanciaMetros;
|
|
final DateTime fecha;
|
|
final String direccionCasa;
|
|
final bool leida;
|
|
|
|
const AlertaModel({
|
|
required this.id,
|
|
required this.tipo,
|
|
required this.distanciaMetros,
|
|
required this.fecha,
|
|
required this.direccionCasa,
|
|
this.leida = false,
|
|
});
|
|
|
|
String get distanciaTexto {
|
|
if (distanciaMetros < 1000) {
|
|
return '${distanciaMetros.toStringAsFixed(0)} m';
|
|
}
|
|
return '${(distanciaMetros / 1000).toStringAsFixed(1)} km';
|
|
}
|
|
|
|
String get tiempoEstimadoTexto {
|
|
// ~5 km/h velocidad promedio del camión
|
|
final segundos = (distanciaMetros / (5000 / 3600)).round();
|
|
if (segundos < 60) return 'Menos de 1 min';
|
|
final minutos = (segundos / 60).ceil();
|
|
return '~$minutos min';
|
|
}
|
|
|
|
String get fechaFormateada {
|
|
final ahora = DateTime.now();
|
|
final hoy = DateTime(ahora.year, ahora.month, ahora.day);
|
|
final fechaDia = DateTime(fecha.year, fecha.month, fecha.day);
|
|
|
|
if (fechaDia == hoy) {
|
|
return 'Hoy, ${_formatHora(fecha)}';
|
|
}
|
|
final ayer = hoy.subtract(const Duration(days: 1));
|
|
if (fechaDia == ayer) return 'Ayer, ${_formatHora(fecha)}';
|
|
|
|
const dias = ['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom'];
|
|
const meses = ['ene','feb','mar','abr','may','jun','jul','ago','sep','oct','nov','dic'];
|
|
return '${dias[fecha.weekday - 1]} ${fecha.day} ${meses[fecha.month - 1]}, ${_formatHora(fecha)}';
|
|
}
|
|
|
|
String get etiquetaFecha {
|
|
final ahora = DateTime.now();
|
|
final hoy = DateTime(ahora.year, ahora.month, ahora.day);
|
|
final fechaDia = DateTime(fecha.year, fecha.month, fecha.day);
|
|
if (fechaDia == hoy) return 'Hoy';
|
|
const dias = ['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom'];
|
|
return dias[fecha.weekday - 1];
|
|
}
|
|
|
|
String _formatHora(DateTime dt) {
|
|
final h = dt.hour > 12 ? dt.hour - 12 : dt.hour == 0 ? 12 : dt.hour;
|
|
final m = dt.minute.toString().padLeft(2, '0');
|
|
final ampm = dt.hour >= 12 ? 'p.m.' : 'a.m.';
|
|
return '$h:$m $ampm';
|
|
}
|
|
}
|