Compare commits

..

No commits in common. "9b715a6765b8efaa699c8ee7b0dbb13b72406d7a" and "fa041950c520064763719c50072044b047cbd61a" have entirely different histories.

59 changed files with 598 additions and 916 deletions

View File

@ -1,3 +0,0 @@
{
"java.configuration.updateBuildConfiguration": "interactive"
}

View File

@ -35,11 +35,11 @@ This project uses several packages to support various functionalities. Below is
## Installation Guide ## Installation Guide
1. Clone the repository: 1. Clone the repository:
```bash ```bash
git clone https://gitlab.com/profile-image/kedaireka/smartfarming/mobile-smartfarming.git git clone https://github.com/username/smart-farming.git
``` ```
2. Navigate to the flutter project directory: 2. Navigate to the project directory:
```bash ```bash
cd agrilink_vocpro cd smart-farming
``` ```
3. Install dependencies: 3. Install dependencies:
```bash ```bash
@ -48,22 +48,10 @@ This project uses several packages to support various functionalities. Below is
if it does't work try: if it does't work try:
```bash ```bash
flutter outdated flutter outdated
// follow with //follow with
flutter pub upgrade --major-versions flutter pub upgrade --major-versions
``` ```
or check your latest dart version make sure it compatible with this project or check your latest dart version make sure it compatible with this project
project tool version
```
• Flutter version 3.27.0-1.0.pre.685
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 227f6a04f7, 2024-12-03 13:21:59 +0100
• Engine revision f9d4f744e0
• Dart version 3.7.0 (build 3.7.0-207.0.dev)
• DevTools version 2.41.0
```
4. Run the project: 4. Run the project:
```bash ```bash
flutter run flutter run
@ -75,48 +63,26 @@ Berikan deskripsi singkat tentang struktur folder dan file penting di dalam proy
## Project Structure ## Project Structure
- `lib/`: Contains the Flutter app source code. - `lib/`: Contains the Flutter app source code.
- `core/`: Contains all constant value and data needed for the project. - `core/`: Contains all constant vaalue and data needed for the project.
- `data/`: Contains model and data response - `data/`: Conatains model and data response
- `domain/`: logic and service of the application - `domain/`: logic and service of the application
- `feature/`: Contains every feature in the app - `feature/`: Contains every feature in the app
- `provider/`: Contains a function to integrate with domain layer - `provider/`
- `view` : contains the main screen UI code - `view`
- `widget` : conatins the widget UI code - `widget`
- `pubspec.yaml`: Project dependencies and configurations. - `pubspec.yaml`: Project dependencies and configurations.
## Progress Report ## Progress Report
| Date | Type | Description | | Date | Type | Description |
|------------|-------|------------------------------------------------------------------------------------------------------| |------------|-------|-----------------------------------------------------------------------------------------------------|
| 2024-09-09 | feat | Created basic app structure for Agrilink Vocpro. | | 2024-10-09 | feat | Completed the integration of MQTT for sensor data and IoT device control. |
| 2024-09-10 | feat | Sliced splash screen and login screen. | | 2024-10-02 | fix | Implemented auto-reconnect for MQTT on app open/close. |
| 2024-09-11 | feat | Sliced home page for Agrilink Vocpro. | | 2024-09-30 | feat | Added UI for displaying soil pH level with a linear bar. |
| 2024-09-12 | fix | Revamped home page for Agrilink Vocpro. | | 2024-09-27 | feat | Finalized group display for 'Doses' in ExpansionTile for medicine dosage recommendations. |
| 2024-09-13 | feat | Created and animated graph or flowchart with `fl_chart`. | | 2024-09-24 | feat | Completed sorting dialog functionality with single sorter selection capability. |
| 2024-09-16 | learn | Learned about implementing graphics UI in Flutter. | | 2024-09-20 | feat | Implemented patient data creation form with validation and state management using dialogs. |
| 2024-09-17 | feat | Created bottom nav bar and revamped data display widgets in Agrilink app. |
| 2024-09-18 | feat | Added detail screen for Potassium, Nitrogen, and Phosphorus. |
| 2024-09-19 | feat | Created custom screen for soil pH data. |
| 2024-09-20 | feat | Handled POST requests with dialog. |
| 2024-09-23 | feat | Added basic app routes for Agrilink app. |
| 2024-09-24 | fix | Revamped home page again in Agrilink app. |
| 2024-09-25 | feat | Created detail screen for temperature and light intensity features. |
| 2024-09-26 | feat | Sliced setting screen. |
| 2024-09-27 | feat | Implemented infinite scroll with `infinite_scroll_pagination` package. |
| 2024-10-01 | meet | Conducted progress report with Pak Vipkas. |
| 2024-10-02 | feat | Connected Flutter with MQTT broker using `mqtt_client` dependency. |
| 2024-10-03 | feat | Created request to publish message to MQTT broker. |
| 2024-10-04 | test | Tested subscribe and publish message to real device. |
| 2024-10-07 | feat | Added error and no data screens in Agrilink Vocpro. |
| 2024-10-08 | fix | Revamped graph UI in Agrilink app; integrated relay control with backend. |
| 2024-10-09 | doc | Created project documentation in `README.md` on GitLab. |
| 2024-10-10 | fix | Revamped detail screen for each DHT data sensor. |
| 2024-10-11 | fix | Revamped detail screen for each NPK data sensor. |
| 2024-10-14 | feat | Integrated REST API for fetching current data. |
| 2024-10-15 | feat | Integrated REST API for fetching historical data and displaying it in a graph. |
| 2024-10-16 | feat | Integrated REST API for controlling relay. |
| 2024-11-06 | feat | Tidy up the code |
## Contributing ## Contributing

View File

@ -11,7 +11,7 @@ plugins {
android { android {
namespace = "com.pis.agrilink_vocpro" namespace = "com.pis.agrilink_vocpro"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = "27.0.12077973" ndkVersion = flutter.ndkVersion
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8
@ -33,19 +33,11 @@ android {
versionName = flutter.versionName versionName = flutter.versionName
} }
signingConfigs {
release {
keyAlias 'agrilink-upload'
keyPassword '100403'
storeFile file('D:/Code/real_project/flutter/mobile-smartfarming/upload-keystore.jks')
storePassword '100403'
}
}
buildTypes { buildTypes {
release { release {
signingConfig signingConfigs.release // TODO: Add your own signing config for the release build.
minifyEnabled true // You can set to true for release builds // Signing with the debug keys for now, so `flutter run --release` works.
shrinkResources true // Set to true if minify is true signingConfig = signingConfigs.debug
} }
} }
} }

View File

@ -3,7 +3,7 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application <application
android:label="Agrilink Vocpro" android:label="agrilink_vocpro"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:enableOnBackInvokedCallback="true"> android:enableOnBackInvokedCallback="true">
@ -21,12 +21,12 @@
while the Flutter UI initializes. After that, this theme continues while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. --> to determine the Window background behind the Flutter UI. -->
<meta-data <meta-data
android:name="io.flutter.embedding.android.NormalTheme" android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" android:resource="@style/NormalTheme"
/> />
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
</activity> </activity>
<!-- Don't delete the meta-data below. <!-- Don't delete the meta-data below.
@ -42,8 +42,8 @@
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. --> In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries> <queries>
<intent> <intent>
<action android:name="android.intent.action.PROCESS_TEXT" /> <action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain" /> <data android:mimeType="text/plain"/>
</intent> </intent>
</queries> </queries>
</manifest> </manifest>

View File

@ -18,11 +18,11 @@ pluginManagement {
plugins { plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.7.0" apply false id "com.android.application" version "7.3.0" apply false
// START: FlutterFire Configuration // START: FlutterFire Configuration
id "com.google.gms.google-services" version "4.3.15" apply false id "com.google.gms.google-services" version "4.3.15" apply false
// END: FlutterFire Configuration // END: FlutterFire Configuration
id "org.jetbrains.kotlin.android" version "2.0.20" apply false id "org.jetbrains.kotlin.android" version "1.7.10" apply false
} }
include ":app" include ":app"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -2,33 +2,27 @@ class AppConstant {
static const String appName = 'Kebun Pintar'; static const String appName = 'Kebun Pintar';
static const String appVersion = '1.0.0'; static const String appVersion = '1.0.0';
static const String baseUrl = 'http://192.168.60.108'; static const String baseUrl = 'https://jx027dj4-3333.asse.devtunnels.ms';
static const String mqttServer = 'armadillo.rmq.cloudamqp.com'; static const String mqttServer = 'armadillo.rmq.cloudamqp.com';
static const String mqttUsername = 'obyskxhx:obyskxhx'; static const String mqttUsername = 'obyskxhx:obyskxhx';
static const String mqttPassword = 'Fe_3_tBuwmc8vMMqT2hYiboTsBlBmPz1'; static const String mqttPassword = 'Fe_3_tBuwmc8vMMqT2hYiboTsBlBmPz1';
static const String soilTempInfo = static const String soilTempInfo =
'Suhu tanah mengacu pada suhu tanah di permukaan atau pada kedalaman tertentu, ' 'Suhu tanah mengacu pada suhu tanah di permukaan atau pada kedalaman tertentu, yang berperan penting dalam pertumbuhan tanaman dan proses pertanian. Suhu ini memengaruhi perkecambahan benih, aktivitas akar, serta penyerapan air dan nutrisi, yang semuanya esensial bagi perkembangan tanaman. Selain itu, suhu tanah juga memengaruhi aktivitas mikroorganisme yang berkontribusi pada kesuburan tanah. Dalam pertanian pintar, sensor suhu tanah sering digunakan untuk memantau dan mengoptimalkan kondisi tanah, memastikan tanaman tumbuh dalam rentang suhu yang ideal.';
'yang berperan penting dalam pertumbuhan tanaman dan proses pertanian. '
'Suhu ini memengaruhi perkecambahan benih, aktivitas akar, serta penyerapan air dan nutrisi, '
'yang semuanya esensial bagi perkembangan tanaman. Selain itu, '
'suhu tanah juga memengaruhi aktivitas mikroorganisme yang berkontribusi pada kesuburan tanah. '
'Dalam pertanian pintar, sensor suhu tanah sering digunakan untuk memantau dan mengoptimalkan '
'kondisi tanah, memastikan tanaman tumbuh dalam rentang suhu yang ideal.';
static const String npk1 = 'npk1'; static const String npk1 = 'npk1';
static const String npk2 = 'npk2'; static const String npk2 = 'npk2';
static const String dht = 'dht'; static const String dht = 'dht';
static const String soilTemp = 'soilTemperature'; static const String soilTemp = 'soilTemperature';
static const String soilMoisture = 'soilHumidity'; static const String soilMoisture = 'soilMoisture';
static const String airTemp = 'viciTemperature'; static const String airTemp = 'viciTemperature';
static const String humidity = 'viciHumidity'; static const String humidity = 'humidity';
static const String lightIntensity = 'viciluminosity'; static const String lightIntensity = 'lightIntensity';
static const String conductivity = 'soilConductivity'; static const String conductivity = 'conductivity';
static const String ph = 'soilPh'; static const String ph = 'ph';
static const String nitrogen = 'soilNitrogen'; static const String nitrogen = 'nitrogen';
static const String phosphorus = 'soilPhosphorus'; static const String phosphorus = 'phosphorus';
static const String potassium = 'soilPotassium'; static const String potassium = 'potassium';
} }

View File

@ -16,10 +16,6 @@ String dateFormatterShort(String date) {
return formatter.format(dateTime); return formatter.format(dateTime);
} }
String setTwoDigitAfterComma(double number) {
return number.toStringAsFixed(2);
}
String getGreeting(String time) { String getGreeting(String time) {
DateTime parsedTime = DateTime.parse(time); DateTime parsedTime = DateTime.parse(time);
int hour = parsedTime.hour; int hour = parsedTime.hour;
@ -34,32 +30,3 @@ String getGreeting(String time) {
return 'Selamat Malam'; return 'Selamat Malam';
} }
} }
String timeAgo(String? dateString) {
if (dateString == null) {
return '';
}
DateTime date = DateTime.parse(dateString);
DateTime now = DateTime.now();
Duration difference = now.difference(date);
if (difference.inMinutes < 1) {
return "Baru saja";
} else if (difference.inMinutes < 60) {
return "${difference.inMinutes} menit yang lalu";
} else if (difference.inHours < 24) {
return "${difference.inHours} jam yang lalu";
} else if (difference.inDays < 7) {
return "${difference.inDays} hari yang lalu";
} else if (difference.inDays < 30) {
int weeks = (difference.inDays / 7).floor();
return "$weeks minggu yang lalu";
} else if (difference.inDays < 365) {
int months = (difference.inDays / 30).floor();
return "$months bulan yang lalu";
} else {
int years = (difference.inDays / 365).floor();
return "$years tahun yang lalu";
}
}

View File

@ -1,16 +1,15 @@
import 'package:agrilink_vocpro/features/auth/view/login_screen.dart'; import 'package:agrilink_vocpro/features/auth/view/login_screen.dart';
import 'package:agrilink_vocpro/features/dashboard/view/dashboard_screen.dart'; import 'package:agrilink_vocpro/features/dashboard/view/dashboard_screen.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/conductivity/view/conductivity_screen.dart'; import 'package:agrilink_vocpro/features/home/pages/conductivity/view/conductivity_screen.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/humidity/view/humidity_screen.dart'; import 'package:agrilink_vocpro/features/home/pages/humidity/view/humidity_screen.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/luminosity/view/light_screen.dart'; import 'package:agrilink_vocpro/features/home/pages/luminosity/view/light_screen.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/nitrogen/view/nitrogen_screen.dart'; import 'package:agrilink_vocpro/features/home/pages/nitrogen/view/nitrogen_screen.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/ph/view/ph_screen.dart'; import 'package:agrilink_vocpro/features/home/pages/ph/view/ph_screen.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/phosphorus/view/phosphorus_screen.dart'; import 'package:agrilink_vocpro/features/home/pages/phosphorus/view/phosphorus_screen.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/potassium/view/potassium_screen.dart'; import 'package:agrilink_vocpro/features/home/pages/potassium/view/potassium_screen.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/soil_moisture/view/soil_moisture_screen.dart'; import 'package:agrilink_vocpro/features/home/pages/soil_moisture/view/soil_moisture_screen.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/soil_temperature/view/soil_temperature_screen.dart'; import 'package:agrilink_vocpro/features/home/pages/soil_temperature/view/soil_temperature_screen.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/temperature/view/temperature_screen.dart'; import 'package:agrilink_vocpro/features/home/pages/temperature/view/temperature_screen.dart';
import 'package:agrilink_vocpro/features/setting/view/account_screen.dart';
import 'package:agrilink_vocpro/features/splash/view/splash_screen.dart'; import 'package:agrilink_vocpro/features/splash/view/splash_screen.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@ -22,7 +21,6 @@ class AppRoute {
static const String home = '/home'; static const String home = '/home';
static const String profile = '/profile'; static const String profile = '/profile';
static const String setting = '/setting'; static const String setting = '/setting';
static const String account = '/dashboard/account';
static const String humidity = '/dashboard/humidity'; static const String humidity = '/dashboard/humidity';
static const String temperature = '/dashboard/temperature'; static const String temperature = '/dashboard/temperature';
static const String soilTemperature = '/dashboard/soil_temperature'; static const String soilTemperature = '/dashboard/soil_temperature';
@ -71,11 +69,6 @@ class AppRoute {
buildPhosphorusRoute(), buildPhosphorusRoute(),
// potassium // potassium
buildPotassiumRoute(), buildPotassiumRoute(),
GoRoute(
path: 'account',
builder: (context, state) {
return AccountScreen();
})
], ],
), ),
], ],

View File

@ -1,30 +0,0 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class ErrorDataStateWidget extends StatelessWidget {
const ErrorDataStateWidget({
super.key,
});
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
BootstrapIcons.exclamation_circle,
color: Colors.grey.shade400,
),
SizedBox(height: 8.h),
Text(
'Terjadi Kesalahan',
style: AppTheme.labelSmall,
),
],
),
);
}
}

View File

@ -1 +1,28 @@
import 'package:flutter/material.dart';
Future<dynamic> showInfo(BuildContext context, String title, String content) {
return showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(title),
const SizedBox(height: 16),
Text(
style: Theme.of(context).textTheme.bodySmall,
content,
),
],
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('OK'),
)
],
),
);
}

View File

@ -31,6 +31,7 @@ class Relay {
String? disabledAt; String? disabledAt;
bool? currentStatus; bool? currentStatus;
String? createdAt; String? createdAt;
String? updatedAt;
Relay( Relay(
{this.id, {this.id,
@ -38,7 +39,8 @@ class Relay {
this.enabledAt, this.enabledAt,
this.disabledAt, this.disabledAt,
this.currentStatus, this.currentStatus,
this.createdAt}); this.createdAt,
this.updatedAt});
Relay.fromJson(Map<String, dynamic> json) { Relay.fromJson(Map<String, dynamic> json) {
id = json['id']; id = json['id'];
@ -47,6 +49,7 @@ class Relay {
disabledAt = json['disabled_at']; disabledAt = json['disabled_at'];
currentStatus = json['current_status']; currentStatus = json['current_status'];
createdAt = json['created_at']; createdAt = json['created_at'];
updatedAt = json['updated_at'];
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -57,6 +60,7 @@ class Relay {
data['disabled_at'] = disabledAt; data['disabled_at'] = disabledAt;
data['current_status'] = currentStatus; data['current_status'] = currentStatus;
data['created_at'] = createdAt; data['created_at'] = createdAt;
data['updated_at'] = updatedAt;
return data; return data;
} }
} }

View File

@ -107,14 +107,14 @@ class AppService {
final String auth = 'Bearer ${pref.getString('token')}'; final String auth = 'Bearer ${pref.getString('token')}';
try { try {
await Future.delayed(const Duration(seconds: 3)); await Future.delayed(const Duration(seconds: 3));
final response = await _dioWithoutInterceptor.get( final result = await _dioWithoutInterceptor.get(
'/api/relay/get-relay', '/api/get-relay',
options: Options( options: Options(
headers: {'Authorization': auth}, headers: {'Authorization': auth},
), ),
); );
if (response.statusCode == 200) { if (result.statusCode == 200) {
final data = RelayResponse.fromJson(response.data); final data = RelayResponse.fromJson(result.data);
return data; return data;
} else { } else {
throw Exception('Failed to load data'); throw Exception('Failed to load data');
@ -134,7 +134,7 @@ class AppService {
try { try {
final response = await _dioWithoutInterceptor.post( final response = await _dioWithoutInterceptor.post(
'/api/relay/set-relay', '/api/set-relay',
data: { data: {
'id': relayNumber, 'id': relayNumber,
'state': state, 'state': state,

View File

@ -1,4 +1,5 @@
import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
class FirebaseApi { class FirebaseApi {
final _firebaseMessaging = FirebaseMessaging.instance; final _firebaseMessaging = FirebaseMessaging.instance;
@ -10,5 +11,10 @@ class FirebaseApi {
provisional: false, provisional: false,
sound: true, sound: true,
); );
final fCMToken = await _firebaseMessaging.getToken();
if (kDebugMode) {
print('FCM Token: $fCMToken');
}
} }
} }

View File

@ -1,11 +1,11 @@
// import 'dart:convert'; import 'dart:convert';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/domain/service/app_service.dart'; import 'package:agrilink_vocpro/domain/service/app_service.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
// import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
// import 'package:googleapis_auth/auth_io.dart'; import 'package:googleapis_auth/auth_io.dart';
// import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
class AuthProvider extends ChangeNotifier { class AuthProvider extends ChangeNotifier {
TextEditingController emailController = TextEditingController(); TextEditingController emailController = TextEditingController();
@ -80,30 +80,30 @@ class AuthProvider extends ChangeNotifier {
return true; return true;
} }
// Future<void> getAccessToken() async { Future<void> getAccessToken() async {
// try { try {
// final serviceAccountJson = await rootBundle.loadString( final serviceAccountJson = await rootBundle.loadString(
// 'assets/json/agrilink-vocpro-b37f9-firebase-adminsdk-a4f6g-e6565344e3.json', 'assets/json/agrilink-vocpro-b37f9-firebase-adminsdk-a4f6g-e6565344e3.json',
// ); );
// final accountCredentials = ServiceAccountCredentials.fromJson( final accountCredentials = ServiceAccountCredentials.fromJson(
// json.decode(serviceAccountJson), json.decode(serviceAccountJson),
// ); );
// const scope = ['https://www.googleapis.com/auth/firebase.messaging']; const scope = ['https://www.googleapis.com/auth/firebase.messaging'];
// final client = http.Client(); final client = http.Client();
// try { try {
// final accessCredential = await obtainAccessCredentialsViaServiceAccount( final accessCredential = await obtainAccessCredentialsViaServiceAccount(
// accountCredentials, scope, client); accountCredentials, scope, client);
// final accessToken = accessCredential.accessToken.data; final accessToken = accessCredential.accessToken.data;
// print('Access Token: $accessToken'); print('Access Token: $accessToken');
// } catch (e) { } catch (e) {
// print('Error: $e'); print('Error: $e');
// } }
// } catch (e) { } catch (e) {
// print('Error 2: $e'); print('Error 2: $e');
// } }
// } }
} }

View File

@ -23,15 +23,15 @@ class LoginScreen extends StatelessWidget {
children: [ children: [
const SizedBox(height: 40), const SizedBox(height: 40),
Text( Text(
'Halo, Selamat Datang 👋', 'Hello, Welcome back 👋',
style: AppTheme.titleLarge, style: AppTheme.titleLarge,
), ),
Text( Text(
'Senang melihatmu kembali', 'Happy to have you back',
style: AppTheme.titleMedium, style: AppTheme.titleMedium,
), ),
const SizedBox(height: 40), const SizedBox(height: 40),
Text('Alamat Email', style: AppTheme.labelLarge), Text('Email address', style: AppTheme.labelLarge),
const SizedBox(height: 4), const SizedBox(height: 4),
AppTextfield( AppTextfield(
controller: authP.emailController, controller: authP.emailController,
@ -77,11 +77,11 @@ class LoginScreen extends StatelessWidget {
text: 'Login', text: 'Login',
), ),
SizedBox(height: 24), SizedBox(height: 24),
// AppButton( AppButton(
// onPressed: () { onPressed: () {
// authP.getAccessToken(); authP.getAccessToken();
// }, },
// text: 'Get Access Token'), text: 'Get Access Token'),
], ],
); );
}, },

View File

@ -1,5 +1,4 @@
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/data/model/relay_response.dart';
import 'package:agrilink_vocpro/domain/service/app_service.dart'; import 'package:agrilink_vocpro/domain/service/app_service.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
@ -12,24 +11,43 @@ class ControlProvider extends ChangeNotifier {
bool _control_2 = false; bool _control_2 = false;
bool get control_2 => _control_2; bool get control_2 => _control_2;
bool _control_3 = false;
bool get control_3 => _control_3;
Relay _relay1 = Relay();
Relay get relay1 => _relay1;
Relay _relay2 = Relay();
Relay get relay2 => _relay2;
Relay _relay3 = Relay();
Relay get relay3 => _relay3;
ControlProvider() { ControlProvider() {
getRelayStatus(); getRelayStatus();
} }
// ResultState mqttState = ResultState.initial;
// ResultState subscribeState = ResultState.initial;
ResultState relayState = ResultState.initial; ResultState relayState = ResultState.initial;
// Future<void> connectMqtt() async {
// mqttState = ResultState.loading;
// subscribeState = ResultState.loading;
// notifyListeners();
// try {
// final result = await _mqttService.setupMqtt();
// if (result == ResultState.hasData) {
// mqttState = result;
// final result2 = await _mqttService.subscribeToRelayStatus();
// // if (result2 == true) {
// // subscribeState = ResultState.hasData;
// // _control_1 = true;
// // } else {
// // subscribeState = ResultState.hasData;
// // _control_1 = false;
// // }
// } else {
// mqttState = ResultState.error;
// }
// } catch (e) {
// mqttState = ResultState.error;
// print(e);
// }
// notifyListeners();
// }
Future<void> getRelayStatus() async { Future<void> getRelayStatus() async {
relayState = ResultState.loading; relayState = ResultState.loading;
notifyListeners(); notifyListeners();
@ -41,16 +59,10 @@ class ControlProvider extends ChangeNotifier {
if (result.success == true) { if (result.success == true) {
for (var element in result.data!) { for (var element in result.data!) {
if (element.number == 1) { if (element.number == 1) {
_relay1 = element; switchControl1(element.currentStatus ?? false);
switchControl(element.currentStatus ?? false, relayNumber: 1);
} }
if (element.number == 2) { if (element.number == 2) {
_relay2 = element; switchControl2(element.currentStatus ?? false);
switchControl(element.currentStatus ?? false, relayNumber: 2);
}
if (element.number == 3) {
_relay3 = element;
switchControl(element.currentStatus ?? false, relayNumber: 3);
} }
} }
relayState = ResultState.hasData; relayState = ResultState.hasData;
@ -63,7 +75,7 @@ class ControlProvider extends ChangeNotifier {
relayState = ResultState.error; relayState = ResultState.error;
notifyListeners(); notifyListeners();
if (kDebugMode) { if (kDebugMode) {
print('Error Getting Relay Status: $e'); print(e);
} }
} }
} }
@ -72,13 +84,15 @@ class ControlProvider extends ChangeNotifier {
relayState = ResultState.loading; relayState = ResultState.loading;
notifyListeners(); notifyListeners();
final int stateConverted = state ? 1 : 0; final int stateConverted;
if (state == true) {
stateConverted = 1;
} else {
stateConverted = 0;
}
try { try {
final result = await _appService.switchRelay( final result = await _appService.switchRelay(
relayNumber: relayNumber, relayNumber: relayNumber, state: stateConverted);
state: stateConverted,
);
if (result.success == true) { if (result.success == true) {
relayState = ResultState.hasData; relayState = ResultState.hasData;
notifyListeners(); notifyListeners();
@ -99,20 +113,32 @@ class ControlProvider extends ChangeNotifier {
} }
} }
void switchControl(bool value, {required int relayNumber}) { void switchControl1(bool value) {
switch (relayNumber) { _control_1 = value;
case 1:
_control_1 = value;
break;
case 2:
_control_2 = value;
break;
case 3:
_control_3 = value;
break;
default:
return;
}
notifyListeners(); notifyListeners();
} }
void switchControl2(bool value) {
_control_2 = value;
notifyListeners();
}
// Future<ResultState> publishMessage(String topic, String message) async {
// try {
// final result = await _mqttService.publishMessage(topic, message);
// return result;
// } catch (e) {
// print(e);
// rethrow;
// }
// }
// Future<void> subscribeToTopic(String topic) async {
// try {
// await _mqttService.subscribeToTopic(topic);
// } catch (e) {
// print(e);
// rethrow;
// }
// }
} }

View File

@ -2,8 +2,6 @@ import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/state/result_state.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/provider/control_provider.dart';
import 'package:agrilink_vocpro/features/control/widgets/control_button_widget.dart'; import 'package:agrilink_vocpro/features/control/widgets/control_button_widget.dart';
import 'package:agrilink_vocpro/features/control/widgets/pump_status_widget.dart';
import 'package:agrilink_vocpro/features/control/widgets/relay_status_history_widget.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -18,7 +16,7 @@ class ControlScreen extends StatelessWidget {
final provider = Provider.of<ControlProvider>(context, listen: true); final provider = Provider.of<ControlProvider>(context, listen: true);
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('Kontrol', style: AppTheme.labelMedium), title: Text('Control', style: AppTheme.labelMedium),
centerTitle: true, centerTitle: true,
backgroundColor: Colors.white, backgroundColor: Colors.white,
scrolledUnderElevation: 0, scrolledUnderElevation: 0,
@ -36,7 +34,7 @@ class ControlScreen extends StatelessWidget {
return const StatusBarWidget( return const StatusBarWidget(
text: 'Memuat...', text: 'Memuat...',
icon: BootstrapIcons.cloud, icon: BootstrapIcons.cloud,
color: Colors.grey, color: Colors.cyan,
isLoading: true, isLoading: true,
); );
case ResultState.hasData: case ResultState.hasData:
@ -61,12 +59,6 @@ class ControlScreen extends StatelessWidget {
); );
} }
}), }),
PumpStatusWidget(
title: 'Pompa Air',
subtitle: 'Relay 3',
isActive: provider.control_3,
onTap: () {},
),
SizedBox(height: 16.h), SizedBox(height: 16.h),
GridView( GridView(
padding: EdgeInsets.all(16.r), padding: EdgeInsets.all(16.r),
@ -80,118 +72,36 @@ class ControlScreen extends StatelessWidget {
), ),
children: [ children: [
ControlButtonWidget( ControlButtonWidget(
title: 'Katup Nutrisi', title: 'Katup Air',
subtitle: 'Relay 1', subtitle: 'Relay 1',
isActive: provider.control_1, isActive: provider.control_1,
onTap: () async { onTap: () async {
await _changeRelayStateAction( final result = provider.control_1 != true
provider: provider, ? await provider.switchRelay(1, true)
relayOn: 1, : await provider.switchRelay(1, false);
relayOff: 2, result == true
); ? provider.switchControl1(!provider.control_1)
: provider.switchControl1(provider.control_1);
}, },
), ),
ControlButtonWidget( ControlButtonWidget(
title: 'Katup Air', title: 'Lampu Utama',
subtitle: 'Relay 2', subtitle: 'Relay 2',
isActive: provider.control_2, isActive: provider.control_2,
onTap: () async { onTap: () {
await _changeRelayStateAction( provider.control_2 != true
provider: provider, ? provider.switchControl2(true)
relayOn: 2, : provider.switchControl2(false);
relayOff: 1,
);
}, },
), ),
], ],
), ),
SizedBox(height: 16.h),
Padding(
padding: EdgeInsets.fromLTRB(16.r, 0, 16.r, 16.h),
child: Row(
children: [
Icon(
BootstrapIcons.clock,
size: 20.r,
),
SizedBox(width: 8.w),
Text(
'Terakhir Diperbarui',
style: AppTheme.labelMedium,
),
],
),
),
Consumer<ControlProvider>(builder: (context, provider, child) {
return Column(
children: [
RelayStatusHistoryWidget(
name: 'Katup Nutrisi',
imageUrl: 'assets/images/valve.png',
enabledAt: provider.relay1.enabledAt,
disabledAt: provider.relay1.disabledAt,
),
RelayStatusHistoryWidget(
name: 'Katup Air',
imageUrl: 'assets/images/valve.png',
enabledAt: provider.relay2.enabledAt,
disabledAt: provider.relay2.disabledAt,
),
RelayStatusHistoryWidget(
name: 'Pompa Air',
imageUrl: 'assets/images/water_pump.png',
enabledAt: provider.relay3.enabledAt,
disabledAt: provider.relay3.disabledAt,
),
],
);
}),
], ],
), ),
), ),
), ),
); );
} }
Future<void> _changeRelayStateAction({
required ControlProvider provider,
required int relayOn,
required int relayOff,
}) async {
if (relayOn == 1) {
// Aktifkan relay 1 dan relay 3, matikan relay 2
if (provider.control_1 == false) {
await provider.switchRelay(relayOff, false); // Matikan relay 2
await provider.switchRelay(3, true); // Aktifkan relay 3
await provider.switchRelay(relayOn, true); // Aktifkan relay 1
provider.switchControl(true, relayNumber: 1);
provider.switchControl(true, relayNumber: 3);
provider.switchControl(false, relayNumber: 2);
} else {
// Matikan semua relay jika relay 1 dimatikan
await provider.switchRelay(3, false);
await provider.switchRelay(relayOn, false);
provider.switchControl(false, relayNumber: 1);
provider.switchControl(false, relayNumber: 3);
}
} else if (relayOn == 2) {
// Aktifkan relay 2 dan relay 3, matikan relay 1
if (provider.control_2 == false) {
await provider.switchRelay(relayOff, false); // Matikan relay 1
await provider.switchRelay(3, true); // Aktifkan relay 3
await provider.switchRelay(relayOn, true); // Aktifkan relay 2
provider.switchControl(true, relayNumber: 2);
provider.switchControl(true, relayNumber: 3);
provider.switchControl(false, relayNumber: 1);
} else {
// Matikan semua relay jika relay 2 dimatikan
await provider.switchRelay(3, false);
await provider.switchRelay(relayOn, false);
provider.switchControl(false, relayNumber: 2);
provider.switchControl(false, relayNumber: 3);
}
}
}
} }
class StatusBarWidget extends StatelessWidget { class StatusBarWidget extends StatelessWidget {

View File

@ -32,8 +32,8 @@ class ControlButtonWidget extends StatelessWidget {
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: isActive color: isActive
? AppColor.secondary.withValues(alpha: 0.2) ? AppColor.secondary.withOpacity(0.2)
: Colors.grey.withValues(alpha: 0.2), : Colors.grey.withOpacity(0.2),
spreadRadius: 1.r, spreadRadius: 1.r,
blurRadius: 16.r, blurRadius: 16.r,
offset: Offset(0, 12.r), offset: Offset(0, 12.r),

View File

@ -1,75 +0,0 @@
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:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:provider/provider.dart';
class PumpStatusWidget extends StatelessWidget {
const PumpStatusWidget({
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(
height: 100.h,
padding: EdgeInsets.all(16.r),
margin: EdgeInsets.symmetric(horizontal: 16.r),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.r),
boxShadow: [
BoxShadow(
color: isActive
? AppColor.secondary.withValues(alpha: 0.2)
: Colors.grey.withValues(alpha: 0.2),
spreadRadius: 1.r,
blurRadius: 16.r,
offset: Offset(0, 12.r),
),
],
),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: AppTheme.labelMedium),
Text(subtitle, style: AppTheme.labelSmall),
],
),
Spacer(),
Consumer<ControlProvider>(
builder: (context, provider, child) {
switch (provider.relayState) {
case ResultState.loading:
return Image.asset(
'assets/images/water_pump.png',
width: 80.r,
color: AppColor.textDisable,
);
default:
return Image.asset(
'assets/images/water_pump.png',
width: 80.r,
color: isActive ? AppColor.secondary : AppColor.textDisable,
);
}
},
)
],
),
);
}
}

View File

@ -1,68 +0,0 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/extension/extention.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../../core/constant/app_color.dart';
class RelayStatusHistoryWidget extends StatelessWidget {
const RelayStatusHistoryWidget({
super.key,
required this.disabledAt,
required this.enabledAt,
required this.name,
required this.imageUrl,
});
final String? disabledAt;
final String? enabledAt;
final String name;
final String imageUrl;
@override
Widget build(BuildContext context) {
return ListTile(
leading: CircleAvatar(
radius: 26.r,
backgroundColor: AppColor.ternary,
child: Image.asset(
imageUrl,
width: 24.r,
color: Colors.white,
),
),
title: Text(
name,
style: AppTheme.labelMedium,
),
subtitle: Column(
children: [
Row(
children: [
CircleAvatar(
backgroundColor: Colors.greenAccent,
radius: 4.r,
),
Text(
' Aktif ${timeAgo(enabledAt)}',
style: AppTheme.labelSmall,
),
],
),
Row(
children: [
CircleAvatar(
backgroundColor: Colors.grey.shade300,
radius: 4.r,
),
Text(
' Nonaktif ${timeAgo(disabledAt)}',
style: AppTheme.labelSmall,
),
],
)
],
),
);
}
}

View File

@ -26,22 +26,22 @@ class DashboardScreen extends StatelessWidget {
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(BootstrapIcons.house), icon: Icon(BootstrapIcons.house),
activeIcon: Icon(BootstrapIcons.house_fill), activeIcon: Icon(BootstrapIcons.house_fill),
label: 'Beranda', label: 'Home',
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(BootstrapIcons.toggle_off), icon: Icon(BootstrapIcons.toggle_off),
activeIcon: Icon(BootstrapIcons.toggle_on), activeIcon: Icon(BootstrapIcons.toggle_on),
label: 'Kontrol', label: 'Control',
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(BootstrapIcons.flower1), icon: Icon(BootstrapIcons.flower1),
activeIcon: Icon(BootstrapIcons.flower1), activeIcon: Icon(BootstrapIcons.flower1),
label: 'Tanaman', label: 'Plants',
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(BootstrapIcons.gear), icon: Icon(BootstrapIcons.gear),
activeIcon: Icon(BootstrapIcons.gear_fill), activeIcon: Icon(BootstrapIcons.gear_fill),
label: 'Pengaturan', label: 'Setting',
), ),
], ],
), ),

View File

@ -1,4 +1,3 @@
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/data/model/latest_data_response.dart'; import 'package:agrilink_vocpro/data/model/latest_data_response.dart';
import 'package:agrilink_vocpro/domain/service/app_service.dart'; import 'package:agrilink_vocpro/domain/service/app_service.dart';
@ -18,8 +17,8 @@ class ConductivityProvider extends ChangeNotifier {
dataState = ResultState.loading; dataState = ResultState.loading;
notifyListeners(); notifyListeners();
try { try {
final result = await AppService() final result =
.getGraphicDataNpk1(metric: AppConstant.conductivity); await AppService().getGraphicDataNpk1(metric: 'soilConductivity');
if (result.data == null || result.data!.npk1!.isEmpty) { if (result.data == null || result.data!.npk1!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {
@ -28,7 +27,7 @@ class ConductivityProvider extends ChangeNotifier {
} }
} catch (e) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
print('Get Grafik Conductivity Error: $e'); print('Get Grafik Soil Temp Error: $e');
} }
dataState = ResultState.error; dataState = ResultState.error;
} }
@ -39,8 +38,8 @@ class ConductivityProvider extends ChangeNotifier {
dataState = ResultState.loading; dataState = ResultState.loading;
notifyListeners(); notifyListeners();
try { try {
final result = await AppService() final result =
.getGraphicDataNpk2(metric: AppConstant.conductivity); await AppService().getGraphicDataNpk2(metric: 'soilConductivity');
if (result.data == null || result.data!.npk2!.isEmpty) { if (result.data == null || result.data!.npk2!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {
@ -49,7 +48,7 @@ class ConductivityProvider extends ChangeNotifier {
} }
} catch (e) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
print('Get Grafik Conductivity Error: $e'); print('Get Grafik Soil Temp Error: $e');
} }
dataState = ResultState.error; dataState = ResultState.error;
} }

View File

@ -1,8 +1,7 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/core/widgets/error_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/pages/conductivity/provider/conductivity_provider.dart';
import 'package:agrilink_vocpro/core/widgets/no_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_error_widget.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/conductivity/provider/conductivity_provider.dart';
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -95,7 +94,7 @@ class ConductivityScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'Konduktifitas Tanah', 'Soil Condutivity',
style: AppTheme.labelMedium, style: AppTheme.labelMedium,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -144,12 +143,14 @@ class ConductivityScreen extends StatelessWidget {
? provider.dataFetchedNpk1[index].soilconductivity ?? 0 ? provider.dataFetchedNpk1[index].soilconductivity ?? 0
: provider.dataFetchedNpk2[index].soilconductivity ?? 0, : provider.dataFetchedNpk2[index].soilconductivity ?? 0,
), ),
maxValue: 1,
); );
case ResultState.error: case ResultState.error:
return const ErrorDataStateWidget(); return const GraphicErrorWidget(message: 'Terjadi Kesalahan');
case ResultState.noData: case ResultState.noData:
return const NoDataStateWidget(); return const GraphicErrorWidget(message: 'Tidak Ada Data');
case ResultState.initial: case ResultState.initial:
default:
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
}, },

View File

@ -1,4 +1,3 @@
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/data/model/latest_data_response.dart'; import 'package:agrilink_vocpro/data/model/latest_data_response.dart';
import 'package:agrilink_vocpro/domain/service/app_service.dart'; import 'package:agrilink_vocpro/domain/service/app_service.dart';
@ -17,7 +16,7 @@ class HumidityProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
try { try {
final result = final result =
await AppService().getGrafikDataDht(metric: AppConstant.humidity); await AppService().getGrafikDataDht(metric: 'viciHumidity');
if (result.data == null || result.data!.dht!.isEmpty) { if (result.data == null || result.data!.dht!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {

View File

@ -1,8 +1,6 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/core/widgets/error_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/pages/humidity/provider/humidity_provider.dart';
import 'package:agrilink_vocpro/core/widgets/no_data_state_widget.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/humidity/provider/humidity_provider.dart';
import 'package:agrilink_vocpro/features/home/provider/home_provider.dart'; import 'package:agrilink_vocpro/features/home/provider/home_provider.dart';
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
@ -96,7 +94,7 @@ class HumidityScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'Kelembaban Udara', 'Humidity',
style: AppTheme.labelMedium, style: AppTheme.labelMedium,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -110,7 +108,7 @@ class HumidityScreen extends StatelessWidget {
const SizedBox(height: 16), const SizedBox(height: 16),
Padding( Padding(
padding: EdgeInsets.only(left: 16.w), padding: EdgeInsets.only(left: 16.w),
child: const Text('Grafik'), child: const Text('Grafik dalam 7 hari terakhir'),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
AspectRatio( AspectRatio(
@ -147,16 +145,54 @@ class HumidityScreen extends StatelessWidget {
0), 0),
); );
case ResultState.error: case ResultState.error:
return const ErrorDataStateWidget(); return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
BootstrapIcons.exclamation_circle,
color: Colors.grey.shade400,
),
SizedBox(height: 8.h),
Text(
'Terjadi Kesalahan',
style: AppTheme.labelSmall,
),
],
),
);
case ResultState.noData: case ResultState.noData:
return const NoDataStateWidget(); return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
BootstrapIcons.database_fill_x,
color: Colors.grey.shade400,
),
SizedBox(height: 8.h),
Text(
'Tidak Ada Data',
style: AppTheme.labelSmall,
),
],
),
);
case ResultState.initial: case ResultState.initial:
return const SizedBox.shrink(); return const SizedBox.shrink();
default:
return const Center(
child: Text('Default Error'),
);
} }
}), }),
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Padding(
padding: EdgeInsets.only(left: 16.w),
child: const Text('Deskripsi'),
),
], ],
); );
}), }),

View File

@ -1,4 +1,3 @@
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/data/model/latest_data_response.dart'; import 'package:agrilink_vocpro/data/model/latest_data_response.dart';
import 'package:agrilink_vocpro/domain/service/app_service.dart'; import 'package:agrilink_vocpro/domain/service/app_service.dart';
@ -16,8 +15,8 @@ class LumProvider extends ChangeNotifier {
dataState = ResultState.loading; dataState = ResultState.loading;
notifyListeners(); notifyListeners();
try { try {
final result = await AppService() final result =
.getGrafikDataDht(metric: AppConstant.lightIntensity); await AppService().getGrafikDataDht(metric: 'viciluminosity');
if (result.data == null || result.data!.dht!.isEmpty) { if (result.data == null || result.data!.dht!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {

View File

@ -1,6 +1,6 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/luminosity/provider/lum_provider.dart'; import 'package:agrilink_vocpro/features/home/pages/luminosity/provider/lum_provider.dart';
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -64,7 +64,7 @@ class LightScreen extends StatelessWidget {
axis: GaugeAxis( axis: GaugeAxis(
degrees: 360, degrees: 360,
min: 0, min: 0,
max: 500, max: 1000,
style: GaugeAxisStyle( style: GaugeAxisStyle(
background: Colors.grey.shade100, background: Colors.grey.shade100,
thickness: 100, thickness: 100,
@ -82,7 +82,7 @@ class LightScreen extends StatelessWidget {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'$value lux', '${value.toStringAsFixed(0)} lux',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: const TextStyle( style: const TextStyle(
fontSize: 28, fontSize: 28,
@ -137,7 +137,6 @@ class LightScreen extends StatelessWidget {
provider.dataFetched[index].vicihumidity provider.dataFetched[index].vicihumidity
?.toDouble() ?? ?.toDouble() ??
0), 0),
maxValue: 500,
); );
case ResultState.error: case ResultState.error:
return Center( return Center(
@ -175,6 +174,10 @@ class LightScreen extends StatelessWidget {
); );
case ResultState.initial: case ResultState.initial:
return const SizedBox.shrink(); return const SizedBox.shrink();
default:
return const Center(
child: Text('Default Error'),
);
} }
}), }),
), ),

View File

@ -1,4 +1,3 @@
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/data/model/latest_data_response.dart'; import 'package:agrilink_vocpro/data/model/latest_data_response.dart';
import 'package:agrilink_vocpro/domain/service/app_service.dart'; import 'package:agrilink_vocpro/domain/service/app_service.dart';
@ -19,7 +18,7 @@ class NitrogenProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
try { try {
final result = final result =
await AppService().getGraphicDataNpk1(metric: AppConstant.nitrogen); await AppService().getGraphicDataNpk1(metric: 'soilNitrogen');
if (result.data == null || result.data!.npk1!.isEmpty) { if (result.data == null || result.data!.npk1!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {
@ -40,7 +39,7 @@ class NitrogenProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
try { try {
final result = final result =
await AppService().getGraphicDataNpk2(metric: AppConstant.nitrogen); await AppService().getGraphicDataNpk2(metric: 'soilNitrogen');
if (result.data == null || result.data!.npk2!.isEmpty) { if (result.data == null || result.data!.npk2!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {

View File

@ -1,8 +1,7 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/core/widgets/error_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/pages/nitrogen/provider/nitrogen_provider.dart';
import 'package:agrilink_vocpro/core/widgets/no_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_error_widget.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/nitrogen/provider/nitrogen_provider.dart';
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -84,7 +83,7 @@ class NitrogenScreen extends StatelessWidget {
size: 64.r, size: 64.r,
color: Colors.blue, color: Colors.blue,
), ),
Text('$value mg/L', style: AppTheme.headline1), Text('$value ppm', style: AppTheme.headline1),
], ],
), ),
); );
@ -95,7 +94,7 @@ class NitrogenScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'Nitrogen Tanah', 'Soil Nitrogen',
style: AppTheme.labelMedium, style: AppTheme.labelMedium,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -144,13 +143,14 @@ class NitrogenScreen extends StatelessWidget {
? provider.dataFetchedNpk1[index].soilnitrogen ?? 0 ? provider.dataFetchedNpk1[index].soilnitrogen ?? 0
: provider.dataFetchedNpk2[index].soilnitrogen ?? 0, : provider.dataFetchedNpk2[index].soilnitrogen ?? 0,
), ),
maxValue: 10, maxValue: 1,
); );
case ResultState.error: case ResultState.error:
return const ErrorDataStateWidget(); return const GraphicErrorWidget(message: 'Terjadi Kesalahan');
case ResultState.noData: case ResultState.noData:
return const NoDataStateWidget(); return const GraphicErrorWidget(message: 'Tidak Ada Data');
case ResultState.initial: case ResultState.initial:
default:
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
}, },

View File

@ -1,4 +1,3 @@
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/data/model/latest_data_response.dart'; import 'package:agrilink_vocpro/data/model/latest_data_response.dart';
import 'package:agrilink_vocpro/domain/service/app_service.dart'; import 'package:agrilink_vocpro/domain/service/app_service.dart';
@ -18,8 +17,7 @@ class PhProvider extends ChangeNotifier {
dataState = ResultState.loading; dataState = ResultState.loading;
notifyListeners(); notifyListeners();
try { try {
final result = final result = await AppService().getGraphicDataNpk1(metric: 'soilPh');
await AppService().getGraphicDataNpk1(metric: AppConstant.ph);
if (result.data == null || result.data!.npk1!.isEmpty) { if (result.data == null || result.data!.npk1!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {
@ -28,7 +26,7 @@ class PhProvider extends ChangeNotifier {
} }
} catch (e) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
print('Get Grafik Soil pH Error: $e'); print('Get Grafik Soil Temp Error: $e');
} }
dataState = ResultState.error; dataState = ResultState.error;
} }
@ -39,8 +37,7 @@ class PhProvider extends ChangeNotifier {
dataState = ResultState.loading; dataState = ResultState.loading;
notifyListeners(); notifyListeners();
try { try {
final result = final result = await AppService().getGraphicDataNpk2(metric: 'soilPh');
await AppService().getGraphicDataNpk2(metric: AppConstant.ph);
if (result.data == null || result.data!.npk2!.isEmpty) { if (result.data == null || result.data!.npk2!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {
@ -49,7 +46,7 @@ class PhProvider extends ChangeNotifier {
} }
} catch (e) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
print('Get Grafik Soil pH Error: $e'); print('Get Grafik Soil Temp Error: $e');
} }
dataState = ResultState.error; dataState = ResultState.error;
} }

View File

@ -1,9 +1,8 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/core/widgets/error_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/pages/ph/provider/ph_provider.dart';
import 'package:agrilink_vocpro/core/widgets/no_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/pages/ph/widget/ph_bar_pointer.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/ph/provider/ph_provider.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_error_widget.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/ph/widget/ph_bar_pointer.dart';
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -86,7 +85,7 @@ class PhScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'pH Tanah', 'Soil Acidity',
style: AppTheme.labelMedium, style: AppTheme.labelMedium,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -138,10 +137,11 @@ class PhScreen extends StatelessWidget {
maxValue: 14, maxValue: 14,
); );
case ResultState.error: case ResultState.error:
return const ErrorDataStateWidget(); return const GraphicErrorWidget(message: 'Terjadi Kesalahan');
case ResultState.noData: case ResultState.noData:
return const NoDataStateWidget(); return const GraphicErrorWidget(message: 'Tidak Ada Data');
case ResultState.initial: case ResultState.initial:
default:
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
}, },

View File

@ -1,4 +1,3 @@
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/data/model/latest_data_response.dart'; import 'package:agrilink_vocpro/data/model/latest_data_response.dart';
import 'package:agrilink_vocpro/domain/service/app_service.dart'; import 'package:agrilink_vocpro/domain/service/app_service.dart';
@ -19,7 +18,7 @@ class PhosporusProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
try { try {
final result = final result =
await AppService().getGraphicDataNpk1(metric: AppConstant.phosphorus); await AppService().getGraphicDataNpk1(metric: 'soilPhosphorus');
if (result.data == null || result.data!.npk1!.isEmpty) { if (result.data == null || result.data!.npk1!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {
@ -28,7 +27,7 @@ class PhosporusProvider extends ChangeNotifier {
} }
} catch (e) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
print('Get Grafik Phosphor Error: $e'); print('Get Grafik Soil Temp Error: $e');
} }
dataState = ResultState.error; dataState = ResultState.error;
} }
@ -40,7 +39,7 @@ class PhosporusProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
try { try {
final result = final result =
await AppService().getGraphicDataNpk2(metric: AppConstant.phosphorus); await AppService().getGraphicDataNpk2(metric: 'soilPhosphorus');
if (result.data == null || result.data!.npk2!.isEmpty) { if (result.data == null || result.data!.npk2!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {
@ -49,7 +48,7 @@ class PhosporusProvider extends ChangeNotifier {
} }
} catch (e) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
print('Get Grafik Phosphor Error: $e'); print('Get Grafik Soil Temp Error: $e');
} }
dataState = ResultState.error; dataState = ResultState.error;
} }

View File

@ -1,8 +1,7 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/core/widgets/error_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/pages/phosphorus/provider/phosporus_provider.dart';
import 'package:agrilink_vocpro/core/widgets/no_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_error_widget.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/phosphorus/provider/phosporus_provider.dart';
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -84,7 +83,7 @@ class PhosphorusScreen extends StatelessWidget {
size: 64.r, size: 64.r,
color: Colors.blue, color: Colors.blue,
), ),
Text('$value mg/L', style: AppTheme.headline1), Text('$value ppm', style: AppTheme.headline1),
], ],
), ),
); );
@ -95,7 +94,7 @@ class PhosphorusScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'Fosfor Tanah', 'Soil Phosphorus',
style: AppTheme.labelMedium, style: AppTheme.labelMedium,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -144,13 +143,14 @@ class PhosphorusScreen extends StatelessWidget {
? provider.dataFetchedNpk1[index].soilphosphorus ?? 0 ? provider.dataFetchedNpk1[index].soilphosphorus ?? 0
: provider.dataFetchedNpk2[index].soilphosphorus ?? 0, : provider.dataFetchedNpk2[index].soilphosphorus ?? 0,
), ),
maxValue: 100, maxValue: 10,
); );
case ResultState.error: case ResultState.error:
return const ErrorDataStateWidget(); return const GraphicErrorWidget(message: 'Terjadi Kesalahan');
case ResultState.noData: case ResultState.noData:
return const NoDataStateWidget(); return const GraphicErrorWidget(message: 'Tidak Ada Data');
case ResultState.initial: case ResultState.initial:
default:
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
}, },

View File

@ -1,4 +1,3 @@
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/data/model/latest_data_response.dart'; import 'package:agrilink_vocpro/data/model/latest_data_response.dart';
import 'package:agrilink_vocpro/domain/service/app_service.dart'; import 'package:agrilink_vocpro/domain/service/app_service.dart';
@ -19,7 +18,7 @@ class PotassiumProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
try { try {
final result = final result =
await AppService().getGraphicDataNpk1(metric: AppConstant.potassium); await AppService().getGraphicDataNpk1(metric: 'soilPotassium');
if (result.data == null || result.data!.npk1!.isEmpty) { if (result.data == null || result.data!.npk1!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {
@ -28,7 +27,7 @@ class PotassiumProvider extends ChangeNotifier {
} }
} catch (e) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
print('Get Grafik Potassium Error: $e'); print('Get Grafik Soil Temp Error: $e');
} }
dataState = ResultState.error; dataState = ResultState.error;
} }
@ -40,7 +39,7 @@ class PotassiumProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
try { try {
final result = final result =
await AppService().getGraphicDataNpk2(metric: AppConstant.potassium); await AppService().getGraphicDataNpk2(metric: 'soilPotassium');
if (result.data == null || result.data!.npk2!.isEmpty) { if (result.data == null || result.data!.npk2!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {
@ -49,7 +48,7 @@ class PotassiumProvider extends ChangeNotifier {
} }
} catch (e) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
print('Get Grafik Potassium Error: $e'); print('Get Grafik Soil Temp Error: $e');
} }
dataState = ResultState.error; dataState = ResultState.error;
} }

View File

@ -1,8 +1,7 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/core/widgets/error_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/pages/potassium/provider/potassium_provider.dart';
import 'package:agrilink_vocpro/core/widgets/no_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_error_widget.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/potassium/provider/potassium_provider.dart';
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -25,7 +24,7 @@ class PotassiumScreen extends StatelessWidget {
length: 2, length: 2,
child: Scaffold( child: Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('Soil Potassium (Kalium)', style: AppTheme.labelMedium), title: Text('Soil Potassium', style: AppTheme.labelMedium),
centerTitle: true, centerTitle: true,
backgroundColor: Colors.white, backgroundColor: Colors.white,
scrolledUnderElevation: 0, scrolledUnderElevation: 0,
@ -84,7 +83,7 @@ class PotassiumScreen extends StatelessWidget {
size: 64.r, size: 64.r,
color: Colors.red, color: Colors.red,
), ),
Text('$value mg/L', style: AppTheme.headline1), Text('$value ppm', style: AppTheme.headline1),
], ],
), ),
); );
@ -95,7 +94,7 @@ class PotassiumScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'Kalium Tanah', 'Soil Potassium',
style: AppTheme.labelMedium, style: AppTheme.labelMedium,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -144,13 +143,14 @@ class PotassiumScreen extends StatelessWidget {
? provider.dataFetchedNpk1[index].soilpotassium ?? 0 ? provider.dataFetchedNpk1[index].soilpotassium ?? 0
: provider.dataFetchedNpk2[index].soilpotassium ?? 0, : provider.dataFetchedNpk2[index].soilpotassium ?? 0,
), ),
maxValue: 100, maxValue: 1,
); );
case ResultState.error: case ResultState.error:
return const ErrorDataStateWidget(); return const GraphicErrorWidget(message: 'Terjadi Kesalahan');
case ResultState.noData: case ResultState.noData:
return const NoDataStateWidget(); return const GraphicErrorWidget(message: 'Tidak Ada Data');
case ResultState.initial: case ResultState.initial:
default:
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
}, },

View File

@ -1,4 +1,3 @@
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/data/model/latest_data_response.dart'; import 'package:agrilink_vocpro/data/model/latest_data_response.dart';
import 'package:agrilink_vocpro/domain/service/app_service.dart'; import 'package:agrilink_vocpro/domain/service/app_service.dart';
@ -18,8 +17,8 @@ class SoilMoistureProvider extends ChangeNotifier {
dataState = ResultState.loading; dataState = ResultState.loading;
notifyListeners(); notifyListeners();
try { try {
final result = await AppService() final result =
.getGraphicDataNpk1(metric: AppConstant.soilMoisture); await AppService().getGraphicDataNpk1(metric: 'soilhumidity');
if (result.data == null || result.data!.npk1!.isEmpty) { if (result.data == null || result.data!.npk1!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {
@ -39,8 +38,8 @@ class SoilMoistureProvider extends ChangeNotifier {
dataState = ResultState.loading; dataState = ResultState.loading;
notifyListeners(); notifyListeners();
try { try {
final result = await AppService() final result =
.getGraphicDataNpk2(metric: AppConstant.soilMoisture); await AppService().getGraphicDataNpk2(metric: 'soilhumidity');
if (result.data == null || result.data!.npk2!.isEmpty) { if (result.data == null || result.data!.npk2!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {

View File

@ -1,8 +1,7 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/core/widgets/error_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/pages/soil_moisture/provider/soil_moisture_provider.dart';
import 'package:agrilink_vocpro/core/widgets/no_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_error_widget.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/soil_moisture/provider/soil_moisture_provider.dart';
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -125,7 +124,7 @@ class SoilMoistureScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'Kelembaban Tanah', 'Soil Moisture',
style: AppTheme.labelMedium, style: AppTheme.labelMedium,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -151,6 +150,7 @@ class SoilMoistureScreen extends StatelessWidget {
child: Consumer<SoilMoistureProvider>( child: Consumer<SoilMoistureProvider>(
builder: (context, provider, child) { builder: (context, provider, child) {
final dataState = provider.dataState; final dataState = provider.dataState;
switch (dataState) { switch (dataState) {
case ResultState.loading: case ResultState.loading:
return const Center(child: CupertinoActivityIndicator()); return const Center(child: CupertinoActivityIndicator());
@ -173,12 +173,14 @@ class SoilMoistureScreen extends StatelessWidget {
? provider.dataFetchedNpk1[index].soilhumidity ?? 0 ? provider.dataFetchedNpk1[index].soilhumidity ?? 0
: provider.dataFetchedNpk2[index].soilhumidity ?? 0, : provider.dataFetchedNpk2[index].soilhumidity ?? 0,
), ),
maxValue: 1,
); );
case ResultState.error: case ResultState.error:
return const ErrorDataStateWidget(); return const GraphicErrorWidget(message: 'Terjadi Kesalahan');
case ResultState.noData: case ResultState.noData:
return const NoDataStateWidget(); return const GraphicErrorWidget(message: 'Tidak Ada Data');
case ResultState.initial: case ResultState.initial:
default:
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
}, },

View File

@ -1,4 +1,3 @@
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/data/model/latest_data_response.dart'; import 'package:agrilink_vocpro/data/model/latest_data_response.dart';
import 'package:agrilink_vocpro/domain/service/app_service.dart'; import 'package:agrilink_vocpro/domain/service/app_service.dart';
@ -19,7 +18,7 @@ class SoilTempProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
try { try {
final result = final result =
await AppService().getGraphicDataNpk1(metric: AppConstant.soilTemp); await AppService().getGraphicDataNpk1(metric: 'soilTemperature');
if (result.data == null || result.data!.npk1!.isEmpty) { if (result.data == null || result.data!.npk1!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {
@ -40,7 +39,7 @@ class SoilTempProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
try { try {
final result = final result =
await AppService().getGraphicDataNpk2(metric: AppConstant.soilTemp); await AppService().getGraphicDataNpk2(metric: 'soilTemperature');
if (result.data == null || result.data!.npk2!.isEmpty) { if (result.data == null || result.data!.npk2!.isEmpty) {
dataState = ResultState.noData; dataState = ResultState.noData;
} else { } else {

View File

@ -1,5 +1,4 @@
import 'package:agrilink_vocpro/core/widgets/error_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_error_widget.dart';
import 'package:agrilink_vocpro/core/widgets/no_data_state_widget.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -7,7 +6,8 @@ import 'package:provider/provider.dart';
import 'package:agrilink_vocpro/core/constant/app_constant.dart'; import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/soil_temperature/provider/soil_temp_provider.dart'; import 'package:agrilink_vocpro/core/widgets/show_info.dart';
import 'package:agrilink_vocpro/features/home/pages/soil_temperature/provider/soil_temp_provider.dart';
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:gauge_indicator/gauge_indicator.dart'; import 'package:gauge_indicator/gauge_indicator.dart';
@ -149,7 +149,7 @@ class SoilTemperatureScreen extends StatelessWidget {
height: 100.h, height: 100.h,
width: 100.w, width: 100.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: color.withValues(alpha: 0.1), color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
border: Border.all(color: color, width: 2), border: Border.all(color: color, width: 2),
), ),
@ -171,7 +171,7 @@ class SoilTemperatureScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'Suhu Tanah', 'Soil Temperature',
style: AppTheme.labelMedium, style: AppTheme.labelMedium,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -179,7 +179,7 @@ class SoilTemperatureScreen extends StatelessWidget {
iconSize: 20.r, iconSize: 20.r,
color: Colors.blue, color: Colors.blue,
onPressed: () { onPressed: () {
showInfo(context, 'Suhu Tanah', AppConstant.soilTempInfo); showInfo(context, 'Soil Temperature', AppConstant.soilTempInfo);
}, },
icon: const Icon(BootstrapIcons.info_circle), icon: const Icon(BootstrapIcons.info_circle),
), ),
@ -226,10 +226,11 @@ class SoilTemperatureScreen extends StatelessWidget {
maxValue: 70, maxValue: 70,
); );
case ResultState.error: case ResultState.error:
return const ErrorDataStateWidget(); return const GraphicErrorWidget(message: 'Terjadi Kesalahan');
case ResultState.noData: case ResultState.noData:
return const NoDataStateWidget(); return const GraphicErrorWidget(message: 'Tidak Ada Data');
case ResultState.initial: case ResultState.initial:
default:
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
}, },
@ -238,30 +239,3 @@ class SoilTemperatureScreen extends StatelessWidget {
); );
} }
} }
Future<dynamic> showInfo(BuildContext context, String title, String content) {
return showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(title),
const SizedBox(height: 16),
Text(
style: Theme.of(context).textTheme.bodySmall,
content,
),
],
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('OK'),
)
],
),
);
}

View File

@ -1,8 +1,6 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/core/widgets/error_data_state_widget.dart'; import 'package:agrilink_vocpro/features/home/pages/temperature/provider/temp_provider.dart';
import 'package:agrilink_vocpro/core/widgets/no_data_state_widget.dart';
import 'package:agrilink_vocpro/features/home/detail_pages/temperature/provider/temp_provider.dart';
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -32,7 +30,7 @@ class TemperatureScreen extends StatelessWidget {
padding: EdgeInsets.only(right: 16), padding: EdgeInsets.only(right: 16),
child: Icon( child: Icon(
BootstrapIcons.thermometer_half, BootstrapIcons.thermometer_half,
color: Colors.orange, color: Colors.red,
), ),
) )
], ],
@ -98,7 +96,7 @@ class TemperatureScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'Suhu Ruangan', 'Temperature',
style: AppTheme.labelMedium, style: AppTheme.labelMedium,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -118,7 +116,7 @@ class TemperatureScreen extends StatelessWidget {
width: 100.w, width: 100.w,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
color: Colors.blue.withValues(alpha: 0.1), color: Colors.blue.withOpacity(0.1),
border: Border.all( border: Border.all(
color: Colors.blue, color: Colors.blue,
width: 2, width: 2,
@ -143,7 +141,7 @@ class TemperatureScreen extends StatelessWidget {
height: 100.h, height: 100.h,
width: 100.w, width: 100.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.green.withValues(alpha: 0.1), color: Colors.green.withOpacity(0.1),
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
border: Border.all( border: Border.all(
color: Colors.green, color: Colors.green,
@ -169,7 +167,7 @@ class TemperatureScreen extends StatelessWidget {
height: 100.h, height: 100.h,
width: 100.w, width: 100.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.orange.withValues(alpha: 0.1), color: Colors.orange.withOpacity(0.1),
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
border: Border.all( border: Border.all(
color: Colors.orange.shade800, color: Colors.orange.shade800,
@ -228,14 +226,47 @@ class TemperatureScreen extends StatelessWidget {
provider.dataFetched[index].vicitemperature provider.dataFetched[index].vicitemperature
?.toDouble() ?? ?.toDouble() ??
0), 0),
maxValue: 60,
); );
case ResultState.error: case ResultState.error:
return ErrorDataStateWidget(); return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
BootstrapIcons.exclamation_circle,
color: Colors.grey.shade400,
),
SizedBox(height: 8.h),
Text(
'Terjadi Kesalahan',
style: AppTheme.labelSmall,
),
],
),
);
case ResultState.noData: case ResultState.noData:
return NoDataStateWidget(); return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
BootstrapIcons.database_fill_x,
color: Colors.grey.shade400,
),
SizedBox(height: 8.h),
Text(
'Tidak Ada Data',
style: AppTheme.labelSmall,
),
],
),
);
case ResultState.initial: case ResultState.initial:
return const SizedBox.shrink(); return const SizedBox.shrink();
default:
return const Center(
child: Text('Default Error'),
);
} }
}, },
), ),

View File

@ -98,7 +98,7 @@ class HomeProvider extends ChangeNotifier {
if (kDebugMode) { if (kDebugMode) {
print('Get Latest Error: $e'); print('Get Latest Error: $e');
} }
dataState = ResultState.hasData; dataState = ResultState.error;
notifyListeners(); notifyListeners();
} }
} }

View File

@ -126,7 +126,6 @@ class _HomeScreenState extends State<HomeScreen> {
), ),
), ),
body: DefaultTabController( body: DefaultTabController(
initialIndex: 1,
length: 3, length: 3,
child: Stack( child: Stack(
children: [ children: [

View File

@ -41,7 +41,7 @@ class DataDisplayerWidget extends StatelessWidget {
borderRadius: BorderRadius.circular(16.r), // Bentuk sudut yang bundar borderRadius: BorderRadius.circular(16.r), // Bentuk sudut yang bundar
), ),
elevation: 20, // Efek bayangan elevation: 20, // Efek bayangan
shadowColor: Colors.grey.withValues(alpha: 0.2), shadowColor: Colors.grey.withOpacity(0.2),
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -52,7 +52,7 @@ class DataDisplayerWidget extends StatelessWidget {
child: Text( child: Text(
censorIdentifier ?? '', censorIdentifier ?? '',
style: AppTheme.labelSmall style: AppTheme.labelSmall
.copyWith(color: textColor.withValues(alpha: 0.5)), .copyWith(color: textColor.withOpacity(0.5)),
), ),
), ),
Icon(icon, color: iconColor, size: 32.r), Icon(icon, color: iconColor, size: 32.r),
@ -67,7 +67,7 @@ class DataDisplayerWidget extends StatelessWidget {
Text( Text(
subtitle, subtitle,
style: AppTheme.labelSmall style: AppTheme.labelSmall
.copyWith(color: textColor.withValues(alpha: 0.5)), .copyWith(color: textColor.withOpacity(0.5)),
), ),
], ],
), ),

View File

@ -3,10 +3,10 @@ import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
class NoDataStateWidget extends StatelessWidget { class GraphicErrorWidget extends StatelessWidget {
const NoDataStateWidget({ const GraphicErrorWidget({super.key, required this.message});
super.key,
}); final String message;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -14,15 +14,9 @@ class NoDataStateWidget extends StatelessWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( Icon(BootstrapIcons.exclamation_circle, color: Colors.grey.shade400),
BootstrapIcons.database_fill_x,
color: Colors.grey.shade400,
),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Text( Text(message, style: AppTheme.labelSmall),
'Tidak Ada Data',
style: AppTheme.labelSmall,
),
], ],
), ),
); );

View File

@ -111,7 +111,7 @@ class GarphicWidget extends StatelessWidget {
show: true, show: true,
gradient: LinearGradient( gradient: LinearGradient(
colors: gradientColors colors: gradientColors
.map((color) => color.withValues(alpha: 0.3)) .map((color) => color.withOpacity(0.3))
.toList()), .toList()),
), ),
), ),

View File

@ -1,4 +1,4 @@
import 'package:agrilink_vocpro/core/extension/extention.dart'; import 'package:agrilink_vocpro/core/constant/app_color.dart';
import 'package:agrilink_vocpro/core/route/app_route.dart'; import 'package:agrilink_vocpro/core/route/app_route.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/features/home/provider/home_provider.dart'; import 'package:agrilink_vocpro/features/home/provider/home_provider.dart';
@ -50,11 +50,13 @@ class ListDataFromCensorDht extends StatelessWidget {
DataDisplayerWidget( DataDisplayerWidget(
title: 'Humidity', title: 'Humidity',
subtitle: 'kelembaban udara', subtitle: 'kelembaban udara',
value: setTwoDigitAfterComma(provider.dhtHumidity.toDouble()), value: provider.dhtHumidity.toString(),
unit: '%', unit: '%',
icon: BootstrapIcons.droplet_half, icon: BootstrapIcons.droplet_half,
color: Colors.white, textColor: Colors.white,
censorIdentifier: 'DHT', color: AppColor.secondary,
iconColor: Colors.white,
censorIdentifier: 'NPK 1',
onTap: () async { onTap: () async {
await context await context
.push('${AppRoute.humidity}/${provider.dhtHumidity}'); .push('${AppRoute.humidity}/${provider.dhtHumidity}');
@ -67,7 +69,6 @@ class ListDataFromCensorDht extends StatelessWidget {
unit: '°C', unit: '°C',
icon: BootstrapIcons.thermometer_half, icon: BootstrapIcons.thermometer_half,
color: Colors.white, color: Colors.white,
censorIdentifier: 'DHT',
onTap: () async { onTap: () async {
await context.push( await context.push(
'${AppRoute.temperature}/${provider.dhtTemperature}'); '${AppRoute.temperature}/${provider.dhtTemperature}');
@ -80,7 +81,6 @@ class ListDataFromCensorDht extends StatelessWidget {
unit: 'lux', unit: 'lux',
icon: BootstrapIcons.sun, icon: BootstrapIcons.sun,
color: Colors.white, color: Colors.white,
censorIdentifier: 'DHT',
onTap: () async { onTap: () async {
await context await context
.push('${AppRoute.light}/${provider.dhtLuminosity}'); .push('${AppRoute.light}/${provider.dhtLuminosity}');
@ -102,6 +102,8 @@ class ListDataFromCensorDht extends StatelessWidget {
)); ));
case ResultState.initial: case ResultState.initial:
return const SizedBox.shrink(); return const SizedBox.shrink();
default:
return const SizedBox.shrink();
} }
}); });
} }

View File

@ -46,58 +46,15 @@ class ListDataFromCensorNpk1 extends StatelessWidget {
childAspectRatio: 0.9, childAspectRatio: 0.9,
), ),
children: [ children: [
DataDisplayerWidget(
title: 'Nitrogen',
subtitle: 'Kadar Nitrogen',
value: provider.npk1SoilNitrogen.toString(),
unit: 'mg/L',
icon: CupertinoIcons.eyedropper,
textColor: Colors.white,
color: AppColor.secondary,
iconColor: Colors.white,
censorIdentifier: censorIdentifier,
onTap: () async {
await context.push(
'${AppRoute.nitrogen}/${provider.npk1SoilNitrogen}/${provider.npk2SoilNitrogen}');
},
),
DataDisplayerWidget(
title: 'Phosphorus',
subtitle: 'Kadar Fosfor',
value: provider.npk1SoilPhosphorus.toString(),
unit: 'mg/L',
icon: CupertinoIcons.eyedropper,
textColor: Colors.white,
color: AppColor.secondary,
iconColor: Colors.white,
censorIdentifier: censorIdentifier,
onTap: () async {
await context.push(
'${AppRoute.phosphorus}/${provider.npk1SoilPhosphorus}/${provider.npk2SoilPhosphorus}');
},
),
DataDisplayerWidget(
title: 'Kalium',
subtitle: 'Kadar kalium',
value: provider.npk1SoilPotassium.toString(),
unit: 'mg/L',
icon: CupertinoIcons.eyedropper,
textColor: Colors.white,
color: AppColor.secondary,
iconColor: Colors.white,
censorIdentifier: censorIdentifier,
onTap: () async {
await context.push(
'${AppRoute.potassium}/${provider.npk1SoilPotassium}/${provider.npk2SoilPotassium}');
},
),
DataDisplayerWidget( DataDisplayerWidget(
title: 'Temperature', title: 'Temperature',
subtitle: 'Suhu tanah', subtitle: 'Suhu tanah',
value: provider.npk1Temperature.toString(), value: provider.npk1Temperature.toString(),
unit: '°C', unit: '°C',
icon: BootstrapIcons.thermometer_half, icon: BootstrapIcons.thermometer_half,
color: Colors.white, textColor: Colors.white,
color: AppColor.secondary,
iconColor: Colors.white,
censorIdentifier: censorIdentifier, censorIdentifier: censorIdentifier,
onTap: () async { onTap: () async {
await context.push( await context.push(
@ -143,6 +100,42 @@ class ListDataFromCensorNpk1 extends StatelessWidget {
'${AppRoute.conductivity}/${provider.npk1SoilEc}/${provider.npk2SoilEc}'); '${AppRoute.conductivity}/${provider.npk1SoilEc}/${provider.npk2SoilEc}');
}, },
), ),
DataDisplayerWidget(
title: 'Nitrogen',
subtitle: 'Kadar Nitrogen',
value: provider.npk1SoilNitrogen.toString(),
unit: 'ppm',
icon: CupertinoIcons.eyedropper,
color: Colors.white,
onTap: () async {
await context.push(
'${AppRoute.nitrogen}/${provider.npk2SoilNitrogen}/${provider.npk1SoilNitrogen}');
},
),
DataDisplayerWidget(
title: 'Potassium',
subtitle: 'Kadar kalium',
value: provider.npk1SoilPotassium.toString(),
unit: 'ppm',
icon: CupertinoIcons.eyedropper,
color: Colors.white,
onTap: () async {
await context.push(
'${AppRoute.potassium}/${provider.npk1SoilPotassium}/${provider.npk2SoilPotassium}');
},
),
DataDisplayerWidget(
title: 'Phosphorus',
subtitle: 'Kadar Fosfor',
value: provider.npk1SoilPhosphorus.toString(),
unit: 'ppm',
icon: CupertinoIcons.eyedropper,
color: Colors.white,
onTap: () async {
await context.push(
'${AppRoute.phosphorus}/${provider.npk1SoilPhosphorus}/${provider.npk2SoilPhosphorus}');
},
),
], ],
); );
case ResultState.noData: case ResultState.noData:

View File

@ -18,7 +18,7 @@ class ListDataFromCensorNpk2 extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
const String censorIdentifier = 'NPK 2'; const String censorIdentifier = 'NPK 1';
return Consumer<HomeProvider>(builder: (context, provider, child) { return Consumer<HomeProvider>(builder: (context, provider, child) {
switch (provider.dataState) { switch (provider.dataState) {
case ResultState.loading: case ResultState.loading:
@ -46,58 +46,15 @@ class ListDataFromCensorNpk2 extends StatelessWidget {
childAspectRatio: 0.9, childAspectRatio: 0.9,
), ),
children: [ children: [
DataDisplayerWidget(
title: 'Nitrogen',
subtitle: 'Kadar Nitrogen',
value: provider.npk2SoilNitrogen.toString(),
unit: 'mg/L',
icon: CupertinoIcons.eyedropper,
textColor: Colors.white,
color: AppColor.secondary,
censorIdentifier: censorIdentifier,
iconColor: Colors.white,
onTap: () async {
await context.push(
'${AppRoute.nitrogen}/${provider.npk1SoilNitrogen}/${provider.npk2SoilNitrogen}');
},
),
DataDisplayerWidget(
title: 'Phosphorus',
subtitle: 'Kadar Fosfor',
value: provider.npk2SoilPhosphorus.toString(),
unit: 'mg/L',
icon: CupertinoIcons.eyedropper,
textColor: Colors.white,
color: AppColor.secondary,
iconColor: Colors.white,
censorIdentifier: censorIdentifier,
onTap: () async {
await context.push(
'${AppRoute.phosphorus}/${provider.npk1SoilPhosphorus}/${provider.npk2SoilPhosphorus}');
},
),
DataDisplayerWidget(
title: 'Kalium',
subtitle: 'Kadar kalium',
value: provider.npk2SoilPotassium.toString(),
unit: 'mg/L',
icon: CupertinoIcons.eyedropper,
textColor: Colors.white,
color: AppColor.secondary,
iconColor: Colors.white,
censorIdentifier: censorIdentifier,
onTap: () async {
await context.push(
'${AppRoute.potassium}/${provider.npk1SoilPotassium}/${provider.npk2SoilPotassium}');
},
),
DataDisplayerWidget( DataDisplayerWidget(
title: 'Temperature', title: 'Temperature',
subtitle: 'Suhu tanah', subtitle: 'Suhu tanah',
value: provider.npk2Temperature.toString(), value: provider.npk2Temperature.toString(),
unit: '°C', unit: '°C',
icon: BootstrapIcons.thermometer_half, icon: BootstrapIcons.thermometer_half,
color: Colors.white, textColor: Colors.white,
color: AppColor.secondary,
iconColor: Colors.white,
censorIdentifier: censorIdentifier, censorIdentifier: censorIdentifier,
onTap: () async { onTap: () async {
await context.push( await context.push(
@ -143,6 +100,42 @@ class ListDataFromCensorNpk2 extends StatelessWidget {
'${AppRoute.conductivity}/${provider.npk1SoilEc}/${provider.npk2SoilEc}'); '${AppRoute.conductivity}/${provider.npk1SoilEc}/${provider.npk2SoilEc}');
}, },
), ),
DataDisplayerWidget(
title: 'Nitrogen',
subtitle: 'Kadar Nitrogen',
value: provider.npk2SoilNitrogen.toString(),
unit: 'ppm',
icon: CupertinoIcons.eyedropper,
color: Colors.white,
onTap: () async {
await context.push(
'${AppRoute.nitrogen}/${provider.npk2SoilNitrogen}/${provider.npk1SoilNitrogen}');
},
),
DataDisplayerWidget(
title: 'Potassium',
subtitle: 'Kadar kalium',
value: provider.npk2SoilPotassium.toString(),
unit: 'ppm',
icon: CupertinoIcons.eyedropper,
color: Colors.white,
onTap: () async {
await context.push(
'${AppRoute.potassium}/${provider.npk1SoilPotassium}/${provider.npk2SoilPotassium}');
},
),
DataDisplayerWidget(
title: 'Phosphorus',
subtitle: 'Kadar Fosfor',
value: provider.npk2SoilPhosphorus.toString(),
unit: 'ppm',
icon: CupertinoIcons.eyedropper,
color: Colors.white,
onTap: () async {
await context.push(
'${AppRoute.phosphorus}/${provider.npk1SoilPhosphorus}/${provider.npk2SoilPhosphorus}');
},
),
], ],
); );
case ResultState.noData: case ResultState.noData:

View File

@ -15,10 +15,10 @@ class PlantsScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.eco_rounded, size: 100.r, color: AppColor.secondary), Icon(Icons.eco_rounded, size: 100.r, color: AppColor.secondary),
Text('Segera Hadir', style: AppTheme.titleLarge), Text('Coming Soon', style: AppTheme.titleLarge),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Text( Text(
'Fitur ini sedang dalam tahap pengembangan', 'This featureis under development',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: AppTheme.labelSmall, style: AppTheme.labelSmall,
), ),

View File

@ -10,13 +10,11 @@ class SettingProvider extends ChangeNotifier {
String userFullName = ''; String userFullName = '';
String userEmail = ''; String userEmail = '';
String userName = '';
void _init() async { void _init() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
userFullName = prefs.getString('fullName') ?? 'unknown'; userFullName = prefs.getString('fullName') ?? 'unknown';
userEmail = prefs.getString('email') ?? 'unknown'; userEmail = prefs.getString('email') ?? 'unknown';
userName = prefs.getString('username') ?? 'unknown';
notifyListeners(); notifyListeners();
} }

View File

@ -1,40 +0,0 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/features/setting/provider/setting_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:provider/provider.dart';
class AccountScreen extends StatelessWidget {
const AccountScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Detail Akun', style: AppTheme.labelMedium),
centerTitle: true,
backgroundColor: Colors.white,
scrolledUnderElevation: 0,
),
body: Consumer<SettingProvider>(builder: (context, provider, child) {
return ListView(
padding: EdgeInsets.all(16.r),
children: [
ListTile(
title: Text('Username', style: AppTheme.labelMedium),
trailing: Text(provider.userName, style: AppTheme.labelSmall),
),
ListTile(
title: Text('Email', style: AppTheme.labelMedium),
trailing: Text(provider.userEmail, style: AppTheme.labelSmall),
),
ListTile(
title: Text('Name', style: AppTheme.labelMedium),
trailing: Text(provider.userFullName, style: AppTheme.labelSmall),
),
],
);
}),
);
}
}

View File

@ -16,7 +16,7 @@ class SettingScreen extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('Pengaturan', style: AppTheme.labelMedium), title: Text('Setting', style: AppTheme.labelMedium),
centerTitle: true, centerTitle: true,
backgroundColor: Colors.white, backgroundColor: Colors.white,
scrolledUnderElevation: 0, scrolledUnderElevation: 0,
@ -52,7 +52,7 @@ class SettingScreen extends StatelessWidget {
children: [ children: [
ListTile( ListTile(
tileColor: Colors.white, tileColor: Colors.white,
title: Text('Akun', title: Text('Account',
style: AppTheme.labelSmall style: AppTheme.labelSmall
.copyWith(color: Colors.black87)), .copyWith(color: Colors.black87)),
leading: const Icon(BootstrapIcons.person), leading: const Icon(BootstrapIcons.person),
@ -60,37 +60,35 @@ class SettingScreen extends StatelessWidget {
Icons.arrow_forward_ios, Icons.arrow_forward_ios,
size: 16.r, size: 16.r,
), ),
onTap: () { onTap: () {},
context.go(AppRoute.account);
},
), ),
// 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( ListTile(
tileColor: Colors.white, tileColor: Colors.white,
title: Text('Keluar', 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)), style: AppTheme.labelSmall.copyWith(color: Colors.red)),
leading: const Icon( leading: const Icon(
BootstrapIcons.box_arrow_right, BootstrapIcons.box_arrow_right,

View File

@ -58,7 +58,7 @@ class _SplashScreenState extends State<SplashScreen> {
} }
void _navigateAfterSplash(bool isLoggedIn) { void _navigateAfterSplash(bool isLoggedIn) {
Timer(const Duration(seconds: 1), () { Timer(const Duration(seconds: 2), () {
if (isLoggedIn == true) { if (isLoggedIn == true) {
context.go(AppRoute.dashboard); context.go(AppRoute.dashboard);
} else { } else {

View File

@ -5,10 +5,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _flutterfire_internals name: _flutterfire_internals
sha256: eae3133cbb06de9205899b822e3897fc6a8bc278ad4c944b4ce612689369694b sha256: "5534e701a2c505fed1f0799e652dd6ae23bd4d2c4cf797220e5ced5764a7c1c2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.47" version: "1.3.44"
animated_segmented_tab_control: animated_segmented_tab_control:
dependency: "direct main" dependency: "direct main"
description: description:
@ -29,18 +29,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: async name: async
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.12.0" version: "2.11.0"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
name: boolean_selector name: boolean_selector
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.2" version: "2.1.1"
bootstrap_icons: bootstrap_icons:
dependency: "direct main" dependency: "direct main"
description: description:
@ -61,42 +61,42 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: charcode name: charcode
sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.3.1"
clock: clock:
dependency: transitive dependency: transitive
description: description:
name: clock name: clock
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.2" version: "1.1.1"
collection: collection:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.19.0" version: "1.18.0"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
name: crypto name: crypto
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.6" version: "3.0.5"
csslib: csslib:
dependency: transitive dependency: transitive
description: description:
name: csslib name: csslib
sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.2" version: "1.0.0"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
@ -125,10 +125,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: equatable name: equatable
sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.7" version: "2.0.5"
event_bus: event_bus:
dependency: transitive dependency: transitive
description: description:
@ -141,10 +141,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: fake_async name: fake_async
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.2" version: "1.3.1"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
@ -165,58 +165,58 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: firebase_core name: firebase_core
sha256: fef81a53ba1ca618def1f8bef4361df07968434e62cb204c1fb90bb880a03da2 sha256: "51dfe2fbf3a984787a2e7b8592f2f05c986bfedd6fdacea3f9e0a7beb334de96"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.8.1" version: "3.6.0"
firebase_core_platform_interface: firebase_core_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: firebase_core_platform_interface name: firebase_core_platform_interface
sha256: b94b217e3ad745e784960603d33d99471621ecca151c99c670869b76e50ad2a6 sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.3.1" version: "5.3.0"
firebase_core_web: firebase_core_web:
dependency: transitive dependency: transitive
description: description:
name: firebase_core_web name: firebase_core_web
sha256: "9e69806bb3d905aeec3c1242e0e1475de6ea6d48f456af29d598fb229a2b4e5e" sha256: f967a7138f5d2ffb1ce15950e2a382924239eaa521150a8f144af34e68b3b3e5
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.18.2" version: "2.18.1"
firebase_messaging: firebase_messaging:
dependency: "direct main" dependency: "direct main"
description: description:
name: firebase_messaging name: firebase_messaging
sha256: "151a3ee68736abf293aab66d1317ade53c88abe1db09c75a0460aebf7767bbdf" sha256: eb6e28a3a35deda61fe8634967c84215efc19133ba58d8e0fc6c9a2af2cba05e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "15.1.6" version: "15.1.3"
firebase_messaging_platform_interface: firebase_messaging_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: firebase_messaging_platform_interface name: firebase_messaging_platform_interface
sha256: f331ee51e40c243f90cc7bc059222dfec4e5df53125b08d31fb28961b00d2a9d sha256: b316c4ee10d93d32c033644207afc282d9b2b4372f3cf9c6022f3558b3873d2d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.5.49" version: "4.5.46"
firebase_messaging_web: firebase_messaging_web:
dependency: transitive dependency: transitive
description: description:
name: firebase_messaging_web name: firebase_messaging_web
sha256: efaf3fdc54cd77e0eedb8e75f7f01c808828c64d052ddbf94d3009974e47d30f sha256: d7f0147a1a9fe4313168e20154a01fd5cf332898de1527d3930ff77b8c7f5387
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.9.5" version: "3.9.2"
fl_chart: fl_chart:
dependency: "direct main" dependency: "direct main"
description: description:
name: fl_chart name: fl_chart
sha256: "74959b99b92b9eebeed1a4049426fd67c4abc3c5a0f4d12e2877097d6a11ae08" sha256: "94307bef3a324a0d329d3ab77b2f0c6e5ed739185ffc029ed28c0f9b019ea7ef"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.69.2" version: "0.69.0"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -260,10 +260,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: go_router name: go_router
sha256: "2fd11229f59e23e967b0775df8d5948a519cd7e1e8b6e849729e010587b46539" sha256: "6f1b756f6e863259a99135ff3c95026c3cdca17d10ebef2bba2261a25ddc8bbc"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.6.2" version: "14.3.0"
google_fonts: google_fonts:
dependency: "direct main" dependency: "direct main"
description: description:
@ -276,10 +276,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: google_identity_services_web name: google_identity_services_web
sha256: "55580f436822d64c8ff9a77e37d61f5fb1e6c7ec9d632a43ee324e2a05c3c6c9" sha256: "5be191523702ba8d7a01ca97c17fca096822ccf246b0a9f11923a6ded06199b6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.3" version: "0.3.1+4"
googleapis_auth: googleapis_auth:
dependency: "direct main" dependency: "direct main"
description: description:
@ -292,10 +292,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: html name: html
sha256: "1fc58edeaec4307368c60d59b7e15b9d658b57d7f3125098b6294153c75337ec" sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.15.5" version: "0.15.4"
http: http:
dependency: "direct main" dependency: "direct main"
description: description:
@ -308,10 +308,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: http_parser name: http_parser
sha256: "76d306a1c3afb33fe82e2bbacad62a61f409b5634c915fceb0d799de1a913360" sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.1" version: "4.0.2"
intl: intl:
dependency: "direct main" dependency: "direct main"
description: description:
@ -332,18 +332,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker name: leak_tracker
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.8" version: "10.0.5"
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_flutter_testing name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.9" version: "3.0.5"
leak_tracker_testing: leak_tracker_testing:
dependency: transitive dependency: transitive
description: description:
@ -356,18 +356,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: lints name: lints
sha256: "4a16b3f03741e1252fda5de3ce712666d010ba2122f8e912c94f9f7b90e1a4c3" sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.1.0" version: "5.0.0"
logging: logging:
dependency: transitive dependency: transitive
description: description:
name: logging name: logging
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.2.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@ -412,34 +412,34 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.9.0"
path_provider: path_provider:
dependency: transitive dependency: transitive
description: description:
name: path_provider name: path_provider
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.5" version: "2.1.4"
path_provider_android: path_provider_android:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.15" version: "2.2.12"
path_provider_foundation: path_provider_foundation:
dependency: transitive dependency: transitive
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.1" version: "2.4.0"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
@ -468,10 +468,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: platform name: platform
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.6" version: "3.1.5"
plugin_platform_interface: plugin_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -492,18 +492,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences name: shared_preferences
sha256: "95f9997ca1fb9799d494d0cb2a780fd7be075818d59f00c43832ed112b158a82" sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.3" version: "2.3.2"
shared_preferences_android: shared_preferences_android:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: "7f172d1b06de5da47b6264c2692ee2ead20bbbc246690427cdb4fc301cd0c549" sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.4" version: "2.3.3"
shared_preferences_foundation: shared_preferences_foundation:
dependency: transitive dependency: transitive
description: description:
@ -556,7 +556,7 @@ packages:
dependency: transitive dependency: transitive
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.99"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
@ -569,10 +569,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.12.0" version: "1.11.1"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
@ -585,10 +585,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: string_scanner name: string_scanner
sha256: "0bd04f5bb74fcd6ff0606a888a30e917af9bd52820b178eaa464beb11dca84b6" sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.2.0"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
@ -601,18 +601,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.3" version: "0.7.2"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
name: typed_data name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.3.2"
universal_html: universal_html:
dependency: transitive dependency: transitive
description: description:
@ -641,10 +641,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.3.1" version: "14.2.5"
web: web:
dependency: transitive dependency: transitive
description: description:
@ -662,5 +662,5 @@ packages:
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
sdks: sdks:
dart: ">=3.6.0-0 <4.0.0" dart: ">=3.5.1 <4.0.0"
flutter: ">=3.24.0" flutter: ">=3.24.0"

Binary file not shown.