feat: add detail screen (npk sensor)
This commit is contained in:
parent
10880bddfd
commit
fc4350f1dd
BIN
agrilink_vocpro/assets/images/error_image.png
Normal file
BIN
agrilink_vocpro/assets/images/error_image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
agrilink_vocpro/assets/images/no_data_image.png
Normal file
BIN
agrilink_vocpro/assets/images/no_data_image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
13
agrilink_vocpro/lib/core/constant/app_constant.dart
Normal file
13
agrilink_vocpro/lib/core/constant/app_constant.dart
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
class AppConstant {
|
||||
static const String appName = 'Kebun Pintar';
|
||||
static const String appVersion = '1.0.0';
|
||||
|
||||
static const String baseUrl = 'https://agrilinkvocpropisdev.id/api/v1';
|
||||
|
||||
static const String mqttServer = 'armadillo.rmq.cloudamqp.com';
|
||||
static const String mqttUsername = 'obyskxhx:obyskxhx';
|
||||
static const String mqttPassword = 'Fe_3_tBuwmc8vMMqT2hYiboTsBlBmPz1';
|
||||
|
||||
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.';
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
class AppContant {
|
||||
static const String appName = 'Kebun Pintar';
|
||||
static const String appVersion = '1.0.0';
|
||||
|
||||
static const String baseUrl = 'https://kebunpintar.id/api/v1';
|
||||
}
|
||||
|
|
@ -1,8 +1,15 @@
|
|||
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/home/pages/conductivity/view/conductivity_screen.dart';
|
||||
import 'package:agrilink_vocpro/features/home/pages/humidity/view/humidity_screen.dart';
|
||||
import 'package:agrilink_vocpro/features/home/pages/light/view/light_screen.dart';
|
||||
import 'package:agrilink_vocpro/features/home/pages/nitrogen/view/nitrogen_screen.dart';
|
||||
import 'package:agrilink_vocpro/features/home/pages/ph/view/ph_screen.dart';
|
||||
import 'package:agrilink_vocpro/features/home/pages/phosphorus/view/phosphorus_screen.dart';
|
||||
import 'package:agrilink_vocpro/features/home/pages/potassium/view/potassium_screen.dart';
|
||||
import 'package:agrilink_vocpro/features/home/pages/soil_moisture/view/soil_moisture_screen.dart';
|
||||
import 'package:agrilink_vocpro/features/home/pages/soil_temperature/view/soil_temperature_screen.dart';
|
||||
import 'package:agrilink_vocpro/features/home/pages/temperature/view/temperature_screen.dart';
|
||||
import 'package:agrilink_vocpro/features/splash/view/splash_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
|
@ -15,12 +22,15 @@ class AppRoute {
|
|||
static const String profile = '/profile';
|
||||
static const String setting = '/setting';
|
||||
static const String humidity = '/dashboard/humidity';
|
||||
static const String temperature = '/temperature';
|
||||
static const String soil = '/soil';
|
||||
static const String temperature = '/dashboard/temperature';
|
||||
static const String soilTemperature = '/dashboard/soil_temperature';
|
||||
static const String soilMoisture = '/dashboard/soil_moisture';
|
||||
static const String light = '/dashboard/light';
|
||||
static const String ph = '/dashboard/ph';
|
||||
static const String water = '/water';
|
||||
static const String acidity = '/acidity';
|
||||
static const String conductivity = '/dashboard/conductivity';
|
||||
static const String nitrogen = '/dashboard/nitrogen';
|
||||
static const String phosphorus = '/dashboard/phosphorus';
|
||||
static const String potassium = '/dashboard/potassium';
|
||||
|
||||
static final GoRouter router = GoRouter(
|
||||
initialLocation: root,
|
||||
|
|
@ -35,35 +45,30 @@ class AppRoute {
|
|||
path: login,
|
||||
builder: (context, state) => const LoginScreen(),
|
||||
),
|
||||
//dashboard
|
||||
GoRoute(
|
||||
path: dashboard,
|
||||
builder: (context, state) => const DashboardScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: dashboard,
|
||||
builder: (context, state) => const DashboardScreen(),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'humidity',
|
||||
builder: (context, state) => const HumidityScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: 'light/:value',
|
||||
builder: (context, state) {
|
||||
final double value =
|
||||
double.tryParse(state.pathParameters['value'] ?? '') ?? 0.0;
|
||||
return LightScreen(lightIntensity: value);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: 'ph/:value',
|
||||
builder: (context, state) {
|
||||
final double value =
|
||||
double.tryParse(state.pathParameters['value'] ?? '') ?? 0.0;
|
||||
return PhScreen(phValue: value);
|
||||
},
|
||||
),
|
||||
// humidity
|
||||
buildHumidityRoute(),
|
||||
// light intensity
|
||||
buildLightIntensityRoute(),
|
||||
// temperature
|
||||
buildTemperatureRoute(),
|
||||
// ph
|
||||
buildAcidityRoute(),
|
||||
// soil moisture
|
||||
buildSoilTempRoute(),
|
||||
// soil moisture
|
||||
buildSoilMoistureRoute(),
|
||||
// conductivity
|
||||
buildConductivityRoute(),
|
||||
// nitrogen
|
||||
buildNitrogenRoute(),
|
||||
// phosphorus
|
||||
buildPhosphorusRoute(),
|
||||
// potassium
|
||||
buildPotassiumRoute(),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
@ -73,4 +78,114 @@ class AppRoute {
|
|||
),
|
||||
),
|
||||
);
|
||||
|
||||
static GoRoute buildPotassiumRoute() {
|
||||
return GoRoute(
|
||||
path: 'potassium/:value',
|
||||
builder: (context, state) {
|
||||
final double value =
|
||||
double.tryParse(state.pathParameters['value'] ?? '') ?? 0.0;
|
||||
return PotassiumScreen(potassium: value);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static GoRoute buildPhosphorusRoute() {
|
||||
return GoRoute(
|
||||
path: 'phosphorus/:value',
|
||||
builder: (context, state) {
|
||||
final double value =
|
||||
double.tryParse(state.pathParameters['value'] ?? '') ?? 0.0;
|
||||
return PhosphorusScreen(phosphorus: value);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static GoRoute buildNitrogenRoute() {
|
||||
return GoRoute(
|
||||
path: 'nitrogen/:value',
|
||||
builder: (context, state) {
|
||||
final double value =
|
||||
double.tryParse(state.pathParameters['value'] ?? '') ?? 0.0;
|
||||
return NitrogenScreen(nitrogen: value);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static GoRoute buildConductivityRoute() {
|
||||
return GoRoute(
|
||||
path: 'conductivity/:value',
|
||||
builder: (context, state) {
|
||||
final double value =
|
||||
double.tryParse(state.pathParameters['value'] ?? '') ?? 0.0;
|
||||
return ConductivityScreen(conductivity: value);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static GoRoute buildSoilMoistureRoute() {
|
||||
return GoRoute(
|
||||
path: 'soil_moisture/:value',
|
||||
builder: (context, state) {
|
||||
final double value =
|
||||
double.tryParse(state.pathParameters['value'] ?? '') ?? 0.0;
|
||||
return SoilMoistureScreen(moisture: value);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static GoRoute buildSoilTempRoute() {
|
||||
return GoRoute(
|
||||
path: 'soil_temperature/:value',
|
||||
builder: (context, state) {
|
||||
final double value =
|
||||
double.tryParse(state.pathParameters['value'] ?? '') ?? 0.0;
|
||||
return SoilTemperatureScreen(temperature: value);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static GoRoute buildAcidityRoute() {
|
||||
return GoRoute(
|
||||
path: 'ph/:value',
|
||||
builder: (context, state) {
|
||||
final double value =
|
||||
double.tryParse(state.pathParameters['value'] ?? '') ?? 0.0;
|
||||
return PhScreen(phValue: value);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static GoRoute buildTemperatureRoute() {
|
||||
return GoRoute(
|
||||
path: 'temperature/:value',
|
||||
builder: (context, state) {
|
||||
final double value =
|
||||
double.tryParse(state.pathParameters['value'] ?? '') ?? 0.0;
|
||||
return TemperatureScreen(temperature: value);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static GoRoute buildLightIntensityRoute() {
|
||||
return GoRoute(
|
||||
path: 'light/:value',
|
||||
builder: (context, state) {
|
||||
final double value =
|
||||
double.tryParse(state.pathParameters['value'] ?? '') ?? 0.0;
|
||||
return LightScreen(lightIntensity: value);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static GoRoute buildHumidityRoute() {
|
||||
return GoRoute(
|
||||
path: 'humidity/:value',
|
||||
builder: (context, state) {
|
||||
final double value =
|
||||
double.tryParse(state.pathParameters['value'] ?? '') ?? 0.0;
|
||||
return HumidityScreen(humidity: value);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class CensorProvider extends ChangeNotifier {
|
||||
Future<void> setupMqtt() async {}
|
||||
}
|
||||
20
agrilink_vocpro/lib/domain/service/app_service.dart
Normal file
20
agrilink_vocpro/lib/domain/service/app_service.dart
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import 'package:agrilink_vocpro/core/constant/app_contant.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class AppService {
|
||||
final Dio _dioWithoutInterceptor = Dio(
|
||||
BaseOptions(
|
||||
baseUrl: AppConstant.baseUrl,
|
||||
),
|
||||
);
|
||||
|
||||
Future<void> getGreenHouseData() async {
|
||||
try {} on DioException catch (e) {
|
||||
if (kDebugMode) {
|
||||
print(e);
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
|
||||
import 'package:agrilink_vocpro/core/state/result_state.dart';
|
||||
import 'package:mqtt_client/mqtt_client.dart';
|
||||
import 'package:mqtt_client/mqtt_server_client.dart';
|
||||
|
|
@ -6,11 +9,11 @@ class MQTTService {
|
|||
MqttServerClient? client;
|
||||
|
||||
Future<ResultState> setupMqtt() async {
|
||||
client = MqttServerClient('armadillo.rmq.cloudamqp.com', '');
|
||||
client = MqttServerClient(AppConstant.mqttServer, '');
|
||||
client!.port = 1883;
|
||||
|
||||
client!.connectionMessage = MqttConnectMessage()
|
||||
.authenticateAs('obyskxhx:obyskxhx', 'Fe_3_tBuwmc8vMMqT2hYiboTsBlBmPz1')
|
||||
.authenticateAs(AppConstant.mqttUsername, AppConstant.mqttPassword)
|
||||
.withClientIdentifier('mobile_client_controller')
|
||||
.startClean() // reset session
|
||||
.withWillQos(MqttQos.atLeastOnce);
|
||||
|
|
@ -90,14 +93,14 @@ class MQTTService {
|
|||
|
||||
client!.updates!.listen(
|
||||
(List<MqttReceivedMessage<MqttMessage?>>? messages) {
|
||||
print('MQTT: Message received!');
|
||||
print('MQTT: Subscribe Message received!');
|
||||
if (messages != null && messages.isNotEmpty) {
|
||||
final MqttPublishMessage recMessage =
|
||||
messages[0].payload as MqttPublishMessage;
|
||||
final String payload = MqttPublishPayload.bytesToStringAsString(
|
||||
recMessage.payload.message);
|
||||
print(
|
||||
'MQTT: Message received on topic ${messages[0].topic}: $payload');
|
||||
'MQTT: Subscribe Message received on topic ${messages[0].topic}: $payload');
|
||||
|
||||
if (payload == 'ON') {
|
||||
isActive = true;
|
||||
|
|
@ -105,9 +108,11 @@ class MQTTService {
|
|||
} else if (payload == 'OFF') {
|
||||
isActive = false;
|
||||
// Update UI atau provider untuk menandakan relay OFF
|
||||
} else {
|
||||
print('MQTT: Invalid Subscribe message received');
|
||||
}
|
||||
} else {
|
||||
print('MQTT: No messages received');
|
||||
print('MQTT: No Subscribe messages received');
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
@ -122,4 +127,44 @@ class MQTTService {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<ResultState> subscribeToRelayStatus() async {
|
||||
if (client != null &&
|
||||
client!.connectionStatus!.state == MqttConnectionState.connected) {
|
||||
try {
|
||||
print('MQTT: Subscribing to /smartfarming/getRelayStatus');
|
||||
client!.subscribe('smartfarming/getRelayStatus', MqttQos.atMostOnce);
|
||||
print('MQTT: Subscribed to /smartfarming/getRelayStatus');
|
||||
|
||||
client!.updates!
|
||||
.listen((List<MqttReceivedMessage<MqttMessage?>>? messages) {
|
||||
if (messages != null && messages.isNotEmpty) {
|
||||
final MqttPublishMessage recMessage =
|
||||
messages[0].payload as MqttPublishMessage;
|
||||
final String payload = MqttPublishPayload.bytesToStringAsString(
|
||||
recMessage.payload.message);
|
||||
print(
|
||||
'MQTT: Message received on topic ${messages[0].topic}: $payload');
|
||||
|
||||
// Parse the received JSON payload
|
||||
final Map<String, dynamic> relayStatus = jsonDecode(payload);
|
||||
|
||||
print('MQTT: Relay status: $relayStatus');
|
||||
|
||||
// Assuming you are using provider, notify it with new relay status
|
||||
// _updateRelayStatus(relayStatus);
|
||||
} else {
|
||||
print('MQTT: No messages received');
|
||||
}
|
||||
});
|
||||
return ResultState.hasData;
|
||||
} catch (e) {
|
||||
print('MQTT: Error subscribing: $e');
|
||||
return ResultState.error;
|
||||
}
|
||||
} else {
|
||||
print('MQTT: Not connected, cannot subscribe.');
|
||||
return ResultState.error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
class Service {}
|
||||
|
|
@ -25,14 +25,14 @@ class ControlProvider extends ChangeNotifier {
|
|||
final result = await _mqttService.setupMqtt();
|
||||
if (result == ResultState.hasData) {
|
||||
mqttState = result;
|
||||
final result2 = await _mqttService.subscribeToTopic('relay1');
|
||||
if (result2 == true) {
|
||||
subscribeState = ResultState.hasData;
|
||||
_control_1 = true;
|
||||
} else {
|
||||
subscribeState = ResultState.hasData;
|
||||
_control_1 = false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,55 +18,40 @@ class ControlScreen extends StatelessWidget {
|
|||
backgroundColor: Colors.white,
|
||||
scrolledUnderElevation: 0,
|
||||
),
|
||||
body: Consumer<ControlProvider>(builder: (context, provider, child) {
|
||||
return SafeArea(
|
||||
body: Consumer<ControlProvider>(
|
||||
builder: (context, provider, child) {
|
||||
return SafeArea(
|
||||
child: ListView(
|
||||
children: [
|
||||
Center(
|
||||
child: provider.mqttState == ResultState.loading
|
||||
? const CupertinoActivityIndicator()
|
||||
: provider.mqttState == ResultState.hasData
|
||||
? const Text('Terhubung ke Broker')
|
||||
: const Text('Gagal terhubung ke Broker'),
|
||||
children: [
|
||||
Center(
|
||||
child: provider.mqttState == ResultState.loading
|
||||
? const CupertinoActivityIndicator()
|
||||
: provider.mqttState == ResultState.hasData
|
||||
? const Text('Terhubung ke Broker')
|
||||
: const Text('Gagal terhubung ke Broker'),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
ListTile(
|
||||
title: Text('Control 1', style: AppTheme.labelMedium),
|
||||
subtitle: const Text('Control 1 description'),
|
||||
trailing: Switch(
|
||||
value: provider.control_1,
|
||||
onChanged: (value) {
|
||||
provider.control_1 == false
|
||||
? provider.publishMessage(
|
||||
'smartfarming/relay/232', 'ON')
|
||||
: provider.publishMessage(
|
||||
'smartfarming/relay/232', 'OFF');
|
||||
provider.switchControl1();
|
||||
},
|
||||
),
|
||||
),
|
||||
// Control lainnya...
|
||||
],
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
ListTile(
|
||||
title: Text('Control 1', style: AppTheme.labelMedium),
|
||||
subtitle: const Text('Control 1 description'),
|
||||
trailing: Switch(
|
||||
value: provider.control_1,
|
||||
onChanged: (value) {
|
||||
provider.control_1 == false
|
||||
? provider.publishMessage('relay1', 'ON')
|
||||
: provider.publishMessage('relay1', 'OFF');
|
||||
provider.switchControl1();
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (context) => AlertDialog(
|
||||
// title: const Text('Konfirmasi'),
|
||||
// content: const Text('Atur Relay 1?'),
|
||||
// actions: [
|
||||
// TextButton(
|
||||
// onPressed: () {
|
||||
// provider.control_1 == false
|
||||
// ? provider.publishMessage('relay1', 'ON')
|
||||
// : provider.publishMessage('relay1', 'OFF');
|
||||
// provider.switchControl1();
|
||||
// Navigator.pop(context);
|
||||
// },
|
||||
// child:
|
||||
// Text(provider.control_1 == false ? 'ON' : 'OFF'),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
},
|
||||
),
|
||||
),
|
||||
// Control lainnya...
|
||||
],
|
||||
));
|
||||
}),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
|
||||
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
|
||||
import 'package:bootstrap_icons/bootstrap_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class ConductivityScreen extends StatelessWidget {
|
||||
const ConductivityScreen({super.key, this.conductivity = 0.0});
|
||||
|
||||
final double conductivity;
|
||||
double get value => conductivity;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Conductivity', style: AppTheme.labelMedium),
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.white,
|
||||
scrolledUnderElevation: 0,
|
||||
actions: const [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(
|
||||
Icons.electric_bolt_rounded,
|
||||
color: Colors.blue,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
body: Center(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.all(16.w),
|
||||
children: [
|
||||
SizedBox(height: 32.h),
|
||||
Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.electric_bolt_rounded,
|
||||
size: 64.r,
|
||||
color: Colors.blue,
|
||||
),
|
||||
Text('$value µS/cm', style: AppTheme.headline1),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Daya Arus Listrik',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
IconButton(
|
||||
iconSize: 20.r,
|
||||
color: Colors.blue,
|
||||
onPressed: () {},
|
||||
icon: const Icon(BootstrapIcons.info_circle))
|
||||
],
|
||||
),
|
||||
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(),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,10 @@ import 'package:gauge_indicator/gauge_indicator.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
|
||||
class HumidityScreen extends StatelessWidget {
|
||||
const HumidityScreen({super.key});
|
||||
const HumidityScreen({super.key, this.humidity = 0});
|
||||
|
||||
final double humidity;
|
||||
double get value => humidity;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
|
||||
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
|
||||
import 'package:bootstrap_icons/bootstrap_icons.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class NitrogenScreen extends StatelessWidget {
|
||||
const NitrogenScreen({super.key, this.nitrogen = 0.0});
|
||||
|
||||
final double nitrogen;
|
||||
double get value => nitrogen;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Nitrogen', style: AppTheme.labelMedium),
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.white,
|
||||
scrolledUnderElevation: 0,
|
||||
actions: const [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(
|
||||
CupertinoIcons.eyedropper,
|
||||
color: Colors.blue,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
body: Center(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.all(16.w),
|
||||
children: [
|
||||
SizedBox(height: 32.h),
|
||||
Column(
|
||||
children: [
|
||||
Icon(
|
||||
CupertinoIcons.eyedropper,
|
||||
size: 64.r,
|
||||
color: Colors.blue,
|
||||
),
|
||||
Text('$value µS/cm', style: AppTheme.headline1),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Nitrogen',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
IconButton(
|
||||
iconSize: 20.r,
|
||||
color: Colors.blue,
|
||||
onPressed: () {},
|
||||
icon: const Icon(BootstrapIcons.info_circle))
|
||||
],
|
||||
),
|
||||
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(),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -24,8 +24,8 @@ class PhScreen extends StatelessWidget {
|
|||
Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(
|
||||
BootstrapIcons.thermometer_half,
|
||||
color: Colors.red,
|
||||
BootstrapIcons.pie_chart,
|
||||
color: Colors.orange,
|
||||
),
|
||||
)
|
||||
],
|
||||
|
|
@ -58,105 +58,105 @@ class PhScreen extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
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),
|
||||
// const Icon(
|
||||
// BootstrapIcons.thermometer_low,
|
||||
// color: Colors.blue,
|
||||
// ),
|
||||
SizedBox(height: 8.h),
|
||||
Text(
|
||||
'<20°C',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
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),
|
||||
// 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),
|
||||
// // const Icon(
|
||||
// // BootstrapIcons.thermometer_low,
|
||||
// // color: Colors.blue,
|
||||
// // ),
|
||||
// SizedBox(height: 8.h),
|
||||
// Text(
|
||||
// '<20°C',
|
||||
// style: AppTheme.labelMedium,
|
||||
// textAlign: TextAlign.center,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// 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(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
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';
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
|
||||
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
|
||||
import 'package:bootstrap_icons/bootstrap_icons.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class PhosphorusScreen extends StatelessWidget {
|
||||
const PhosphorusScreen({super.key, this.phosphorus = 0.0});
|
||||
|
||||
final double phosphorus;
|
||||
double get value => phosphorus;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Phosphorus', style: AppTheme.labelMedium),
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.white,
|
||||
scrolledUnderElevation: 0,
|
||||
actions: const [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(
|
||||
CupertinoIcons.eyedropper,
|
||||
color: Colors.blue,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
body: Center(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.all(16.w),
|
||||
children: [
|
||||
SizedBox(height: 32.h),
|
||||
Column(
|
||||
children: [
|
||||
Icon(
|
||||
CupertinoIcons.eyedropper,
|
||||
size: 64.r,
|
||||
color: Colors.blue,
|
||||
),
|
||||
Text('$value ppm', style: AppTheme.headline1),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Fosfor',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
IconButton(
|
||||
iconSize: 20.r,
|
||||
color: Colors.blue,
|
||||
onPressed: () {},
|
||||
icon: const Icon(BootstrapIcons.info_circle))
|
||||
],
|
||||
),
|
||||
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(),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
|
||||
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
|
||||
import 'package:bootstrap_icons/bootstrap_icons.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class PotassiumScreen extends StatelessWidget {
|
||||
const PotassiumScreen({super.key, this.potassium = 0.0});
|
||||
|
||||
final double potassium;
|
||||
double get value => potassium;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Potassium', style: AppTheme.labelMedium),
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.white,
|
||||
scrolledUnderElevation: 0,
|
||||
actions: const [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(
|
||||
CupertinoIcons.eyedropper,
|
||||
color: Colors.green,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
body: Center(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.all(16.w),
|
||||
children: [
|
||||
SizedBox(height: 32.h),
|
||||
Column(
|
||||
children: [
|
||||
Icon(
|
||||
CupertinoIcons.eyedropper,
|
||||
size: 64.r,
|
||||
color: Colors.green,
|
||||
),
|
||||
Text('$value ppm', style: AppTheme.headline1),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 32.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Kalium',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
IconButton(
|
||||
iconSize: 20.r,
|
||||
color: Colors.blue,
|
||||
onPressed: () {},
|
||||
icon: const Icon(BootstrapIcons.info_circle))
|
||||
],
|
||||
),
|
||||
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(),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,10 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|||
import 'package:gauge_indicator/gauge_indicator.dart';
|
||||
|
||||
class SoilMoistureScreen extends StatelessWidget {
|
||||
const SoilMoistureScreen({super.key});
|
||||
const SoilMoistureScreen({super.key, this.moisture = 0});
|
||||
|
||||
final double moisture;
|
||||
double get value => moisture;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -55,7 +58,7 @@ class SoilMoistureScreen extends StatelessWidget {
|
|||
child: AnimatedRadialGauge(
|
||||
duration: const Duration(seconds: 3),
|
||||
curve: Curves.easeOut,
|
||||
value: 60,
|
||||
value: value,
|
||||
axis: GaugeAxis(
|
||||
degrees: 360,
|
||||
min: 0,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,256 @@
|
|||
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
|
||||
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
|
||||
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
|
||||
import 'package:bootstrap_icons/bootstrap_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:gauge_indicator/gauge_indicator.dart';
|
||||
|
||||
class SoilTemperatureScreen extends StatelessWidget {
|
||||
const SoilTemperatureScreen({super.key, this.temperature = 0});
|
||||
|
||||
final double temperature;
|
||||
double get value => temperature;
|
||||
|
||||
@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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
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,
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const SizedBox(height: 16),
|
||||
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),
|
||||
// const Icon(
|
||||
// BootstrapIcons.thermometer_low,
|
||||
// color: Colors.blue,
|
||||
// ),
|
||||
SizedBox(height: 8.h),
|
||||
Text(
|
||||
'<20°C',
|
||||
style: AppTheme.labelMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
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(),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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'),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,9 +6,10 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|||
import 'package:gauge_indicator/gauge_indicator.dart';
|
||||
|
||||
class TemperatureScreen extends StatelessWidget {
|
||||
const TemperatureScreen({super.key});
|
||||
const TemperatureScreen({super.key, this.temperature = 0});
|
||||
|
||||
double get value => 29;
|
||||
final double temperature;
|
||||
double get value => temperature;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -1,7 +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/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';
|
||||
|
|
@ -59,7 +58,7 @@ class ListDataFromCensorDht extends StatelessWidget {
|
|||
iconColor: Colors.white,
|
||||
censorIdentifier: 'NPK 1',
|
||||
onTap: () async {
|
||||
context.push(AppRoute.humidity, extra: '60');
|
||||
await context.push('${AppRoute.humidity}/60');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
|
|
@ -70,29 +69,34 @@ class ListDataFromCensorDht extends StatelessWidget {
|
|||
icon: BootstrapIcons.thermometer_half,
|
||||
color: Colors.white,
|
||||
onTap: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const TemperatureScreen()));
|
||||
await context.push('${AppRoute.temperature}/28');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Light',
|
||||
subtitle: 'intensitas cahaya',
|
||||
value: '1000',
|
||||
value: '320.5',
|
||||
unit: 'lux',
|
||||
icon: BootstrapIcons.sun,
|
||||
color: Colors.white,
|
||||
onTap: () async {
|
||||
context.push('${AppRoute.light}/300');
|
||||
await context.push('${AppRoute.light}/320.5');
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
case ResultState.noData:
|
||||
return const Center(child: Text('No Data'));
|
||||
return Center(
|
||||
child: Image.asset(
|
||||
'assets/images/no_data_image.png',
|
||||
width: 200.w,
|
||||
));
|
||||
case ResultState.error:
|
||||
return const Center(child: Text('Error'));
|
||||
return Center(
|
||||
child: Image.asset(
|
||||
'assets/images/error_image.png',
|
||||
width: 200.w,
|
||||
));
|
||||
case ResultState.initial:
|
||||
return const SizedBox.shrink();
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
@ -59,10 +57,7 @@ class ListDataFromCensorNpk1 extends StatelessWidget {
|
|||
iconColor: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const TemperatureScreen()));
|
||||
await context.push('${AppRoute.soilTemperature}/28');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
|
|
@ -74,12 +69,7 @@ class ListDataFromCensorNpk1 extends StatelessWidget {
|
|||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const SoilMoistureScreen(),
|
||||
),
|
||||
);
|
||||
await context.push('${AppRoute.soilMoisture}/40');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
|
|
@ -103,7 +93,7 @@ class ListDataFromCensorNpk1 extends StatelessWidget {
|
|||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
context.push(AppRoute.humidity, extra: '60');
|
||||
await context.push('${AppRoute.conductivity}/234');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
|
|
@ -113,7 +103,9 @@ class ListDataFromCensorNpk1 extends StatelessWidget {
|
|||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () {},
|
||||
onTap: () async {
|
||||
await context.push('${AppRoute.nitrogen}/30');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Potassium',
|
||||
|
|
@ -122,7 +114,9 @@ class ListDataFromCensorNpk1 extends StatelessWidget {
|
|||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () {},
|
||||
onTap: () async {
|
||||
await context.push('${AppRoute.potassium}/20');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Phosphorus',
|
||||
|
|
@ -131,14 +125,24 @@ class ListDataFromCensorNpk1 extends StatelessWidget {
|
|||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () {},
|
||||
onTap: () async {
|
||||
await context.push('${AppRoute.phosphorus}/54');
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
case ResultState.noData:
|
||||
return const Center(child: Text('No Data'));
|
||||
return Center(
|
||||
child: Image.asset(
|
||||
'assets/images/no_data_image.png',
|
||||
width: 200.w,
|
||||
));
|
||||
case ResultState.error:
|
||||
return const Center(child: Text('Error'));
|
||||
return Center(
|
||||
child: Image.asset(
|
||||
'assets/images/error_image.png',
|
||||
width: 200.w,
|
||||
));
|
||||
default:
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
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';
|
||||
import 'package:bootstrap_icons/bootstrap_icons.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ListDataFromCensorNpk2 extends StatelessWidget {
|
||||
const ListDataFromCensorNpk2({
|
||||
|
|
@ -17,100 +21,133 @@ class ListDataFromCensorNpk2 extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const String censorIdentifier = 'NPK 1';
|
||||
return GridView(
|
||||
padding: EdgeInsets.all(16.r),
|
||||
shrinkWrap: true,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16.r,
|
||||
mainAxisSpacing: 16.r,
|
||||
childAspectRatio: 0.9,
|
||||
),
|
||||
children: [
|
||||
DataDisplayerWidget(
|
||||
title: 'Temperature',
|
||||
subtitle: 'Suhu tanah',
|
||||
value: '28',
|
||||
unit: '°C',
|
||||
icon: BootstrapIcons.thermometer_half,
|
||||
textColor: Colors.white,
|
||||
color: AppColor.secondary,
|
||||
iconColor: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const TemperatureScreen()));
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Soil Moisture',
|
||||
subtitle: 'kelembaban tanah',
|
||||
value: '40',
|
||||
unit: '%',
|
||||
icon: Icons.water_outlined,
|
||||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const SoilMoistureScreen(),
|
||||
return Consumer<HomeProvider>(builder: (context, provider, child) {
|
||||
switch (provider.dataState) {
|
||||
case ResultState.loading:
|
||||
return GridView(
|
||||
padding: EdgeInsets.all(16.r),
|
||||
shrinkWrap: true,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16.r,
|
||||
mainAxisSpacing: 16.r,
|
||||
childAspectRatio: 0.9,
|
||||
),
|
||||
children: [
|
||||
for (int i = 0; i < 4; i++) const CensorItemLoadingWidgets(),
|
||||
],
|
||||
);
|
||||
case ResultState.hasData:
|
||||
return GridView(
|
||||
padding: EdgeInsets.all(16.r),
|
||||
shrinkWrap: true,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16.r,
|
||||
mainAxisSpacing: 16.r,
|
||||
childAspectRatio: 0.9,
|
||||
),
|
||||
children: [
|
||||
DataDisplayerWidget(
|
||||
title: 'Temperature',
|
||||
subtitle: 'Suhu tanah',
|
||||
value: '28',
|
||||
unit: '°C',
|
||||
icon: BootstrapIcons.thermometer_half,
|
||||
textColor: Colors.white,
|
||||
color: AppColor.secondary,
|
||||
iconColor: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const TemperatureScreen()));
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Acid Level (PH)',
|
||||
subtitle: 'tingkat keasaman',
|
||||
value: '6.5',
|
||||
unit: 'pH',
|
||||
icon: BootstrapIcons.pie_chart,
|
||||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () {},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Conductivity',
|
||||
subtitle: 'Daya Arus Listrik',
|
||||
value: '234',
|
||||
unit: 'µS/cm',
|
||||
icon: Icons.electric_bolt,
|
||||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
context.push(AppRoute.humidity, extra: '60');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Nitrogen',
|
||||
subtitle: 'Kadar Nitrogen',
|
||||
value: '30',
|
||||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () {},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Potassium',
|
||||
subtitle: 'Kadar kalium',
|
||||
value: '20',
|
||||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () {},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Phosphorus',
|
||||
subtitle: 'Kadar Fosfor',
|
||||
value: '54',
|
||||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () {},
|
||||
),
|
||||
],
|
||||
);
|
||||
DataDisplayerWidget(
|
||||
title: 'Soil Moisture',
|
||||
subtitle: 'kelembaban tanah',
|
||||
value: '40',
|
||||
unit: '%',
|
||||
icon: Icons.water_outlined,
|
||||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const SoilMoistureScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Acid Level (PH)',
|
||||
subtitle: 'tingkat keasaman',
|
||||
value: '6.5',
|
||||
unit: 'pH',
|
||||
icon: BootstrapIcons.pie_chart,
|
||||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () {},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Conductivity',
|
||||
subtitle: 'Daya Arus Listrik',
|
||||
value: '234',
|
||||
unit: 'µS/cm',
|
||||
icon: Icons.electric_bolt,
|
||||
color: Colors.white,
|
||||
censorIdentifier: censorIdentifier,
|
||||
onTap: () async {
|
||||
context.push(AppRoute.humidity, extra: '60');
|
||||
},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Nitrogen',
|
||||
subtitle: 'Kadar Nitrogen',
|
||||
value: '30',
|
||||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () {},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Potassium',
|
||||
subtitle: 'Kadar kalium',
|
||||
value: '20',
|
||||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () {},
|
||||
),
|
||||
DataDisplayerWidget(
|
||||
title: 'Phosphorus',
|
||||
subtitle: 'Kadar Fosfor',
|
||||
value: '54',
|
||||
unit: 'ppm',
|
||||
icon: CupertinoIcons.eyedropper,
|
||||
color: Colors.white,
|
||||
onTap: () {},
|
||||
),
|
||||
],
|
||||
);
|
||||
case ResultState.noData:
|
||||
return Center(
|
||||
child: Image.asset(
|
||||
'assets/images/no_data_image.png',
|
||||
width: 200.w,
|
||||
));
|
||||
case ResultState.error:
|
||||
return Center(
|
||||
child: Image.asset(
|
||||
'assets/images/error_image.png',
|
||||
width: 200.w,
|
||||
));
|
||||
default:
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:agrilink_vocpro/core/constant/app_color.dart';
|
||||
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
|
||||
import 'package:agrilink_vocpro/core/route/app_route.dart';
|
||||
import 'package:bootstrap_icons/bootstrap_icons.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user