mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
84 lines
3.0 KiB
Dart
84 lines
3.0 KiB
Dart
import 'dart:math' as math show max;
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/interactive_heat_map.dart';
|
|
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_heat_map_days.dart';
|
|
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_heat_map_gradient.dart';
|
|
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_heat_map_months.dart';
|
|
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_painter.dart';
|
|
import 'package:syncrow_web/utils/color_manager.dart';
|
|
|
|
class OccupancyHeatMap extends StatelessWidget {
|
|
const OccupancyHeatMap({required this.heatMapData, super.key});
|
|
final Map<DateTime, int> heatMapData;
|
|
|
|
static const _cellSize = 16.0;
|
|
static const _totalWeeks = 53;
|
|
|
|
int get _maxValue => heatMapData.isNotEmpty
|
|
? heatMapData.keys.map((key) => heatMapData[key] ?? 0).reduce(math.max)
|
|
: 0;
|
|
|
|
DateTime _getStartingDate() {
|
|
final jan1 = DateTime.utc(DateTime.now().year, 1, 1);
|
|
final startOfWeek = jan1.subtract(Duration(days: jan1.weekday - 1));
|
|
return startOfWeek;
|
|
}
|
|
|
|
List<OccupancyPaintItem> _generatePaintItems(DateTime startDate) {
|
|
return List.generate(_totalWeeks * 7, (index) {
|
|
final date = startDate.add(Duration(days: index));
|
|
final value = heatMapData[date] ?? 0;
|
|
return OccupancyPaintItem(index: index, value: value, date: date);
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final startDate = _getStartingDate();
|
|
final paintItems = _generatePaintItems(startDate);
|
|
|
|
return Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
OccupancyHeatMapMonths(startDate: startDate, cellSize: _cellSize),
|
|
Container(
|
|
decoration: const BoxDecoration(
|
|
border: Border(
|
|
bottom: BorderSide(color: ColorsManager.grayBorder),
|
|
top: BorderSide(color: ColorsManager.grayBorder),
|
|
),
|
|
),
|
|
width: double.infinity,
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
child: FittedBox(
|
|
fit: BoxFit.fill,
|
|
child: Row(
|
|
children: [
|
|
const OccupancyHeatMapDays(cellSize: _cellSize),
|
|
SizedBox(
|
|
width: _totalWeeks * _cellSize,
|
|
height: 7 * _cellSize,
|
|
child: InteractiveHeatMap(
|
|
items: paintItems,
|
|
maxValue: _maxValue,
|
|
cellSize: _cellSize,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
OccupancyHeatMapGradient(maxValue: _maxValue),
|
|
],
|
|
);
|
|
}
|
|
}
|