Refactoring
Some checks failed
Build Linux App / build (push) Failing after 1m33s

This commit is contained in:
2026-02-23 10:02:23 -05:00
parent 21f1387fa8
commit 0c9eb8878d
57 changed files with 8179 additions and 1114 deletions

View File

@@ -1,7 +1,9 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:trainhub_flutter/core/theme/app_colors.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:trainhub_flutter/core/constants/ui_constants.dart';
import 'package:trainhub_flutter/core/router/app_router.dart';
import 'package:trainhub_flutter/core/theme/app_colors.dart';
@RoutePage()
class ShellPage extends StatelessWidget {
@@ -22,50 +24,10 @@ class ShellPage extends StatelessWidget {
return Scaffold(
body: Row(
children: [
// NavigationRail with logo area at top
NavigationRail(
selectedIndex: tabsRouter.activeIndex,
_Sidebar(
activeIndex: tabsRouter.activeIndex,
onDestinationSelected: tabsRouter.setActiveIndex,
labelType: NavigationRailLabelType.all,
leading: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Column(
children: [
Icon(Icons.fitness_center, color: AppColors.accent, size: 28),
const SizedBox(height: 4),
Text('TrainHub', style: TextStyle(color: AppColors.textPrimary, fontSize: 10, fontWeight: FontWeight.w600)),
],
),
),
destinations: const [
NavigationRailDestination(
icon: Icon(Icons.dashboard_outlined),
selectedIcon: Icon(Icons.dashboard),
label: Text('Home'),
),
NavigationRailDestination(
icon: Icon(Icons.fitness_center_outlined),
selectedIcon: Icon(Icons.fitness_center),
label: Text('Trainings'),
),
NavigationRailDestination(
icon: Icon(Icons.video_library_outlined),
selectedIcon: Icon(Icons.video_library),
label: Text('Analysis'),
),
NavigationRailDestination(
icon: Icon(Icons.calendar_today_outlined),
selectedIcon: Icon(Icons.calendar_today),
label: Text('Calendar'),
),
NavigationRailDestination(
icon: Icon(Icons.chat_bubble_outline),
selectedIcon: Icon(Icons.chat_bubble),
label: Text('AI Chat'),
),
],
),
const VerticalDivider(thickness: 1, width: 1),
Expanded(child: child),
],
),
@@ -74,3 +36,259 @@ class ShellPage extends StatelessWidget {
);
}
}
// ---------------------------------------------------------------------------
// Sidebar
// ---------------------------------------------------------------------------
class _NavItemData {
final IconData icon;
final IconData activeIcon;
final String label;
const _NavItemData({
required this.icon,
required this.activeIcon,
required this.label,
});
}
class _Sidebar extends StatelessWidget {
final int activeIndex;
final ValueChanged<int> onDestinationSelected;
const _Sidebar({
required this.activeIndex,
required this.onDestinationSelected,
});
static const _items = [
_NavItemData(
icon: Icons.dashboard_outlined,
activeIcon: Icons.dashboard_rounded,
label: 'Home',
),
_NavItemData(
icon: Icons.fitness_center_outlined,
activeIcon: Icons.fitness_center,
label: 'Trainings',
),
_NavItemData(
icon: Icons.video_library_outlined,
activeIcon: Icons.video_library,
label: 'Analysis',
),
_NavItemData(
icon: Icons.calendar_today_outlined,
activeIcon: Icons.calendar_today,
label: 'Calendar',
),
_NavItemData(
icon: Icons.chat_bubble_outline,
activeIcon: Icons.chat_bubble,
label: 'AI Chat',
),
];
@override
Widget build(BuildContext context) {
return Container(
width: 200,
decoration: const BoxDecoration(
color: AppColors.surfaceContainer,
border: Border(right: BorderSide(color: AppColors.border)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// --- Logo ---
Padding(
padding: const EdgeInsets.fromLTRB(16, 20, 16, 20),
child: Row(
children: [
Container(
width: 34,
height: 34,
decoration: BoxDecoration(
color: AppColors.accentMuted,
borderRadius: BorderRadius.circular(8),
),
child: const Icon(
Icons.fitness_center,
color: AppColors.accent,
size: 18,
),
),
const SizedBox(width: 10),
Text(
'TrainHub',
style: GoogleFonts.inter(
fontSize: 15,
fontWeight: FontWeight.w700,
color: AppColors.textPrimary,
letterSpacing: -0.3,
),
),
],
),
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 12),
child: Divider(height: 1),
),
const SizedBox(height: UIConstants.spacing8),
// --- Nav items ---
for (int i = 0; i < _items.length; i++)
_NavItem(
data: _items[i],
isActive: activeIndex == i,
onTap: () => onDestinationSelected(i),
),
const Spacer(),
// --- Footer ---
Padding(
padding: const EdgeInsets.fromLTRB(12, 8, 12, 12),
child: Row(
children: [
Text(
'v2.0.0',
style: GoogleFonts.inter(
fontSize: 11,
color: AppColors.textMuted,
),
),
const Spacer(),
const _SettingsButton(),
],
),
),
],
),
);
}
}
class _NavItem extends StatefulWidget {
final _NavItemData data;
final bool isActive;
final VoidCallback onTap;
const _NavItem({
required this.data,
required this.isActive,
required this.onTap,
});
@override
State<_NavItem> createState() => _NavItemState();
}
class _NavItemState extends State<_NavItem> {
bool _isHovered = false;
@override
Widget build(BuildContext context) {
final active = widget.isActive;
return MouseRegion(
onEnter: (_) => setState(() => _isHovered = true),
onExit: (_) => setState(() => _isHovered = false),
child: GestureDetector(
onTap: widget.onTap,
child: AnimatedContainer(
duration: UIConstants.animationDuration,
height: 40,
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 1),
decoration: BoxDecoration(
color: active
? AppColors.zinc800
: _isHovered
? AppColors.zinc900
: Colors.transparent,
borderRadius: BorderRadius.circular(6),
),
child: Row(
children: [
// Left accent indicator
AnimatedContainer(
duration: UIConstants.animationDuration,
width: 3,
height: active ? 20 : 0,
margin: const EdgeInsets.only(left: 4, right: 8),
decoration: BoxDecoration(
color: AppColors.accent,
borderRadius: BorderRadius.circular(2),
),
),
if (!active) const SizedBox(width: 15),
Icon(
active ? widget.data.activeIcon : widget.data.icon,
size: 17,
color: active ? AppColors.textPrimary : AppColors.textMuted,
),
const SizedBox(width: 9),
Text(
widget.data.label,
style: GoogleFonts.inter(
fontSize: 13,
fontWeight: active ? FontWeight.w600 : FontWeight.w400,
color: active
? AppColors.textPrimary
: _isHovered
? AppColors.textSecondary
: AppColors.textMuted,
),
),
],
),
),
),
);
}
}
// ---------------------------------------------------------------------------
// Settings icon button in sidebar footer
// ---------------------------------------------------------------------------
class _SettingsButton extends StatefulWidget {
const _SettingsButton();
@override
State<_SettingsButton> createState() => _SettingsButtonState();
}
class _SettingsButtonState extends State<_SettingsButton> {
bool _hovered = false;
@override
Widget build(BuildContext context) {
return Tooltip(
message: 'Settings',
child: MouseRegion(
onEnter: (_) => setState(() => _hovered = true),
onExit: (_) => setState(() => _hovered = false),
child: GestureDetector(
onTap: () => context.router.push(const SettingsRoute()),
child: AnimatedContainer(
duration: UIConstants.animationDuration,
width: 28,
height: 28,
decoration: BoxDecoration(
color: _hovered ? AppColors.zinc800 : Colors.transparent,
borderRadius: BorderRadius.circular(6),
),
child: Icon(
Icons.settings_outlined,
size: 16,
color: _hovered ? AppColors.textSecondary : AppColors.textMuted,
),
),
),
),
);
}
}