Files
syncrow-web/lib/pages/analytics/modules/occupancy/widgets/occupancy_heat_map.dart
2025-05-14 12:05:34 +03:00

84 lines
2.9 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(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),
],
);
}
}