This commit is contained in:
kleponijo 2026-05-02 14:22:34 +07:00
parent d19c5fcaf8
commit 47fc79455b
4 changed files with 34 additions and 15 deletions

View File

@ -104,7 +104,7 @@ class SensorCard extends StatelessWidget {
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Colors.black.withValues(alpha: 0.05),
blurRadius: 8, blurRadius: 8,
offset: const Offset(0, 2), offset: const Offset(0, 2),
), ),

View File

@ -50,15 +50,8 @@ class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
(json) => MyWindSpeed.fromJson(json), (json) => MyWindSpeed.fromJson(json),
); );
/// 2. Mapping default (harian) // Ini saja yang benar
final raw = TimeSeriesMapper.toDaily( final dailyGraph = TimeSeriesMapper.smooth(
data: history,
getTime: (e) => e.timestamp,
getValue: (e) => e.speed,
);
final dailyGraph = TimeSeriesMapper.smooth(raw);
final daily = TimeSeriesMapper.smooth(
TimeSeriesMapper.toDaily( TimeSeriesMapper.toDaily(
data: history, data: history,
getTime: (e) => e.timestamp, getTime: (e) => e.timestamp,
@ -93,6 +86,9 @@ class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
weeklySpeeds: weekly, weeklySpeeds: weekly,
monthlySpeeds: monthly, monthlySpeeds: monthly,
isLoading: false, isLoading: false,
alertLevel: history.isNotEmpty // tambah ini
? _getAlertLevel(history.last.speed)
: "Normal",
)); ));
/// 3. Start realtime stream (manual subscription) /// 3. Start realtime stream (manual subscription)
@ -138,6 +134,7 @@ class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
emit(state.copyWith( emit(state.copyWith(
currentSpeed: newValue, currentSpeed: newValue,
dailySpeeds: updated, dailySpeeds: updated,
alertLevel: _getAlertLevel(newValue),
)); ));
} }
@ -194,6 +191,12 @@ class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
return super.close(); return super.close();
} }
String _getAlertLevel(double speed) {
if (speed >= _kWindDanger) return "Bahaya";
if (speed >= _kWindWarning) return "Waspada";
return "Normal";
}
// ========================= // =========================
// HELPER: kirim alert ke NotificationBloc // HELPER: kirim alert ke NotificationBloc
// ========================= // =========================

View File

@ -8,6 +8,7 @@ class WindSpeedState extends Equatable {
final List<double> monthlySpeeds; final List<double> monthlySpeeds;
final bool isLoading; final bool isLoading;
final List<MyWindSpeed> history; final List<MyWindSpeed> history;
final String alertLevel; // "Normal" | "Waspada" | "Bahaya"
const WindSpeedState({ const WindSpeedState({
this.currentSpeed = 0.0, this.currentSpeed = 0.0,
@ -17,6 +18,7 @@ class WindSpeedState extends Equatable {
this.history = const [], this.history = const [],
this.monthlySpeeds = const [], this.monthlySpeeds = const [],
this.weeklySpeeds = const [], this.weeklySpeeds = const [],
this.alertLevel = "Normal",
}); });
WindSpeedState copyWith({ WindSpeedState copyWith({
@ -27,6 +29,7 @@ class WindSpeedState extends Equatable {
List<double>? monthlySpeeds, List<double>? monthlySpeeds,
bool? isLoading, bool? isLoading,
List<MyWindSpeed>? history, List<MyWindSpeed>? history,
String? alertLevel,
}) { }) {
return WindSpeedState( return WindSpeedState(
currentSpeed: currentSpeed ?? this.currentSpeed, currentSpeed: currentSpeed ?? this.currentSpeed,
@ -36,10 +39,18 @@ class WindSpeedState extends Equatable {
monthlySpeeds: monthlySpeeds ?? this.monthlySpeeds, monthlySpeeds: monthlySpeeds ?? this.monthlySpeeds,
isLoading: isLoading ?? this.isLoading, isLoading: isLoading ?? this.isLoading,
history: history ?? this.history, history: history ?? this.history,
alertLevel: alertLevel ?? this.alertLevel,
); );
} }
@override @override
List<Object> get props => List<Object> get props => [
[currentSpeed, selectedPeriod, dailySpeeds, isLoading, history]; currentSpeed,
selectedPeriod,
dailySpeeds,
weeklySpeeds,
monthlySpeeds,
isLoading,
history
];
} }

View File

@ -85,7 +85,7 @@ class WindSpeedScreen extends StatelessWidget {
const SizedBox(height: 30), const SizedBox(height: 30),
// 3. Info Tambahan (Status/Periode) // 3. Info Tambahan (Status/Periode)
_buildDetailRow(state.selectedPeriod), _buildDetailRow(state.selectedPeriod, state.alertLevel),
const SizedBox(height: 24), const SizedBox(height: 24),
// Tombol Export PDF // Tombol Export PDF
@ -143,11 +143,16 @@ class WindSpeedScreen extends StatelessWidget {
); );
} }
Widget _buildDetailRow(String period) { Widget _buildDetailRow(String period, String alertLevel) {
final (icon, color) = switch (alertLevel) {
"Bahaya" => (Icons.warning_rounded, Colors.red),
"Waspada" => (Icons.info_outline, Colors.orange),
_ => (Icons.check_circle, Colors.green),
};
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
_miniInfoCard("Status", "Normal", Icons.check_circle, Colors.green), _miniInfoCard("Status", alertLevel, icon, color),
_miniInfoCard("Periode", period, Icons.timer, Colors.orange), _miniInfoCard("Periode", period, Icons.timer, Colors.orange),
], ],
); );