diff --git a/assets/images/web_Background.png b/assets/images/web_Background.png new file mode 100644 index 00000000..1d1dac6e Binary files /dev/null and b/assets/images/web_Background.png differ diff --git a/lib/pages/analytics/models/occupacy.dart b/lib/pages/analytics/models/occupacy.dart index ab53e5c2..b4b8dac9 100644 --- a/lib/pages/analytics/models/occupacy.dart +++ b/lib/pages/analytics/models/occupacy.dart @@ -1,18 +1,32 @@ import 'package:equatable/equatable.dart'; class Occupacy extends Equatable { - final String date; + final DateTime date; final String occupancy; + final String spaceUuid; + final int occupiedSeconds; - const Occupacy({required this.date, required this.occupancy}); + const Occupacy({ + required this.date, + required this.occupancy, + required this.spaceUuid, + required this.occupiedSeconds, + }); factory Occupacy.fromJson(Map json) { return Occupacy( - date: json['date'] as String, - occupancy: json['occupancy'] as String, + date: DateTime.parse(json['event_date'] as String? ?? '${DateTime.now()}'), + occupancy: (json['occupancy_percentage'] ?? 0).toString(), + spaceUuid: json['space_uuid'] as String? ?? '', + occupiedSeconds: json['occupied_seconds'] as int? ?? 0, ); } @override - List get props => [date, occupancy]; + List get props => [ + date, + occupancy, + spaceUuid, + occupiedSeconds, + ]; } diff --git a/lib/pages/analytics/modules/analytics/strategies/energy_management_data_loading_strategy.dart b/lib/pages/analytics/modules/analytics/strategies/energy_management_data_loading_strategy.dart index 1e251a41..c0d03879 100644 --- a/lib/pages/analytics/modules/analytics/strategies/energy_management_data_loading_strategy.dart +++ b/lib/pages/analytics/modules/analytics/strategies/energy_management_data_loading_strategy.dart @@ -14,7 +14,6 @@ class EnergyManagementDataLoadingStrategy implements AnalyticsDataLoadingStrateg CommunityModel community, List spaces, ) { - // Add to space tree bloc first context.read().add( OnCommunitySelected( community.uuid, @@ -69,7 +68,9 @@ class EnergyManagementDataLoadingStrategy implements AnalyticsDataLoadingStrateg CommunityModel community, SpaceModel child, ) { - // Do nothing else as per original implementation + if (child.children.isNotEmpty) { + return onSpaceSelected(context, community, child); + } } @override diff --git a/lib/pages/analytics/modules/analytics/strategies/occupancy_data_loading_strategy.dart b/lib/pages/analytics/modules/analytics/strategies/occupancy_data_loading_strategy.dart index 534d275f..158f5128 100644 --- a/lib/pages/analytics/modules/analytics/strategies/occupancy_data_loading_strategy.dart +++ b/lib/pages/analytics/modules/analytics/strategies/occupancy_data_loading_strategy.dart @@ -14,7 +14,7 @@ class OccupancyDataLoadingStrategy implements AnalyticsDataLoadingStrategy { CommunityModel community, List spaces, ) { - // Do nothing + // Do Nothing } @override @@ -24,26 +24,17 @@ class OccupancyDataLoadingStrategy implements AnalyticsDataLoadingStrategy { SpaceModel space, ) { final spaceTreeBloc = context.read(); - final selectedSpacesIds = spaceTreeBloc.state.selectedSpaces; - final isSpaceSelected = selectedSpacesIds.contains(space.uuid); + final isSpaceSelected = spaceTreeBloc.state.selectedSpaces.contains(space.uuid); - if (selectedSpacesIds.isEmpty) { - spaceTreeBloc.add(OnSpaceSelected(community, space.uuid ?? '', [])); - } else if (isSpaceSelected) { - spaceTreeBloc.add(const SpaceTreeClearSelectionEvent()); - } else { - spaceTreeBloc - ..add(const SpaceTreeClearSelectionEvent()) - ..add(OnSpaceSelected(community, space.uuid ?? '', [])); - } - - final spaceTreeState = context.read().state; - if (spaceTreeState.selectedCommunities.contains(community.uuid) || - spaceTreeState.selectedSpaces.contains(space.uuid)) { + if (isSpaceSelected) { clearData(context); return; } + spaceTreeBloc + ..add(const SpaceTreeClearSelectionEvent()) + ..add(OnSpaceSelected(community, space.uuid ?? '', [])); + FetchOccupancyDataHelper.loadOccupancyData( context, communityId: community.uuid, diff --git a/lib/pages/analytics/modules/analytics/views/analytics_page.dart b/lib/pages/analytics/modules/analytics/views/analytics_page.dart index 72cc7d51..18f86a90 100644 --- a/lib/pages/analytics/modules/analytics/views/analytics_page.dart +++ b/lib/pages/analytics/modules/analytics/views/analytics_page.dart @@ -17,7 +17,7 @@ import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_en import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_occupancy_analytics_devices_service.dart'; import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/remote_energy_consumption_by_phases_service.dart'; import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/remote_energy_consumption_per_device_service.dart'; -import 'package:syncrow_web/pages/analytics/services/occupacy/fake_occupacy_service.dart'; +import 'package:syncrow_web/pages/analytics/services/occupacy/remote_occupancy_service.dart'; import 'package:syncrow_web/pages/analytics/services/occupancy_heat_map/remote_occupancy_heat_map_service.dart'; import 'package:syncrow_web/pages/analytics/services/power_clamp_info/remote_power_clamp_info_service.dart'; import 'package:syncrow_web/pages/analytics/services/realtime_device_service/firebase_realtime_device_service.dart'; @@ -75,7 +75,11 @@ class _AnalyticsPageState extends State { FirebaseRealtimeDeviceService(), ), ), - BlocProvider(create: (context) => OccupancyBloc(FakeOccupacyService())), + BlocProvider( + create: (context) => OccupancyBloc( + RemoteOccupancyService(_httpService), + ), + ), BlocProvider( create: (context) => OccupancyHeatMapBloc( RemoteOccupancyHeatMapService(_httpService), diff --git a/lib/pages/analytics/modules/occupancy/helpers/fetch_occupancy_data_helper.dart b/lib/pages/analytics/modules/occupancy/helpers/fetch_occupancy_data_helper.dart index 5882ada5..0b01fda2 100644 --- a/lib/pages/analytics/modules/occupancy/helpers/fetch_occupancy_data_helper.dart +++ b/lib/pages/analytics/modules/occupancy/helpers/fetch_occupancy_data_helper.dart @@ -30,7 +30,6 @@ abstract final class FetchOccupancyDataHelper { loadOccupancyChartData( context, - communityUuid: communityId, spaceUuid: spaceId, date: datePickerState.monthlyDate, ); @@ -59,16 +58,14 @@ abstract final class FetchOccupancyDataHelper { static void loadOccupancyChartData( BuildContext context, { - required String communityUuid, required String spaceUuid, required DateTime date, }) { context.read().add( LoadOccupancyEvent( GetOccupancyParam( - monthDate: '${date.year}-${date.month}', + monthDate: '${date.year}-${date.month.toString().padLeft(2, '0')}', spaceUuid: spaceUuid, - communityUuid: communityUuid, ), ), ); diff --git a/lib/pages/analytics/modules/occupancy/widgets/occupancy_chart.dart b/lib/pages/analytics/modules/occupancy/widgets/occupancy_chart.dart index 3e362f5d..4ff85841 100644 --- a/lib/pages/analytics/modules/occupancy/widgets/occupancy_chart.dart +++ b/lib/pages/analytics/modules/occupancy/widgets/occupancy_chart.dart @@ -16,10 +16,10 @@ class OccupancyChart extends StatelessWidget { Widget build(BuildContext context) { return BarChart( BarChartData( - maxY: 1.0, + maxY: 100.0, gridData: EnergyManagementChartsHelper.gridData().copyWith( checkToShowHorizontalLine: (value) => true, - horizontalInterval: 0.2, + horizontalInterval: 20, ), borderData: EnergyManagementChartsHelper.borderData(), barTouchData: _barTouchData(context), @@ -33,20 +33,21 @@ class OccupancyChart extends StatelessWidget { ), barGroups: List.generate(chartData.length, (index) { final actual = chartData[index]; + final occupancyValue = double.parse(actual.occupancy); return BarChartGroupData( x: index, barsSpace: 0, groupVertically: true, barRods: [ BarChartRodData( - toY: 1.0, - fromY: double.parse(actual.occupancy) + 0.025, + toY: 100.0, + fromY: occupancyValue == 0 ? occupancyValue : occupancyValue + 2.5, color: ColorsManager.graysColor, width: _chartWidth, borderRadius: BorderRadius.circular(10), ), BarChartRodData( - toY: double.parse(actual.occupancy), + toY: occupancyValue, color: ColorsManager.vividBlue.withValues(alpha: 0.8), width: _chartWidth, borderRadius: BorderRadius.circular(10), @@ -88,7 +89,7 @@ class OccupancyChart extends StatelessWidget { final data = chartData; final occupancyValue = double.parse(data[group.x.toInt()].occupancy); - final percentage = '${(occupancyValue * 100).toStringAsFixed(0)}%'; + final percentage = '${(occupancyValue).toStringAsFixed(0)}%'; return BarTooltipItem( percentage, @@ -108,14 +109,14 @@ class OccupancyChart extends StatelessWidget { final leftTitles = titlesData.leftTitles.copyWith( sideTitles: titlesData.leftTitles.sideTitles.copyWith( reservedSize: 70, - interval: 0.2, + interval: 20, getTitlesWidget: (value, meta) => Padding( padding: const EdgeInsetsDirectional.only(end: 12), child: FittedBox( alignment: AlignmentDirectional.centerStart, fit: BoxFit.scaleDown, child: Text( - '${(value * 100).toStringAsFixed(0)}%', + '${(value).toStringAsFixed(0)}%', style: context.textTheme.bodySmall?.copyWith( fontSize: 12, color: ColorsManager.greyColor, diff --git a/lib/pages/analytics/modules/occupancy/widgets/occupancy_chart_box.dart b/lib/pages/analytics/modules/occupancy/widgets/occupancy_chart_box.dart index 8c41da48..ab1d1699 100644 --- a/lib/pages/analytics/modules/occupancy/widgets/occupancy_chart_box.dart +++ b/lib/pages/analytics/modules/occupancy/widgets/occupancy_chart_box.dart @@ -50,9 +50,6 @@ class OccupancyChartBox extends StatelessWidget { if (spaceTreeState.selectedSpaces.isNotEmpty) { FetchOccupancyDataHelper.loadOccupancyChartData( context, - communityUuid: - spaceTreeState.selectedCommunities.firstOrNull ?? - '', spaceUuid: spaceTreeState.selectedSpaces.firstOrNull ?? '', date: value, diff --git a/lib/pages/analytics/params/get_occupancy_param.dart b/lib/pages/analytics/params/get_occupancy_param.dart index ed1b9375..b083197b 100644 --- a/lib/pages/analytics/params/get_occupancy_param.dart +++ b/lib/pages/analytics/params/get_occupancy_param.dart @@ -1,19 +1,11 @@ class GetOccupancyParam { final String monthDate; final String? spaceUuid; - final String communityUuid; GetOccupancyParam({ required this.monthDate, required this.spaceUuid, - required this.communityUuid, }); - Map toJson() { - return { - 'monthDate': monthDate, - 'spaceUuid': spaceUuid, - 'communityUuid': communityUuid, - }; - } + Map toJson() => {'monthDate': monthDate}; } diff --git a/lib/pages/analytics/services/occupacy/fake_occupacy_service.dart b/lib/pages/analytics/services/occupacy/fake_occupacy_service.dart deleted file mode 100644 index 503a358b..00000000 --- a/lib/pages/analytics/services/occupacy/fake_occupacy_service.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:syncrow_web/pages/analytics/models/occupacy.dart'; -import 'package:syncrow_web/pages/analytics/params/get_occupancy_param.dart'; -import 'package:syncrow_web/pages/analytics/services/occupacy/occupacy_service.dart'; - -class FakeOccupacyService implements OccupacyService { - @override - Future> load(GetOccupancyParam param) async { - return await Future.delayed( - const Duration(seconds: 1), - () => List.generate( - 30, - (index) => Occupacy( - date: DateTime.now().subtract(Duration(days: index)).toString(), - occupancy: ((index / 100)).toString(), - ), - ), - ); - } -} diff --git a/lib/pages/analytics/services/occupacy/remote_occupancy_service.dart b/lib/pages/analytics/services/occupacy/remote_occupancy_service.dart new file mode 100644 index 00000000..b8cce70a --- /dev/null +++ b/lib/pages/analytics/services/occupacy/remote_occupancy_service.dart @@ -0,0 +1,32 @@ +import 'package:syncrow_web/pages/analytics/models/occupacy.dart'; +import 'package:syncrow_web/pages/analytics/params/get_occupancy_param.dart'; +import 'package:syncrow_web/pages/analytics/services/occupacy/occupacy_service.dart'; +import 'package:syncrow_web/services/api/http_service.dart'; + +final class RemoteOccupancyService implements OccupacyService { + const RemoteOccupancyService(this._httpService); + + final HTTPService _httpService; + + @override + Future> load(GetOccupancyParam param) async { + try { + final response = await _httpService.get( + path: '/occupancy/duration/space/${param.spaceUuid}', + showServerMessage: true, + queryParameters: param.toJson(), + expectedResponseModel: (data) { + final json = data as Map? ?? {}; + final mappedData = json['data'] as List? ?? []; + return mappedData.map((e) { + final jsonData = e as Map; + return Occupacy.fromJson(jsonData); + }).toList(); + }, + ); + return response; + } catch (e) { + throw Exception('Failed to load energy consumption per phase: $e'); + } + } +} \ No newline at end of file diff --git a/lib/pages/common/custom_table.dart b/lib/pages/common/custom_table.dart index 3ec902ef..04334393 100644 --- a/lib/pages/common/custom_table.dart +++ b/lib/pages/common/custom_table.dart @@ -112,8 +112,8 @@ class _DynamicTableState extends State { trackVisibility: true, child: Scrollbar( controller: _horizontalScrollController, - thumbVisibility: false, - trackVisibility: false, + thumbVisibility: true, + trackVisibility: true, notificationPredicate: (notif) => notif.depth == 1, child: SingleChildScrollView( controller: _verticalScrollController, diff --git a/lib/utils/constants/assets.dart b/lib/utils/constants/assets.dart index a1d782f2..c86b7458 100644 --- a/lib/utils/constants/assets.dart +++ b/lib/utils/constants/assets.dart @@ -2,6 +2,7 @@ class Assets { Assets._(); static const String background = "assets/images/Background.png"; 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 logo = "assets/images/Logo.svg"; static const String logoHorizontal = "assets/images/logo_horizontal.png"; diff --git a/lib/web_layout/web_scaffold.dart b/lib/web_layout/web_scaffold.dart index c1d6075f..a37727db 100644 --- a/lib/web_layout/web_scaffold.dart +++ b/lib/web_layout/web_scaffold.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.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/web_layout/web_app_bar.dart'; + import 'menu_sidebar.dart'; class WebScaffold extends StatelessWidget with HelperResponsiveLayout { @@ -28,14 +28,11 @@ class WebScaffold extends StatelessWidget with HelperResponsiveLayout { SizedBox( width: MediaQuery.sizeOf(context).width, height: MediaQuery.sizeOf(context).height, - child: SvgPicture.asset( - Assets.webBackground, + child: Image.asset( + Assets.webBackgroundPng, fit: BoxFit.cover, ), ), - Container( - color: Colors.white.withOpacity(0.7), - ), Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [