Files
trainhub-flutter/lib/presentation/analysis/widgets/analysis_session_list.dart
Kazimierz Ciołek f943e89430 Some refactors
2026-02-19 14:16:03 +01:00

165 lines
5.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:trainhub_flutter/core/theme/app_colors.dart';
import 'package:trainhub_flutter/core/constants/ui_constants.dart';
import 'package:trainhub_flutter/domain/entities/analysis_session.dart';
class AnalysisSessionList extends StatelessWidget {
final List<AnalysisSessionEntity> sessions;
final Function(AnalysisSessionEntity) onSessionSelected;
final Function(AnalysisSessionEntity) onDeleteSession;
const AnalysisSessionList({
super.key,
required this.sessions,
required this.onSessionSelected,
required this.onDeleteSession,
});
@override
Widget build(BuildContext context) {
return ListView.builder(
padding: const EdgeInsets.all(UIConstants.spacing24),
itemCount: sessions.length,
itemBuilder: (context, index) {
final session = sessions[index];
return _SessionCard(
session: session,
onTap: () => onSessionSelected(session),
onDelete: () => onDeleteSession(session),
);
},
);
}
}
class _SessionCard extends StatefulWidget {
final AnalysisSessionEntity session;
final VoidCallback onTap;
final VoidCallback onDelete;
const _SessionCard({
required this.session,
required this.onTap,
required this.onDelete,
});
@override
State<_SessionCard> createState() => _SessionCardState();
}
class _SessionCardState extends State<_SessionCard> {
bool _isHovered = false;
@override
Widget build(BuildContext context) {
return MouseRegion(
onEnter: (_) => setState(() => _isHovered = true),
onExit: (_) => setState(() => _isHovered = false),
child: AnimatedContainer(
duration: UIConstants.animationDuration,
margin: const EdgeInsets.only(bottom: UIConstants.spacing12),
decoration: BoxDecoration(
color: _isHovered ? AppColors.surfaceContainerHigh : AppColors.surfaceContainer,
borderRadius: UIConstants.cardBorderRadius,
border: Border.all(
color: _isHovered ? AppColors.zinc600 : AppColors.border,
),
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: widget.onTap,
borderRadius: UIConstants.cardBorderRadius,
child: Padding(
padding: const EdgeInsets.all(UIConstants.cardPadding),
child: Row(
children: [
Container(
width: 44,
height: 44,
decoration: BoxDecoration(
color: AppColors.purpleMuted,
borderRadius: BorderRadius.circular(10),
),
child: const Icon(
Icons.play_circle_outline,
color: AppColors.purple,
size: 24,
),
),
const SizedBox(width: UIConstants.spacing16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.session.name,
style: const TextStyle(
color: AppColors.textPrimary,
fontSize: 15,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 4),
Row(
children: [
const Icon(
Icons.calendar_today_outlined,
size: 12,
color: AppColors.textMuted,
),
const SizedBox(width: 4),
Text(
widget.session.date,
style: const TextStyle(
color: AppColors.textMuted,
fontSize: 12,
),
),
if (widget.session.videoPath != null) ...[
const SizedBox(width: UIConstants.spacing12),
const Icon(
Icons.videocam_outlined,
size: 12,
color: AppColors.info,
),
const SizedBox(width: 4),
const Text(
'Video',
style: TextStyle(
color: AppColors.info,
fontSize: 12,
),
),
],
],
),
],
),
),
if (_isHovered)
IconButton(
icon: const Icon(
Icons.delete_outline,
size: 18,
color: AppColors.destructive,
),
onPressed: widget.onDelete,
tooltip: 'Delete',
)
else
const Icon(
Icons.chevron_right,
size: 20,
color: AppColors.textMuted,
),
],
),
),
),
),
),
);
}
}