Compare commits

...
Author SHA1 Message Date
Faris Armoush 9d27ed2dc5 SP-1506 rework, coloring and padding. 2025-05-25 11:13:24 +03:00
Faris Armoush a878b9328a SP-1493 rework, can select a subspace in sidebar even when the space has no child-spaces. 2025-05-25 11:06:36 +03:00
Faris Armoush 0f9227a6f5 Merge pull request #200 from SyncrowIOT/SP-1591-FE-Implement-Space-Level-Structure-Selection-and-Air-Quality-Device-Dropdown
Sp 1591 fe implement space level structure selection and air quality device dropdown
2025-05-22 15:59:19 +03:00
Faris Armoush 5b13962d41 removed unnecessary * 1 calculation of height. 2025-05-22 15:57:03 +03:00
Faris Armoush 8c53d5322a SP-1591 2025-05-22 15:53:18 +03:00
Faris Armoush af4d37939b Merge branch 'dev' of https://github.com/SyncrowIOT/web into SP-1591-FE-Implement-Space-Level-Structure-Selection-and-Air-Quality-Device-Dropdown 2025-05-22 15:48:47 +03:00
Faris Armoush d43c1847ff SP-1591 2025-05-22 15:44:19 +03:00
Faris Armoush 4c5b390887 Fixed typos. 2025-05-22 15:42:49 +03:00
Faris Armoush 5eeac01666 cannot select a community in AirQualityDataLoadingStrategy. 2025-05-22 15:35:04 +03:00
Faris Armoush 717d698378 can select child spaces with children in AirQualityDataLoadingStrategy. 2025-05-22 15:23:42 +03:00
Faris Armoush 9adbbb9a2d Integrated and implemented devices dropdown into the newly created widget AirQualityEndSideWidget. 2025-05-22 15:19:50 +03:00
Faris Armoush e792dbd72f SP-1591/ Implement business logic in AirQualityDataLoadingStrategy for community structure loading strategy. 2025-05-22 14:58:42 +03:00
Rafeek Alkhoudare 9eaa367d32 fix horizontal scroll bar 2025-05-22 05:48:49 -05:00
Faris Armoush d2eea33714 Prepared AirQualityView layout and structure with PlaceHolder widgets. 2025-05-22 12:24:13 +03:00
Faris Armoush 24372a0618 Merge pull request #198 from SyncrowIOT/SP-1580-FE-Watermark-Does-Not-Match-Design-Specification
SP-1580-FE-Watermark-Does-Not-Match-Design-Specification
2025-05-22 11:25:49 +03:00
Faris Armoush 8988947694 Merge pull request #191 from SyncrowIOT/syncrow_analytics_sidebar_selection_behavior
Syncrow analytics sidebar selection behavior
2025-05-22 11:25:22 +03:00
Faris Armoush ef875ef7dc Merge pull request #197 from SyncrowIOT/SP-1510-occupancy_chart_api_integration
Sp 1510 occupancy chart api integration
2025-05-22 11:24:55 +03:00
Faris Armoush 5a61647fe4 Prepared and created the necessary component for the air quality loading strategy for the side bar selection, and for loading data in different parts of the UI. 2025-05-21 16:49:30 +03:00
Faris Armoush 568b6be354 Created AirQualityView widget for the new Air Quality analytics module. 2025-05-21 16:46:38 +03:00
Faris Armoush 94e4fbd5db Apply correct business logic in OccupancyDataLoadingStrategy. 2025-05-21 16:08:48 +03:00
Faris Armoush 302ef36b17 Merge branch 'dev' of https://github.com/SyncrowIOT/web into syncrow_analytics_sidebar_selection_behavior 2025-05-21 15:56:29 +03:00
Faris Armoush c508d016c2 SP-1580-FE-Watermark-Does-Not-Match-Design-Specification 2025-05-21 11:08:00 +03:00
mohammadnemer1 64a29681de Merge pull request #196 from SyncrowIOT/SP-1475-FE-Only-the-arrow-button-is-clickable-make-the-whole-name-clickable-with-the-arrow
Sp 1475 fe only the arrow button is clickable make the whole name clickable with the arrow
2025-05-21 10:31:25 +03:00
mohammad 06b320a75d move icon to the center and change subspace title name 2025-05-21 10:16:12 +03:00
mohammad a15b5439f0 Refactor user dropdown menu to display user's full name and arrow icon in a row for better layout consistency 2025-05-20 16:39:10 +03:00
Faris Armoush baaf5111b1 Applied correct business logic in EnergyManagementDataLoadingStrategy. 2025-05-15 12:48:18 +03:00
Faris Armoush 745205063e added correct behavior to OccupancyDataLoadingStrategy. 2025-05-15 12:46:12 +03:00
19 changed files with 364 additions and 113 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@@ -0,0 +1,52 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/analytics/blocs/analytics_devices/analytics_devices_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/realtime_device_changes/realtime_device_changes_bloc.dart';
import 'package:syncrow_web/pages/analytics/params/get_analytics_devices_param.dart';
abstract final class FetchAirQualityDataHelper {
const FetchAirQualityDataHelper._();
static void loadAirQualityData(
BuildContext context, {
required String communityUuid,
required String spaceUuid,
}) {
loadAnalyticsDevices(
context,
communityUuid: communityUuid,
spaceUuid: spaceUuid,
);
}
static void clearAllData(BuildContext context) {
context.read<AnalyticsDevicesBloc>().add(
const ClearAnalyticsDeviceEvent(),
);
context.read<RealtimeDeviceChangesBloc>().add(
const RealtimeDeviceChangesClosed(),
);
}
static void loadAnalyticsDevices(
BuildContext context, {
required String communityUuid,
required String spaceUuid,
}) {
context.read<AnalyticsDevicesBloc>().add(
LoadAnalyticsDevicesEvent(
param: GetAnalyticsDevicesParam(
communityUuid: communityUuid,
spaceUuid: spaceUuid,
deviceTypes: ['AQI'],
requestType: AnalyticsDeviceRequestType.energyManagement,
),
onSuccess: (device) {
context.read<RealtimeDeviceChangesBloc>()
..add(const RealtimeDeviceChangesClosed())
..add(RealtimeDeviceChangesStarted(device.uuid));
},
),
);
}
}
@@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/air_quality_end_side_widget.dart';
class AirQualityView extends StatelessWidget {
const AirQualityView({super.key});
static const _padding = EdgeInsetsDirectional.all(32);
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final isMediumOrLess = constraints.maxWidth <= 900;
final height = MediaQuery.sizeOf(context).height;
if (isMediumOrLess) {
return SingleChildScrollView(
padding: _padding,
child: Column(
spacing: 32,
children: [
SizedBox(
height: height * 1.2,
child: const AirQualityEndSideWidget(),
),
SizedBox(height: height * 0.5, child: const Placeholder()),
SizedBox(height: height * 0.5, child: const Placeholder()),
],
),
);
}
return SingleChildScrollView(
child: Container(
padding: _padding,
height: height,
child: const Column(
children: [
Expanded(
child: Row(
spacing: 32,
children: [
Expanded(
flex: 2,
child: Column(
spacing: 20,
children: [
Expanded(child: Placeholder()),
Expanded(child: Placeholder()),
],
),
),
Expanded(child: AirQualityEndSideWidget()),
],
),
),
],
),
),
);
},
);
}
}
@@ -0,0 +1,88 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/analytics/blocs/analytics_devices/analytics_devices_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/helpers/fetch_energy_management_data_helper.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/analytics_device_dropdown.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/utils/style.dart';
class AirQualityEndSideWidget extends StatelessWidget {
const AirQualityEndSideWidget({super.key});
@override
Widget build(BuildContext context) {
return Container(
decoration: subSectionContainerDecoration.copyWith(
borderRadius: BorderRadius.circular(30),
),
padding: const EdgeInsetsDirectional.all(32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildHeader(context),
Text(
'Device ID:',
style: context.textTheme.bodySmall?.copyWith(
color: ColorsManager.textPrimaryColor,
fontWeight: FontWeight.w400,
fontSize: 12,
),
),
const SizedBox(height: 6),
SelectableText(
context.watch<AnalyticsDevicesBloc>().state.selectedDevice?.uuid ??
'N/A',
style: context.textTheme.bodySmall?.copyWith(
color: ColorsManager.blackColor,
fontWeight: FontWeight.w400,
fontSize: 12,
),
),
],
),
);
}
Widget _buildHeader(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
flex: 3,
child: FittedBox(
fit: BoxFit.scaleDown,
alignment: AlignmentDirectional.centerStart,
child: SelectableText(
'AQI Sensor',
style: context.textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.w700,
color: ColorsManager.vividBlue.withValues(alpha: 0.6),
fontSize: 18,
),
),
),
),
const Spacer(),
Expanded(
flex: 2,
child: FittedBox(
fit: BoxFit.scaleDown,
alignment: AlignmentDirectional.centerEnd,
child: AnalyticsDeviceDropdown(
onChanged: (value) {
context.read<AnalyticsDevicesBloc>().add(
SelectAnalyticsDeviceEvent(value),
);
FetchEnergyManagementDataHelper.loadRealtimeDeviceChanges(
context,
deviceUuid: value.uuid,
);
},
),
),
),
],
);
}
}
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/analytics/modules/air_quality/views/air_quality_view.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/views/analytics_energy_management_view.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/views/analytics_energy_management_view.dart';
import 'package:syncrow_web/pages/analytics/modules/occupancy/views/analytics_occupancy_view.dart'; import 'package:syncrow_web/pages/analytics/modules/occupancy/views/analytics_occupancy_view.dart';
@@ -10,6 +11,10 @@ enum AnalyticsPageTab {
occupancy( occupancy(
title: 'Occupancy', title: 'Occupancy',
child: AnalyticsOccupancyView(), child: AnalyticsOccupancyView(),
),
airQuality(
title: 'Air Quality',
child: AirQualityView(),
); );
const AnalyticsPageTab({ const AnalyticsPageTab({
@@ -0,0 +1,59 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/air_quality/helpers/fetch_air_quality_data_helper.dart';
import 'package:syncrow_web/pages/analytics/modules/analytics/strategies/analytics_data_loading_strategy.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
final class AirQualityDataLoadingStrategy implements AnalyticsDataLoadingStrategy {
@override
void onCommunitySelected(
BuildContext context,
CommunityModel community,
List<SpaceModel> spaces,
) {
// Do nothing
}
@override
void onSpaceSelected(
BuildContext context,
CommunityModel community,
SpaceModel space,
) {
final spaceTreeBloc = context.read<SpaceTreeBloc>();
final isSpaceSelected = spaceTreeBloc.state.selectedSpaces.contains(space.uuid);
if (isSpaceSelected) {
clearData(context);
return;
}
spaceTreeBloc
..add(const SpaceTreeClearSelectionEvent())
..add(OnSpaceSelected(community, space.uuid ?? '', []));
FetchAirQualityDataHelper.loadAirQualityData(
context,
communityUuid: community.uuid,
spaceUuid: space.uuid ?? '',
);
}
@override
void onChildSpaceSelected(
BuildContext context,
CommunityModel community,
SpaceModel child,
) {
return onSpaceSelected(context, community, child);
}
@override
void clearData(BuildContext context) {
context.read<SpaceTreeBloc>().add(const SpaceTreeClearSelectionEvent());
FetchAirQualityDataHelper.clearAllData(context);
}
}
@@ -1,4 +1,5 @@
import 'package:syncrow_web/pages/analytics/modules/analytics/enums/analytics_page_tab.dart'; import 'package:syncrow_web/pages/analytics/modules/analytics/enums/analytics_page_tab.dart';
import 'package:syncrow_web/pages/analytics/modules/analytics/strategies/air_quality_data_loading_strategy.dart';
import 'package:syncrow_web/pages/analytics/modules/analytics/strategies/analytics_data_loading_strategy.dart'; import 'package:syncrow_web/pages/analytics/modules/analytics/strategies/analytics_data_loading_strategy.dart';
import 'package:syncrow_web/pages/analytics/modules/analytics/strategies/energy_management_data_loading_strategy.dart'; import 'package:syncrow_web/pages/analytics/modules/analytics/strategies/energy_management_data_loading_strategy.dart';
import 'package:syncrow_web/pages/analytics/modules/analytics/strategies/occupancy_data_loading_strategy.dart'; import 'package:syncrow_web/pages/analytics/modules/analytics/strategies/occupancy_data_loading_strategy.dart';
@@ -9,6 +10,7 @@ abstract final class AnalyticsDataLoadingStrategyFactory {
return switch (tab) { return switch (tab) {
AnalyticsPageTab.energyManagement => EnergyManagementDataLoadingStrategy(), AnalyticsPageTab.energyManagement => EnergyManagementDataLoadingStrategy(),
AnalyticsPageTab.occupancy => OccupancyDataLoadingStrategy(), AnalyticsPageTab.occupancy => OccupancyDataLoadingStrategy(),
AnalyticsPageTab.airQuality => AirQualityDataLoadingStrategy(),
}; };
} }
} }
@@ -14,7 +14,6 @@ class EnergyManagementDataLoadingStrategy implements AnalyticsDataLoadingStrateg
CommunityModel community, CommunityModel community,
List<SpaceModel> spaces, List<SpaceModel> spaces,
) { ) {
// Add to space tree bloc first
context.read<SpaceTreeBloc>().add( context.read<SpaceTreeBloc>().add(
OnCommunitySelected( OnCommunitySelected(
community.uuid, community.uuid,
@@ -69,7 +68,7 @@ class EnergyManagementDataLoadingStrategy implements AnalyticsDataLoadingStrateg
CommunityModel community, CommunityModel community,
SpaceModel child, SpaceModel child,
) { ) {
// Do nothing else as per original implementation return onSpaceSelected(context, community, child);
} }
@override @override
@@ -14,23 +14,7 @@ class OccupancyDataLoadingStrategy implements AnalyticsDataLoadingStrategy {
CommunityModel community, CommunityModel community,
List<SpaceModel> spaces, List<SpaceModel> spaces,
) { ) {
context.read<SpaceTreeBloc>().add( // Do Nothing
OnCommunitySelected(
community.uuid,
spaces.isNotEmpty ? [spaces.first] : [],
),
);
final spaceTreeState = context.read<SpaceTreeBloc>().state;
if (spaceTreeState.selectedCommunities.contains(community.uuid)) {
clearData(context);
return;
}
FetchOccupancyDataHelper.loadOccupancyData(
context,
communityId: community.uuid,
spaceId: spaces.isNotEmpty ? spaces.first.uuid ?? '' : '',
);
} }
@override @override
@@ -40,26 +24,17 @@ class OccupancyDataLoadingStrategy implements AnalyticsDataLoadingStrategy {
SpaceModel space, SpaceModel space,
) { ) {
final spaceTreeBloc = context.read<SpaceTreeBloc>(); final spaceTreeBloc = context.read<SpaceTreeBloc>();
final selectedSpacesIds = spaceTreeBloc.state.selectedSpaces; final isSpaceSelected = spaceTreeBloc.state.selectedSpaces.contains(space.uuid);
final isSpaceSelected = selectedSpacesIds.contains(space.uuid);
if (selectedSpacesIds.isEmpty) { if (isSpaceSelected) {
spaceTreeBloc.add(OnCommunitySelected(community.uuid, [space]));
} else if (isSpaceSelected) {
spaceTreeBloc.add(const SpaceTreeClearSelectionEvent());
} else {
spaceTreeBloc
..add(const SpaceTreeClearSelectionEvent())
..add(OnSpaceSelected(community, space.uuid ?? '', []));
}
final spaceTreeState = context.read<SpaceTreeBloc>().state;
if (spaceTreeState.selectedCommunities.contains(community.uuid) ||
spaceTreeState.selectedSpaces.contains(space.uuid)) {
clearData(context); clearData(context);
return; return;
} }
spaceTreeBloc
..add(const SpaceTreeClearSelectionEvent())
..add(OnSpaceSelected(community, space.uuid ?? '', []));
FetchOccupancyDataHelper.loadOccupancyData( FetchOccupancyDataHelper.loadOccupancyData(
context, context,
communityId: community.uuid, communityId: community.uuid,
@@ -73,7 +48,7 @@ class OccupancyDataLoadingStrategy implements AnalyticsDataLoadingStrategy {
CommunityModel community, CommunityModel community,
SpaceModel child, SpaceModel child,
) { ) {
// Do nothing return onSpaceSelected(context, community, child);
} }
@override @override
@@ -38,7 +38,7 @@ abstract final class EnergyManagementChartsHelper {
sideTitles: SideTitles( sideTitles: SideTitles(
showTitles: true, showTitles: true,
maxIncluded: false, maxIncluded: false,
minIncluded: true, minIncluded: false,
interval: leftTitlesInterval, interval: leftTitlesInterval,
reservedSize: 110, reservedSize: 110,
getTitlesWidget: (value, meta) => Padding( getTitlesWidget: (value, meta) => Padding(
@@ -50,7 +50,7 @@ abstract final class EnergyManagementChartsHelper {
value.formatNumberToKwh, value.formatNumberToKwh,
style: context.textTheme.bodySmall?.copyWith( style: context.textTheme.bodySmall?.copyWith(
fontSize: 12, fontSize: 12,
color: ColorsManager.greyColor, color: ColorsManager.lightGreyColor,
), ),
), ),
), ),
@@ -170,7 +170,7 @@ class EnergyConsumptionByPhasesChart extends StatelessWidget {
child: Text( child: Text(
month, month,
style: context.textTheme.bodySmall?.copyWith( style: context.textTheme.bodySmall?.copyWith(
color: ColorsManager.greyColor, color: ColorsManager.lightGreyColor,
fontSize: 11, fontSize: 11,
), ),
), ),
@@ -19,10 +19,12 @@ class EnergyConsumptionByPhasesChartBox extends StatelessWidget {
decoration: secondarySection, decoration: secondarySection,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
spacing: 20,
children: [ children: [
AnalyticsErrorWidget(state.errorMessage), AnalyticsErrorWidget(state.errorMessage),
EnergyConsumptionByPhasesTitle(isLoading: state.status == EnergyConsumptionByPhasesStatus.loading,), EnergyConsumptionByPhasesTitle(
isLoading: state.status == EnergyConsumptionByPhasesStatus.loading,
),
const SizedBox(height: 20),
Expanded( Expanded(
child: EnergyConsumptionByPhasesChart( child: EnergyConsumptionByPhasesChart(
energyData: state.chartData, energyData: state.chartData,
+53 -34
View File
@@ -63,7 +63,8 @@ class _DynamicTableState extends State<DynamicTable> {
} }
} }
bool _compareListOfLists(List<List<dynamic>> oldList, List<List<dynamic>> newList) { bool _compareListOfLists(
List<List<dynamic>> oldList, List<List<dynamic>> newList) {
// Check if the old and new lists are the same // Check if the old and new lists are the same
if (oldList.length != newList.length) return false; if (oldList.length != newList.length) return false;
@@ -111,8 +112,8 @@ class _DynamicTableState extends State<DynamicTable> {
trackVisibility: true, trackVisibility: true,
child: Scrollbar( child: Scrollbar(
controller: _horizontalScrollController, controller: _horizontalScrollController,
thumbVisibility: false, thumbVisibility: true,
trackVisibility: false, trackVisibility: true,
notificationPredicate: (notif) => notif.depth == 1, notificationPredicate: (notif) => notif.depth == 1,
child: SingleChildScrollView( child: SingleChildScrollView(
controller: _verticalScrollController, controller: _verticalScrollController,
@@ -132,46 +133,60 @@ class _DynamicTableState extends State<DynamicTable> {
children: [ children: [
if (widget.withCheckBox) _buildSelectAllCheckbox(), if (widget.withCheckBox) _buildSelectAllCheckbox(),
...List.generate(widget.headers.length, (index) { ...List.generate(widget.headers.length, (index) {
return _buildTableHeaderCell(widget.headers[index], index); return _buildTableHeaderCell(
widget.headers[index], index);
}) })
//...widget.headers.map((header) => _buildTableHeaderCell(header)), //...widget.headers.map((header) => _buildTableHeaderCell(header)),
], ],
), ),
), ),
widget.isEmpty widget.isEmpty
? Column( ? SizedBox(
mainAxisAlignment: MainAxisAlignment.center, height: widget.size.height * 0.5,
children: [ width: widget.size.width,
Row( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, children: [
children: [ Row(
Column( crossAxisAlignment: CrossAxisAlignment.center,
children: [ mainAxisAlignment: MainAxisAlignment.center,
SvgPicture.asset(Assets.emptyTable), children: [
const SizedBox( Column(
height: 15, children: [
), SvgPicture.asset(Assets.emptyTable),
Text( const SizedBox(
widget.tableName == 'AccessManagement' ? 'No Password ' : 'No Devices', height: 15,
style: Theme.of(context) ),
.textTheme Text(
.bodySmall! widget.tableName == 'AccessManagement'
.copyWith(color: ColorsManager.grayColor), ? 'No Password '
) : 'No Devices',
], style: Theme.of(context)
), .textTheme
], .bodySmall!
), .copyWith(
], color:
ColorsManager.grayColor),
)
],
),
],
),
],
),
) )
: Column( : Column(
children: List.generate(widget.data.length, (index) { children:
List.generate(widget.data.length, (index) {
final row = widget.data[index]; final row = widget.data[index];
return Row( return Row(
children: [ children: [
if (widget.withCheckBox) _buildRowCheckbox(index, widget.size.height * 0.08), if (widget.withCheckBox)
...row.map((cell) => _buildTableCell(cell.toString(), widget.size.height * 0.08)), _buildRowCheckbox(
index, widget.size.height * 0.08),
...row.map((cell) => _buildTableCell(
cell.toString(),
widget.size.height * 0.08)),
], ],
); );
}), }),
@@ -196,7 +211,9 @@ class _DynamicTableState extends State<DynamicTable> {
), ),
child: Checkbox( child: Checkbox(
value: _selectAll, value: _selectAll,
onChanged: widget.withSelectAll && widget.data.isNotEmpty ? _toggleSelectAll : null, onChanged: widget.withSelectAll && widget.data.isNotEmpty
? _toggleSelectAll
: null,
), ),
); );
} }
@@ -238,7 +255,9 @@ class _DynamicTableState extends State<DynamicTable> {
constraints: const BoxConstraints.expand(height: 40), constraints: const BoxConstraints.expand(height: 40),
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(horizontal: index == widget.headers.length - 1 ? 12 : 8.0, vertical: 4), padding: EdgeInsets.symmetric(
horizontal: index == widget.headers.length - 1 ? 12 : 8.0,
vertical: 4),
child: Text( child: Text(
title, title,
style: context.textTheme.titleSmall!.copyWith( style: context.textTheme.titleSmall!.copyWith(
@@ -97,7 +97,8 @@ class DeviceControlDialog extends StatelessWidget with RouteControlsBasedCode {
children: [ children: [
_buildInfoRow('Space Name:', _buildInfoRow('Space Name:',
device.spaces?.firstOrNull?.spaceName ?? 'N/A'), device.spaces?.firstOrNull?.spaceName ?? 'N/A'),
_buildInfoRow('Room:', device.subspace?.subspaceName ?? 'N/A'), _buildInfoRow(
'Sub space:', device.subspace?.subspaceName ?? 'N/A'),
], ],
), ),
TableRow( TableRow(
@@ -38,7 +38,7 @@ class VisitorPasswordDialog extends StatelessWidget {
if (visitorBloc.passwordStatus!.failedOperations.isNotEmpty) if (visitorBloc.passwordStatus!.failedOperations.isNotEmpty)
Column( Column(
children: [ children: [
const Text('Failed Devises'), const Text('Failed Devices'),
SizedBox( SizedBox(
width: 200, width: 200,
height: 50, height: 50,
@@ -63,7 +63,7 @@ class VisitorPasswordDialog extends StatelessWidget {
if (visitorBloc.passwordStatus!.successOperations.isNotEmpty) if (visitorBloc.passwordStatus!.successOperations.isNotEmpty)
Column( Column(
children: [ children: [
const Text('Success Devises'), const Text('Success Devices'),
SizedBox( SizedBox(
width: 200, width: 200,
height: 50, height: 50,
+1
View File
@@ -2,6 +2,7 @@ class Assets {
Assets._(); Assets._();
static const String background = "assets/images/Background.png"; static const String background = "assets/images/Background.png";
static const String webBackground = "assets/images/web_Background.svg"; static const String webBackground = "assets/images/web_Background.svg";
static const String webBackgroundPng = "assets/images/web_Background.png";
static const String blackLogo = "assets/images/black-logo.png"; static const String blackLogo = "assets/images/black-logo.png";
static const String logo = "assets/images/Logo.svg"; static const String logo = "assets/images/Logo.svg";
static const String logoHorizontal = "assets/images/logo_horizontal.png"; static const String logoHorizontal = "assets/images/logo_horizontal.png";
+18 -7
View File
@@ -41,13 +41,24 @@ class _UserDropdownMenuState extends State<UserDropdownMenu> {
_isDropdownOpen = false; _isDropdownOpen = false;
}); });
}, },
child: Transform.rotate( child: Row(
angle: _isDropdownOpen ? -1.5708 : 1.5708, children: [
child: const Icon( const SizedBox(width: 12),
Icons.arrow_forward_ios, if (widget.user != null)
color: Colors.white, Text(
size: 16, '${widget.user!.firstName} ${widget.user!.lastName}',
), style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(width: 12),
Transform.rotate(
angle: _isDropdownOpen ? -1.5708 : 1.5708,
child: const Icon(
Icons.arrow_forward_ios,
color: Colors.white,
size: 16,
),
),
],
), ),
), ),
], ],
-23
View File
@@ -92,13 +92,6 @@ class DesktopAppBar extends StatelessWidget {
if (rightBody != null) rightBody!, if (rightBody != null) rightBody!,
const SizedBox(width: 24), const SizedBox(width: 24),
_UserAvatar(), _UserAvatar(),
const SizedBox(width: 12),
if (user != null)
Text(
'${user.firstName} ${user.lastName}',
style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(width: 12),
UserDropdownMenu(user: user), UserDropdownMenu(user: user),
], ],
); );
@@ -146,14 +139,6 @@ class TabletAppBar extends StatelessWidget {
if (rightBody != null) rightBody!, if (rightBody != null) rightBody!,
const SizedBox(width: 16), const SizedBox(width: 16),
_UserAvatar(), _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), UserDropdownMenu(user: user),
], ],
); );
@@ -215,14 +200,6 @@ class MobileAppBar extends StatelessWidget {
return Row( return Row(
children: [ children: [
_UserAvatar(), _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), UserDropdownMenu(user: user),
], ],
); );
+3 -6
View File
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.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/helpers/responsice_layout_helper/responsive_layout_helper.dart';
import 'package:syncrow_web/web_layout/web_app_bar.dart'; import 'package:syncrow_web/web_layout/web_app_bar.dart';
import 'menu_sidebar.dart'; import 'menu_sidebar.dart';
class WebScaffold extends StatelessWidget with HelperResponsiveLayout { class WebScaffold extends StatelessWidget with HelperResponsiveLayout {
@@ -28,14 +28,11 @@ class WebScaffold extends StatelessWidget with HelperResponsiveLayout {
SizedBox( SizedBox(
width: MediaQuery.sizeOf(context).width, width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height, height: MediaQuery.sizeOf(context).height,
child: SvgPicture.asset( child: Image.asset(
Assets.webBackground, Assets.webBackgroundPng,
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
), ),
Container(
color: Colors.white.withOpacity(0.7),
),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [