diff --git a/b0esche_cloud/lib/blocs/organization/organization_bloc.dart b/b0esche_cloud/lib/blocs/organization/organization_bloc.dart index 8829b1b..6fd992e 100644 --- a/b0esche_cloud/lib/blocs/organization/organization_bloc.dart +++ b/b0esche_cloud/lib/blocs/organization/organization_bloc.dart @@ -73,10 +73,18 @@ class OrganizationBloc extends Bloc { ) { final currentState = state; if (currentState is OrganizationLoaded) { - final selected = currentState.organizations.firstWhere( - (org) => org.id == event.orgId, - orElse: () => currentState.selectedOrg!, - ); + Organization? selected; + + if (event.orgId.isEmpty) { + // Personal workspace - set to null to indicate no org selected + selected = null; + } else { + selected = currentState.organizations.firstWhere( + (org) => org.id == event.orgId, + orElse: () => currentState.selectedOrg!, + ); + } + emit( OrganizationLoaded( organizations: currentState.organizations, diff --git a/b0esche_cloud/lib/main.dart b/b0esche_cloud/lib/main.dart index 7f85d35..a6785b9 100644 --- a/b0esche_cloud/lib/main.dart +++ b/b0esche_cloud/lib/main.dart @@ -95,13 +95,13 @@ class _MainAppState extends State { theme: AppTheme.darkTheme, home: const Scaffold( body: Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - AppTheme.accentColor, + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + AppTheme.accentColor, + ), ), ), ), - ), ); } return MaterialApp.router( diff --git a/b0esche_cloud/lib/pages/home_page.dart b/b0esche_cloud/lib/pages/home_page.dart index a11468a..51df23e 100644 --- a/b0esche_cloud/lib/pages/home_page.dart +++ b/b0esche_cloud/lib/pages/home_page.dart @@ -131,8 +131,9 @@ class _HomePageState extends State with TickerProviderStateMixin { final name = controller.text.trim(); if (name.isNotEmpty) { // Use the parent context, not the dialog context - BlocProvider.of(context) - .add(CreateOrganization(name)); + BlocProvider.of( + context, + ).add(CreateOrganization(name)); Navigator.of(dialogContext).pop(); } }, @@ -151,8 +152,9 @@ class _HomePageState extends State with TickerProviderStateMixin { final name = controller.text.trim(); if (name.isNotEmpty) { // Use the parent context, not the dialog context - BlocProvider.of(context) - .add(CreateOrganization(name)); + BlocProvider.of( + context, + ).add(CreateOrganization(name)); Navigator.of(dialogContext).pop(); } }, @@ -189,6 +191,18 @@ class _HomePageState extends State with TickerProviderStateMixin { children: [ Row( children: [ + // Personal workspace button (always show when logged in) + _buildOrgButton( + Organization(id: '', name: 'Personal'), + selectedOrg == null, + () { + context.read().add( + SelectOrganization(''), + ); + }, + ), + const SizedBox(width: 16), + // Organization tabs ...orgs.map( (org) => Row( children: [ diff --git a/b0esche_cloud/lib/services/api_client.dart b/b0esche_cloud/lib/services/api_client.dart index ea721b4..ff135b9 100644 --- a/b0esche_cloud/lib/services/api_client.dart +++ b/b0esche_cloud/lib/services/api_client.dart @@ -120,8 +120,17 @@ class ApiClient { ); } - String code = data?['code'] ?? 'UNKNOWN'; - String message = data?['message'] ?? 'Unknown error'; + // Only try to extract code/message if data is a Map + String code = 'UNKNOWN'; + String message = 'Unknown error'; + + if (data is Map) { + code = data['code'] ?? 'UNKNOWN'; + message = data['message'] ?? 'Unknown error'; + } else if (data != null) { + message = data.toString(); + } + return ApiError(code: code, message: message, status: status); } }