Files
jizhi/frontend/lib/features/home/pages/main_shell.dart
T

137 lines
4.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:miaoji_zhang/shared/api/config_api.dart';
import 'package:miaoji_zhang/shared/services/session_store.dart';
import 'package:miaoji_zhang/shared/theme/app_theme.dart';
import 'package:miaoji_zhang/shared/widgets/app_icons.dart';
class MainShell extends StatefulWidget {
final StatefulNavigationShell shell;
const MainShell({super.key, required this.shell});
@override
State<MainShell> createState() => _MainShellState();
}
class _MainShellState extends State<MainShell> {
@override
void initState() {
super.initState();
PublicConfigApi.refreshCompanion();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: SessionStore.instance,
builder: (context, _) {
return Scaffold(
body: AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
switchInCurve: Curves.easeOut,
switchOutCurve: Curves.easeIn,
child: KeyedSubtree(
key: ValueKey(widget.shell.currentIndex),
child: widget.shell,
),
),
bottomNavigationBar: Container(
decoration: BoxDecoration(
color: context.jz.card,
border: Border(
top: BorderSide(color: context.jz.line, width: 0.5),
),
),
child: SafeArea(
child: SizedBox(
height: 64,
child: Row(
children: [
_tab('明细', AppIcons.home, 0),
_tab('统计', AppIcons.chart, 1),
SizedBox(width: 72, child: _fab()),
ValueListenableBuilder<CompanionDisplay>(
valueListenable: PublicConfigApi.companionNotifier,
builder: (_, companion, __) =>
_tab(companion.name, AppIcons.chat, 2),
),
_tab('我的', AppIcons.user, 3),
],
),
),
),
),
);
},
);
}
Widget _tab(String label, String icon, int branch) {
final active = widget.shell.currentIndex == branch;
final color = active ? AppTheme.primary : context.jz.text3;
return Expanded(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () => widget.shell.goBranch(branch),
child: SizedBox(
height: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AppIcons.icon(icon, size: 21, color: color),
const SizedBox(height: 3),
Text(
label,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 10,
color: color,
fontWeight: active ? FontWeight.w600 : null,
),
),
],
),
),
),
),
);
}
Widget _fab() {
return Material(
color: Colors.transparent,
child: InkWell(
onTap: () async {
final amount = await context.push<double>('/add');
if (!mounted || amount == null) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('已记一笔 ¥${amount.toStringAsFixed(2)}')),
);
},
child: Center(
child: Container(
width: 46,
height: 46,
margin: const EdgeInsets.only(top: 4),
decoration: BoxDecoration(
color: AppTheme.primary,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: AppTheme.primary.withValues(alpha: 0.24),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: AppIcons.icon(AppIcons.plus, size: 22, color: Colors.white),
),
),
),
);
}
}