90 lines
3.2 KiB
Dart
90 lines
3.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:intl/intl.dart';
|
|
import '../../../core/api/client.dart';
|
|
import '../../../core/api/endpoints.dart';
|
|
import '../../../models/voice.dart';
|
|
import '../../../widgets/loading_indicator.dart';
|
|
import '../../../widgets/empty_state.dart';
|
|
import '../../../core/theme/app_theme.dart';
|
|
|
|
class VoiceSessionsScreen extends ConsumerStatefulWidget {
|
|
const VoiceSessionsScreen({super.key});
|
|
|
|
@override
|
|
ConsumerState<VoiceSessionsScreen> createState() =>
|
|
_VoiceSessionsScreenState();
|
|
}
|
|
|
|
class _VoiceSessionsScreenState extends ConsumerState<VoiceSessionsScreen> {
|
|
List<VoiceSession> _sessions = [];
|
|
bool _isLoading = true;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadSessions();
|
|
}
|
|
|
|
Future<void> _loadSessions() async {
|
|
setState(() => _isLoading = true);
|
|
try {
|
|
final api = ref.read(apiClientProvider);
|
|
final response = await api.get(Endpoints.voiceSessions);
|
|
final list = (response.data as List<dynamic>)
|
|
.map((e) => VoiceSession.fromJson(e as Map<String, dynamic>))
|
|
.toList();
|
|
if (mounted) setState(() => _sessions = list);
|
|
} catch (_) {}
|
|
if (mounted) setState(() => _isLoading = false);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(title: const Text('История сессий')),
|
|
body: _isLoading
|
|
? const LoadingIndicator()
|
|
: _sessions.isEmpty
|
|
? const EmptyState(
|
|
icon: Icons.history,
|
|
title: 'Нет сессий',
|
|
subtitle: 'Начните голосовой ввод',
|
|
)
|
|
: RefreshIndicator(
|
|
onRefresh: _loadSessions,
|
|
child: ListView.builder(
|
|
padding: const EdgeInsets.all(16),
|
|
itemCount: _sessions.length,
|
|
itemBuilder: (_, i) {
|
|
final session = _sessions[i];
|
|
return Card(
|
|
margin: const EdgeInsets.only(bottom: 12),
|
|
child: ListTile(
|
|
leading: CircleAvatar(
|
|
backgroundColor:
|
|
VoIdeaColors.primary.withOpacity(0.1),
|
|
child: const Icon(Icons.mic,
|
|
color: VoIdeaColors.primary),
|
|
),
|
|
title: Text(
|
|
session.title ?? 'Сессия ${i + 1}'),
|
|
subtitle: Text(
|
|
'${session.messageCount} сообщений · ${DateFormat('d MMM').format(session.createdAt)}',
|
|
style: const TextStyle(fontSize: 12),
|
|
),
|
|
trailing: Chip(
|
|
label: Text(
|
|
session.status,
|
|
style: const TextStyle(fontSize: 11),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|