mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
Merge branch 'dev' into 1511-occupancy-heat-map-tooltip
This commit is contained in:
@ -1,22 +1,28 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
class OccupancyHeatMapModel extends Equatable {
|
class OccupancyHeatMapModel extends Equatable {
|
||||||
final DateTime date;
|
final String uuid;
|
||||||
|
|
||||||
final int occupancy;
|
final DateTime eventDate;
|
||||||
|
|
||||||
|
final int countTotalPresenceDetected;
|
||||||
|
|
||||||
const OccupancyHeatMapModel({
|
const OccupancyHeatMapModel({
|
||||||
required this.date,
|
required this.uuid,
|
||||||
required this.occupancy,
|
required this.eventDate,
|
||||||
|
required this.countTotalPresenceDetected,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory OccupancyHeatMapModel.fromJson(Map<String, dynamic> json) {
|
factory OccupancyHeatMapModel.fromJson(Map<String, dynamic> json) {
|
||||||
return OccupancyHeatMapModel(
|
return OccupancyHeatMapModel(
|
||||||
date: DateTime.parse(json['date'] as String),
|
uuid: json['uuid'] as String? ?? '',
|
||||||
occupancy: json['occupancy'] as int,
|
eventDate: DateTime.parse(
|
||||||
|
json['event_date'] as String? ?? '${DateTime.now()}',
|
||||||
|
),
|
||||||
|
countTotalPresenceDetected: json['count_total_presence_detected'] as int? ?? 0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [date, occupancy];
|
List<Object?> get props => [uuid, eventDate, countTotalPresenceDetected];
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import 'package:syncrow_web/pages/analytics/modules/occupancy/blocs/occupancy_he
|
|||||||
import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/fake_energy_consumption_by_phases_service.dart';
|
import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/fake_energy_consumption_by_phases_service.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/fake_energy_consumption_per_device_service.dart';
|
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/fake_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/fake_occupacy_service.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/services/occupancy_heat_map/fake_occupancy_heat_map_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/power_clamp_info/remote_power_clamp_info_service.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/services/realtime_device_service/firebase_realtime_device_service.dart';
|
import 'package:syncrow_web/pages/analytics/services/realtime_device_service/firebase_realtime_device_service.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/services/total_energy_consumption/remote_total_energy_consumption_service.dart';
|
import 'package:syncrow_web/pages/analytics/services/total_energy_consumption/remote_total_energy_consumption_service.dart';
|
||||||
@ -60,7 +60,9 @@ class AnalyticsPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
BlocProvider(create: (context) => OccupancyBloc(FakeOccupacyService())),
|
BlocProvider(create: (context) => OccupancyBloc(FakeOccupacyService())),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => OccupancyHeatMapBloc(FakeOccupancyHeatMapService()),
|
create: (context) => OccupancyHeatMapBloc(
|
||||||
|
RemoteOccupancyHeatMapService(HTTPService()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
BlocProvider(create: (context) => AnalyticsDatePickerBloc()),
|
BlocProvider(create: (context) => AnalyticsDatePickerBloc()),
|
||||||
],
|
],
|
||||||
|
@ -35,8 +35,7 @@ abstract final class FetchOccupancyDataHelper {
|
|||||||
context.read<OccupancyHeatMapBloc>().add(
|
context.read<OccupancyHeatMapBloc>().add(
|
||||||
LoadOccupancyHeatMapEvent(
|
LoadOccupancyHeatMapEvent(
|
||||||
GetOccupancyHeatMapParam(
|
GetOccupancyHeatMapParam(
|
||||||
spaceId: spaceId,
|
spaceUuid: spaceId,
|
||||||
communityId: communityId,
|
|
||||||
year: datePickerState.yearlyDate,
|
year: datePickerState.yearlyDate,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -15,8 +15,9 @@ class OccupancyHeatMap extends StatelessWidget {
|
|||||||
static const _cellSize = 16.0;
|
static const _cellSize = 16.0;
|
||||||
static const _totalWeeks = 53;
|
static const _totalWeeks = 53;
|
||||||
|
|
||||||
int get _maxValue =>
|
int get _maxValue => heatMapData.isNotEmpty
|
||||||
heatMapData.isNotEmpty ? heatMapData.values.reduce(math.max) : 0;
|
? heatMapData.keys.map((key) => heatMapData[key] ?? 0).reduce(math.max)
|
||||||
|
: 0;
|
||||||
|
|
||||||
DateTime _getStartingDate() {
|
DateTime _getStartingDate() {
|
||||||
final jan1 = DateTime(DateTime.now().year, 1, 1);
|
final jan1 = DateTime(DateTime.now().year, 1, 1);
|
||||||
|
@ -68,7 +68,10 @@ class OccupancyHeatMapBox extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: OccupancyHeatMap(
|
child: OccupancyHeatMap(
|
||||||
heatMapData: state.heatMapData.asMap().map(
|
heatMapData: state.heatMapData.asMap().map(
|
||||||
(_, value) => MapEntry(value.date, value.occupancy),
|
(_, value) => MapEntry(
|
||||||
|
value.eventDate,
|
||||||
|
value.countTotalPresenceDetected,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,19 +1,13 @@
|
|||||||
class GetOccupancyHeatMapParam {
|
class GetOccupancyHeatMapParam {
|
||||||
final DateTime year;
|
final DateTime year;
|
||||||
final String communityId;
|
final String spaceUuid;
|
||||||
final String spaceId;
|
|
||||||
|
|
||||||
const GetOccupancyHeatMapParam({
|
const GetOccupancyHeatMapParam({
|
||||||
required this.year,
|
required this.year,
|
||||||
required this.communityId,
|
required this.spaceUuid,
|
||||||
required this.spaceId,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return {
|
return {'year': year.year};
|
||||||
'year': year.toIso8601String(),
|
|
||||||
'communityId': communityId,
|
|
||||||
'spaceId': spaceId,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
import 'package:syncrow_web/pages/analytics/models/occupancy_heat_map_model.dart';
|
|
||||||
import 'package:syncrow_web/pages/analytics/params/get_occupancy_heat_map_param.dart';
|
|
||||||
import 'package:syncrow_web/pages/analytics/services/occupancy_heat_map/occupancy_heat_map_service.dart';
|
|
||||||
|
|
||||||
class FakeOccupancyHeatMapService implements OccupancyHeatMapService {
|
|
||||||
@override
|
|
||||||
Future<List<OccupancyHeatMapModel>> load(GetOccupancyHeatMapParam param) {
|
|
||||||
return Future.delayed(const Duration(milliseconds: 200), () {
|
|
||||||
final now = DateTime.now();
|
|
||||||
final startOfYear = DateTime(now.year, 1, 1);
|
|
||||||
final endOfYear = DateTime(now.year, 12, 31);
|
|
||||||
final daysInYear = endOfYear.difference(startOfYear).inDays + 1;
|
|
||||||
|
|
||||||
final List<OccupancyHeatMapModel> data = List.generate(
|
|
||||||
daysInYear,
|
|
||||||
(index) => OccupancyHeatMapModel(
|
|
||||||
date: startOfYear.add(Duration(days: index)),
|
|
||||||
occupancy: ((index + 1) * 10) % 100,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,35 @@
|
|||||||
|
import 'package:syncrow_web/pages/analytics/models/occupancy_heat_map_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/params/get_occupancy_heat_map_param.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/services/occupancy_heat_map/occupancy_heat_map_service.dart';
|
||||||
|
import 'package:syncrow_web/services/api/http_service.dart';
|
||||||
|
|
||||||
|
final class RemoteOccupancyHeatMapService implements OccupancyHeatMapService {
|
||||||
|
const RemoteOccupancyHeatMapService(this._httpService);
|
||||||
|
|
||||||
|
final HTTPService _httpService;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<OccupancyHeatMapModel>> load(GetOccupancyHeatMapParam param) async {
|
||||||
|
try {
|
||||||
|
final response = await _httpService.get(
|
||||||
|
path: '/occupancy/heat-map/space/${param.spaceUuid}',
|
||||||
|
showServerMessage: true,
|
||||||
|
queryParameters: param.toJson(),
|
||||||
|
expectedResponseModel: (response) {
|
||||||
|
final json = response as Map<String, dynamic>;
|
||||||
|
final dailyData = json['data'] as List<dynamic>? ?? <dynamic>[];
|
||||||
|
|
||||||
|
final result = dailyData.map(
|
||||||
|
(json) => OccupancyHeatMapModel.fromJson(json as Map<String, dynamic>),
|
||||||
|
);
|
||||||
|
|
||||||
|
return result.toList();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
throw Exception('Failed to load total energy consumption:');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@ class AnalyticsErrorWidget extends StatelessWidget {
|
|||||||
return Visibility(
|
return Visibility(
|
||||||
visible: errorMessage != null || (errorMessage?.isNotEmpty ?? false),
|
visible: errorMessage != null || (errorMessage?.isNotEmpty ?? false),
|
||||||
child: Text(
|
child: Text(
|
||||||
'$errorMessage ?? "Something went wrong"',
|
errorMessage ?? 'Something went wrong',
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: context.textTheme.bodySmall?.copyWith(
|
style: context.textTheme.bodySmall?.copyWith(
|
||||||
|
Reference in New Issue
Block a user