Files
virtus 2b8fa4ee57
Build Android APK / build-apk (push) Successful in 19m27s
Build Android AAB / build-aab (push) Successful in 12m5s
feat: Update app layout with MainAppHeader and enhance user settings interface
2026-04-23 03:09:24 +07:00

131 lines
4.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../../app/router/route_names.dart';
class AppShell extends StatelessWidget {
const AppShell({super.key, required this.child});
final Widget child;
String _tabForLocation(String location) {
if (location.startsWith(RouteNames.bookshelf)) return RouteNames.bookshelf;
if (location.startsWith(RouteNames.genres)) return RouteNames.genres;
if (location.startsWith(RouteNames.profile)) return RouteNames.profile;
return RouteNames.home;
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final colorScheme = theme.colorScheme;
final location = GoRouterState.of(context).uri.path;
final selectedTab = _tabForLocation(location);
return Scaffold(
body: child,
bottomNavigationBar: Container(
decoration: BoxDecoration(
color: colorScheme.surface,
border: Border(
top: BorderSide(color: colorScheme.outlineVariant.withAlpha(80)),
),
),
child: SafeArea(
top: false,
child: Padding(
padding: const EdgeInsets.fromLTRB(10, 8, 10, 6),
child: Row(
children: [
_ShellNavItem(
icon: Icons.home_rounded,
label: 'Trang chủ',
selected: selectedTab == RouteNames.home,
onTap: () => context.go(RouteNames.home),
),
_ShellNavItem(
icon: Icons.layers_rounded,
label: 'Tủ sách',
selected: selectedTab == RouteNames.bookshelf,
onTap: () => context.go(RouteNames.bookshelf),
),
_ShellNavItem(
icon: Icons.category_rounded,
label: 'Thể loại',
selected: selectedTab == RouteNames.genres,
onTap: () => context.go(RouteNames.genres),
),
_ShellNavItem(
icon: Icons.person_rounded,
label: 'Tài khoản',
selected: selectedTab == RouteNames.profile,
onTap: () => context.go(RouteNames.profile),
),
],
),
),
),
),
);
}
}
class _ShellNavItem extends StatelessWidget {
const _ShellNavItem({
required this.icon,
required this.label,
required this.selected,
required this.onTap,
});
final IconData icon;
final String label;
final bool selected;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final activeColor = const Color(0xFF14B8A6);
final inactiveColor = colorScheme.onSurfaceVariant;
return Expanded(
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(18),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
AnimatedContainer(
duration: const Duration(milliseconds: 180),
padding: const EdgeInsets.all(6),
decoration: BoxDecoration(
color: selected ? activeColor.withAlpha(28) : Colors.transparent,
shape: BoxShape.circle,
),
child: Icon(
icon,
size: 22,
color: selected ? activeColor : inactiveColor,
),
),
const SizedBox(height: 4),
Text(
label,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.labelSmall?.copyWith(
color: selected ? const Color(0xFFF7B500) : inactiveColor,
fontWeight: selected ? FontWeight.w700 : FontWeight.w500,
),
),
],
),
),
),
);
}
}