WebAppBar ResponsiveLayout

This commit is contained in:
mohammad
2025-02-26 12:00:30 +03:00
parent ba44d1d359
commit fe52726f6e
13 changed files with 368 additions and 251 deletions

View File

@ -17,6 +17,7 @@ import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
import 'package:syncrow_web/utils/theme/responsive_text_theme.dart';
import 'package:syncrow_web/web_layout/web_scaffold.dart'; import 'package:syncrow_web/web_layout/web_scaffold.dart';
class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout { class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
@ -27,19 +28,19 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
final isLargeScreen = isLargeScreenSize(context); final isLargeScreen = isLargeScreenSize(context);
final isSmallScreen = isSmallScreenSize(context); final isSmallScreen = isSmallScreenSize(context);
final isHalfMediumScreen = isHafMediumScreenSize(context); final isHalfMediumScreen = isHafMediumScreenSize(context);
final padding = isLargeScreen ? const EdgeInsets.all(30) : const EdgeInsets.all(15); final padding =
isLargeScreen ? const EdgeInsets.all(30) : const EdgeInsets.all(15);
return WebScaffold( return WebScaffold(
enableMenuSidebar: false, enableMenuSidebar: false,
appBarTitle: FittedBox( appBarTitle: Text(
child: Text( 'Access Management',
'Access Management', style: ResponsiveTextTheme.of(context).deviceManagementTitle,
style: Theme.of(context).textTheme.headlineLarge,
),
), ),
rightBody: const NavigateHomeGridView(), rightBody: const NavigateHomeGridView(),
scaffoldBody: BlocProvider( scaffoldBody: BlocProvider(
create: (BuildContext context) => AccessBloc()..add(FetchTableData()), create: (BuildContext context) =>
AccessBloc()..add(FetchTableData()),
child: BlocConsumer<AccessBloc, AccessState>( child: BlocConsumer<AccessBloc, AccessState>(
listener: (context, state) {}, listener: (context, state) {},
builder: (context, state) { builder: (context, state) {
@ -93,11 +94,14 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
return [ return [
item.passwordName, item.passwordName,
item.passwordType.value, item.passwordType.value,
accessBloc.timestampToDate(item.effectiveTime), accessBloc
accessBloc.timestampToDate(item.invalidTime), .timestampToDate(item.effectiveTime),
accessBloc
.timestampToDate(item.invalidTime),
item.deviceName.toString(), item.deviceName.toString(),
item.authorizerEmail.toString(), item.authorizerEmail.toString(),
accessBloc.timestampToDate(item.invalidTime), accessBloc
.timestampToDate(item.invalidTime),
item.passwordStatus.value, item.passwordStatus.value,
]; ];
}).toList(), }).toList(),
@ -108,7 +112,8 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
}))); })));
} }
Wrap _buildVisitorAdminPasswords(BuildContext context, AccessBloc accessBloc) { Wrap _buildVisitorAdminPasswords(
BuildContext context, AccessBloc accessBloc) {
return Wrap( return Wrap(
spacing: 10, spacing: 10,
runSpacing: 10, runSpacing: 10,
@ -134,7 +139,8 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
borderRadius: 8, borderRadius: 8,
child: Text( child: Text(
'Create Visitor Password ', 'Create Visitor Password ',
style: context.textTheme.titleSmall!.copyWith(color: Colors.white, fontSize: 12), style: context.textTheme.titleSmall!
.copyWith(color: Colors.white, fontSize: 12),
)), )),
), ),
// Container( // Container(
@ -172,8 +178,10 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
description: '', description: '',
onSubmitted: (value) { onSubmitted: (value) {
accessBloc.add(FilterDataEvent( accessBloc.add(FilterDataEvent(
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(), emailAuthorizer:
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex, accessBloc.emailAuthorizer.text.toLowerCase(),
selectedTabIndex:
BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(), passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp, startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp)); endTime: accessBloc.expirationTimeTimeStamp));
@ -191,8 +199,10 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
description: '', description: '',
onSubmitted: (value) { onSubmitted: (value) {
accessBloc.add(FilterDataEvent( accessBloc.add(FilterDataEvent(
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(), emailAuthorizer:
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex, accessBloc.emailAuthorizer.text.toLowerCase(),
selectedTabIndex:
BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(), passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp, startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp)); endTime: accessBloc.expirationTimeTimeStamp));
@ -221,7 +231,8 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
onSearch: () { onSearch: () {
accessBloc.add(FilterDataEvent( accessBloc.add(FilterDataEvent(
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(), emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex, selectedTabIndex:
BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(), passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp, startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp)); endTime: accessBloc.expirationTimeTimeStamp));
@ -249,8 +260,10 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
description: '', description: '',
onSubmitted: (value) { onSubmitted: (value) {
accessBloc.add(FilterDataEvent( accessBloc.add(FilterDataEvent(
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(), emailAuthorizer:
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex, accessBloc.emailAuthorizer.text.toLowerCase(),
selectedTabIndex:
BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(), passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp, startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp)); endTime: accessBloc.expirationTimeTimeStamp));
@ -274,7 +287,8 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
onSearch: () { onSearch: () {
accessBloc.add(FilterDataEvent( accessBloc.add(FilterDataEvent(
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(), emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex, selectedTabIndex:
BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(), passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp, startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp)); endTime: accessBloc.expirationTimeTimeStamp));

View File

@ -8,6 +8,8 @@ class ForgetPasswordPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const ResponsiveLayout( return const ResponsiveLayout(
desktopBody: ForgetPasswordWebPage(), mobileBody: ForgetPasswordWebPage()); tablet: ForgetPasswordWebPage(),
desktopBody: ForgetPasswordWebPage(),
mobileBody: ForgetPasswordWebPage());
} }
} }

View File

@ -9,6 +9,8 @@ class LoginPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const ResponsiveLayout( return const ResponsiveLayout(
desktopBody: LoginWebPage(), mobileBody: LoginWebPage()); tablet: LoginWebPage(),
desktopBody: LoginWebPage(),
mobileBody: LoginWebPage());
} }
} }

View File

@ -9,6 +9,7 @@ import 'package:syncrow_web/pages/routines/view/routines_view.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
import 'package:syncrow_web/utils/theme/responsive_text_theme.dart';
import 'package:syncrow_web/web_layout/web_scaffold.dart'; import 'package:syncrow_web/web_layout/web_scaffold.dart';
class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout { class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
@ -19,17 +20,17 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
return MultiBlocProvider( return MultiBlocProvider(
providers: [ providers: [
BlocProvider( BlocProvider(
create: (context) => DeviceManagementBloc()..add(FetchDevices(context)), create: (context) =>
DeviceManagementBloc()..add(FetchDevices(context)),
), ),
], ],
child: WebScaffold( child: WebScaffold(
appBarTitle: FittedBox( appBarTitle: Text(
child: Text( 'Device Management',
'Device Management', style: ResponsiveTextTheme.of(context).deviceManagementTitle,
style: Theme.of(context).textTheme.headlineLarge,
),
), ),
centerBody: BlocBuilder<RoutineBloc, RoutineState>(builder: (context, state) { centerBody:
BlocBuilder<RoutineBloc, RoutineState>(builder: (context, state) {
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -45,8 +46,11 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
child: Text( child: Text(
'Devices', 'Devices',
style: context.textTheme.titleMedium?.copyWith( style: context.textTheme.titleMedium?.copyWith(
color: !state.routineTab ? ColorsManager.whiteColors : ColorsManager.grayColor, color: !state.routineTab
fontWeight: !state.routineTab ? FontWeight.w700 : FontWeight.w400, ? ColorsManager.whiteColors
: ColorsManager.grayColor,
fontWeight:
!state.routineTab ? FontWeight.w700 : FontWeight.w400,
), ),
), ),
), ),
@ -55,13 +59,18 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
backgroundColor: null, backgroundColor: null,
), ),
onPressed: () { onPressed: () {
context.read<RoutineBloc>().add(const TriggerSwitchTabsEvent(isRoutineTab: true)); context
.read<RoutineBloc>()
.add(const TriggerSwitchTabsEvent(isRoutineTab: true));
}, },
child: Text( child: Text(
'Routines', 'Routines',
style: context.textTheme.titleMedium?.copyWith( style: context.textTheme.titleMedium?.copyWith(
color: state.routineTab ? ColorsManager.whiteColors : ColorsManager.grayColor, color: state.routineTab
fontWeight: state.routineTab ? FontWeight.w700 : FontWeight.w400, ? ColorsManager.whiteColors
: ColorsManager.grayColor,
fontWeight:
state.routineTab ? FontWeight.w700 : FontWeight.w400,
), ),
), ),
), ),
@ -69,7 +78,8 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
); );
}), }),
rightBody: const NavigateHomeGridView(), rightBody: const NavigateHomeGridView(),
scaffoldBody: BlocBuilder<RoutineBloc, RoutineState>(builder: (context, state) { scaffoldBody:
BlocBuilder<RoutineBloc, RoutineState>(builder: (context, state) {
if (state.routineTab) { if (state.routineTab) {
return const RoutinesView(); return const RoutinesView();
} }
@ -84,7 +94,8 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
} else if (deviceState is DeviceManagementLoaded) { } else if (deviceState is DeviceManagementLoaded) {
return DeviceManagementBody(devices: deviceState.devices); return DeviceManagementBody(devices: deviceState.devices);
} else if (deviceState is DeviceManagementFiltered) { } else if (deviceState is DeviceManagementFiltered) {
return DeviceManagementBody(devices: deviceState.filteredDevices); return DeviceManagementBody(
devices: deviceState.filteredDevices);
} else { } else {
return const Center(child: Text('Error fetching Devices')); return const Center(child: Text('Error fetching Devices'));
} }

View File

@ -95,7 +95,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
const DeviceSearchFilters(), const DeviceSearchFilters(),
const SizedBox(height: 12), const SizedBox(height: 12),
Container( Container(
height: 45, // height: 45,
width: 125, width: 125,
decoration: containerDecoration, decoration: containerDecoration,
child: Center( child: Center(

View File

@ -147,6 +147,9 @@ class LivingRoomBloc extends Bloc<LivingRoomEvent, LivingRoomState> {
await DevicesManagementApi().getBatchStatus(event.devicesIds); await DevicesManagementApi().getBatchStatus(event.devicesIds);
deviceStatus = deviceStatus =
LivingRoomStatusModel.fromJson(event.devicesIds.first, status.status); LivingRoomStatusModel.fromJson(event.devicesIds.first, status.status);
// for (var deviceId in event.devicesIds) {
// _listenToChanges(deviceId);
// }
emit(LivingRoomDeviceStatusLoaded(deviceStatus)); emit(LivingRoomDeviceStatusLoaded(deviceStatus));
} catch (e) { } catch (e) {
emit(LivingRoomDeviceManagementError(e.toString())); emit(LivingRoomDeviceManagementError(e.toString()));

View File

@ -1,5 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:firebase_database/firebase_database.dart'; import 'package:firebase_database/firebase_database.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
@ -7,7 +6,6 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/device_sta
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/models/two_gang_glass_status_model.dart'; import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/models/two_gang_glass_status_model.dart';
import 'package:syncrow_web/services/devices_mang_api.dart'; import 'package:syncrow_web/services/devices_mang_api.dart';
part 'two_gang_glass_switch_event.dart'; part 'two_gang_glass_switch_event.dart';
part 'two_gang_glass_switch_state.dart'; part 'two_gang_glass_switch_state.dart';
@ -15,7 +13,6 @@ class TwoGangGlassSwitchBloc
extends Bloc<TwoGangGlassSwitchEvent, TwoGangGlassSwitchState> { extends Bloc<TwoGangGlassSwitchEvent, TwoGangGlassSwitchState> {
TwoGangGlassStatusModel deviceStatus; TwoGangGlassStatusModel deviceStatus;
Timer? _timer; Timer? _timer;
TwoGangGlassSwitchBloc({required String deviceId}) TwoGangGlassSwitchBloc({required String deviceId})
: deviceStatus = TwoGangGlassStatusModel( : deviceStatus = TwoGangGlassStatusModel(
uuid: deviceId, uuid: deviceId,
@ -29,6 +26,7 @@ class TwoGangGlassSwitchBloc
on<TwoGangGlassSwitchBatchControl>(_onBatchControl); on<TwoGangGlassSwitchBatchControl>(_onBatchControl);
on<TwoGangGlassSwitchFetchBatchStatusEvent>(_onFetchBatchStatus); on<TwoGangGlassSwitchFetchBatchStatusEvent>(_onFetchBatchStatus);
on<TwoGangGlassFactoryReset>(_onFactoryReset); on<TwoGangGlassFactoryReset>(_onFactoryReset);
on<StatusUpdated>(_onStatusUpdated);
} }
Future<void> _onFetchDeviceStatus(TwoGangGlassSwitchFetchDeviceEvent event, Future<void> _onFetchDeviceStatus(TwoGangGlassSwitchFetchDeviceEvent event,
@ -181,7 +179,7 @@ class TwoGangGlassSwitchBloc
return super.close(); return super.close();
} }
_listenToChanges(deviceId) { _listenToChanges(deviceId) {
try { try {
DatabaseReference ref = DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$deviceId'); FirebaseDatabase.instance.ref('device-status/$deviceId');
@ -197,8 +195,8 @@ class TwoGangGlassSwitchBloc
.add(Status(code: element['code'], value: element['value'])); .add(Status(code: element['code'], value: element['value']));
}); });
deviceStatus = deviceStatus = TwoGangGlassStatusModel.fromJson(
TwoGangGlassStatusModel.fromJson(usersMap['productUuid'], statusList); usersMap['productUuid'], statusList);
if (!isClosed) { if (!isClosed) {
add(StatusUpdated(deviceStatus)); add(StatusUpdated(deviceStatus));
} }
@ -206,31 +204,9 @@ class TwoGangGlassSwitchBloc
} catch (_) {} } catch (_) {}
} }
void _onStatusUpdated(StatusUpdated event, Emitter<TwoGangGlassSwitchState> emit) { void _onStatusUpdated(
StatusUpdated event, Emitter<TwoGangGlassSwitchState> emit) {
deviceStatus = event.deviceStatus; deviceStatus = event.deviceStatus;
emit(TwoGangGlassSwitchBatchStatusLoaded(deviceStatus)); emit(TwoGangGlassSwitchBatchStatusLoaded(deviceStatus));
} }
// _listenToChanges(deviceId, Emitter<TwoGangGlassSwitchState> emit) {
// try {
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$deviceId');
// Stream<DatabaseEvent> stream = ref.onValue;
// stream.listen((DatabaseEvent event) {
// Map<dynamic, dynamic> usersMap =
// event.snapshot.value as Map<dynamic, dynamic>;
// List<Status> statusList = [];
// usersMap['status'].forEach((element) {
// statusList
// .add(Status(code: element['code'], value: element['value']));
// });
// deviceStatus = TwoGangGlassStatusModel.fromJson(deviceId, statusList);
// emit(TwoGangGlassSwitchBatchStatusLoaded(deviceStatus));
// });
// } catch (_) {}
// }
} }

View File

@ -106,7 +106,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
List<HomeItemModel> homeItems = [ List<HomeItemModel> homeItems = [
HomeItemModel( HomeItemModel(
title: 'Access', title: 'Access Management',
icon: Assets.accessIcon, icon: Assets.accessIcon,
active: true, active: true,
onPress: (context) { onPress: (context) {
@ -124,7 +124,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
color: ColorsManager.primaryColor, color: ColorsManager.primaryColor,
), ),
HomeItemModel( HomeItemModel(
title: 'Devices', title: 'Devices Management',
icon: Assets.devicesIcon, icon: Assets.devicesIcon,
active: true, active: true,
onPress: (context) { onPress: (context) {
@ -134,6 +134,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
}, },
color: ColorsManager.primaryColor, color: ColorsManager.primaryColor,
), ),
// HomeItemModel( // HomeItemModel(
// title: 'Move in', // title: 'Move in',
// icon: Assets.moveinIcon, // icon: Assets.moveinIcon,

View File

@ -8,6 +8,7 @@ import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/bl
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/view/users_page.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/view/users_page.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/utils/theme/responsive_text_theme.dart';
import 'package:syncrow_web/web_layout/web_scaffold.dart'; import 'package:syncrow_web/web_layout/web_scaffold.dart';
class RolesAndPermissionPage extends StatelessWidget { class RolesAndPermissionPage extends StatelessWidget {
@ -26,11 +27,10 @@ class RolesAndPermissionPage extends StatelessWidget {
? const Center(child: CircularProgressIndicator()) ? const Center(child: CircularProgressIndicator())
: WebScaffold( : WebScaffold(
enableMenuSidebar: false, enableMenuSidebar: false,
appBarTitle: FittedBox( appBarTitle: Text(
child: Text( 'Roles & Permissions',
'Roles & Permissions', style:
style: Theme.of(context).textTheme.headlineLarge, ResponsiveTextTheme.of(context).deviceManagementTitle,
),
), ),
rightBody: const NavigateHomeGridView(), rightBody: const NavigateHomeGridView(),
centerBody: Row( centerBody: Row(

View File

@ -10,6 +10,7 @@ import 'package:syncrow_web/pages/spaces_management/structure_selector/view/cent
import 'package:syncrow_web/services/product_api.dart'; import 'package:syncrow_web/services/product_api.dart';
import 'package:syncrow_web/services/space_mana_api.dart'; import 'package:syncrow_web/services/space_mana_api.dart';
import 'package:syncrow_web/services/space_model_mang_api.dart'; import 'package:syncrow_web/services/space_model_mang_api.dart';
import 'package:syncrow_web/utils/theme/responsive_text_theme.dart';
import 'package:syncrow_web/web_layout/web_scaffold.dart'; import 'package:syncrow_web/web_layout/web_scaffold.dart';
class SpaceManagementPage extends StatefulWidget { class SpaceManagementPage extends StatefulWidget {
@ -36,8 +37,10 @@ class SpaceManagementPageState extends State<SpaceManagementPage> {
), ),
], ],
child: WebScaffold( child: WebScaffold(
appBarTitle: Text('Space Management', appBarTitle: Text(
style: Theme.of(context).textTheme.headlineLarge), 'Space Management',
style: ResponsiveTextTheme.of(context).deviceManagementTitle,
),
enableMenuSidebar: false, enableMenuSidebar: false,
centerBody: CenterBodyWidget(), centerBody: CenterBodyWidget(),
rightBody: const NavigateHomeGridView(), rightBody: const NavigateHomeGridView(),

View File

@ -1,18 +1,37 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class ResponsiveLayout extends StatelessWidget { class ResponsiveLayout extends StatelessWidget {
final Widget desktopBody;
final Widget mobileBody; final Widget mobileBody;
const ResponsiveLayout( final Widget? tablet;
{super.key, required this.desktopBody, required this.mobileBody}); final Widget desktopBody;
const ResponsiveLayout({
super.key,
required this.mobileBody,
this.tablet,
required this.desktopBody,
});
static bool isMobile(BuildContext context) =>
MediaQuery.of(context).size.width < 650;
static bool isTablet(BuildContext context) =>
MediaQuery.of(context).size.width < 1100 &&
MediaQuery.of(context).size.width >= 650;
static bool isDesktop(BuildContext context) =>
MediaQuery.of(context).size.width >= 1100;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return LayoutBuilder( return LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
if (constraints.maxWidth < 600) { if (constraints.maxWidth >= 1100) {
return mobileBody;
} else {
return desktopBody; return desktopBody;
} else if (constraints.maxWidth >= 650) {
return tablet!;
} else {
return mobileBody;
} }
}, },
); );

View File

@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/responsive_layout.dart';
class ResponsiveTextTheme extends ThemeExtension<ResponsiveTextTheme> {
final TextStyle deviceManagementTitle;
ResponsiveTextTheme({
required this.deviceManagementTitle,
});
@override
ThemeExtension<ResponsiveTextTheme> copyWith() => this;
@override
ThemeExtension<ResponsiveTextTheme> lerp(
ThemeExtension<ResponsiveTextTheme>? other, double t) =>
this;
static ResponsiveTextTheme of(BuildContext context) {
final isMobile = ResponsiveLayout.isMobile(context);
return Theme.of(context).extension<ResponsiveTextTheme>() ??
ResponsiveTextTheme(
deviceManagementTitle: TextStyle(
fontSize: isMobile ? 20 : 30,
fontWeight: FontWeight.w700,
color: ColorsManager.whiteColors),
);
}
}

View File

@ -5,10 +5,10 @@ import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_state.dart'; import 'package:syncrow_web/pages/home/bloc/home_state.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/responsive_layout.dart';
import 'package:syncrow_web/utils/user_drop_down_menu.dart'; import 'package:syncrow_web/utils/user_drop_down_menu.dart';
class WebAppBar extends StatefulWidget { class WebAppBar extends StatelessWidget {
final Widget? title; final Widget? title;
final Widget? centerBody; final Widget? centerBody;
final Widget? rightBody; final Widget? rightBody;
@ -16,178 +16,234 @@ class WebAppBar extends StatefulWidget {
const WebAppBar({super.key, this.title, this.centerBody, this.rightBody}); const WebAppBar({super.key, this.title, this.centerBody, this.rightBody});
@override @override
State<WebAppBar> createState() => _WebAppBarState(); Widget build(BuildContext context) {
return BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) {
final user = context.read<HomeBloc>().user;
return ResponsiveLayout(
mobileBody: MobileAppBar(
title: title,
centerBody: centerBody,
rightBody: rightBody,
user: user,
),
tablet: TabletAppBar(
title: title,
centerBody: centerBody,
rightBody: rightBody,
user: user,
),
desktopBody: DesktopAppBar(
title: title,
centerBody: centerBody,
rightBody: rightBody,
user: user,
),
);
},
);
}
} }
class _WebAppBarState extends State<WebAppBar> with HelperResponsiveLayout { class DesktopAppBar extends StatelessWidget {
@override final Widget? title;
void initState() { final Widget? centerBody;
super.initState(); final Widget? rightBody;
} final dynamic user;
const DesktopAppBar({
super.key,
this.title,
this.centerBody,
this.rightBody,
required this.user,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
bool isSmallScreen = isSmallScreenSize(context); return Container(
bool isHalfMediumScreen = isHafMediumScreenSize(context); height: 100,
return BlocBuilder<HomeBloc, HomeState>(builder: (context, state) { decoration: const BoxDecoration(color: ColorsManager.secondaryColor),
final user = context.read<HomeBloc>().user; padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10),
return Container( child: Row(
height: (isSmallScreen || isHalfMediumScreen) ? 130 : 100, mainAxisAlignment: MainAxisAlignment.spaceBetween,
decoration: const BoxDecoration(color: ColorsManager.secondaryColor), children: [
padding: const EdgeInsets.all(10), Expanded(
child: isSmallScreen || isHalfMediumScreen child: Row(
? Column( children: [
crossAxisAlignment: CrossAxisAlignment.start, if (title != null) title!,
children: [ if (centerBody != null)
if (widget.title != null) Padding(
Align( padding: const EdgeInsets.only(left: 80),
alignment: Alignment.centerLeft, child: centerBody!,
child: widget.title!,
),
if (widget.centerBody != null)
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: widget.centerBody,
),
if (widget.rightBody != null || user != null)
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (widget.rightBody != null) widget.rightBody!,
Row(
children: [
SizedBox.square(
dimension: 40,
child: CircleAvatar(
backgroundColor: ColorsManager.whiteColors,
child: SizedBox.square(
dimension: 35,
child: SvgPicture.asset(
Assets.logoGrey,
fit: BoxFit.cover,
),
),
),
),
const SizedBox(
width: 10,
),
if (user != null)
Text(
'${user.firstName} ${user.lastName}',
style: Theme.of(context).textTheme.bodyLarge,
),
],
),
],
),
],
)
: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Row(
children: [
widget.title!,
if (widget.centerBody != null)
Padding(
padding: const EdgeInsets.only(left: 80),
child: widget.centerBody!,
),
],
),
), ),
Row( ],
mainAxisSize: MainAxisSize.min, ),
children: [ ),
if (widget.rightBody != null) _buildUserSection(context),
Align( ],
alignment: Alignment.centerRight, ),
child: widget.rightBody, );
), }
const SizedBox(
width: 10, Widget _buildUserSection(BuildContext context) {
), return Row(
SizedBox.square( children: [
dimension: 40, if (rightBody != null) rightBody!,
child: CircleAvatar( const SizedBox(width: 24),
backgroundColor: ColorsManager.whiteColors, _UserAvatar(),
child: SizedBox.square( const SizedBox(width: 12),
dimension: 35, if (user != null)
child: SvgPicture.asset( Text(
Assets.logoGrey, '${user.firstName} ${user.lastName}',
fit: BoxFit.cover, style: Theme.of(context).textTheme.bodyLarge,
), ),
), const SizedBox(width: 12),
), UserDropdownMenu(user: user),
), ],
const SizedBox( );
width: 10, }
), }
if (user != null)
Text( class TabletAppBar extends StatelessWidget {
'${user.firstName} ${user.lastName}', final Widget? title;
style: Theme.of(context).textTheme.bodyLarge, final Widget? centerBody;
), final Widget? rightBody;
const SizedBox( final dynamic user;
width: 10,
), const TabletAppBar({
UserDropdownMenu(user: user), super.key,
// GestureDetector( this.title,
// onTap: () { this.centerBody,
// showCustomDialog( this.rightBody,
// context: context, required this.user,
// barrierDismissible: true, });
// title: 'Logout',
// message: 'Are you sure you want to logout?', @override
// actions: [ Widget build(BuildContext context) {
// GestureDetector( return Container(
// onTap: () { height: 100,
// AuthBloc.logout(); decoration: const BoxDecoration(color: ColorsManager.secondaryColor),
// context.go(RoutesConst.auth); padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
// }, child: Column(
// child: DefaultButton( children: [
// child: Text( Row(
// 'Ok', mainAxisAlignment: MainAxisAlignment.spaceBetween,
// style: Theme.of(context) children: [
// .textTheme if (title != null) Expanded(child: title!),
// .bodyMedium! _buildUserSection(context),
// .copyWith(fontSize: 12, color: Colors.white), ],
// ), ),
// ), if (centerBody != null) Expanded(child: centerBody!),
// ), ],
// const SizedBox( ),
// height: 10, );
// ), }
// GestureDetector(
// onTap: () { Widget _buildUserSection(BuildContext context) {
// context.pop(); return Row(
// }, children: [
// child: DefaultButton( if (rightBody != null) rightBody!,
// child: Text( const SizedBox(width: 16),
// 'Cancel', _UserAvatar(),
// style: Theme.of(context) if (user != null) ...[
// .textTheme const SizedBox(width: 8),
// .bodyMedium! Text(
// .copyWith(fontSize: 12, color: Colors.white), '${user.firstName} ${user.lastName}',
// ), style:
// ), Theme.of(context).textTheme.bodyLarge?.copyWith(fontSize: 14),
// ), ),
// ], ],
// ); UserDropdownMenu(user: user),
// }, ],
// child: const Icon( );
// Icons.logout, }
// color: ColorsManager.whiteColors, }
// ),
// ) class MobileAppBar extends StatelessWidget {
], final Widget? title;
), final Widget? centerBody;
], final Widget? rightBody;
), final dynamic user;
);
}); const MobileAppBar({
super.key,
this.title,
this.centerBody,
this.rightBody,
required this.user,
});
@override
Widget build(BuildContext context) {
return Container(
height: 135,
decoration: const BoxDecoration(color: ColorsManager.secondaryColor),
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (title != null) title!,
_buildUserSection(context),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (centerBody != null)
Padding(
padding: const EdgeInsets.only(top: 8),
child: centerBody!,
),
if (rightBody != null)
Padding(
padding: const EdgeInsets.only(top: 8),
child: rightBody!,
),
],
),
],
),
);
}
Widget _buildUserSection(BuildContext context) {
return Row(
children: [
_UserAvatar(),
if (user != null) ...[
const SizedBox(width: 8),
Text(
'${user.firstName} ${user.lastName}',
style:
Theme.of(context).textTheme.bodyLarge?.copyWith(fontSize: 14),
),
],
UserDropdownMenu(user: user),
],
);
}
}
class _UserAvatar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SizedBox.square(
dimension: 40,
child: CircleAvatar(
backgroundColor: ColorsManager.whiteColors,
child: SizedBox.square(
dimension: 35,
child: SvgPicture.asset(
Assets.logoGrey,
fit: BoxFit.cover,
),
),
),
);
} }
} }