feat: add basic route, splash, and login screen

This commit is contained in:
Syaroful 2024-09-23 16:34:20 +07:00
parent 0c4ab9995c
commit 0ce3129da5
24 changed files with 477 additions and 73 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

View File

@ -11,4 +11,5 @@ class AppColor {
static const Color greenTextDark = Color(0xFF00913A);
static const Color textDisable = Color(0xFFBDBDBD);
static const Color textDark = Color(0xFF4B4B51);
}

View File

@ -7,15 +7,16 @@ class AppTheme {
letterSpacing: 1,
color: Colors.black,
);
static TextStyle titleLarge = const TextStyle(
fontSize: 16,
fontSize: 17,
fontWeight: FontWeight.w500,
color: Colors.black,
);
static TextStyle titleMedium = const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.black,
static TextStyle titleMedium = TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Colors.grey.shade600,
);
static TextStyle titleSmall = const TextStyle(
fontSize: 12,
@ -23,13 +24,24 @@ class AppTheme {
color: Colors.black,
);
static TextStyle labelLarge = const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.black,
);
static TextStyle labelMedium = const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.black,
);
static TextStyle labelSmall = const TextStyle(
fontSize: 10,
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.grey,
);
static TextStyle hintStyle = const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
color: Colors.grey,
);

View File

@ -0,0 +1,57 @@
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/humidity/view/humidity_screen.dart';
import 'package:agrilink_vocpro/features/splash/view/splash_screen.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class AppRoute {
static const String root = '/';
static const String login = '/login';
static const String dashboard = '/dashboard';
static const String home = '/home';
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 light = '/light';
static const String water = '/water';
static const String acidity = '/acidity';
static final GoRouter router = GoRouter(
initialLocation: root,
routes: [
//splash
GoRoute(
path: root,
builder: (context, state) => const SplashScreen(),
),
//login
GoRoute(
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(),
),
],
),
],
errorBuilder: (context, state) => Scaffold(
body: Center(
child: Text('Error: ${state.error}'),
),
),
);
}

View File

@ -1,7 +1,7 @@
enum ResultState {
initial,
loading,
noData,
hasData,
noData,
error,
}

View File

@ -1,6 +1,5 @@
import 'package:agrilink_vocpro/core/constant/app_color.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class AppButton extends StatelessWidget {
const AppButton({
@ -24,14 +23,14 @@ class AppButton extends StatelessWidget {
onPressed: onPressed,
style: ElevatedButton.styleFrom(
shadowColor: Colors.transparent,
textStyle: TextStyle(
fontSize: 14.sp, fontWeight: FontWeight.w500, fontFamily: 'Onest'),
textStyle: const TextStyle(
fontSize: 14, fontWeight: FontWeight.w500, fontFamily: 'Urbanist'),
backgroundColor: backgroundColor,
foregroundColor: foregroundColor,
minimumSize: Size(double.infinity, 48.h),
minimumSize: const Size(double.infinity, 48),
shape: RoundedRectangleBorder(
side: borderSide ?? BorderSide.none,
borderRadius: BorderRadius.circular(10.r),
borderRadius: BorderRadius.circular(10),
),
),
child: Text(text),

View File

@ -1,9 +1,9 @@
import 'package:agrilink_vocpro/core/constant/app_color.dart';
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class CustomTextField extends StatelessWidget {
const CustomTextField({
class AppTextfield extends StatelessWidget {
const AppTextfield({
super.key,
required this.controller,
this.hintText = 'Enter Here',
@ -20,16 +20,16 @@ class CustomTextField extends StatelessWidget {
controller: controller,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: AppColor.textDisable, width: 1.r),
borderRadius: BorderRadius.circular(8.r),
gapPadding: 10.r),
borderSide: const BorderSide(color: AppColor.textDisable, width: 1),
borderRadius: BorderRadius.circular(8),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: AppColor.primary, width: 1.r),
borderRadius: BorderRadius.circular(8.r),
gapPadding: 10.r),
borderSide: const BorderSide(color: AppColor.primary, width: 1),
borderRadius: BorderRadius.circular(8),
),
hintText: hintText,
// hintStyle: AppTheme.hintStyle,
suffixIcon: suffixIcon),
hintStyle: AppTheme.hintStyle,
suffixIcon: (suffixIcon != null) ? suffixIcon : null),
);
}
}

View File

@ -0,0 +1,12 @@
import 'package:flutter/material.dart';
class AuthProvider extends ChangeNotifier {
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
void controllerClear() {
emailController.clear();
passwordController.clear();
notifyListeners();
}
}

View File

@ -0,0 +1,74 @@
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:agrilink_vocpro/core/widgets/app_button.dart';
import 'package:agrilink_vocpro/core/widgets/app_textfield.dart';
import 'package:agrilink_vocpro/features/auth/provider/auth_provider.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
class LoginScreen extends StatelessWidget {
const LoginScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: SafeArea(
child: Consumer<AuthProvider>(builder: (context, authP, child) {
return ListView(
padding: const EdgeInsets.all(16),
children: [
const SizedBox(height: 40),
Text(
'Hello Wellcome back 👋',
style: AppTheme.titleLarge,
),
Text(
'Happy to have you back',
style: AppTheme.titleMedium,
),
const SizedBox(height: 40),
Text('Email address', style: AppTheme.labelLarge),
const SizedBox(height: 4),
AppTextfield(
controller: authP.emailController,
hintText: 'Masukkan username',
),
const SizedBox(height: 24),
Text('Password', style: AppTheme.labelLarge),
const SizedBox(height: 4),
AppTextfield(
controller: authP.passwordController,
hintText: 'Masukkan password',
),
const SizedBox(height: 24),
GestureDetector(
onTap: () {
print('Forgot password?');
},
child: Text(
'Forgot password?',
textAlign: TextAlign.end,
style: AppTheme.labelMedium
.copyWith(color: AppColor.secondary),
),
),
const SizedBox(height: 24),
AppButton(
onPressed: () {
GoRouter.of(context).go(AppRoute.dashboard);
},
text: 'Login'),
],
);
}),
),
),
);
}
}

View File

@ -1,7 +1,7 @@
import 'package:agrilink_vocpro/core/constant/app_color.dart';
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/features/humidity/widgets/circle_chart.dart';
import 'package:agrilink_vocpro/features/home/pages/humidity/widgets/circle_chart.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class HumidityScreen extends StatelessWidget {
@ -11,8 +11,12 @@ class HumidityScreen extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Humidity', style: AppTheme.titleLarge),
title: Text('Humidity', style: AppTheme.labelLarge),
centerTitle: true,
leading: IconButton(
icon: const Icon(CupertinoIcons.back),
onPressed: () => Navigator.pop(context),
),
backgroundColor: Colors.white,
actions: const [
Padding(
@ -33,7 +37,10 @@ class HumidityScreen extends StatelessWidget {
const SizedBox(
height: 320,
width: double.infinity,
child: CircleChart(humidityPercentage: 60.5),
child: CircleChart(
percentage: 60.5,
icon: BootstrapIcons.droplet_half,
),
),
const SizedBox(height: 16),
],

View File

@ -1,11 +1,15 @@
import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
class CircleChart extends StatefulWidget {
const CircleChart({super.key, required this.humidityPercentage});
const CircleChart({
super.key,
required this.percentage,
required this.icon,
});
final double humidityPercentage;
final double percentage;
final IconData icon;
@override
State<CircleChart> createState() => _CircleChartState();
@ -17,7 +21,7 @@ class _CircleChartState extends State<CircleChart> {
void initState() {
super.initState();
Future.delayed(Duration.zero, () async {
for (double i = 0; i <= widget.humidityPercentage; i++) {
for (double i = 0; i <= widget.percentage; i++) {
await Future.delayed(const Duration(milliseconds: 25), () {
setState(() {
currentPercentage = i;
@ -62,8 +66,7 @@ class _CircleChartState extends State<CircleChart> {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(BootstrapIcons.droplet_fill,
size: 32, color: _getAnimatedColor(value)),
Icon(widget.icon, size: 32, color: _getAnimatedColor(value)),
Text(
'${value.toStringAsFixed(0)}%', // Animated percentage text
style: const TextStyle(
@ -81,11 +84,11 @@ class _CircleChartState extends State<CircleChart> {
);
}
List<PieChartSectionData> _createSections(double humidityPercentage) {
List<PieChartSectionData> _createSections(double percentage) {
return [
PieChartSectionData(
color: Colors.white,
value: humidityPercentage,
value: percentage,
title: '',
radius: 50, // Size of the pie slice
titleStyle: const TextStyle(
@ -96,7 +99,7 @@ class _CircleChartState extends State<CircleChart> {
),
PieChartSectionData(
color: Colors.white24,
value: 100 - humidityPercentage,
value: 100 - percentage,
title: '',
radius: 50,
),
@ -105,6 +108,6 @@ class _CircleChartState extends State<CircleChart> {
Color _getAnimatedColor(double percentage) {
return Color.lerp(
Colors.green, Colors.blue, percentage / widget.humidityPercentage)!;
Colors.green, Colors.blue, percentage / widget.percentage)!;
}
}

View File

@ -0,0 +1,50 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/features/home/pages/humidity/widgets/circle_chart.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class SoilMoistureScreen extends StatelessWidget {
const SoilMoistureScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Soil Moisture', style: AppTheme.labelMedium),
centerTitle: true,
backgroundColor: Colors.white,
leading: IconButton(
icon: const Icon(CupertinoIcons.back),
onPressed: () => Navigator.pop(context),
),
actions: const [
Padding(
padding: EdgeInsets.only(right: 16),
child: Icon(
Icons.water_outlined,
color: Colors.blue,
),
)
],
),
body: SafeArea(
child: ListView(
children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.05,
),
const SizedBox(
height: 320,
width: double.infinity,
child: CircleChart(
percentage: 60.5,
icon: Icons.water_outlined,
),
),
const SizedBox(height: 16),
],
),
),
);
}
}

View File

@ -0,0 +1,48 @@
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/material.dart';
class TemperatureScreen extends StatelessWidget {
const TemperatureScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Temperature', style: AppTheme.titleLarge),
centerTitle: true,
backgroundColor: Colors.white,
actions: const [
Padding(
padding: EdgeInsets.only(right: 16),
child: Icon(
BootstrapIcons.thermometer_half,
color: Colors.red,
),
)
],
),
body: SafeArea(
child: ListView(
children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.05,
),
Center(
child: SizedBox(
height: 320,
width: 320,
child: CircularProgressIndicator(
strokeWidth: 10,
backgroundColor: Colors.grey.shade200,
value: 0.5,
valueColor: const AlwaysStoppedAnimation<Color>(Colors.red),
),
)),
const SizedBox(height: 16),
],
),
),
);
}
}

View File

@ -1,11 +1,15 @@
import 'package:agrilink_vocpro/core/constant/app_color.dart';
import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/extension/extention.dart';
import 'package:agrilink_vocpro/core/route/app_route.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/data_display_widget.dart';
import 'package:agrilink_vocpro/features/humidity/view/humidity_screen.dart';
import 'package:agrilink_vocpro/features/home/pages/humidity/view/humidity_screen.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
class HomeScreen extends StatelessWidget {
@ -14,14 +18,6 @@ class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Home',
style: AppTheme.titleMedium,
),
centerTitle: true,
backgroundColor: Colors.white,
),
body: SafeArea(
child: RefreshIndicator(
onRefresh: () async {
@ -30,11 +26,34 @@ class HomeScreen extends StatelessWidget {
child: ListView(
padding: const EdgeInsets.all(16),
children: [
Text(
'${getGreeting(DateTime.now().toString())}, Fikril',
style: AppTheme.titleLarge,
Row(
children: [
const CircleAvatar(
radius: 24,
backgroundColor: AppColor.primary,
child: Icon(
Icons.person,
color: Colors.white,
size: 24,
),
),
const SizedBox(width: 16),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
getGreeting(DateTime.now().toString()),
style: AppTheme.titleMedium,
),
Text(
'Fikril Mahesaputra',
style: AppTheme.titleLarge,
),
],
),
],
),
const SizedBox(height: 12),
const SizedBox(height: 24),
Consumer<HomeProvider>(builder: (context, provider, child) {
return Container(
padding: const EdgeInsets.all(16),
@ -83,7 +102,7 @@ class HomeScreen extends StatelessWidget {
);
}),
const SizedBox(height: 16),
Text('Recent Activity', style: AppTheme.titleMedium),
Text('Linked Device', style: AppTheme.titleMedium),
const SizedBox(height: 16),
GridView(
physics: const NeverScrollableScrollPhysics(),
@ -104,19 +123,22 @@ class HomeScreen extends StatelessWidget {
color: AppColor.secondary,
iconColor: Colors.white,
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const HumidityScreen()));
context.push(AppRoute.humidity, extra: '60');
},
),
const DataDisplayerWidget(
DataDisplayerWidget(
title: 'Temperature',
subtitle: 'suhu greenhouse',
value: '28',
unit: '°C',
icon: BootstrapIcons.thermometer_half,
color: Colors.white,
onTap: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const TemperatureScreen()));
},
),
const DataDisplayerWidget(
title: 'Light',
@ -126,13 +148,29 @@ class HomeScreen extends StatelessWidget {
icon: BootstrapIcons.sun,
color: Colors.white,
),
const DataDisplayerWidget(
DataDisplayerWidget(
title: 'Soil Moisture',
subtitle: 'kelembaban tanah',
value: '40',
unit: '%',
icon: Icons.water_outlined,
color: Colors.white,
onTap: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SoilMoistureScreen(),
),
);
},
),
const DataDisplayerWidget(
title: 'Acid Level',
subtitle: 'tingkat keasaman',
value: '6.5',
unit: '',
icon: BootstrapIcons.pie_chart,
color: Colors.white,
)
],
)

View File

@ -1,4 +1,8 @@
import 'dart:async';
import 'package:agrilink_vocpro/core/route/app_route.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class SplashScreen extends StatefulWidget {
const SplashScreen({super.key});
@ -8,8 +12,64 @@ class SplashScreen extends StatefulWidget {
}
class _SplashScreenState extends State<SplashScreen> {
bool isLoggedIn = false;
@override
void initState() {
super.initState();
_initialize();
}
Future<void> _initialize() async {
// final authProvider = Provider.of<AuthProvider>(context, listen: false);
// bool isLoggedIn = await _checkLoginStatus(authProvider);
_navigateAfterSplash(isLoggedIn);
}
// Future<bool> _checkLoginStatus(AuthProvider authProvider) async {
// SharedPreferences prefs = await SharedPreferences.getInstance();
// if (prefs.getKeys().isEmpty) return false;
// if (prefs.getBool('isLoggedIn') == true) {
// String? token = prefs.getString('token');
// String? refreshToken = prefs.getString('refreshToken');
// if (token != null && !JwtDecoder.isExpired(token)) {
// return true;
// } else if (refreshToken != null && !JwtDecoder.isExpired(refreshToken)) {
// final result = await authProvider.refreshToken();
// return result == ResultState.hasData;
// } else {
// prefs.remove('token');
// return false;
// }
// }
// return false;
// }
void _navigateAfterSplash(bool isLoggedIn) {
Timer(const Duration(seconds: 2), () {
if (isLoggedIn == true) {
context.go(AppRoute.dashboard);
} else {
context.go(AppRoute.login);
}
});
}
@override
Widget build(BuildContext context) {
return const Placeholder();
return Scaffold(
body: SafeArea(
child: Center(
child: Image.asset(
'assets/images/app_logo.png',
width: 80,
),
),
),
);
}
}

View File

@ -1,7 +1,7 @@
import 'package:agrilink_vocpro/core/route/app_route.dart';
import 'package:agrilink_vocpro/features/auth/provider/auth_provider.dart';
import 'package:agrilink_vocpro/features/dashboard/provider/dashboard_provider.dart';
import 'package:agrilink_vocpro/features/dashboard/view/dashboard_screen.dart';
import 'package:agrilink_vocpro/features/home/provider/home_provider.dart';
import 'package:agrilink_vocpro/features/home/view/home_screen.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -17,10 +17,11 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => AuthProvider()),
ChangeNotifierProvider(create: (context) => HomeProvider()),
ChangeNotifierProvider(create: (context) => DashboardProvider()),
],
child: MaterialApp(
child: MaterialApp.router(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
@ -28,7 +29,7 @@ class MyApp extends StatelessWidget {
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
useMaterial3: true,
),
home: const DashboardScreen(),
routerConfig: AppRoute.router,
),
);
}

View File

@ -5,8 +5,10 @@
import FlutterMacOS
import Foundation
import path_provider_foundation
import shared_preferences_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
}

View File

@ -49,6 +49,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.18.0"
crypto:
dependency: transitive
description:
name: crypto
sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27
url: "https://pub.dev"
source: hosted
version: "3.0.5"
cupertino_icons:
dependency: "direct main"
description:
@ -126,14 +134,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.0"
flutter_screenutil:
dependency: "direct main"
description:
name: flutter_screenutil
sha256: "8239210dd68bee6b0577aa4a090890342d04a136ce1c81f98ee513fc0ce891de"
url: "https://pub.dev"
source: hosted
version: "5.9.3"
flutter_test:
dependency: "direct dev"
description: flutter
@ -152,6 +152,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "14.2.7"
google_fonts:
dependency: "direct main"
description:
name: google_fonts
sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82
url: "https://pub.dev"
source: hosted
version: "6.2.1"
http:
dependency: transitive
description:
name: http
sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
url: "https://pub.dev"
source: hosted
version: "1.2.2"
http_parser:
dependency: transitive
description:
@ -248,6 +264,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.0"
path_provider:
dependency: transitive
description:
name: path_provider
sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378
url: "https://pub.dev"
source: hosted
version: "2.1.4"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7"
url: "https://pub.dev"
source: hosted
version: "2.2.10"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
url: "https://pub.dev"
source: hosted
version: "2.4.0"
path_provider_linux:
dependency: transitive
description:

View File

@ -39,9 +39,9 @@ dependencies:
intl: ^0.19.0
dio: ^5.7.0
go_router: ^14.2.7
flutter_screenutil: ^5.9.3
bootstrap_icons: ^1.11.3
fl_chart: ^0.69.0
google_fonts: ^6.2.1
dev_dependencies:
flutter_test: