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:
113
mobile/lib/features/archive/archive_screen.dart
Normal file
113
mobile/lib/features/archive/archive_screen.dart
Normal file
@@ -0,0 +1,113 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import '../../app/theme.dart';
|
||||
import '../../shared/premium_dialog.dart';
|
||||
import '../matches/team_providers.dart';
|
||||
|
||||
class ArchiveScreen extends ConsumerWidget {
|
||||
const ArchiveScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final teamAsync = ref.watch(primaryTeamProvider);
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Archivio gare'),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => context.go('/matches'),
|
||||
),
|
||||
),
|
||||
body: teamAsync.when(
|
||||
loading: () => const Center(
|
||||
child: CircularProgressIndicator(color: AppTheme.primaryRed),
|
||||
),
|
||||
error: (e, _) => Center(child: Text('Errore: $e')),
|
||||
data: (team) {
|
||||
if (team == null) {
|
||||
return const Center(child: Text('Nessuna squadra'));
|
||||
}
|
||||
if (!team.canUseRecordings) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Archivio replay con Premium Light o Full',
|
||||
style: theme.textTheme.titleMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilledButton(
|
||||
onPressed: () => showPremiumRequiredDialog(
|
||||
context,
|
||||
message: 'Salva e rivedi le gare per 90 giorni con il piano Premium.',
|
||||
billingUrl: team.billingUrl,
|
||||
),
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: AppTheme.primaryRed,
|
||||
),
|
||||
child: const Text('Scopri Premium'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final recsAsync = ref.watch(recordingsProvider(team.id));
|
||||
return recsAsync.when(
|
||||
loading: () => const Center(
|
||||
child: CircularProgressIndicator(color: AppTheme.primaryRed),
|
||||
),
|
||||
error: (e, _) => Center(child: Text('$e')),
|
||||
data: (recs) {
|
||||
if (recs.isEmpty) {
|
||||
return const Center(child: Text('Nessuna gara in archivio'));
|
||||
}
|
||||
final df = DateFormat('d MMM yyyy · HH:mm', 'it_IT');
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: recs.length,
|
||||
itemBuilder: (context, i) {
|
||||
final r = recs[i];
|
||||
return Card(
|
||||
color: AppTheme.surface,
|
||||
child: ListTile(
|
||||
title: Text('${r.teamName} vs ${r.opponentName}'),
|
||||
subtitle: Text(
|
||||
r.endedAt != null ? df.format(r.endedAt!.toLocal()) : '—',
|
||||
),
|
||||
trailing: const Icon(Icons.play_circle_outline),
|
||||
onTap: () async {
|
||||
final url = r.replayUrl;
|
||||
if (url == null) return;
|
||||
final uri = Uri.parse(url);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(
|
||||
uri,
|
||||
mode: team.canDownloadOnPhone
|
||||
? LaunchMode.externalApplication
|
||||
: LaunchMode.inAppBrowserView,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user