Files
note-book/frontend/lib/app.dart
2026-05-19 11:46:42 +08:00

128 lines
4.4 KiB
Dart

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'providers/auth_provider.dart';
import 'screens/home/home_screen.dart';
import 'screens/auth/login_screen.dart';
import 'screens/auth/register_screen.dart';
import 'screens/profile/profile_screen.dart';
import 'screens/statistics/statistics_screen.dart';
import 'screens/add_bill/add_bill_screen.dart';
import 'screens/auth/user_profile_screen.dart';
import 'screens/auth/bind_email_screen.dart';
import 'screens/family/family_management_screen.dart';
class AppShell extends ConsumerStatefulWidget {
const AppShell({super.key});
@override
ConsumerState<AppShell> createState() => _AppShellState();
}
class _AppShellState extends ConsumerState<AppShell> {
int _currentTab = 0;
bool _showAddBill = false;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
ref.read(authProvider.notifier).restoreSession();
});
}
@override
Widget build(BuildContext context) {
final authState = ref.watch(authProvider);
Widget body;
if (_showAddBill) {
return const AddBillScreen();
}
switch (_currentTab) {
case 0:
body = const HomeScreen();
break;
case 1:
body = const StatisticsScreen();
break;
case 2:
body = const ProfileScreen();
break;
default:
body = const HomeScreen();
}
return Scaffold(
body: body,
bottomNavigationBar: Container(
padding: const EdgeInsets.only(bottom: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(
color: AppColors.cardBg,
borderRadius: BorderRadius.circular(30),
border: Border.all(color: Colors.white.withOpacity(0.8)),
boxShadow: [BoxShadow(color: AppColors.brand.withOpacity(0.08), blurRadius: 32, offset: const Offset(0, 8))],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(30),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 30, sigmaY: 30),
child: BottomNavigationBar(
currentIndex: _currentTab,
onTap: (i) => setState(() => _currentTab = i),
backgroundColor: Colors.transparent,
elevation: 0,
selectedItemColor: AppColors.brand,
unselectedItemColor: AppColors.textSecondary,
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home_outlined, size: 22), activeIcon: Icon(Icons.home, size: 22), label: '首页'),
BottomNavigationBarItem(icon: Icon(Icons.bar_chart_outlined, size: 22), activeIcon: Icon(Icons.bar_chart, size: 22), label: '统计'),
BottomNavigationBarItem(icon: Icon(Icons.person_outline, size: 22), activeIcon: Icon(Icons.person, size: 22), label: '我的'),
],
),
),
),
),
const SizedBox(width: 8),
GestureDetector(
onTap: () {
if (!authState.isLoggedIn && mounted) {
_navigateToLogin();
return;
}
setState(() => _showAddBill = true);
},
child: Container(
width: 48,
height: 48,
decoration: BoxDecoration(
gradient: const LinearGradient(colors: [Color(0xFFFF6B35), Color(0xFFFF9F5B)]),
shape: BoxShape.circle,
boxShadow: [BoxShadow(color: AppColors.brand.withOpacity(0.3), blurRadius: 12, offset: const Offset(0, 4))],
),
child: const Icon(Icons.add, color: Colors.white, size: 24),
),
),
],
),
),
);
}
void _navigateToLogin() {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => const LoginScreen()));
}
}
// Colors used in this file
class AppColors {
static const brand = Color(0xFFFF6B35);
static const brandLight = Color(0xFFFF9F5B);
static const cardBg = Color(0xA6FFFFFF);
static const textPrimary = Color(0xFF1C1C1E);
static const textSecondary = Color(0xFF8E8E93);
}