Initial commit: monorepo Match Live TV.

Rails API, app Flutter, infrastruttura Docker/MediaMTX, sito marketing e documentazione di deploy.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-26 17:45:37 +02:00
commit bba6df52c0
381 changed files with 20599 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
class MatchModel {
const MatchModel({
required this.id,
required this.teamId,
required this.teamName,
required this.opponentName,
this.location,
this.scheduledAt,
this.sport = 'volleyball',
this.setsToWin = 3,
this.scoringRules,
this.rosterNumbers = const [],
this.category,
this.phase,
this.activeSessionId,
this.activeSessionStatus,
});
final String id;
final String teamId;
final String teamName;
final String opponentName;
final String? location;
final DateTime? scheduledAt;
final String sport;
final int setsToWin;
final Map<String, dynamic>? scoringRules;
final List<int> rosterNumbers;
final String? category;
final String? phase;
final String? activeSessionId;
final String? activeSessionStatus;
/// Sessione avviata (o in ripresa) — si può rientrare in camera senza rifare il wizard.
bool get canResumeCamera {
const resumable = {'connecting', 'live', 'reconnecting', 'paused'};
return activeSessionId != null &&
activeSessionStatus != null &&
resumable.contains(activeSessionStatus);
}
bool get hasActiveSession => activeSessionId != null;
factory MatchModel.fromJson(Map<String, dynamic> json) {
return MatchModel(
id: json['id'] as String,
teamId: json['team_id'] as String,
teamName: json['team_name'] as String? ?? '',
opponentName: json['opponent_name'] as String,
location: json['location'] as String?,
scheduledAt: json['scheduled_at'] != null
? DateTime.tryParse(json['scheduled_at'] as String)
: null,
sport: json['sport'] as String? ?? 'volleyball',
setsToWin: json['sets_to_win'] as int? ?? 3,
scoringRules: json['scoring_rules'] is Map
? Map<String, dynamic>.from(json['scoring_rules'] as Map)
: null,
rosterNumbers: (json['roster_numbers'] as List<dynamic>?)
?.map((e) => (e as num).toInt())
.toList() ??
const [],
category: json['category'] as String?,
phase: json['phase'] as String?,
activeSessionId: json['active_session_id'] as String?,
activeSessionStatus: json['active_session_status'] as String?,
);
}
Map<String, dynamic> toJson() => {
'opponent_name': opponentName,
'location': location,
'scheduled_at': scheduledAt?.toIso8601String(),
'sport': sport,
'sets_to_win': setsToWin,
if (scoringRules != null) 'scoring_rules': scoringRules,
'roster_numbers': rosterNumbers,
'category': category,
'phase': phase,
};
}