depor_os/lib/models/booking.dart

174 lines
5.1 KiB
Dart
Raw Permalink Normal View History

2026-03-18 11:47:06 +00:00
// ── Activity ──────────────────────────────────────────────────────────────────
class BookingActivity {
final int id;
final String name;
const BookingActivity({required this.id, required this.name});
factory BookingActivity.fromJson(Map<String, dynamic> json) =>
BookingActivity(
id: json['pk_i_id'] ?? 0,
name: json['s_name'] ?? '',
);
}
// ── Grid ──────────────────────────────────────────────────────────────────────
class BookingCell {
final String raw;
const BookingCell(this.raw);
bool get isEmpty => raw.isEmpty;
bool get isPaid => raw.isNotEmpty && raw.endsWith('+');
bool get isBooked => raw.isNotEmpty;
int? get memberId {
final m = RegExp(r'^(\d+)\.').firstMatch(raw);
return m != null ? int.tryParse(m.group(1)!) : null;
}
int? get familyId {
final m = RegExp(r'\.(\d+)[+\-]?$').firstMatch(raw);
return m != null ? int.tryParse(m.group(1)!) : null;
}
}
class BookingRow {
final int slotIndex;
final String timeLabel;
final List<BookingCell> cells; // one per court
const BookingRow({
required this.slotIndex,
required this.timeLabel,
required this.cells,
});
}
class BookingGrid {
final List<BookingRow> rows;
final List<String> courtTitles; // ["01", "02", ...]
final String activityName;
final int light;
final int extra;
final String? celebrations;
const BookingGrid({
required this.rows,
required this.courtTitles,
required this.activityName,
required this.light,
required this.extra,
this.celebrations,
});
factory BookingGrid.fromJson(Map<String, dynamic> json) {
final aoColumns = json['aoColumns'] as List<dynamic>? ?? [];
final aaData = json['aaData'] as List<dynamic>? ?? [];
final courtTitles = aoColumns
.skip(1)
.map((c) => (c as Map<String, dynamic>)['sTitle'] as String? ?? '')
.toList();
final rows = aaData.map((rowData) {
final row = rowData as List<dynamic>;
final firstCell = row[0] as String? ?? '';
final idMatch = RegExp(r'id="(\d+)"').firstMatch(firstCell);
final slotIndex = idMatch != null ? int.parse(idMatch.group(1)!) : 0;
final timeMatch = RegExp(r'>([^<]+)<').firstMatch(firstCell);
final timeLabel = timeMatch?.group(1) ?? firstCell;
final cells = row
.skip(1)
.map((c) => BookingCell(c as String? ?? ''))
.toList();
return BookingRow(slotIndex: slotIndex, timeLabel: timeLabel, cells: cells);
}).toList();
final ac = json['ac'] as Map<String, dynamic>? ?? {};
return BookingGrid(
rows: rows,
courtTitles: courtTitles,
activityName: ac['s_name'] as String? ?? '',
light: (json['light'] as num?)?.toInt() ?? 0,
extra: (json['extra'] as num?)?.toInt() ?? 0,
celebrations: json['celebrations'] as String?,
);
}
}
// ── Booking detail (single cell) ──────────────────────────────────────────────
class TicketLine {
final String concepto;
final double precio;
const TicketLine({required this.concepto, required this.precio});
factory TicketLine.fromJson(Map<String, dynamic> json) => TicketLine(
concepto: json['concepto'] ?? '',
precio: (json['precio'] as num?)?.toDouble() ?? 0,
);
}
class TicketPreview {
final String concepto;
final double base;
final double iva;
final double total;
final List<TicketLine> lines;
const TicketPreview({
required this.concepto,
required this.base,
required this.iva,
required this.total,
required this.lines,
});
factory TicketPreview.fromJson(Map<String, dynamic> json) => TicketPreview(
concepto: json['concepto'] ?? '',
base: (json['base'] as num?)?.toDouble() ?? 0,
iva: (json['iva'] as num?)?.toDouble() ?? 0,
total: (json['total'] as num?)?.toDouble() ?? 0,
lines: (json['lines'] as List<dynamic>? ?? [])
.map((l) => TicketLine.fromJson(l as Map<String, dynamic>))
.toList(),
);
}
class BookingDetail {
final int id;
final int memberId;
final int familyId;
final String date;
final bool paid;
final TicketPreview? ticket;
const BookingDetail({
required this.id,
required this.memberId,
required this.familyId,
required this.date,
required this.paid,
this.ticket,
});
factory BookingDetail.fromJson(Map<String, dynamic> json) {
final book = json['book'] as Map<String, dynamic>? ?? {};
final ticketJson = json['ticket'] as Map<String, dynamic>?;
return BookingDetail(
id: book['pk_i_id'] ?? 0,
memberId: book['fk_i_member_id'] ?? 0,
familyId: book['fk_i_family'] ?? 1,
date: book['d_date'] ?? '',
paid: (book['b_paid'] ?? 0) == 1,
ticket: ticketJson != null ? TicketPreview.fromJson(ticketJson) : null,
);
}
}