diff --git a/agrilink_vocpro/assets/images/coming_soon.png b/agrilink_vocpro/assets/images/coming_soon.png new file mode 100644 index 0000000..f129771 Binary files /dev/null and b/agrilink_vocpro/assets/images/coming_soon.png differ diff --git a/agrilink_vocpro/lib/features/control/view/control_screen.dart b/agrilink_vocpro/lib/features/control/view/control_screen.dart index 87e63ec..f1aa872 100644 --- a/agrilink_vocpro/lib/features/control/view/control_screen.dart +++ b/agrilink_vocpro/lib/features/control/view/control_screen.dart @@ -1,7 +1,7 @@ -import 'package:agrilink_vocpro/core/constant/app_color.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/features/control/provider/control_provider.dart'; +import 'package:agrilink_vocpro/features/control/widgets/control_button_widget.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -22,11 +22,43 @@ class ControlScreen extends StatelessWidget { scrolledUnderElevation: 0, ), body: RefreshIndicator( + displacement: 10, onRefresh: () async => await context.read().getRelayStatus(), child: SafeArea( child: ListView( children: [ + Consumer(builder: (context, provider, child) { + switch (provider.relayState) { + case ResultState.loading: + return const StatusBarWidget( + text: 'Memuat...', + icon: BootstrapIcons.cloud, + color: Colors.cyan, + isLoading: true, + ); + case ResultState.hasData: + return const StatusBarWidget( + text: 'Berhasil terhubung', + icon: BootstrapIcons.check_circle, + color: Colors.teal, + ); + case ResultState.noData: + return const StatusBarWidget( + text: 'Data tidak ditemukan', + icon: BootstrapIcons.exclamation_circle, + color: Colors.amber, + ); + case ResultState.initial: + return const SizedBox.shrink(); + case ResultState.error: + return const StatusBarWidget( + text: 'Tidak dapat terhubung', + icon: BootstrapIcons.exclamation_circle, + color: Colors.red, + ); + } + }), SizedBox(height: 16.h), GridView( padding: EdgeInsets.all(16.r), @@ -43,7 +75,11 @@ class ControlScreen extends StatelessWidget { title: 'Katup Air', subtitle: 'Relay 1', isActive: provider.control_1, - onTap: () {}, + onTap: () { + provider.control_1 != true + ? provider.switchControl1(true) + : provider.switchControl1(false); + }, ), ControlButtonWidget( title: 'Lampu Utama', @@ -60,74 +96,46 @@ class ControlScreen extends StatelessWidget { } } -class ControlButtonWidget extends StatelessWidget { - const ControlButtonWidget({ +class StatusBarWidget extends StatelessWidget { + const StatusBarWidget({ super.key, - required this.title, - required this.subtitle, - required this.isActive, - required this.onTap, + required this.text, + required this.icon, + required this.color, + this.isLoading = false, }); - final String title; - final String subtitle; - final bool isActive; - final Function() onTap; - + final String text; + final IconData icon; + final Color color; + final bool isLoading; @override Widget build(BuildContext context) { return Container( - padding: EdgeInsets.all(16.r), + padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 16.w), + margin: EdgeInsets.all(16.r), decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16.r), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.2), - spreadRadius: 1.r, - blurRadius: 16.r, - offset: Offset(0, 12.r), - ), - ], + color: color.withAlpha(50), + borderRadius: BorderRadius.circular(8.r), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text(title, style: AppTheme.labelMedium), - Text(subtitle, style: AppTheme.labelSmall), + Icon( + icon, + color: color, + size: 16.r, + ), + SizedBox(width: 8.w), + Text(text, style: AppTheme.titleSmall.copyWith(color: color)), const Spacer(), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Consumer( - builder: (context, provider, child) { - switch (provider.relayState) { - case ResultState.loading: - return CircleAvatar( - radius: 20.r, - backgroundColor: Colors.transparent, - child: const CupertinoActivityIndicator(), - ); - default: - return InkWell( - highlightColor: Colors.black, - onTap: onTap, - child: CircleAvatar( - radius: 20.r, - backgroundColor: isActive - ? AppColor.secondary - : Colors.grey.shade400, - child: const Icon( - BootstrapIcons.power, - color: Colors.white, - ), - ), - ); - } - }, - ), - ], - ) + if (isLoading) + Center( + child: CupertinoActivityIndicator( + radius: 8.r, + )) + else + const SizedBox.shrink(), ], ), ); diff --git a/agrilink_vocpro/lib/features/control/widgets/control_button_widget.dart b/agrilink_vocpro/lib/features/control/widgets/control_button_widget.dart new file mode 100644 index 0000000..0857526 --- /dev/null +++ b/agrilink_vocpro/lib/features/control/widgets/control_button_widget.dart @@ -0,0 +1,85 @@ +import 'package:agrilink_vocpro/core/constant/app_color.dart'; +import 'package:agrilink_vocpro/core/constant/app_theme.dart'; +import 'package:agrilink_vocpro/core/state/result_state.dart'; +import 'package:agrilink_vocpro/features/control/provider/control_provider.dart'; +import 'package:bootstrap_icons/bootstrap_icons.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:provider/provider.dart'; + +class ControlButtonWidget extends StatelessWidget { + const ControlButtonWidget({ + super.key, + required this.title, + required this.subtitle, + required this.isActive, + required this.onTap, + }); + + final String title; + final String subtitle; + final bool isActive; + final Function() onTap; + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(16.r), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16.r), + boxShadow: [ + BoxShadow( + color: isActive + ? AppColor.secondary.withOpacity(0.2) + : Colors.grey.withOpacity(0.2), + spreadRadius: 1.r, + blurRadius: 16.r, + offset: Offset(0, 12.r), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, style: AppTheme.labelMedium), + Text(subtitle, style: AppTheme.labelSmall), + const Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Consumer( + builder: (context, provider, child) { + switch (provider.relayState) { + case ResultState.loading: + return CircleAvatar( + radius: 20.r, + backgroundColor: Colors.transparent, + child: const CupertinoActivityIndicator(), + ); + default: + return InkWell( + highlightColor: Colors.black, + onTap: onTap, + child: CircleAvatar( + radius: 20.r, + backgroundColor: isActive + ? AppColor.secondary + : Colors.grey.shade400, + child: const Icon( + BootstrapIcons.power, + color: Colors.white, + ), + ), + ); + } + }, + ), + ], + ) + ], + ), + ); + } +} diff --git a/agrilink_vocpro/lib/features/plants/view/plants_screen.dart b/agrilink_vocpro/lib/features/plants/view/plants_screen.dart index ec4a78f..1a5d423 100644 --- a/agrilink_vocpro/lib/features/plants/view/plants_screen.dart +++ b/agrilink_vocpro/lib/features/plants/view/plants_screen.dart @@ -1,5 +1,7 @@ +import 'package:agrilink_vocpro/core/constant/app_color.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; class PlantsScreen extends StatelessWidget { const PlantsScreen({super.key}); @@ -9,7 +11,19 @@ class PlantsScreen extends StatelessWidget { return Scaffold( body: SafeArea( child: Center( - child: Text('Coming Soon', style: AppTheme.labelMedium), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.eco_rounded, size: 100.r, color: AppColor.secondary), + Text('Coming Soon', style: AppTheme.titleLarge), + SizedBox(height: 8.h), + Text( + 'This featureis under development', + textAlign: TextAlign.center, + style: AppTheme.labelSmall, + ), + ], + ), )), ); }