187 lines
6.2 KiB
Dart
187 lines
6.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '../../../core/app_theme.dart';
|
|
import '../../../models/monitoring_status.dart';
|
|
|
|
class MonitoringCard extends StatelessWidget {
|
|
final String value;
|
|
final String? unit;
|
|
final String subtitle;
|
|
final MonitoringStatus status;
|
|
final Gradient gradient;
|
|
|
|
const MonitoringCard({
|
|
super.key,
|
|
required this.value,
|
|
this.unit,
|
|
required this.subtitle,
|
|
required this.status,
|
|
required this.gradient,
|
|
});
|
|
|
|
Color get _statusColor {
|
|
switch (status) {
|
|
case MonitoringStatus.danger: return AppTheme.statusDanger;
|
|
case MonitoringStatus.warning: return AppTheme.statusWarning;
|
|
case MonitoringStatus.normal: return AppTheme.statusNormal;
|
|
}
|
|
}
|
|
|
|
String get _statusText {
|
|
switch (status) {
|
|
case MonitoringStatus.danger: return 'BAHAYA';
|
|
case MonitoringStatus.warning: return 'PERINGATAN';
|
|
case MonitoringStatus.normal: return 'NORMAL';
|
|
}
|
|
}
|
|
|
|
IconData get _bgIcon {
|
|
final sub = subtitle.toLowerCase();
|
|
if (sub.contains('suhu')) {
|
|
return Icons.thermostat;
|
|
} else if (sub.contains('debit') || sub.contains('alir')) {
|
|
return Icons.waves;
|
|
} else if (sub.contains('volume') || sub.contains('total')) {
|
|
return Icons.opacity;
|
|
} else {
|
|
return Icons.water_drop;
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
height: 160,
|
|
decoration: BoxDecoration(
|
|
gradient: gradient,
|
|
borderRadius: BorderRadius.circular(20),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.15),
|
|
blurRadius: 12,
|
|
offset: const Offset(0, 6),
|
|
),
|
|
],
|
|
),
|
|
child: ClipRRect(
|
|
borderRadius: BorderRadius.circular(20),
|
|
child: Stack(
|
|
children: [
|
|
// Background Watermark Icon
|
|
Positioned(
|
|
right: -15,
|
|
bottom: -15,
|
|
child: Icon(
|
|
_bgIcon,
|
|
size: 130,
|
|
color: Colors.white.withValues(alpha: 0.12),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisSize: MainAxisSize.max,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Ikon di kiri atas agar tidak kosong
|
|
Container(
|
|
padding: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white.withValues(alpha: 0.2),
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Icon(
|
|
_bgIcon,
|
|
color: Colors.white,
|
|
size: 20,
|
|
),
|
|
),
|
|
// Badge Status di kanan atas
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(12),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withValues(alpha: 0.1),
|
|
blurRadius: 4,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(
|
|
status == MonitoringStatus.normal
|
|
? Icons.check_circle_rounded
|
|
: Icons.warning_rounded,
|
|
size: 12,
|
|
color: _statusColor,
|
|
),
|
|
const SizedBox(width: 4),
|
|
Text(
|
|
_statusText,
|
|
style: TextStyle(
|
|
color: _statusColor,
|
|
fontSize: 10,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const Spacer(),
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
value,
|
|
style: const TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 34,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
if (unit != null)
|
|
Padding(
|
|
padding: const EdgeInsets.only(top: 8, left: 4),
|
|
child: Text(
|
|
unit!,
|
|
style: const TextStyle(
|
|
color: Colors.white70,
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w500),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const Spacer(),
|
|
SizedBox(
|
|
height: 34,
|
|
child: Align(
|
|
alignment: Alignment.bottomLeft,
|
|
child: Text(
|
|
subtitle,
|
|
maxLines: 2,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: const TextStyle(color: Colors.white70, fontSize: 12),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|