TKK_E32230206/lib/features/iot/widgets/operation_mode_card.dart

176 lines
5.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../core/app_theme.dart';
import '../providers/control_notifier.dart';
import '../providers/control_state.dart';
class OperationModeCard extends ConsumerWidget {
const OperationModeCard({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final control = ref.watch(controlProvider);
final mode = control.deviceMode;
final isLoading = control.isModeLoading;
return Container(
padding: const EdgeInsets.all(20),
decoration: AppTheme.cardDecoration(radius: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: AppTheme.primary.withValues(alpha: 0.12),
borderRadius: BorderRadius.circular(10),
),
child: Icon(Icons.tune_rounded, color: AppTheme.primary, size: 20),
),
const SizedBox(width: 12),
const Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Mode Operasi',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: AppTheme.textPrimary,
),
),
Text(
'Tentukan bagaimana perangkat bekerja',
style: TextStyle(fontSize: 12, color: AppTheme.textSecondary),
),
],
),
),
if (isLoading)
const SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(strokeWidth: 2),
),
],
),
const SizedBox(height: 16),
_ModeOptions(currentMode: mode, isLoading: isLoading),
],
),
);
}
}
class _ModeOptions extends ConsumerWidget {
final DeviceMode currentMode;
final bool isLoading;
const _ModeOptions({required this.currentMode, required this.isLoading});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Row(
children: DeviceMode.values.where((m) => m != DeviceMode.offline).map((mode) {
final isSelected = currentMode == mode;
return Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: _ModeTile(
mode: mode,
isSelected: isSelected,
isLoading: isLoading,
onTap: () => ref.read(controlProvider.notifier).setDeviceMode(mode),
),
),
);
}).toList(),
);
}
}
class _ModeTile extends StatelessWidget {
final DeviceMode mode;
final bool isSelected;
final bool isLoading;
final VoidCallback onTap;
const _ModeTile({
required this.mode,
required this.isSelected,
required this.isLoading,
required this.onTap,
});
(IconData, Color, Color, String) get _modeStyle {
switch (mode) {
case DeviceMode.auto_:
return (Icons.auto_mode_rounded, const Color(0xFF10B981), const Color(0xFFD1FAE5), 'Otomatis');
case DeviceMode.manual:
return (Icons.pan_tool_alt_rounded, const Color(0xFF3B82F6), const Color(0xFFDBEAFE), 'Manual');
case DeviceMode.offline:
return (Icons.wifi_off_rounded, const Color(0xFFF59E0B), const Color(0xFFFEF3C7), 'Offline');
}
}
@override
Widget build(BuildContext context) {
final (icon, activeColor, bgColor, label) = _modeStyle;
return AnimatedContainer(
duration: const Duration(milliseconds: 250),
curve: Curves.easeOutCubic,
decoration: BoxDecoration(
color: isSelected ? activeColor : Colors.grey.shade100,
borderRadius: BorderRadius.circular(14),
border: Border.all(
color: isSelected ? activeColor : Colors.grey.shade200,
width: isSelected ? 0 : 1,
),
boxShadow: isSelected
? [BoxShadow(color: activeColor.withValues(alpha: 0.35), blurRadius: 10, offset: const Offset(0, 4))]
: [],
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: isLoading ? null : onTap,
borderRadius: BorderRadius.circular(14),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
AnimatedContainer(
duration: const Duration(milliseconds: 250),
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: isSelected ? Colors.white.withValues(alpha: 0.25) : bgColor,
shape: BoxShape.circle,
),
child: Icon(
icon,
size: 20,
color: isSelected ? Colors.white : activeColor,
),
),
const SizedBox(height: 6),
Text(
label,
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w700,
color: isSelected ? Colors.white : AppTheme.textSecondary,
),
),
],
),
),
),
),
);
}
}