import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:marco/helpers/services/api_endpoints.dart'; import 'package:marco/helpers/services/storage/local_storage.dart'; import 'package:marco/helpers/utils/mixins/ui_mixin.dart'; import 'package:marco/helpers/widgets/my_text.dart'; import 'package:marco/images.dart'; import 'package:marco/controller/tenant/tenant_selection_controller.dart'; import 'package:marco/view/splash_screen.dart'; import 'package:marco/helpers/widgets/wave_background.dart'; class TenantSelectionScreen extends StatefulWidget { const TenantSelectionScreen({super.key}); @override State createState() => _TenantSelectionScreenState(); } class _TenantSelectionScreenState extends State with UIMixin, SingleTickerProviderStateMixin { late final TenantSelectionController _controller; late final AnimationController _logoAnimController; late final Animation _logoAnimation; final bool _isBetaEnvironment = ApiEndpoints.baseUrl.contains("stage"); @override void initState() { super.initState(); _controller = Get.put(TenantSelectionController()); _logoAnimController = AnimationController( vsync: this, duration: const Duration(milliseconds: 800), ); _logoAnimation = CurvedAnimation( parent: _logoAnimController, curve: Curves.easeOutBack, ); _logoAnimController.forward(); } @override void dispose() { _logoAnimController.dispose(); Get.delete(); super.dispose(); } Future _onTenantSelected(String tenantId) async { await _controller.onTenantSelected(tenantId); } @override Widget build(BuildContext context) { return Obx(() { // Splash screen for auto-selection if (_controller.isAutoSelecting.value) { return const SplashScreen(); } return Scaffold( body: Stack( children: [ RedWaveBackground(brandRed: contentTheme.primary), SafeArea( child: Center( child: Column( children: [ const SizedBox(height: 24), _AnimatedLogo(animation: _logoAnimation), const SizedBox(height: 8), Expanded( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 24), child: Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 420), child: Column( children: [ const SizedBox(height: 12), const _WelcomeTexts(), if (_isBetaEnvironment) ...[ const SizedBox(height: 12), const _BetaBadge(), ], const SizedBox(height: 36), TenantCardList( controller: _controller, isLoading: _controller.isLoading.value, onTenantSelected: _onTenantSelected, ), ], ), ), ), ), ), ], ), ), ), ], ), ); }); } } /// Animated Logo Widget class _AnimatedLogo extends StatelessWidget { final Animation animation; const _AnimatedLogo({required this.animation}); @override Widget build(BuildContext context) { return ScaleTransition( scale: animation, child: Container( width: 100, height: 100, padding: const EdgeInsets.all(20), decoration: const BoxDecoration( color: Colors.white, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.black12, blurRadius: 10, offset: Offset(0, 4), ), ], ), child: Image.asset(Images.logoDark), ), ); } } /// Welcome Texts class _WelcomeTexts extends StatelessWidget { const _WelcomeTexts(); @override Widget build(BuildContext context) { return Column( children: [ MyText( "Welcome", fontSize: 24, fontWeight: 600, color: Colors.black87, textAlign: TextAlign.center, ), const SizedBox(height: 10), MyText( "Please select which dashboard you want to explore!", fontSize: 14, color: Colors.black54, textAlign: TextAlign.center, ), ], ); } } /// Beta Badge class _BetaBadge extends StatelessWidget { const _BetaBadge(); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: Colors.orangeAccent, borderRadius: BorderRadius.circular(5), ), child: MyText( 'BETA', color: Colors.white, fontWeight: 600, fontSize: 12, ), ); } } /// Tenant Card List class TenantCardList extends StatelessWidget with UIMixin { final TenantSelectionController controller; final bool isLoading; final Function(String tenantId) onTenantSelected; TenantCardList({ required this.controller, required this.isLoading, required this.onTenantSelected, }); @override Widget build(BuildContext context) { return Obx(() { if (controller.isLoading.value || isLoading) { return const Center(child: CircularProgressIndicator(strokeWidth: 2)); } final hasTenants = controller.tenants.isNotEmpty; return Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ if (!hasTenants) ...[ MyText( "No dashboards available for your account.", fontSize: 14, color: Colors.black54, textAlign: TextAlign.center, ), const SizedBox(height: 16), ], if (hasTenants) ...controller.tenants.map( (tenant) => _TenantCard( tenant: tenant, onTap: () => onTenantSelected(tenant.id), ), ), const SizedBox(height: 16), TextButton.icon( onPressed: () async { await LocalStorage.logout(); }, icon: Icon(Icons.arrow_back, size: 20, color: contentTheme.primary,), label: MyText( 'Back to Login', color: contentTheme.primary, fontWeight: 600, fontSize: 14, ), ), ], ); }); } } /// Single Tenant Card class _TenantCard extends StatelessWidget with UIMixin { final dynamic tenant; final VoidCallback onTap; _TenantCard({required this.tenant, required this.onTap}); @override Widget build(BuildContext context) { return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(5), child: Card( elevation: 3, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), margin: const EdgeInsets.only(bottom: 20), child: Padding( padding: const EdgeInsets.all(16), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.circular(5), child: Container( width: 60, height: 60, color: Colors.grey.shade200, child: TenantLogo(logoImage: tenant.logoImage), ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText( tenant.name, fontSize: 18, fontWeight: 700, color: Colors.black87, ), const SizedBox(height: 6), MyText( "Industry: ${tenant.industry?.name ?? "-"}", fontSize: 13, color: Colors.black54, ), ], ), ), Icon(Icons.arrow_forward_ios, size: 24, color: contentTheme.primary,), ], ), ), ), ); } } /// Tenant Logo (supports base64 and URL) class TenantLogo extends StatelessWidget { final String? logoImage; const TenantLogo({required this.logoImage}); @override Widget build(BuildContext context) { if (logoImage == null || logoImage!.isEmpty) { return Center(child: Icon(Icons.business, color: Colors.grey.shade600)); } if (logoImage!.startsWith("data:image")) { try { final base64Str = logoImage!.split(',').last; final bytes = base64Decode(base64Str); return Image.memory(bytes, fit: BoxFit.cover); } catch (_) { return Center(child: Icon(Icons.business, color: Colors.grey.shade600)); } } else { return Image.network( logoImage!, fit: BoxFit.cover, errorBuilder: (_, __, ___) => Center( child: Icon(Icons.business, color: Colors.grey.shade600), ), ); } } }