feat: integrate with Rest API, feature home latest data update
This commit is contained in:
parent
5ddc748bc9
commit
08c7012f1d
|
|
@ -2,7 +2,7 @@ class AppConstant {
|
|||
static const String appName = 'Kebun Pintar';
|
||||
static const String appVersion = '1.0.0';
|
||||
|
||||
static const String baseUrl = 'http://192.168.11.41:3333/api/';
|
||||
static const String baseUrl = 'https://jx027dj4-3333.asse.devtunnels.ms/api';
|
||||
|
||||
static const String mqttServer = 'armadillo.rmq.cloudamqp.com';
|
||||
static const String mqttUsername = 'obyskxhx:obyskxhx';
|
||||
|
|
@ -10,4 +10,19 @@ class AppConstant {
|
|||
|
||||
static const String soilTempInfo =
|
||||
'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.';
|
||||
|
||||
static const String npk1 = 'npk1';
|
||||
static const String npk2 = 'npk2';
|
||||
static const String dht = 'dht';
|
||||
|
||||
static const String soilTemp = 'soilTemperature';
|
||||
static const String soilMoisture = 'soilMoisture';
|
||||
static const String airTemp = 'viciTemperature';
|
||||
static const String humidity = 'humidity';
|
||||
static const String lightIntensity = 'lightIntensity';
|
||||
static const String conductivity = 'conductivity';
|
||||
static const String ph = 'ph';
|
||||
static const String nitrogen = 'nitrogen';
|
||||
static const String phosphorus = 'phosphorus';
|
||||
static const String potassium = 'potassium';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,12 @@ String dateFormater(String date) {
|
|||
return formatter.format(dateTime);
|
||||
}
|
||||
|
||||
String dateFormatterShort(String date) {
|
||||
final DateTime dateTime = DateTime.parse(date);
|
||||
final DateFormat formatter = DateFormat('yyyy-MM-dd');
|
||||
return formatter.format(dateTime);
|
||||
}
|
||||
|
||||
String getGreeting(String time) {
|
||||
DateTime parsedTime = DateTime.parse(time);
|
||||
int hour = parsedTime.hour;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
|
||||
import 'package:agrilink_vocpro/core/extension/extention.dart';
|
||||
import 'package:agrilink_vocpro/data/model/relay_response.dart';
|
||||
import 'package:agrilink_vocpro/features/home/model/latest_data_response.dart';
|
||||
import 'package:agrilink_vocpro/features/home/model/npk1_soil_temp_grafik.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
|
|
@ -27,4 +30,47 @@ class AppService {
|
|||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Npk1SoilTempGrafik> getNpk1SoilTempGrafik({
|
||||
required String metric,
|
||||
required String sensor,
|
||||
}) async {
|
||||
String dateNow = DateTime.now().toString();
|
||||
String dateYesterday =
|
||||
DateTime.now().subtract(Duration(days: 1)).toString();
|
||||
final formatedDateNow = dateFormatterShort(dateNow);
|
||||
final formatedDateYesterday = dateFormatterShort(dateYesterday);
|
||||
try {
|
||||
final result = await _dioWithoutInterceptor.get(
|
||||
'/sensor/getData?metric=$metric&range[start]=$formatedDateYesterday&range[end]=$formatedDateNow&range[time_range]=HOURLY&sensor=$sensor',
|
||||
);
|
||||
if (result.statusCode == 200) {
|
||||
print(result.data.toString());
|
||||
final data = Npk1SoilTempGrafik.fromJson(result.data);
|
||||
return data;
|
||||
} else {
|
||||
throw Exception('Failed to load data');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
print(e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<LatestDataResponse> getLatestData() async {
|
||||
try {
|
||||
final result = await _dioWithoutInterceptor.get(
|
||||
'/sensor/getLatest',
|
||||
);
|
||||
if (result.statusCode == 200) {
|
||||
final data = LatestDataResponse.fromJson(result.data);
|
||||
return data;
|
||||
} else {
|
||||
throw Exception('Failed to load data');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
print(e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ class ControlProvider extends ChangeNotifier {
|
|||
relayState = ResultState.loading;
|
||||
notifyListeners();
|
||||
try {
|
||||
print('try to get relay status...');
|
||||
final result = await _appService.getRelayStatus();
|
||||
if (result.success == true) {
|
||||
for (var element in result.data!) {
|
||||
|
|
|
|||
|
|
@ -61,33 +61,38 @@ class ControlScreen extends StatelessWidget {
|
|||
}),
|
||||
SizedBox(height: 16.h),
|
||||
GridView(
|
||||
padding: EdgeInsets.all(16.r),
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16.r,
|
||||
mainAxisSpacing: 16.r,
|
||||
childAspectRatio: 1.4.h,
|
||||
padding: EdgeInsets.all(16.r),
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16.r,
|
||||
mainAxisSpacing: 16.r,
|
||||
childAspectRatio: 1.35.h,
|
||||
),
|
||||
children: [
|
||||
ControlButtonWidget(
|
||||
title: 'Katup Air',
|
||||
subtitle: 'Relay 1',
|
||||
isActive: provider.control_1,
|
||||
onTap: () {
|
||||
provider.control_1 != true
|
||||
? provider.switchControl1(true)
|
||||
: provider.switchControl1(false);
|
||||
},
|
||||
),
|
||||
children: [
|
||||
ControlButtonWidget(
|
||||
title: 'Katup Air',
|
||||
subtitle: 'Relay 1',
|
||||
isActive: provider.control_1,
|
||||
onTap: () {
|
||||
provider.control_1 != true
|
||||
? provider.switchControl1(true)
|
||||
: provider.switchControl1(false);
|
||||
},
|
||||
),
|
||||
ControlButtonWidget(
|
||||
title: 'Lampu Utama',
|
||||
subtitle: 'Relay 2',
|
||||
isActive: provider.control_2,
|
||||
onTap: () {},
|
||||
),
|
||||
]),
|
||||
ControlButtonWidget(
|
||||
title: 'Lampu Utama',
|
||||
subtitle: 'Relay 2',
|
||||
isActive: provider.control_2,
|
||||
onTap: () {
|
||||
provider.control_2 != true
|
||||
? provider.switchControl2(true)
|
||||
: provider.switchControl2(false);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
class DhtGraphicResponse {
|
||||
DataDht? data;
|
||||
int? statusCode;
|
||||
String? message;
|
||||
|
||||
DhtGraphicResponse({this.data, this.statusCode, this.message});
|
||||
|
||||
DhtGraphicResponse.fromJson(Map<String, dynamic> json) {
|
||||
data = json['data'] != null ? DataDht.fromJson(json['data']) : null;
|
||||
statusCode = json['statusCode'];
|
||||
message = json['message'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (this.data != null) {
|
||||
data['data'] = this.data!.toJson();
|
||||
}
|
||||
data['statusCode'] = statusCode;
|
||||
data['message'] = message;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class DataDht {
|
||||
List<Dht>? dht;
|
||||
|
||||
DataDht({this.dht});
|
||||
|
||||
DataDht.fromJson(Map<String, dynamic> json) {
|
||||
if (json['dht'] != null) {
|
||||
dht = <Dht>[];
|
||||
json['dht'].forEach((v) {
|
||||
dht!.add(Dht.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (dht != null) {
|
||||
data['dht'] = dht!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Dht {
|
||||
int? hour;
|
||||
double? vicitemperatureAvg;
|
||||
double? vicihumidityAvg;
|
||||
double? viciluminosityAvg;
|
||||
|
||||
Dht(
|
||||
{this.hour,
|
||||
this.vicitemperatureAvg,
|
||||
this.vicihumidityAvg,
|
||||
this.viciluminosityAvg});
|
||||
|
||||
Dht.fromJson(Map<String, dynamic> json) {
|
||||
hour = json['hour'];
|
||||
vicitemperatureAvg = json['vicitemperature_avg'];
|
||||
vicihumidityAvg = json['vicihumidity_avg'];
|
||||
viciluminosityAvg = json['viciluminosity_avg'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['hour'] = hour;
|
||||
data['vicitemperature_avg'] = vicitemperatureAvg;
|
||||
data['vicihumidity_avg'] = vicihumidityAvg;
|
||||
data['viciluminosity_avg'] = viciluminosityAvg;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
class LatestDataResponse {
|
||||
Data? data;
|
||||
int? statusCode;
|
||||
String? message;
|
||||
|
||||
LatestDataResponse({this.data, this.statusCode, this.message});
|
||||
|
||||
LatestDataResponse.fromJson(Map<String, dynamic> json) {
|
||||
data = json['data'] != null ? Data.fromJson(json['data']) : null;
|
||||
statusCode = json['statusCode'];
|
||||
message = json['message'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (this.data != null) {
|
||||
data['data'] = this.data!.toJson();
|
||||
}
|
||||
data['statusCode'] = statusCode;
|
||||
data['message'] = message;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Data {
|
||||
List<Dht>? dht;
|
||||
List<Npk1>? npk1;
|
||||
List<Npk2>? npk2;
|
||||
|
||||
Data({this.dht, this.npk1, this.npk2});
|
||||
|
||||
Data.fromJson(Map<String, dynamic> json) {
|
||||
if (json['dht'] != null) {
|
||||
dht = <Dht>[];
|
||||
json['dht'].forEach((v) {
|
||||
dht!.add(Dht.fromJson(v));
|
||||
});
|
||||
}
|
||||
if (json['npk1'] != null) {
|
||||
npk1 = <Npk1>[];
|
||||
json['npk1'].forEach((v) {
|
||||
npk1!.add(Npk1.fromJson(v));
|
||||
});
|
||||
}
|
||||
if (json['npk2'] != null) {
|
||||
npk2 = <Npk2>[];
|
||||
json['npk2'].forEach((v) {
|
||||
npk2!.add(Npk2.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (dht != null) {
|
||||
data['dht'] = dht!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
if (npk1 != null) {
|
||||
data['npk1'] = npk1!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
if (npk2 != null) {
|
||||
data['npk2'] = npk2!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Dht {
|
||||
int? hour;
|
||||
num? vicitemperatureAvg;
|
||||
num? vicihumidityAvg;
|
||||
num? viciluminosityAvg;
|
||||
|
||||
Dht(
|
||||
{this.hour,
|
||||
this.vicitemperatureAvg,
|
||||
this.vicihumidityAvg,
|
||||
this.viciluminosityAvg});
|
||||
|
||||
Dht.fromJson(Map<String, dynamic> json) {
|
||||
hour = json['hour'];
|
||||
vicitemperatureAvg = json['vicitemperature_avg'];
|
||||
vicihumidityAvg = json['vicihumidity_avg'];
|
||||
viciluminosityAvg = json['viciluminosity_avg'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['hour'] = hour;
|
||||
data['vicitemperature_avg'] = vicitemperatureAvg;
|
||||
data['vicihumidity_avg'] = vicihumidityAvg;
|
||||
data['viciluminosity_avg'] = viciluminosityAvg;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Npk1 {
|
||||
int? hour;
|
||||
num? soiltemperatureAvg;
|
||||
num? soilhumidityAvg;
|
||||
num? soilconductivityAvg;
|
||||
num? soilphAvg;
|
||||
num? soilnitrogenAvg;
|
||||
num? soilphosphorusAvg;
|
||||
num? soilpotassiumAvg;
|
||||
|
||||
Npk1(
|
||||
{this.hour,
|
||||
this.soiltemperatureAvg,
|
||||
this.soilhumidityAvg,
|
||||
this.soilconductivityAvg,
|
||||
this.soilphAvg,
|
||||
this.soilnitrogenAvg,
|
||||
this.soilphosphorusAvg,
|
||||
this.soilpotassiumAvg});
|
||||
|
||||
Npk1.fromJson(Map<String, dynamic> json) {
|
||||
hour = json['hour'];
|
||||
soiltemperatureAvg = json['soiltemperature_avg'];
|
||||
soilhumidityAvg = json['soilhumidity_avg'];
|
||||
soilconductivityAvg = json['soilconductivity_avg'];
|
||||
soilphAvg = json['soilph_avg'];
|
||||
soilnitrogenAvg = json['soilnitrogen_avg'];
|
||||
soilphosphorusAvg = json['soilphosphorus_avg'];
|
||||
soilpotassiumAvg = json['soilpotassium_avg'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['hour'] = hour;
|
||||
data['soiltemperature_avg'] = soiltemperatureAvg;
|
||||
data['soilhumidity_avg'] = soilhumidityAvg;
|
||||
data['soilconductivity_avg'] = soilconductivityAvg;
|
||||
data['soilph_avg'] = soilphAvg;
|
||||
data['soilnitrogen_avg'] = soilnitrogenAvg;
|
||||
data['soilphosphorus_avg'] = soilphosphorusAvg;
|
||||
data['soilpotassium_avg'] = soilpotassiumAvg;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Npk2 {
|
||||
int? hour;
|
||||
num? soiltemperatureAvg;
|
||||
num? soilhumidityAvg;
|
||||
num? soilconductivityAvg;
|
||||
num? soilphAvg;
|
||||
num? soilnitrogenAvg;
|
||||
num? soilphosphorusAvg;
|
||||
num? soilpotassiumAvg;
|
||||
|
||||
Npk2(
|
||||
{this.hour,
|
||||
this.soiltemperatureAvg,
|
||||
this.soilhumidityAvg,
|
||||
this.soilconductivityAvg,
|
||||
this.soilphAvg,
|
||||
this.soilnitrogenAvg,
|
||||
this.soilphosphorusAvg,
|
||||
this.soilpotassiumAvg});
|
||||
|
||||
Npk2.fromJson(Map<String, dynamic> json) {
|
||||
hour = json['hour'];
|
||||
soiltemperatureAvg = json['soiltemperature_avg'];
|
||||
soilhumidityAvg = json['soilhumidity_avg'];
|
||||
soilconductivityAvg = json['soilconductivity_avg'];
|
||||
soilphAvg = json['soilph_avg'];
|
||||
soilnitrogenAvg = json['soilnitrogen_avg'];
|
||||
soilphosphorusAvg = json['soilphosphorus_avg'];
|
||||
soilpotassiumAvg = json['soilpotassium_avg'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['hour'] = hour;
|
||||
data['soiltemperature_avg'] = soiltemperatureAvg;
|
||||
data['soilhumidity_avg'] = soilhumidityAvg;
|
||||
data['soilconductivity_avg'] = soilconductivityAvg;
|
||||
data['soilph_avg'] = soilphAvg;
|
||||
data['soilnitrogen_avg'] = soilnitrogenAvg;
|
||||
data['soilphosphorus_avg'] = soilphosphorusAvg;
|
||||
data['soilpotassium_avg'] = soilpotassiumAvg;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
class Npk1GraphicResponse {
|
||||
DataNpk1? data;
|
||||
int? statusCode;
|
||||
String? message;
|
||||
|
||||
Npk1GraphicResponse({this.data, this.statusCode, this.message});
|
||||
|
||||
Npk1GraphicResponse.fromJson(Map<String, dynamic> json) {
|
||||
data = json['data'] != null ? DataNpk1.fromJson(json['data']) : null;
|
||||
statusCode = json['statusCode'];
|
||||
message = json['message'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (this.data != null) {
|
||||
data['data'] = this.data!.toJson();
|
||||
}
|
||||
data['statusCode'] = statusCode;
|
||||
data['message'] = message;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class DataNpk1 {
|
||||
List<Npk1>? npk1;
|
||||
|
||||
DataNpk1({this.npk1});
|
||||
|
||||
DataNpk1.fromJson(Map<String, dynamic> json) {
|
||||
if (json['npk1'] != null) {
|
||||
npk1 = <Npk1>[];
|
||||
json['npk1'].forEach((v) {
|
||||
npk1!.add(Npk1.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (npk1 != null) {
|
||||
data['npk1'] = npk1!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Npk1 {
|
||||
int? hour;
|
||||
double? soiltemperatureAvg;
|
||||
double? soilhumidityAvg;
|
||||
double? soilconductivityAvg;
|
||||
double? soilphAvg;
|
||||
double? soilnitrogenAvg;
|
||||
double? soilphosphorusAvg;
|
||||
double? soilpotassiumAvg;
|
||||
|
||||
Npk1(
|
||||
{this.hour,
|
||||
this.soiltemperatureAvg,
|
||||
this.soilhumidityAvg,
|
||||
this.soilconductivityAvg,
|
||||
this.soilphAvg,
|
||||
this.soilnitrogenAvg,
|
||||
this.soilphosphorusAvg,
|
||||
this.soilpotassiumAvg});
|
||||
|
||||
Npk1.fromJson(Map<String, dynamic> json) {
|
||||
hour = json['hour'];
|
||||
soiltemperatureAvg = json['soiltemperature_avg'];
|
||||
soilhumidityAvg = json['soilhumidity_avg'];
|
||||
soilconductivityAvg = json['soilconductivity_avg'];
|
||||
soilphAvg = json['soilph_avg'];
|
||||
soilnitrogenAvg = json['soilnitrogen_avg'];
|
||||
soilphosphorusAvg = json['soilphosphorus_avg'];
|
||||
soilpotassiumAvg = json['soilpotassium_avg'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['hour'] = hour;
|
||||
data['soiltemperature_avg'] = soiltemperatureAvg;
|
||||
data['soilhumidity_avg'] = soilhumidityAvg;
|
||||
data['soilconductivity_avg'] = soilconductivityAvg;
|
||||
data['soilph_avg'] = soilphAvg;
|
||||
data['soilnitrogen_avg'] = soilnitrogenAvg;
|
||||
data['soilphosphorus_avg'] = soilphosphorusAvg;
|
||||
data['soilpotassium_avg'] = soilpotassiumAvg;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
class Npk1SoilTempGrafik {
|
||||
Data? data;
|
||||
int? statusCode;
|
||||
String? message;
|
||||
|
||||
Npk1SoilTempGrafik({this.data, this.statusCode, this.message});
|
||||
|
||||
Npk1SoilTempGrafik.fromJson(Map<String, dynamic> json) {
|
||||
data = json['data'] != null ? Data.fromJson(json['data']) : null;
|
||||
statusCode = json['statusCode'];
|
||||
message = json['message'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (this.data != null) {
|
||||
data['data'] = this.data!.toJson();
|
||||
}
|
||||
data['statusCode'] = statusCode;
|
||||
data['message'] = message;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Data {
|
||||
List<Npk1>? npk1;
|
||||
|
||||
Data({this.npk1});
|
||||
|
||||
Data.fromJson(Map<String, dynamic> json) {
|
||||
if (json['npk1'] != null) {
|
||||
npk1 = <Npk1>[];
|
||||
json['npk1'].forEach((v) {
|
||||
npk1!.add(Npk1.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (npk1 != null) {
|
||||
data['npk1'] = npk1!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Npk1 {
|
||||
num? hour;
|
||||
num? soiltemperatureAvg;
|
||||
|
||||
Npk1({this.hour, this.soiltemperatureAvg});
|
||||
|
||||
Npk1.fromJson(Map<String, dynamic> json) {
|
||||
hour = json['hour'];
|
||||
soiltemperatureAvg = json['soiltemperature_avg'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['hour'] = hour;
|
||||
data['soiltemperature_avg'] = soiltemperatureAvg;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
class Npk2GraphicResponse {
|
||||
DataNpk2? data;
|
||||
int? statusCode;
|
||||
String? message;
|
||||
|
||||
Npk2GraphicResponse({this.data, this.statusCode, this.message});
|
||||
|
||||
Npk2GraphicResponse.fromJson(Map<String, dynamic> json) {
|
||||
data = json['data'] != null ? DataNpk2.fromJson(json['data']) : null;
|
||||
statusCode = json['statusCode'];
|
||||
message = json['message'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (this.data != null) {
|
||||
data['data'] = this.data!.toJson();
|
||||
}
|
||||
data['statusCode'] = statusCode;
|
||||
data['message'] = message;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class DataNpk2 {
|
||||
List<Npk2>? npk2;
|
||||
|
||||
DataNpk2({this.npk2});
|
||||
|
||||
DataNpk2.fromJson(Map<String, dynamic> json) {
|
||||
if (json['npk2'] != null) {
|
||||
npk2 = <Npk2>[];
|
||||
json['npk2'].forEach((v) {
|
||||
npk2!.add(Npk2.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (npk2 != null) {
|
||||
data['npk2'] = npk2!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Npk2 {
|
||||
int? hour;
|
||||
double? soiltemperatureAvg;
|
||||
double? soilhumidityAvg;
|
||||
double? soilconductivityAvg;
|
||||
double? soilphAvg;
|
||||
double? soilnitrogenAvg;
|
||||
double? soilphosphorusAvg;
|
||||
double? soilpotassiumAvg;
|
||||
|
||||
Npk2(
|
||||
{this.hour,
|
||||
this.soiltemperatureAvg,
|
||||
this.soilhumidityAvg,
|
||||
this.soilconductivityAvg,
|
||||
this.soilphAvg,
|
||||
this.soilnitrogenAvg,
|
||||
this.soilphosphorusAvg,
|
||||
this.soilpotassiumAvg});
|
||||
|
||||
Npk2.fromJson(Map<String, dynamic> json) {
|
||||
hour = json['hour'];
|
||||
soiltemperatureAvg = json['soiltemperature_avg'];
|
||||
soilhumidityAvg = json['soilhumidity_avg'];
|
||||
soilconductivityAvg = json['soilconductivity_avg'];
|
||||
soilphAvg = json['soilph_avg'];
|
||||
soilnitrogenAvg = json['soilnitrogen_avg'];
|
||||
soilphosphorusAvg = json['soilphosphorus_avg'];
|
||||
soilpotassiumAvg = json['soilpotassium_avg'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['hour'] = hour;
|
||||
data['soiltemperature_avg'] = soiltemperatureAvg;
|
||||
data['soilhumidity_avg'] = soilhumidityAvg;
|
||||
data['soilconductivity_avg'] = soilconductivityAvg;
|
||||
data['soilph_avg'] = soilphAvg;
|
||||
data['soilnitrogen_avg'] = soilnitrogenAvg;
|
||||
data['soilphosphorus_avg'] = soilphosphorusAvg;
|
||||
data['soilpotassium_avg'] = soilpotassiumAvg;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ class HumidityScreen extends StatelessWidget {
|
|||
children: [
|
||||
const Icon(BootstrapIcons.droplet_half,
|
||||
size: 32, color: Colors.blue),
|
||||
Text('60 %', style: AppTheme.headline1),
|
||||
Text('$humidity %', style: AppTheme.headline1),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -63,7 +63,7 @@ class HumidityScreen extends StatelessWidget {
|
|||
child: AnimatedRadialGauge(
|
||||
duration: const Duration(seconds: 3),
|
||||
curve: Curves.easeOut,
|
||||
value: 60,
|
||||
value: humidity,
|
||||
axis: GaugeAxis(
|
||||
degrees: 360,
|
||||
min: 0,
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class SoilMoistureScreen extends StatelessWidget {
|
|||
children: [
|
||||
const Icon(BootstrapIcons.water,
|
||||
size: 32, color: Colors.blue),
|
||||
Text('60 %', style: AppTheme.headline1),
|
||||
Text('$moisture %', style: AppTheme.headline1),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
import 'package:agrilink_vocpro/core/state/result_state.dart';
|
||||
import 'package:agrilink_vocpro/features/home/model/npk1_soil_temp_grafik.dart';
|
||||
import 'package:agrilink_vocpro/features/home/service/home_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SoilTempProvider extends ChangeNotifier {
|
||||
SoilTempProvider() {
|
||||
getSoilTempData();
|
||||
}
|
||||
|
||||
List<Npk1> dataFetched = [];
|
||||
|
||||
void setSoilTempData(List<Npk1> data) {
|
||||
dataFetched = data;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
ResultState dataState = ResultState.initial;
|
||||
|
||||
Future<void> getSoilTempData() async {
|
||||
dataState = ResultState.loading;
|
||||
notifyListeners();
|
||||
try {
|
||||
final result = await HomeService().getNpk1SoilTempGrafik();
|
||||
if (result.data == null || result.data!.npk1!.isEmpty) {
|
||||
dataState = ResultState.noData;
|
||||
notifyListeners();
|
||||
return;
|
||||
} else {
|
||||
setSoilTempData(result.data?.npk1 ?? []);
|
||||
dataState = ResultState.hasData;
|
||||
notifyListeners();
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error: $e');
|
||||
dataState = ResultState.error;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
dataState = ResultState.initial;
|
||||
dataFetched = [];
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,14 @@
|
|||
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
|
||||
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
|
||||
import 'package:agrilink_vocpro/core/state/result_state.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:bootstrap_icons/bootstrap_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:gauge_indicator/gauge_indicator.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class SoilTemperatureScreen extends StatelessWidget {
|
||||
const SoilTemperatureScreen({super.key, this.temperature = 0});
|
||||
|
|
@ -15,218 +18,269 @@ class SoilTemperatureScreen extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Soil Temperature', style: AppTheme.labelMedium),
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.white,
|
||||
scrolledUnderElevation: 0,
|
||||
actions: const [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(
|
||||
BootstrapIcons.water,
|
||||
color: Colors.green,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
body: SafeArea(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.all(16.w),
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.05,
|
||||
),
|
||||
SizedBox(
|
||||
height: 240.h,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 80.h,
|
||||
),
|
||||
const Icon(BootstrapIcons.water,
|
||||
size: 32, color: Colors.green),
|
||||
Text(
|
||||
'${value.toStringAsFixed(0)}°C', // Animated percentage text
|
||||
style: const TextStyle(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black,
|
||||
return ChangeNotifierProvider(
|
||||
create: (context) => SoilTempProvider(),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Soil Temperature', style: AppTheme.labelMedium),
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.white,
|
||||
scrolledUnderElevation: 0,
|
||||
actions: const [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(
|
||||
BootstrapIcons.water,
|
||||
color: Colors.green,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
body: SafeArea(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.all(16.w),
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.05,
|
||||
),
|
||||
SizedBox(
|
||||
height: 240.h,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 80.h,
|
||||
),
|
||||
const Icon(BootstrapIcons.water,
|
||||
size: 32, color: Colors.green),
|
||||
Text(
|
||||
'$value°C', // Animated percentage text
|
||||
style: const TextStyle(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
AnimatedRadialGauge(
|
||||
duration: const Duration(seconds: 2),
|
||||
curve: Curves.easeOut,
|
||||
value: value,
|
||||
axis: GaugeAxis(
|
||||
degrees: 240,
|
||||
min: 0,
|
||||
max: 56.7,
|
||||
style: GaugeAxisStyle(
|
||||
background: Colors.grey.shade100,
|
||||
thickness: 50,
|
||||
),
|
||||
progressBar: const GaugeBasicProgressBar(
|
||||
gradient: GaugeAxisGradient(colors: [
|
||||
Colors.blue,
|
||||
Colors.orange,
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Soil Temperature',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
IconButton(
|
||||
iconSize: 20.r,
|
||||
color: Colors.blue,
|
||||
onPressed: () {
|
||||
showInfo(
|
||||
context,
|
||||
'Soil Temperature',
|
||||
AppConstant.soilTempInfo,
|
||||
);
|
||||
},
|
||||
icon: const Icon(BootstrapIcons.info_circle))
|
||||
],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Container(
|
||||
height: 100.h,
|
||||
width: 100.w,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
color: Colors.blue.withOpacity(0.1),
|
||||
border: Border.all(
|
||||
color: Colors.blue,
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('Low',
|
||||
style: AppTheme.labelMedium
|
||||
.copyWith(color: Colors.blue)),
|
||||
SizedBox(height: 8.h),
|
||||
Text(
|
||||
'<20°C',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
AnimatedRadialGauge(
|
||||
duration: const Duration(seconds: 2),
|
||||
curve: Curves.easeOut,
|
||||
value: value,
|
||||
axis: GaugeAxis(
|
||||
degrees: 240,
|
||||
min: 0,
|
||||
max: 56.7,
|
||||
style: GaugeAxisStyle(
|
||||
background: Colors.grey.shade100,
|
||||
thickness: 50,
|
||||
Container(
|
||||
height: 100.h,
|
||||
width: 100.w,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.green.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: Colors.green,
|
||||
width: 2,
|
||||
),
|
||||
progressBar: const GaugeBasicProgressBar(
|
||||
gradient: GaugeAxisGradient(colors: [
|
||||
Colors.blue,
|
||||
Colors.orange,
|
||||
]),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('Ideal',
|
||||
style: AppTheme.labelMedium
|
||||
.copyWith(color: Colors.green)),
|
||||
// SizedBox(height: 8.h),
|
||||
// const Icon(
|
||||
// BootstrapIcons.thermometer_half,
|
||||
// color: Colors.green,
|
||||
// ),
|
||||
SizedBox(height: 8.h),
|
||||
Text(
|
||||
'20-30°C',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 100.h,
|
||||
width: 100.w,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.orange.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: Colors.orange.shade800,
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('high',
|
||||
style: AppTheme.labelMedium
|
||||
.copyWith(color: Colors.orange)),
|
||||
SizedBox(height: 8.h),
|
||||
Text(
|
||||
'>30°C',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Soil Temperature',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
IconButton(
|
||||
iconSize: 20.r,
|
||||
color: Colors.blue,
|
||||
onPressed: () {
|
||||
showInfo(
|
||||
context,
|
||||
'Soil Temperature',
|
||||
AppConstant.soilTempInfo,
|
||||
);
|
||||
},
|
||||
icon: const Icon(BootstrapIcons.info_circle))
|
||||
],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Container(
|
||||
height: 100.h,
|
||||
width: 100.w,
|
||||
SizedBox(height: 16.h),
|
||||
const Text('Grafik'),
|
||||
SizedBox(height: 16.h),
|
||||
AspectRatio(
|
||||
aspectRatio: 1.6.h,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
color: Colors.blue.withOpacity(0.1),
|
||||
border: Border.all(
|
||||
color: Colors.blue,
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('Low',
|
||||
style: AppTheme.labelMedium
|
||||
.copyWith(color: Colors.blue)),
|
||||
// SizedBox(height: 8.h),
|
||||
// const Icon(
|
||||
// BootstrapIcons.thermometer_low,
|
||||
// color: Colors.blue,
|
||||
// ),
|
||||
SizedBox(height: 8.h),
|
||||
Text(
|
||||
'<20°C',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16.w),
|
||||
border: Border.all(color: Colors.grey.shade300, width: 1.w),
|
||||
),
|
||||
child: Consumer<SoilTempProvider>(
|
||||
builder: (context, provider, child) {
|
||||
switch (provider.dataState) {
|
||||
case ResultState.loading:
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
case ResultState.hasData:
|
||||
return GarphicWidget(
|
||||
gradientColors: const [
|
||||
Colors.cyan,
|
||||
Colors.amber,
|
||||
],
|
||||
hour: List.generate(provider.dataFetched.length,
|
||||
(index) => provider.dataFetched[index].hour ?? 0),
|
||||
data: List.generate(
|
||||
provider.dataFetched.length,
|
||||
(index) =>
|
||||
provider.dataFetched[index].soiltemperatureAvg
|
||||
?.toDouble() ??
|
||||
0),
|
||||
);
|
||||
case ResultState.error:
|
||||
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:
|
||||
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:
|
||||
return const SizedBox.shrink();
|
||||
default:
|
||||
return const Center(
|
||||
child: Text('Default Error'),
|
||||
);
|
||||
}
|
||||
}),
|
||||
),
|
||||
Container(
|
||||
height: 100.h,
|
||||
width: 100.w,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.green.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: Colors.green,
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('Ideal',
|
||||
style: AppTheme.labelMedium
|
||||
.copyWith(color: Colors.green)),
|
||||
// SizedBox(height: 8.h),
|
||||
// const Icon(
|
||||
// BootstrapIcons.thermometer_half,
|
||||
// color: Colors.green,
|
||||
// ),
|
||||
SizedBox(height: 8.h),
|
||||
Text(
|
||||
'20-30°C',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 100.h,
|
||||
width: 100.w,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.orange.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: Colors.orange.shade800,
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('high',
|
||||
style: AppTheme.labelMedium
|
||||
.copyWith(color: Colors.orange)),
|
||||
// SizedBox(height: 8.h),
|
||||
// const Icon(
|
||||
// BootstrapIcons.thermometer_high,
|
||||
// color: Colors.orange,
|
||||
// ),
|
||||
SizedBox(height: 8.h),
|
||||
Text(
|
||||
'>30°C',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
const Text('Grafik'),
|
||||
SizedBox(height: 16.h),
|
||||
AspectRatio(
|
||||
aspectRatio: 1.6.h,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16.w),
|
||||
border: Border.all(color: Colors.grey.shade300, width: 1.w),
|
||||
),
|
||||
child: const GarphicWidget(
|
||||
gradientColors: [
|
||||
Colors.cyan,
|
||||
Colors.amber,
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,25 +1,101 @@
|
|||
import 'package:agrilink_vocpro/core/state/result_state.dart';
|
||||
import 'package:agrilink_vocpro/domain/service/app_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class HomeProvider extends ChangeNotifier {
|
||||
final DateTime currentDate = DateTime.now();
|
||||
|
||||
num _dhtHumidity = 0;
|
||||
num get dhtHumidity => _dhtHumidity;
|
||||
|
||||
num _dhtTemperature = 0;
|
||||
num get dhtTemperature => _dhtTemperature;
|
||||
|
||||
num _dhtLuminosity = 0;
|
||||
num get dhtLuminosity => _dhtLuminosity;
|
||||
|
||||
num _npk1SoilMoisture = 0;
|
||||
num get npk1SoilMoisture => _npk1SoilMoisture;
|
||||
|
||||
num _npk1Temperature = 0;
|
||||
num get npk1Temperature => _npk1Temperature;
|
||||
|
||||
num _npk1SoilPh = 0;
|
||||
num get npk1SoilPh => _npk1SoilPh;
|
||||
|
||||
num _npk1SoilEc = 0;
|
||||
num get npk1SoilEc => _npk1SoilEc;
|
||||
|
||||
num _npk1SoilNitrogen = 0;
|
||||
num get npk1SoilNitrogen => _npk1SoilNitrogen;
|
||||
|
||||
num _npk1SoilPhosphorus = 0;
|
||||
num get npk1SoilPhosphorus => _npk1SoilPhosphorus;
|
||||
|
||||
num _npk1SoilPotassium = 0;
|
||||
num get npk1SoilPotassium => _npk1SoilPotassium;
|
||||
|
||||
num _npk2SoilMoisture = 0;
|
||||
num get npk2SoilMoisture => _npk2SoilMoisture;
|
||||
|
||||
num _npk2Temperature = 0;
|
||||
num get npk2Temperature => _npk2Temperature;
|
||||
|
||||
num _npk2SoilPh = 0;
|
||||
num get npk2SoilPh => _npk2SoilPh;
|
||||
|
||||
num _npk2SoilEc = 0;
|
||||
num get npk2SoilEc => _npk2SoilEc;
|
||||
|
||||
num _npk2SoilNitrogen = 0;
|
||||
num get npk2SoilNitrogen => _npk2SoilNitrogen;
|
||||
|
||||
num _npk2SoilPhosphorus = 0;
|
||||
num get npk2SoilPhosphorus => _npk2SoilPhosphorus;
|
||||
|
||||
num _npk2SoilPotassium = 0;
|
||||
num get npk2SoilPotassium => _npk2SoilPotassium;
|
||||
|
||||
HomeProvider() {
|
||||
getData();
|
||||
getLatestData();
|
||||
}
|
||||
|
||||
ResultState dataState = ResultState.initial;
|
||||
|
||||
Future<void> getData() async {
|
||||
Future<void> getLatestData() async {
|
||||
dataState = ResultState.loading;
|
||||
notifyListeners();
|
||||
try {
|
||||
print('Fetching data...');
|
||||
await Future.delayed(const Duration(seconds: 3));
|
||||
print('Data fetched');
|
||||
dataState = ResultState.hasData;
|
||||
notifyListeners();
|
||||
final result = await AppService().getLatestData();
|
||||
if (result.data == null) {
|
||||
dataState = ResultState.noData;
|
||||
notifyListeners();
|
||||
} else {
|
||||
final data = result.data!;
|
||||
_dhtHumidity = data.dht?[0].vicihumidityAvg ?? 0;
|
||||
_dhtTemperature = data.dht?[0].vicitemperatureAvg ?? 0;
|
||||
_dhtLuminosity = data.dht?[0].viciluminosityAvg ?? 0;
|
||||
|
||||
_npk1SoilMoisture = data.npk1?[0].soilhumidityAvg ?? 0;
|
||||
_npk1Temperature = data.npk1?[0].soiltemperatureAvg ?? 0;
|
||||
_npk1SoilPh = data.npk1?[0].soilphAvg ?? 0;
|
||||
_npk1SoilEc = data.npk1?[0].soilconductivityAvg ?? 0;
|
||||
_npk1SoilNitrogen = data.npk1?[0].soilnitrogenAvg ?? 0;
|
||||
_npk1SoilPhosphorus = data.npk1?[0].soilphosphorusAvg ?? 0;
|
||||
_npk1SoilPotassium = data.npk1?[0].soilpotassiumAvg ?? 0;
|
||||
|
||||
_npk2SoilMoisture = data.npk2?[0].soilhumidityAvg ?? 0;
|
||||
_npk2Temperature = data.npk2?[0].soiltemperatureAvg ?? 0;
|
||||
_npk2SoilPh = data.npk2?[0].soilphAvg ?? 0;
|
||||
_npk2SoilEc = data.npk2?[0].soilconductivityAvg ?? 0;
|
||||
_npk2SoilNitrogen = data.npk2?[0].soilnitrogenAvg ?? 0;
|
||||
_npk2SoilPhosphorus = data.npk2?[0].soilphosphorusAvg ?? 0;
|
||||
_npk2SoilPotassium = data.npk2?[0].soilpotassiumAvg ?? 0;
|
||||
dataState = ResultState.hasData;
|
||||
notifyListeners();
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error: $e');
|
||||
dataState = ResultState.error;
|
||||
notifyListeners();
|
||||
}
|
||||
|
|
@ -31,57 +107,3 @@ class HomeProvider extends ChangeNotifier {
|
|||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// List<CensorDataRule> humidtyRules = [
|
||||
// CensorDataRule(
|
||||
// minPercentage: 0,
|
||||
// maxPercentage: 30,
|
||||
// censorText: 'Very Low',
|
||||
// description:
|
||||
// 'Udara sangat kering. Tanaman bisa mengalami stress akibat kekurangan air.',
|
||||
// action:
|
||||
// 'Aktifkan sistem penyiraman atau humidifier untuk menaikkan kelembaban. Periksa juga apakah ada kebocoran pada sistem irigasi yang mengakibatkan kelembaban terlalu rendah.',
|
||||
// color: Colors.red,
|
||||
// ),
|
||||
// CensorDataRule(
|
||||
// minPercentage: 31,
|
||||
// maxPercentage: 50,
|
||||
// censorText: 'Low',
|
||||
// description:
|
||||
// 'Kelembaban masih cukup rendah. Beberapa jenis tanaman mungkin sudah mulai terpengaruh.',
|
||||
// action:
|
||||
// 'Pertimbangkan untuk menambah irigasi atau memperpanjang durasi penyiraman. Pantau tanaman secara berkala.',
|
||||
// color: Colors.orange,
|
||||
// ),
|
||||
// CensorDataRule(
|
||||
// minPercentage: 51,
|
||||
// maxPercentage: 70,
|
||||
// censorText: 'Normal',
|
||||
// description:
|
||||
// 'Ini adalah kelembaban yang ideal untuk sebagian besar tanaman dalam greenhouse.',
|
||||
// action:
|
||||
// 'Pertahankan kondisi ini. Tidak ada tindakan yang diperlukan kecuali jika ada perubahan mendadak.',
|
||||
// color: Colors.green,
|
||||
// ),
|
||||
// CensorDataRule(
|
||||
// minPercentage: 71,
|
||||
// maxPercentage: 85,
|
||||
// censorText: 'High',
|
||||
// description:
|
||||
// 'Udara mulai terlalu lembap. Kelembaban tinggi dapat meningkatkan risiko penyakit jamur atau bakteri.',
|
||||
// action:
|
||||
// 'Aktifkan ventilasi atau kipas untuk mengurangi kelembaban. Pastikan aliran udara di greenhouse cukup baik.',
|
||||
// color: Colors.lime,
|
||||
// ),
|
||||
// CensorDataRule(
|
||||
// minPercentage: 86,
|
||||
// maxPercentage: 100,
|
||||
// censorText: 'Very High',
|
||||
// description:
|
||||
// 'Udara sangat lembap, yang bisa berisiko menyebabkan jamur, lumut, dan penyakit tanaman.',
|
||||
// action:
|
||||
// 'Segera aktifkan sistem ventilasi maksimal, mungkin juga gunakan dehumidifier jika diperlukan. Kurangi frekuensi penyiraman atau periksa sistem irigasi agar tidak berlebihan.',
|
||||
// color: Colors.brown,
|
||||
// ),
|
||||
// ];
|
||||
|
|
|
|||
29
agrilink_vocpro/lib/features/home/service/home_service.dart
Normal file
29
agrilink_vocpro/lib/features/home/service/home_service.dart
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
|
||||
import 'package:agrilink_vocpro/features/home/model/npk1_soil_temp_grafik.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
class HomeService {
|
||||
final Dio _dioWithoutInterceptor = Dio(
|
||||
BaseOptions(
|
||||
baseUrl: AppConstant.baseUrl,
|
||||
),
|
||||
);
|
||||
|
||||
Future<Npk1SoilTempGrafik> getNpk1SoilTempGrafik() async {
|
||||
try {
|
||||
final result = await _dioWithoutInterceptor.get(
|
||||
'/sensor/getData?metric=soilTemperature&range[start]=2024-10-03&range[end]=2024-10-03&range[time_range]=HOURLY&sensor=npk1',
|
||||
);
|
||||
if (result.statusCode == 200) {
|
||||
print(result.data.toString());
|
||||
final data = Npk1SoilTempGrafik.fromJson(result.data);
|
||||
return data;
|
||||
} else {
|
||||
throw Exception('Failed to load data');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
print(e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||
const Spacer(),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
context.read<HomeProvider>().getData();
|
||||
context.read<HomeProvider>().getLatestData();
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.refresh_rounded,
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class GarphicWidget extends StatelessWidget {
|
||||
const GarphicWidget({super.key, required this.gradientColors});
|
||||
const GarphicWidget(
|
||||
{super.key, required this.gradientColors, this.data, this.hour});
|
||||
|
||||
final List<Color> gradientColors;
|
||||
|
||||
final List<num>? hour;
|
||||
final List<num>? data;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
|
|
@ -48,6 +50,16 @@ class GarphicWidget extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
int getMaxValue() {
|
||||
int max = 0;
|
||||
for (int i = 0; i < data!.length; i++) {
|
||||
if (data![i] > max) {
|
||||
max = data![i].toInt();
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
LineChartData mainData() {
|
||||
return LineChartData(
|
||||
gridData: const FlGridData(
|
||||
|
|
@ -80,18 +92,16 @@ class GarphicWidget extends StatelessWidget {
|
|||
minX: 0,
|
||||
maxX: 24,
|
||||
minY: 0,
|
||||
maxY: 100,
|
||||
maxY: data == null ? 0 : getMaxValue().toDouble(),
|
||||
lineBarsData: [
|
||||
LineChartBarData(
|
||||
spots: const [
|
||||
FlSpot(0, 38),
|
||||
FlSpot(1, 42),
|
||||
FlSpot(2, 50),
|
||||
FlSpot(3, 53),
|
||||
FlSpot(4, 58),
|
||||
FlSpot(5, 64),
|
||||
FlSpot(7, 49),
|
||||
],
|
||||
spots: data == null && hour == null
|
||||
? [FlSpot(0, 0)]
|
||||
: List.generate(
|
||||
hour!.length,
|
||||
(index) =>
|
||||
FlSpot(hour![index].toDouble(), data![index].toDouble()),
|
||||
),
|
||||
isCurved: true,
|
||||
gradient: LinearGradient(
|
||||
colors: gradientColors,
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class ListDataFromCensorDht extends StatelessWidget {
|
|||
DataDisplayerWidget(
|
||||
title: 'Humidity',
|
||||
subtitle: 'kelembaban udara',
|
||||
value: '60',
|
||||
value: provider.dhtHumidity.toString(),
|
||||
unit: '%',
|
||||
icon: BootstrapIcons.droplet_half,
|
||||
textColor: Colors.white,
|
||||
|
|
@ -58,29 +58,32 @@ class ListDataFromCensorDht extends StatelessWidget {
|
|||
iconColor: Colors.white,
|
||||
censorIdentifier: 'NPK 1',
|
||||
onTap: () async {
|
||||
await context.push('${AppRoute.humidity}/60');
|
||||
await context
|
||||
.push('${AppRoute.humidity}/${provider.dhtHumidity}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Temperature',
|
||||
subtitle: 'suhu greenhouse',
|
||||
value: '43',
|
||||
value: provider.dhtTemperature.toString(),
|
||||
unit: '°C',
|
||||
icon: BootstrapIcons.thermometer_half,
|
||||
color: Colors.white,
|
||||
onTap: () async {
|
||||
await context.push('${AppRoute.temperature}/43');
|
||||
await context.push(
|
||||
'${AppRoute.temperature}/${provider.dhtTemperature}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Light',
|
||||
subtitle: 'intensitas cahaya',
|
||||
value: '320.5',
|
||||
value: provider.dhtLuminosity.toString(),
|
||||
unit: 'lux',
|
||||
icon: BootstrapIcons.sun,
|
||||
color: Colors.white,
|
||||
onTap: () async {
|
||||
await context.push('${AppRoute.light}/320.5');
|
||||
await context
|
||||
.push('${AppRoute.light}/${provider.dhtLuminosity}');
|
||||
},
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class ListDataFromCensorNpk1 extends StatelessWidget {
|
|||
DataDisplayerWidget(
|
||||
title: 'Temperature',
|
||||
subtitle: 'Suhu tanah',
|
||||
value: '28',
|
||||
value: provider.npk1Temperature.toString(),
|
||||
unit: '°C',
|
||||
icon: BootstrapIcons.thermometer_half,
|
||||
textColor: Colors.white,
|
||||
|
|
@ -57,76 +57,82 @@ class ListDataFromCensorNpk1 extends StatelessWidget {
|
|||
iconColor: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
await context.push('${AppRoute.soilTemperature}/28');
|
||||
await context.push(
|
||||
'${AppRoute.soilTemperature}/${provider.npk1Temperature}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Soil Moisture',
|
||||
subtitle: 'kelembaban tanah',
|
||||
value: '40',
|
||||
value: provider.npk1SoilMoisture.toString(),
|
||||
unit: '%',
|
||||
icon: Icons.water_outlined,
|
||||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
await context.push('${AppRoute.soilMoisture}/40');
|
||||
await context.push(
|
||||
'${AppRoute.soilMoisture}/${provider.npk1SoilMoisture}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Acid Level (PH)',
|
||||
subtitle: 'tingkat keasaman',
|
||||
value: '6.5',
|
||||
value: provider.npk1SoilPh.toString(),
|
||||
unit: 'pH',
|
||||
icon: BootstrapIcons.pie_chart,
|
||||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () {
|
||||
context.push('${AppRoute.ph}/6.5');
|
||||
onTap: () async {
|
||||
context.push('${AppRoute.ph}/${provider.npk1SoilPh}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Conductivity',
|
||||
subtitle: 'Daya Arus Listrik',
|
||||
value: '234',
|
||||
value: provider.npk1SoilEc.toString(),
|
||||
unit: 'µS/cm',
|
||||
icon: Icons.electric_bolt,
|
||||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
await context.push('${AppRoute.conductivity}/234');
|
||||
await context
|
||||
.push('${AppRoute.conductivity}/${provider.npk1SoilEc}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Nitrogen',
|
||||
subtitle: 'Kadar Nitrogen',
|
||||
value: '30',
|
||||
value: provider.npk1SoilNitrogen.toString(),
|
||||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () async {
|
||||
await context.push('${AppRoute.nitrogen}/30');
|
||||
await context.push(
|
||||
'${AppRoute.nitrogen}/${provider.npk1SoilNitrogen}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Potassium',
|
||||
subtitle: 'Kadar kalium',
|
||||
value: '20',
|
||||
value: provider.npk1SoilPotassium.toString(),
|
||||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () async {
|
||||
await context.push('${AppRoute.potassium}/20');
|
||||
await context.push(
|
||||
'${AppRoute.potassium}/${provider.npk1SoilPotassium}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Phosphorus',
|
||||
subtitle: 'Kadar Fosfor',
|
||||
value: '54',
|
||||
value: provider.npk1SoilPhosphorus.toString(),
|
||||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () async {
|
||||
await context.push('${AppRoute.phosphorus}/54');
|
||||
await context.push(
|
||||
'${AppRoute.phosphorus}/${provider.npk1SoilPhosphorus}');
|
||||
},
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import 'package:agrilink_vocpro/core/constant/app_color.dart';
|
||||
import 'package:agrilink_vocpro/core/route/app_route.dart';
|
||||
import 'package:agrilink_vocpro/core/state/result_state.dart';
|
||||
import 'package:agrilink_vocpro/features/home/pages/soil_moisture/view/soil_moisture_screen.dart';
|
||||
import 'package:agrilink_vocpro/features/home/pages/temperature/view/temperature_screen.dart';
|
||||
import 'package:agrilink_vocpro/features/home/provider/home_provider.dart';
|
||||
import 'package:agrilink_vocpro/features/home/widgets/censor_item_loading_widgets.dart';
|
||||
import 'package:agrilink_vocpro/features/home/widgets/data_display_widget.dart';
|
||||
|
|
@ -51,7 +49,7 @@ class ListDataFromCensorNpk2 extends StatelessWidget {
|
|||
DataDisplayerWidget(
|
||||
title: 'Temperature',
|
||||
subtitle: 'Suhu tanah',
|
||||
value: '28',
|
||||
value: provider.npk2Temperature.toString(),
|
||||
unit: '°C',
|
||||
icon: BootstrapIcons.thermometer_half,
|
||||
textColor: Colors.white,
|
||||
|
|
@ -59,77 +57,83 @@ class ListDataFromCensorNpk2 extends StatelessWidget {
|
|||
iconColor: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const TemperatureScreen()));
|
||||
await context.push(
|
||||
'${AppRoute.soilTemperature}/${provider.npk2Temperature}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Soil Moisture',
|
||||
subtitle: 'kelembaban tanah',
|
||||
value: '40',
|
||||
value: provider.npk2SoilMoisture.toString(),
|
||||
unit: '%',
|
||||
icon: Icons.water_outlined,
|
||||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const SoilMoistureScreen(),
|
||||
),
|
||||
);
|
||||
await context.push(
|
||||
'${AppRoute.soilMoisture}/${provider.npk2SoilMoisture}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Acid Level (PH)',
|
||||
subtitle: 'tingkat keasaman',
|
||||
value: '6.5',
|
||||
value: provider.npk2SoilPh.toString(),
|
||||
unit: 'pH',
|
||||
icon: BootstrapIcons.pie_chart,
|
||||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () {},
|
||||
onTap: () async {
|
||||
context.push('${AppRoute.ph}/${provider.npk2SoilPh}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Conductivity',
|
||||
subtitle: 'Daya Arus Listrik',
|
||||
value: '234',
|
||||
value: provider.npk2SoilEc.toString(),
|
||||
unit: 'µS/cm',
|
||||
icon: Icons.electric_bolt,
|
||||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
context.push(AppRoute.humidity, extra: '60');
|
||||
await context
|
||||
.push('${AppRoute.conductivity}/${provider.npk2SoilEc}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Nitrogen',
|
||||
subtitle: 'Kadar Nitrogen',
|
||||
value: '30',
|
||||
value: provider.npk2SoilNitrogen.toString(),
|
||||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () {},
|
||||
onTap: () async {
|
||||
await context.push(
|
||||
'${AppRoute.nitrogen}/${provider.npk2SoilNitrogen}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Potassium',
|
||||
subtitle: 'Kadar kalium',
|
||||
value: '20',
|
||||
value: provider.npk2SoilPotassium.toString(),
|
||||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () {},
|
||||
onTap: () async {
|
||||
await context.push(
|
||||
'${AppRoute.potassium}/${provider.npk2SoilPotassium}');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Phosphorus',
|
||||
subtitle: 'Kadar Fosfor',
|
||||
value: '54',
|
||||
value: provider.npk2SoilPhosphorus.toString(),
|
||||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () {},
|
||||
onTap: () async {
|
||||
await context.push(
|
||||
'${AppRoute.phosphorus}/${provider.npk2SoilPhosphorus}');
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -141,10 +141,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
version: "7.0.1"
|
||||
fl_chart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -162,10 +162,10 @@ packages:
|
|||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
|
||||
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
version: "5.0.0"
|
||||
flutter_screenutil:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -196,10 +196,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: go_router
|
||||
sha256: "2ddb88e9ad56ae15ee144ed10e33886777eb5ca2509a914850a5faa7b52ff459"
|
||||
sha256: "6f1b756f6e863259a99135ff3c95026c3cdca17d10ebef2bba2261a25ddc8bbc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.2.7"
|
||||
version: "14.3.0"
|
||||
google_fonts:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -268,10 +268,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
|
||||
sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
version: "5.0.0"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -340,10 +340,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7"
|
||||
sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.10"
|
||||
version: "2.2.12"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -412,18 +412,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e"
|
||||
sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
version: "2.3.3"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_foundation
|
||||
sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f
|
||||
sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.2"
|
||||
version: "2.5.3"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -561,18 +561,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062
|
||||
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.1.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
|
||||
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
version: "1.1.0"
|
||||
sdks:
|
||||
dart: ">=3.5.1 <4.0.0"
|
||||
flutter: ">=3.22.0"
|
||||
flutter: ">=3.24.0"
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ dev_dependencies:
|
|||
# activated in the `analysis_options.yaml` file located at the root of your
|
||||
# package. See that file for information about deactivating specific lint
|
||||
# rules and activating additional ones.
|
||||
flutter_lints: ^4.0.0
|
||||
flutter_lints: ^5.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user