Initial
This commit is contained in:
parent
9ba173f00e
commit
6b0162bb12
9 changed files with 653 additions and 6 deletions
28
.vscode/launch.json
vendored
Normal file
28
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "monarch",
|
||||
"cwd": "Frontend\\monarch",
|
||||
"request": "launch",
|
||||
"type": "dart"
|
||||
},
|
||||
{
|
||||
"name": "monarch (profile mode)",
|
||||
"cwd": "Frontend\\monarch",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"flutterMode": "profile"
|
||||
},
|
||||
{
|
||||
"name": "monarch (release mode)",
|
||||
"cwd": "Frontend\\monarch",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"flutterMode": "release"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -91,7 +91,7 @@ app.post('/api/transaction/add', async (req, res) => {
|
|||
const { description, amount } = req.body;
|
||||
|
||||
// Call your AI prediction endpoint
|
||||
const predictRes = await axios.post('http://10.117.157.140:5000/api/predict', {
|
||||
const predictRes = await axios.post('http://192.168.29.129:5000/api/predict', {
|
||||
description,
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ plugins {
|
|||
android {
|
||||
namespace = "com.example.monarch"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
ndkVersion = "27.0.12077973"
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ import 'dart:convert';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:monarch/static.dart';
|
||||
import 'package:monarch/transaction.dart';
|
||||
|
||||
void main() {
|
||||
WidgetsFlutterBinding.ensureInitialized(); // This fixes the issue
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
|
|
@ -18,7 +20,7 @@ class MyApp extends StatelessWidget {
|
|||
return MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData(primarySwatch: Colors.blue),
|
||||
home: const AddTransactionPage(),
|
||||
home: const Statistics(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -43,7 +45,7 @@ class _AddTransactionPageState extends State<AddTransactionPage> {
|
|||
|
||||
try {
|
||||
final response = await http.post(
|
||||
Uri.parse('http://192.168.172.140:3000/api/transaction/add'),
|
||||
Uri.parse('http://192.168.1.5:3000/api/transaction/add'),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: json.encode({
|
||||
'description': descriptionController.text,
|
||||
|
|
|
|||
501
Frontend/monarch/lib/static.dart
Normal file
501
Frontend/monarch/lib/static.dart
Normal file
|
|
@ -0,0 +1,501 @@
|
|||
// ignore_for_file: sort_child_properties_last, use_build_context_synchronously, deprecated_member_use
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class Transaction {
|
||||
final String description;
|
||||
final double amount;
|
||||
final String category;
|
||||
final DateTime date;
|
||||
|
||||
Transaction({
|
||||
required this.description,
|
||||
required this.amount,
|
||||
required this.category,
|
||||
required this.date,
|
||||
});
|
||||
|
||||
factory Transaction.fromJson(Map<String, dynamic> json) {
|
||||
return Transaction(
|
||||
description: json['description'],
|
||||
amount: (json['amount'] as num).toDouble(),
|
||||
category: json['category'],
|
||||
date: DateTime.parse(json['date']),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Statistics extends StatefulWidget {
|
||||
const Statistics({super.key});
|
||||
|
||||
@override
|
||||
State<Statistics> createState() => StatisticsState();
|
||||
}
|
||||
|
||||
class StatisticsState extends State<Statistics> {
|
||||
List<Transaction> transactions = [];
|
||||
bool isLoading = false;
|
||||
|
||||
final List<String> categories = [
|
||||
'All',
|
||||
'Food',
|
||||
'Shopping',
|
||||
'Bills',
|
||||
'Travel',
|
||||
'Entertainment',
|
||||
'Other',
|
||||
];
|
||||
|
||||
String selectedCategory = 'All';
|
||||
String _selectedPlan = 'Monthly';
|
||||
|
||||
Map<String, double> totalAmountPerCategory = {};
|
||||
|
||||
final Color backgroundColor = Color(0xFF121212); // Deep black
|
||||
final Color accentColor = Color(0xFF00FF88); // Modern green
|
||||
final Color cardColor = Color(0xFF1F1F1F); // Darker gray
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
fetchTransactions();
|
||||
}
|
||||
|
||||
//API Call for Fetch
|
||||
Future<void> fetchTransactions({String category = 'All'}) async {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
final uri = Uri.parse('http://192.168.1.5:3000/api/transactions').replace(
|
||||
queryParameters: category == 'All' ? null : {'category': category},
|
||||
);
|
||||
|
||||
final response = await http.get(uri);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final data = json.decode(response.body);
|
||||
final List<dynamic> list = data['data'];
|
||||
|
||||
final fetched = list.map((json) => Transaction.fromJson(json)).toList();
|
||||
|
||||
final totals = <String, double>{};
|
||||
for (var tx in fetched) {
|
||||
totals[tx.category] = (totals[tx.category] ?? 0) + tx.amount;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
transactions = fetched;
|
||||
totalAmountPerCategory = totals;
|
||||
});
|
||||
} else {
|
||||
throw Exception('Failed to load transactions');
|
||||
}
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Error loading transactions: $e')));
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildCategoryChips() {
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||
child: Row(
|
||||
children:
|
||||
categories.map((cat) {
|
||||
final bool isSelected = cat == selectedCategory;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
child: ChoiceChip(
|
||||
label: Text(cat),
|
||||
selected: isSelected,
|
||||
selectedColor: backgroundColor,
|
||||
backgroundColor: accentColor,
|
||||
labelStyle: GoogleFonts.poppins(
|
||||
color: isSelected ? accentColor : cardColor,
|
||||
),
|
||||
onSelected: (selected) {
|
||||
if (selected) {
|
||||
setState(() {
|
||||
selectedCategory = cat;
|
||||
});
|
||||
fetchTransactions(category: cat);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildTransactionCard(Transaction tx) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: cardColor.withOpacity(0.8),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.4),
|
||||
blurRadius: 10,
|
||||
offset: Offset(0, 6),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
tx.description,
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
'${tx.category} • ${tx.date.toLocal().toString().split(' ')[0]}',
|
||||
style: GoogleFonts.poppins(color: Colors.white60, fontSize: 12),
|
||||
),
|
||||
trailing: Text(
|
||||
'₹${tx.amount.toStringAsFixed(2)}',
|
||||
style: GoogleFonts.poppins(
|
||||
color: accentColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildToggleButton(String label) {
|
||||
final bool isSelected = _selectedPlan == label;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => setState(() => _selectedPlan = label),
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected ? accentColor : cardColor,
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
boxShadow:
|
||||
isSelected
|
||||
? [
|
||||
BoxShadow(
|
||||
color: accentColor.withOpacity(0.4),
|
||||
blurRadius: 12,
|
||||
spreadRadius: 1,
|
||||
),
|
||||
]
|
||||
: [],
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
label,
|
||||
style: GoogleFonts.poppins(
|
||||
color: isSelected ? backgroundColor : Colors.white70,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
int _selectedIndex = 0;
|
||||
|
||||
Widget buildBarChart() {
|
||||
final barData = totalAmountPerCategory.entries.toList();
|
||||
|
||||
if (barData.isEmpty) {
|
||||
return Center(
|
||||
child: Text(
|
||||
'No data to display',
|
||||
style: GoogleFonts.poppins(color: Colors.white70),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
double maxY = barData.map((e) => e.value).reduce((a, b) => a > b ? a : b);
|
||||
|
||||
return AspectRatio(
|
||||
aspectRatio: 1.7,
|
||||
child: BarChart(
|
||||
BarChartData(
|
||||
backgroundColor: backgroundColor,
|
||||
alignment: BarChartAlignment.spaceAround,
|
||||
maxY: maxY + 20,
|
||||
borderData: FlBorderData(show: false),
|
||||
titlesData: FlTitlesData(
|
||||
leftTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
getTitlesWidget: (value, _) {
|
||||
if (value.toInt() < barData.length) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
barData[value.toInt()].key,
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
},
|
||||
reservedSize: 30,
|
||||
),
|
||||
),
|
||||
rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
),
|
||||
barGroups: List.generate(barData.length, (i) {
|
||||
return BarChartGroupData(
|
||||
x: i,
|
||||
barRods: [
|
||||
BarChartRodData(
|
||||
toY: barData[i].value,
|
||||
gradient: LinearGradient(
|
||||
colors: [accentColor, accentColor.withOpacity(0.6)],
|
||||
begin: Alignment.bottomCenter,
|
||||
end: Alignment.topCenter,
|
||||
),
|
||||
width: 20,
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
backgroundColor: backgroundColor,
|
||||
elevation: 0,
|
||||
title: Text(
|
||||
'Statistics',
|
||||
style: GoogleFonts.poppins(color: Colors.white),
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.more_vert, color: Colors.white),
|
||||
onPressed: () {},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(child: _buildToggleButton('Monthly')),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(child: _buildToggleButton('Yearly')),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Text(
|
||||
'₹ ${transactions.fold<double>(0, (sum, tx) => sum + tx.amount).toStringAsFixed(2)}',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: accentColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(padding: const EdgeInsets.all(16.0), child: buildBarChart()),
|
||||
buildCategoryChips(),
|
||||
const SizedBox(height: 10),
|
||||
Expanded(
|
||||
child:
|
||||
isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: transactions.isEmpty
|
||||
? Center(
|
||||
child: Text(
|
||||
'No transactions found.',
|
||||
style: GoogleFonts.poppins(color: Colors.white70),
|
||||
),
|
||||
)
|
||||
: ListView.builder(
|
||||
itemCount: transactions.length,
|
||||
itemBuilder:
|
||||
(context, index) =>
|
||||
buildTransactionCard(transactions[index]),
|
||||
),
|
||||
),
|
||||
|
||||
CustomNavBar(
|
||||
currentIndex: _selectedIndex,
|
||||
onTap: (index) {
|
||||
setState(() => _selectedIndex = index);
|
||||
},
|
||||
backgroundColor: backgroundColor.withOpacity(0.0),
|
||||
accentColor: accentColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CustomNavBar extends StatelessWidget {
|
||||
final int currentIndex;
|
||||
final void Function(int) onTap;
|
||||
final Color backgroundColor;
|
||||
final Color accentColor;
|
||||
|
||||
const CustomNavBar({
|
||||
super.key,
|
||||
required this.currentIndex,
|
||||
required this.onTap,
|
||||
required this.backgroundColor,
|
||||
required this.accentColor,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
|
||||
return Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: SizedBox(
|
||||
width: screenWidth,
|
||||
height: 100, // enough space, but no visible background
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
// Translucent nav bar
|
||||
Positioned(
|
||||
left: 20,
|
||||
bottom: 20,
|
||||
child: Container(
|
||||
width: screenWidth * 0.5,
|
||||
height: 70,
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(40),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 20,
|
||||
spreadRadius: 2,
|
||||
offset: const Offset(0, 10),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(40),
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 12.0, sigmaY: 12.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
_buildNavItem(Icons.home, 0),
|
||||
_buildNavItem(Icons.pie_chart, 1),
|
||||
_buildNavItem(Icons.settings, 2),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Floating Add Button
|
||||
Positioned(
|
||||
right: 20,
|
||||
bottom: 12,
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
shape: const CircleBorder(),
|
||||
child: InkWell(
|
||||
onTap: () => onTap(4),
|
||||
customBorder: const CircleBorder(),
|
||||
splashColor: Colors.white.withOpacity(0.2),
|
||||
child: Container(
|
||||
width: 58,
|
||||
height: 58,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: accentColor,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: accentColor.withOpacity(0.6),
|
||||
blurRadius: 12,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: const Icon(Icons.add, color: Colors.black, size: 30),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildNavItem(IconData icon, int index) {
|
||||
final isActive = currentIndex == index;
|
||||
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
shape: const CircleBorder(),
|
||||
child: InkWell(
|
||||
onTap: () => onTap(index),
|
||||
customBorder: const CircleBorder(),
|
||||
splashColor: accentColor.withOpacity(0.2),
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 250),
|
||||
width: isActive ? 56 : 50,
|
||||
height: isActive ? 56 : 50,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: isActive ? accentColor.withOpacity(0.1) : Colors.transparent,
|
||||
border:
|
||||
isActive
|
||||
? Border.all(color: accentColor.withOpacity(0.5), width: 2)
|
||||
: null,
|
||||
),
|
||||
child: Icon(
|
||||
icon,
|
||||
color: isActive ? accentColor : Colors.white70,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ class _TransactionsPageState extends State<TransactionsPage> {
|
|||
|
||||
try {
|
||||
final uri = Uri.parse(
|
||||
'http://192.168.172.140:3000/api/transactions',
|
||||
'http://192.168.1.5:3000/api/transactions',
|
||||
).replace(
|
||||
queryParameters: category == 'All' ? null : {'category': category},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import path_provider_foundation
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.6"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -49,6 +57,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.8"
|
||||
equatable:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: equatable
|
||||
sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.7"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -57,6 +73,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
fl_chart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: fl_chart
|
||||
sha256: "577aeac8ca414c25333334d7c4bb246775234c0e44b38b10a82b559dd4d764e7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
|
@ -75,6 +107,14 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
google_fonts:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: google_fonts
|
||||
sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.1"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -155,6 +195,70 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.17"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.6"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
|
@ -240,6 +344,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
sdks:
|
||||
dart: ">=3.7.2 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
flutter: ">=3.27.4"
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ dependencies:
|
|||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.8
|
||||
http: ^1.4.0
|
||||
fl_chart: ^1.0.0
|
||||
google_fonts: ^6.2.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Reference in a new issue