// lib/app/modules/navbar/views/navbar_view.dart import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import '../controllers/navbar_controller.dart'; import '../../home/views/home_view.dart'; import '../../history/views/history_view.dart'; class NavbarView extends StatelessWidget { const NavbarView({super.key}); @override Widget build(BuildContext context) { final controller = Get.find(); return Scaffold( backgroundColor: Colors.white, body: Obx( () => IndexedStack( index: controller.selectedIndex.value, children: const [HomeView(), HistoryView()], ), ), bottomNavigationBar: SafeArea( child: Container( margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), height: 70, child: Stack( clipBehavior: Clip.none, alignment: Alignment.center, children: [ // Navbar bar Container( height: 70, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(22), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), blurRadius: 16, offset: const Offset(0, 4), ), ], ), child: Row( children: [ Expanded( child: Obx( () => _NavItem( icon: Icons.home_rounded, label: 'Home', active: controller.selectedIndex.value == 0, onTap: () { HapticFeedback.lightImpact(); controller.changeTabIndex(0); }, ), ), ), const SizedBox(width: 76), Expanded( child: Obx( () => _NavItem( icon: Icons.receipt_long_rounded, label: 'Riwayat', active: controller.selectedIndex.value == 1, onTap: () { HapticFeedback.lightImpact(); controller.changeTabIndex(1); }, ), ), ), ], ), ), // Tombol tengah — posisi sedikit naik dari navbar Positioned( top: -18, // naik 18px dari tengah navbar, tidak terlalu tinggi child: const _CoinSlotButton(), ), ], ), ), ), ); } } class _NavItem extends StatelessWidget { final IconData icon; final String label; final bool active; final VoidCallback onTap; const _NavItem({ required this.icon, required this.label, required this.active, required this.onTap, }); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, behavior: HitTestBehavior.opaque, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( icon, size: 26, color: active ? const Color(0xFF5B9BD5) : const Color(0xFFBDCFE0), ), const SizedBox(height: 3), Text( label, style: TextStyle( color: active ? const Color(0xFF5B9BD5) : const Color(0xFFBDCFE0), fontSize: 10, fontWeight: active ? FontWeight.w700 : FontWeight.w400, ), ), ], ), ); } } class _CoinSlotButton extends StatefulWidget { const _CoinSlotButton(); @override State<_CoinSlotButton> createState() => _CoinSlotButtonState(); } class _CoinSlotButtonState extends State<_CoinSlotButton> with SingleTickerProviderStateMixin { late AnimationController _pressCtrl; late Animation _scaleAnim; final NavbarController controller = Get.find(); @override void initState() { super.initState(); _pressCtrl = AnimationController( vsync: this, duration: const Duration(milliseconds: 100), ); _scaleAnim = Tween( begin: 1.0, end: 0.92, ).animate(CurvedAnimation(parent: _pressCtrl, curve: Curves.easeOut)); } @override void dispose() { _pressCtrl.dispose(); super.dispose(); } void _handleTap() async { HapticFeedback.mediumImpact(); await _pressCtrl.forward(); _pressCtrl.reverse(); controller.toggleIot(); } @override Widget build(BuildContext context) { return Obx(() { final isOn = controller.isIotActive.value; return AnimatedBuilder( animation: _scaleAnim, builder: (_, __) => Transform.scale( scale: _scaleAnim.value, child: GestureDetector( onTap: _handleTap, child: Container( width: 62, height: 62, decoration: BoxDecoration( shape: BoxShape.circle, color: isOn ? const Color(0xFFE57373) : const Color(0xFF5B9BD5), border: Border.all(color: Colors.white, width: 3), boxShadow: [ BoxShadow( color: (isOn ? const Color(0xFFE57373) : const Color(0xFF5B9BD5)) .withOpacity(0.35), blurRadius: 12, offset: const Offset(0, 4), ), ], ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ AnimatedSwitcher( duration: const Duration(milliseconds: 300), transitionBuilder: (child, anim) => ScaleTransition(scale: anim, child: child), child: Icon( isOn ? Icons.move_to_inbox_rounded : Icons.inventory_2, key: ValueKey(isOn), color: Colors.white, size: 26, ), ), const SizedBox(height: 2), Text( isOn ? 'TUTUP' : 'BUKA', style: const TextStyle( color: Colors.white, fontSize: 7, fontWeight: FontWeight.w800, letterSpacing: 1.0, ), ), ], ), ), ), ), ); }); } }