import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; import 'package:qpay/screens/workspaces/workspace_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:uuid/uuid.dart'; import '../../auth_state.dart'; /// Full-screen workspace selector displayed immediately after the splash /// screen. Fetches the user's workspaces from the backend and: /// /// * If exactly one workspace exists → auto-navigates to the home screen. /// * If multiple workspaces exist → shows a picker so the user can choose. /// * On error (e.g. 403 for guests) → falls through to the home screen. class WorkspaceScreen extends StatefulWidget { const WorkspaceScreen({super.key}); @override State createState() => _WorkspaceScreenState(); } class _WorkspaceScreenState extends State with TickerProviderStateMixin { late AnimationController _fadeController; late Animation _fadeAnimation; late Animation _slideAnimation; AuthState authState = AuthState(); bool _navigated = false; @override void initState() { super.initState(); _fadeController = AnimationController( duration: const Duration(milliseconds: 400), vsync: this, ); _fadeAnimation = Tween( begin: 0.0, end: 1.0, ).animate(CurvedAnimation(parent: _fadeController, curve: Curves.easeOut)); _slideAnimation = Tween(begin: const Offset(0, 0.04), end: Offset.zero).animate( CurvedAnimation(parent: _fadeController, curve: Curves.easeOutCubic), ); // Kick off the workspace fetch after the first frame. WidgetsBinding.instance.addPostFrameCallback((_) { _checkAuthAndLoad(); }); } Future _checkAuthAndLoad() async { final prefs = await SharedPreferences.getInstance(); if (prefs.getString("token") != null) { _loadWorkspaces(); } else { // if not logged in then create temp workspace SharedPreferences.getInstance().then((prefs) { prefs.setString('workspaceId', const Uuid().v4()); }); _navigateToHome(); } } Future _loadWorkspaces() async { // Ensure a userId exists in prefs. final prefs = await SharedPreferences.getInstance(); if (prefs.getString("userId") == null) { await prefs.setString("userId", const Uuid().v4()); } final userId = prefs.getString("userId")!; if (!mounted) return; final provider = context.read(); // Start the fade-in animation. _fadeController.forward(); await provider.fetchWorkspaces(userId: userId); if (!mounted) return; _evaluateNavigation(provider); } void _evaluateNavigation(WorkspaceProvider provider) { if (_navigated) return; final workspaces = provider.workspaces; if (workspaces.length == 1) { // Store the selected workspace ID so downstream screens can // reference it if needed. SharedPreferences.getInstance().then((prefs) { prefs.setString('workspaceId', workspaces.first.id); }); _navigateToHome(); } else if (workspaces.isEmpty) { // No workspaces or an error occurred – go to home. _navigateToHome(); } // 2+ workspaces: stay on this screen so the user can pick one. } void _onWorkspaceSelected(String workspaceId) async { if (_navigated) return; _navigated = true; final prefs = await SharedPreferences.getInstance(); await prefs.setString('workspaceId', workspaceId); if (!mounted) return; _navigateToHome(); } void _navigateToHome() { if (_navigated) return; _navigated = true; context.go('/'); } @override void dispose() { _fadeController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final theme = Theme.of(context); return Scaffold( backgroundColor: const Color(0xFFF8F9FA), body: Consumer( builder: (context, provider, _) { if (provider.isLoading) { return const Center(child: CircularProgressIndicator()); } // Error or empty: navigate away (handled above, but show // a brief fallback if navigation hasn't triggered yet). if (provider.hasError || provider.workspaces.isEmpty) { return const SizedBox.shrink(); } // Multiple workspaces → show the picker. final workspaces = provider.workspaces; return SafeArea( child: FadeTransition( opacity: _fadeAnimation, child: SlideTransition( position: _slideAnimation, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Spacer(flex: 2), // Header Container( width: 56, height: 56, decoration: BoxDecoration( color: theme.colorScheme.primary.withValues( alpha: 0.1, ), borderRadius: BorderRadius.circular(16), ), child: Icon( Icons.business_rounded, color: theme.colorScheme.primary, size: 28, ), ), const SizedBox(height: 24), Text( 'Select a workspace', style: theme.textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.w700, color: Colors.black87, ), ), const SizedBox(height: 8), Text( 'Choose the workspace you want to work in.', style: theme.textTheme.bodyMedium?.copyWith( color: Colors.grey.shade600, ), ), const SizedBox(height: 32), // Workspace list Expanded( child: ListView.separated( itemCount: workspaces.length, separatorBuilder: (_, __) => const SizedBox(height: 12), itemBuilder: (context, index) { final ws = workspaces[index]; return _WorkspaceCard( name: ws.name, description: ws.description, email: ws.email, phone: ws.phone, onTap: () => _onWorkspaceSelected(ws.id), ); }, ), ), const Spacer(flex: 1), ], ), ), ), ), ); }, ), ); } } /// A single workspace card shown in the picker list. class _WorkspaceCard extends StatelessWidget { final String name; final String description; final String email; final String phone; final VoidCallback onTap; const _WorkspaceCard({ required this.name, required this.description, required this.email, required this.phone, required this.onTap, }); @override Widget build(BuildContext context) { final theme = Theme.of(context); final isDark = theme.brightness == Brightness.dark; return Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(16), onTap: onTap, child: Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: isDark ? const Color(0xFF1E1E1E) : Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all( color: isDark ? Colors.white.withValues(alpha: 0.06) : Colors.grey.shade200, ), ), child: Row( children: [ // Avatar placeholder Container( width: 48, height: 48, decoration: BoxDecoration( color: theme.colorScheme.primary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Center( child: Text( name.isNotEmpty ? name[0].toUpperCase() : 'W', style: TextStyle( fontSize: 20, fontWeight: FontWeight.w700, color: theme.colorScheme.primary, ), ), ), ), const SizedBox(width: 16), // Details Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( name, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.black87, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), if (description.isNotEmpty) ...[ const SizedBox(height: 4), Text( description, style: TextStyle( fontSize: 13, color: Colors.grey.shade500, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], if (email.isNotEmpty) ...[ const SizedBox(height: 4), Row( children: [ Icon( Icons.email_outlined, size: 14, color: Colors.grey.shade400, ), const SizedBox(width: 6), Expanded( child: Text( email, style: TextStyle( fontSize: 12, color: Colors.grey.shade400, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ], ], ), ), const SizedBox(width: 8), Icon(Icons.chevron_right_rounded, color: Colors.grey.shade400), ], ), ), ), ); } }