diff --git a/agrilink_vocpro/lib/core/constant/app_color.dart b/agrilink_vocpro/lib/core/constant/app_color.dart index 3bd1d45..b861d27 100644 --- a/agrilink_vocpro/lib/core/constant/app_color.dart +++ b/agrilink_vocpro/lib/core/constant/app_color.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; class AppColor { + static const Color backgroundColor = Color(0xFFF7F8F8); static const Color primary = Color(0xFF227267); static const Color darkGreen = Color(0xFF16423C); static const Color secondary = Color(0xFF399C8F); diff --git a/agrilink_vocpro/lib/domain/provider/censor_provider.dart b/agrilink_vocpro/lib/domain/provider/censor_provider.dart new file mode 100644 index 0000000..e69de29 diff --git a/agrilink_vocpro/lib/domain/service/service.dart b/agrilink_vocpro/lib/domain/service/service.dart new file mode 100644 index 0000000..e69de29 diff --git a/agrilink_vocpro/lib/features/control/view/control_screen.dart b/agrilink_vocpro/lib/features/control/view/control_screen.dart index a049203..98f4802 100644 --- a/agrilink_vocpro/lib/features/control/view/control_screen.dart +++ b/agrilink_vocpro/lib/features/control/view/control_screen.dart @@ -1,6 +1,8 @@ import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/features/control/provider/control_provider.dart'; +import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:provider/provider.dart'; class ControlScreen extends StatelessWidget { @@ -20,7 +22,7 @@ class ControlScreen extends StatelessWidget { child: ListView( children: [ ListTile( - title: const Text('Control 1'), + title: Text('Control 1', style: AppTheme.labelMedium), subtitle: const Text('Control 1 description'), trailing: Switch( value: provider.control_1, diff --git a/agrilink_vocpro/lib/features/dashboard/provider/dashboard_provider.dart b/agrilink_vocpro/lib/features/dashboard/provider/dashboard_provider.dart index 8509b6b..8c4eec4 100644 --- a/agrilink_vocpro/lib/features/dashboard/provider/dashboard_provider.dart +++ b/agrilink_vocpro/lib/features/dashboard/provider/dashboard_provider.dart @@ -1,6 +1,7 @@ import 'package:agrilink_vocpro/features/control/view/control_screen.dart'; import 'package:agrilink_vocpro/features/home/view/home_screen.dart'; import 'package:agrilink_vocpro/features/plants/view/plants_screen.dart'; +import 'package:agrilink_vocpro/features/setting/view/setting_screen.dart'; import 'package:flutter/material.dart'; class DashboardProvider extends ChangeNotifier { @@ -18,7 +19,7 @@ class DashboardProvider extends ChangeNotifier { const HomeScreen(), const ControlScreen(), const PlantsScreen(), - const Center(child: Text('Settings')), + const SettingScreen(), ]; List get screens => _screens; diff --git a/agrilink_vocpro/lib/features/home/pages/humidity/view/humidity_screen.dart b/agrilink_vocpro/lib/features/home/pages/humidity/view/humidity_screen.dart index f6d0151..e29157a 100644 --- a/agrilink_vocpro/lib/features/home/pages/humidity/view/humidity_screen.dart +++ b/agrilink_vocpro/lib/features/home/pages/humidity/view/humidity_screen.dart @@ -1,6 +1,7 @@ import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/features/home/pages/humidity/widgets/circle_chart.dart'; import 'package:agrilink_vocpro/features/home/provider/home_provider.dart'; +import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -66,9 +67,25 @@ class HumidityScreen extends StatelessWidget { const SizedBox(height: 16), Padding( padding: EdgeInsets.only(left: 16.w), - child: const Text('Deskripsi'), + child: const Text('Grafik dalam 7 hari terakhir'), ), const SizedBox(height: 16), + AspectRatio( + aspectRatio: 2.h, + child: Container( + margin: EdgeInsets.symmetric(horizontal: 16.w), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16.w), + border: Border.all( + color: Colors.grey.shade300, width: 1.w)), + child: const GarphicWidget()), + ), + SizedBox(height: 16.h), + Padding( + padding: EdgeInsets.only(left: 16.w), + child: const Text('Deskripsi'), + ), ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), @@ -90,10 +107,10 @@ class HumidityScreen extends StatelessWidget { children: [ Text( item.description, - style: AppTheme.hintStyle, + style: AppTheme.labelMedium, ), SizedBox(height: 8.h), - Text('Tindakan', style: AppTheme.labelMedium), + Text('Tindakan', style: AppTheme.labelSmall), SizedBox(height: 8.h), Text(item.action), ], diff --git a/agrilink_vocpro/lib/features/home/pages/light/view/light_screen.dart b/agrilink_vocpro/lib/features/home/pages/light/view/light_screen.dart index 5d811b0..4e5facb 100644 --- a/agrilink_vocpro/lib/features/home/pages/light/view/light_screen.dart +++ b/agrilink_vocpro/lib/features/home/pages/light/view/light_screen.dart @@ -1,4 +1,5 @@ import 'package:agrilink_vocpro/core/constant/app_theme.dart'; +import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -41,20 +42,12 @@ class LightScreen extends StatelessWidget { child: Stack( fit: StackFit.expand, children: [ - Center( + const Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ - const Icon(BootstrapIcons.sun, + Icon(BootstrapIcons.sun, size: 32, color: Colors.orange), - Text( - '${value.toStringAsFixed(0)} lux', // Animated percentage text - style: const TextStyle( - fontSize: 28, - fontWeight: FontWeight.bold, - color: Colors.black, - ), - ), ], ), ), @@ -65,10 +58,10 @@ class LightScreen extends StatelessWidget { axis: GaugeAxis( degrees: 360, min: 0, - max: 5000, + max: 1000, style: GaugeAxisStyle( background: Colors.grey.shade100, - thickness: 50, + thickness: 100, ), progressBar: GaugeBasicProgressBar( gradient: GaugeAxisGradient(colors: [ @@ -82,6 +75,15 @@ class LightScreen extends StatelessWidget { ), ), const SizedBox(height: 16), + Text( + '${value.toStringAsFixed(0)} lux', + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.center, @@ -99,8 +101,18 @@ class LightScreen extends StatelessWidget { ], ), SizedBox(height: 16.h), - const Text('Deskripsi'), + const Text('Grafik'), SizedBox(height: 16.h), + AspectRatio( + aspectRatio: 1.5.h, + child: Container( + decoration: BoxDecoration( + border: Border.all(color: Colors.grey.shade300, width: 1.w), + borderRadius: BorderRadius.circular(16.w), + ), + child: const GarphicWidget(), + ), + ) // Row( // mainAxisAlignment: MainAxisAlignment.spaceAround, // children: [ diff --git a/agrilink_vocpro/lib/features/home/pages/temperature/view/temperature_screen.dart b/agrilink_vocpro/lib/features/home/pages/temperature/view/temperature_screen.dart index 149374c..aa02b8d 100644 --- a/agrilink_vocpro/lib/features/home/pages/temperature/view/temperature_screen.dart +++ b/agrilink_vocpro/lib/features/home/pages/temperature/view/temperature_screen.dart @@ -1,4 +1,5 @@ import 'package:agrilink_vocpro/core/constant/app_theme.dart'; +import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -100,8 +101,6 @@ class TemperatureScreen extends StatelessWidget { ], ), SizedBox(height: 16.h), - const Text('Deskripsi'), - SizedBox(height: 16.h), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ @@ -199,6 +198,20 @@ class TemperatureScreen extends StatelessWidget { ), ), ], + ), + SizedBox(height: 16.h), + const Text('Grafik'), + SizedBox(height: 16.h), + AspectRatio( + aspectRatio: 1.6.h, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16.w), + border: Border.all(color: Colors.grey.shade300, width: 1.w), + ), + child: const GarphicWidget(), + ), ) ], ), diff --git a/agrilink_vocpro/lib/features/home/view/home_screen.dart b/agrilink_vocpro/lib/features/home/view/home_screen.dart index 1f746a1..ff42e8e 100644 --- a/agrilink_vocpro/lib/features/home/view/home_screen.dart +++ b/agrilink_vocpro/lib/features/home/view/home_screen.dart @@ -23,7 +23,7 @@ class _HomeScreenState extends State { appBar: AppBar( toolbarHeight: 200.h, elevation: 0, - backgroundColor: Colors.white, + backgroundColor: AppColor.backgroundColor, scrolledUnderElevation: 0, flexibleSpace: Padding( padding: EdgeInsets.symmetric(horizontal: 12.w), diff --git a/agrilink_vocpro/lib/features/home/widgets/graphic_widget.dart b/agrilink_vocpro/lib/features/home/widgets/graphic_widget.dart new file mode 100644 index 0000000..40630d2 --- /dev/null +++ b/agrilink_vocpro/lib/features/home/widgets/graphic_widget.dart @@ -0,0 +1,191 @@ +import 'package:agrilink_vocpro/core/constant/app_color.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; + +class GarphicWidget extends StatelessWidget { + const GarphicWidget({super.key, thi}); + + @override + Widget build(BuildContext context) { + return BarChart( + BarChartData( + barTouchData: barTouchData, + titlesData: titlesData, + borderData: borderData, + barGroups: barGroups, + gridData: const FlGridData(show: false), + alignment: BarChartAlignment.spaceAround, + maxY: 20, + ), + ); + } +} + +BarTouchData get barTouchData => BarTouchData( + enabled: false, + touchTooltipData: BarTouchTooltipData( + getTooltipColor: (group) => Colors.transparent, + tooltipPadding: EdgeInsets.zero, + tooltipMargin: 8, + getTooltipItem: ( + BarChartGroupData group, + int groupIndex, + BarChartRodData rod, + int rodIndex, + ) { + return BarTooltipItem( + rod.toY.round().toString(), + const TextStyle( + color: AppColor.textDark, + fontWeight: FontWeight.bold, + ), + ); + }, + ), + ); + +Widget getTitles(double value, TitleMeta meta) { + const style = TextStyle( + color: AppColor.textDark, + fontWeight: FontWeight.bold, + fontSize: 14, + ); + String text; + switch (value.toInt()) { + case 0: + text = 'Mon'; + break; + case 1: + text = 'Tue'; + break; + case 2: + text = 'Wed'; + break; + case 3: + text = 'Thu'; + break; + case 4: + text = 'Fri'; + break; + case 5: + text = 'Sat'; + break; + case 6: + text = 'Sun'; + break; + default: + text = ''; + break; + } + return SideTitleWidget( + axisSide: meta.axisSide, + space: 4, + child: Text(text, style: style), + ); +} + +FlTitlesData get titlesData => const FlTitlesData( + show: true, + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 30, + getTitlesWidget: getTitles, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + topTitles: AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + rightTitles: AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + ); + +FlBorderData get borderData => FlBorderData( + show: false, + ); + +LinearGradient get _barsGradient => const LinearGradient( + colors: [ + AppColor.secondary, + AppColor.ternary, + ], + begin: Alignment.bottomCenter, + end: Alignment.topCenter, + ); + +List get barGroups => [ + BarChartGroupData( + x: 0, + barRods: [ + BarChartRodData( + toY: 8, + gradient: _barsGradient, + ) + ], + showingTooltipIndicators: [0], + ), + BarChartGroupData( + x: 1, + barRods: [ + BarChartRodData( + toY: 10, + gradient: _barsGradient, + ) + ], + showingTooltipIndicators: [0], + ), + BarChartGroupData( + x: 2, + barRods: [ + BarChartRodData( + toY: 14, + gradient: _barsGradient, + ) + ], + showingTooltipIndicators: [0], + ), + BarChartGroupData( + x: 3, + barRods: [ + BarChartRodData( + toY: 15, + gradient: _barsGradient, + ) + ], + showingTooltipIndicators: [0], + ), + BarChartGroupData( + x: 4, + barRods: [ + BarChartRodData( + toY: 13, + gradient: _barsGradient, + ) + ], + showingTooltipIndicators: [0], + ), + BarChartGroupData( + x: 5, + barRods: [ + BarChartRodData( + toY: 10, + gradient: _barsGradient, + ) + ], + showingTooltipIndicators: [0], + ), + BarChartGroupData( + x: 6, + barRods: [ + BarChartRodData( + toY: 16, + gradient: _barsGradient, + ) + ], + showingTooltipIndicators: [0], + ), + ]; diff --git a/agrilink_vocpro/lib/features/setting/view/setting_screen.dart b/agrilink_vocpro/lib/features/setting/view/setting_screen.dart new file mode 100644 index 0000000..94eea81 --- /dev/null +++ b/agrilink_vocpro/lib/features/setting/view/setting_screen.dart @@ -0,0 +1,152 @@ +import 'dart:io'; + +import 'package:agrilink_vocpro/core/constant/app_color.dart'; +import 'package:agrilink_vocpro/core/constant/app_theme.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'; + +class SettingScreen extends StatelessWidget { + const SettingScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Setting', style: AppTheme.labelMedium), + centerTitle: true, + backgroundColor: Colors.white, + scrolledUnderElevation: 0, + ), + body: SafeArea( + child: ListView( + padding: EdgeInsets.all(16.r), + children: [ + Row( + children: [ + const CircleAvatar( + radius: 30, + backgroundColor: AppColor.secondary, + child: Icon(BootstrapIcons.person_fill, color: Colors.white), + ), + SizedBox(width: 8.w), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('User Name', style: AppTheme.labelMedium), + Text('useremail@gmail.com', style: AppTheme.labelSmall) + ], + ) + ], + ), + SizedBox(height: 16.h), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8.r), + ), + child: Column( + children: [ + ListTile( + tileColor: Colors.white, + title: Text('Account', + style: + AppTheme.labelSmall.copyWith(color: Colors.black87)), + leading: const Icon(BootstrapIcons.person), + trailing: Icon( + Icons.arrow_forward_ios, + size: 16.r, + ), + onTap: () {}, + ), + ListTile( + tileColor: Colors.white, + title: Text('Kebijakan & privasi', + style: + AppTheme.labelSmall.copyWith(color: Colors.black87)), + leading: const Icon(BootstrapIcons.shield_check), + trailing: Icon( + Icons.arrow_forward_ios, + size: 16.r, + ), + onTap: () {}, + ), + ListTile( + tileColor: Colors.white, + title: Text('Syarat & ketentuan', + style: + AppTheme.labelSmall.copyWith(color: Colors.black87)), + leading: const Icon(BootstrapIcons.file_text), + trailing: Icon( + Icons.arrow_forward_ios, + size: 16.r, + ), + onTap: () {}, + ), + ListTile( + tileColor: Colors.white, + title: Text('Logout', + style: AppTheme.labelSmall.copyWith(color: Colors.red)), + leading: const Icon( + BootstrapIcons.box_arrow_right, + color: Colors.red, + ), + trailing: Icon( + Icons.arrow_forward_ios, + size: 16.r, + ), + onTap: () { + if (Platform.isAndroid) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Logout'), + content: Text('Apakah anda yakin ingin logout?'), + actions: [ + TextButton( + child: Text('Batal'), + onPressed: () { + Navigator.pop(context); + }, + ), + TextButton( + child: Text('Ya'), + onPressed: () { + Navigator.pop(context); + }, + ), + ], + ), + ); + } else { + showDialog( + context: context, + builder: (context) => CupertinoAlertDialog( + title: Text('Logout'), + content: Text('Apakah anda yakin ingin logout?'), + actions: [ + TextButton( + child: Text('Batal'), + onPressed: () { + Navigator.pop(context); + }, + ), + TextButton( + child: Text('Ya'), + onPressed: () { + Navigator.pop(context); + }, + ), + ], + ), + ); + } + }), + ], + ), + ), + ], + )), + ); + } +} diff --git a/agrilink_vocpro/lib/main.dart b/agrilink_vocpro/lib/main.dart index 7d7f3c3..469a3b3 100644 --- a/agrilink_vocpro/lib/main.dart +++ b/agrilink_vocpro/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:agrilink_vocpro/core/constant/app_color.dart'; import 'package:agrilink_vocpro/core/route/app_route.dart'; import 'package:agrilink_vocpro/features/auth/provider/auth_provider.dart'; import 'package:agrilink_vocpro/features/control/provider/control_provider.dart';