fromis_9/app/lib/views/main_shell.dart

155 lines
3.9 KiB
Dart

/// 메인 셸 - 툴바 + 바텀 네비게이션
library;
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:lucide_icons/lucide_icons.dart';
import '../core/constants.dart';
/// 메인 앱 셸 (툴바 + 바텀 네비게이션 + 콘텐츠)
class MainShell extends StatelessWidget {
final Widget child;
const MainShell({super.key, required this.child});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.background,
// 앱바 (툴바)
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
scrolledUnderElevation: 1,
centerTitle: true,
title: Text(
_getTitle(context),
style: const TextStyle(
color: AppColors.primary,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
// 콘텐츠
body: child,
// 바텀 네비게이션
bottomNavigationBar: const _BottomNavBar(),
);
}
/// 현재 경로에 따른 타이틀 반환
String _getTitle(BuildContext context) {
final location = GoRouterState.of(context).uri.path;
switch (location) {
case '/':
return 'fromis_9';
case '/members':
return '멤버';
case '/album':
return '앨범';
case '/schedule':
return '일정';
default:
return 'fromis_9';
}
}
}
/// 바텀 네비게이션 바
class _BottomNavBar extends StatelessWidget {
const _BottomNavBar();
@override
Widget build(BuildContext context) {
final location = GoRouterState.of(context).uri.path;
return Container(
decoration: const BoxDecoration(
color: Colors.white,
border: Border(
top: BorderSide(color: AppColors.border, width: 1),
),
),
child: SafeArea(
child: SizedBox(
height: 64,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_NavItem(
icon: LucideIcons.home,
label: '',
isActive: location == '/',
onTap: () => context.go('/'),
),
_NavItem(
icon: LucideIcons.users,
label: '멤버',
isActive: location == '/members',
onTap: () => context.go('/members'),
),
_NavItem(
icon: LucideIcons.disc3,
label: '앨범',
isActive: location.startsWith('/album'),
onTap: () => context.go('/album'),
),
_NavItem(
icon: LucideIcons.calendar,
label: '일정',
isActive: location.startsWith('/schedule'),
onTap: () => context.go('/schedule'),
),
],
),
),
),
);
}
}
/// 네비게이션 아이템
class _NavItem extends StatelessWidget {
final IconData icon;
final String label;
final bool isActive;
final VoidCallback onTap;
const _NavItem({
required this.icon,
required this.label,
required this.isActive,
required this.onTap,
});
@override
Widget build(BuildContext context) {
final color = isActive ? AppColors.primary : AppColors.textTertiary;
return Expanded(
child: InkWell(
onTap: onTap,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon,
size: 22,
color: color,
),
const SizedBox(height: 4),
Text(
label,
style: TextStyle(
fontSize: 12,
fontWeight: isActive ? FontWeight.w600 : FontWeight.w500,
color: color,
),
),
],
),
),
);
}
}