Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
M
Mapping-Software-Efficient-Routing-Algorithm
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
h703249754
Mapping-Software-Efficient-Routing-Algorithm
Commits
101cfa5c
Commit
101cfa5c
authored
Oct 04, 2025
by
aleenaasghar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: Implement CSV address upload functionality
parent
7ee35231
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
182 additions
and
56 deletions
+182
-56
admin_dashboard_screen.dart
lib/screens/admin_dashboard_screen.dart
+73
-1
profile_screen.dart
lib/screens/profile_screen.dart
+73
-55
firestore_service.dart
lib/services/firestore_service.dart
+10
-0
pubspec.lock
pubspec.lock
+24
-0
pubspec.yaml
pubspec.yaml
+2
-0
No files found.
lib/screens/admin_dashboard_screen.dart
View file @
101cfa5c
import
'dart:convert'
;
import
'package:csv/csv.dart'
;
import
'package:file_picker/file_picker.dart'
;
import
'package:firebase_auth/firebase_auth.dart'
;
import
'package:firebase_auth/firebase_auth.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_svg/flutter_svg.dart'
;
import
'package:flutter_svg/flutter_svg.dart'
;
...
@@ -46,6 +49,74 @@ class _AdminDashboardScreenState extends State<AdminDashboardScreen> {
...
@@ -46,6 +49,74 @@ class _AdminDashboardScreenState extends State<AdminDashboardScreen> {
);
);
}
}
Future
<
void
>
_showUploadCsvDialog
()
async
{
try
{
final
result
=
await
FilePicker
.
platform
.
pickFiles
(
type:
FileType
.
custom
,
allowedExtensions:
[
'csv'
],
);
if
(
result
==
null
||
!
mounted
)
return
;
final
file
=
result
.
files
.
first
;
final
bytes
=
file
.
bytes
;
if
(
bytes
==
null
)
return
;
final
content
=
utf8
.
decode
(
bytes
);
final
list
=
const
CsvToListConverter
().
convert
(
content
);
if
(
list
.
isNotEmpty
)
{
list
.
removeAt
(
0
);
// remove header
}
final
addresses
=
list
.
map
((
row
)
{
try
{
return
DeliveryAddress
(
streetAddress:
row
[
0
].
toString
(),
city:
row
[
1
].
toString
(),
state:
row
[
2
].
toString
(),
zipCode:
row
[
3
].
toString
(),
notes:
row
.
length
>
4
?
row
[
4
].
toString
()
:
null
,
);
}
catch
(
e
)
{
print
(
'Error parsing row:
$row
, error:
$e
'
);
return
null
;
}
}).
where
((
address
)
=>
address
!=
null
).
cast
<
DeliveryAddress
>().
toList
();
if
(!
mounted
)
return
;
// Check if the widget is still in the tree
if
(
addresses
.
isNotEmpty
)
{
try
{
await
_firestoreService
.
saveAddressesFromCsv
(
addresses
);
if
(
mounted
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Addresses uploaded successfully!'
)),
);
}
}
catch
(
e
)
{
if
(
mounted
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'Error uploading addresses:
$e
'
)),
);
}
}
}
else
{
if
(
mounted
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'No valid addresses found in the CSV file.'
)),
);
}
}
}
catch
(
e
)
{
if
(
mounted
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'Error picking file:
$e
'
)),
);
}
}
}
void
_deleteAddress
(
String
addressId
)
{
void
_deleteAddress
(
String
addressId
)
{
_firestoreService
.
deleteAddress
(
addressId
);
_firestoreService
.
deleteAddress
(
addressId
);
}
}
...
@@ -61,6 +132,7 @@ class _AdminDashboardScreenState extends State<AdminDashboardScreen> {
...
@@ -61,6 +132,7 @@ class _AdminDashboardScreenState extends State<AdminDashboardScreen> {
password:
_passwordController
.
text
.
trim
(),
password:
_passwordController
.
text
.
trim
(),
);
);
}
on
FirebaseAuthException
catch
(
e
)
{
}
on
FirebaseAuthException
catch
(
e
)
{
if
(!
mounted
)
return
;
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
"Login Failed:
${e.message}
"
)),
SnackBar
(
content:
Text
(
"Login Failed:
${e.message}
"
)),
);
);
...
@@ -139,7 +211,7 @@ class _AdminDashboardScreenState extends State<AdminDashboardScreen> {
...
@@ -139,7 +211,7 @@ class _AdminDashboardScreenState extends State<AdminDashboardScreen> {
),
),
const
SizedBox
(
width:
16
),
const
SizedBox
(
width:
16
),
OutlinedButton
.
icon
(
OutlinedButton
.
icon
(
onPressed:
null
,
// Disabled for now
onPressed:
_showUploadCsvDialog
,
icon:
const
Icon
(
Icons
.
upload_file
),
icon:
const
Icon
(
Icons
.
upload_file
),
label:
const
Text
(
'Upload CSV'
),
label:
const
Text
(
'Upload CSV'
),
style:
OutlinedButton
.
styleFrom
(
style:
OutlinedButton
.
styleFrom
(
...
...
lib/screens/profile_screen.dart
View file @
101cfa5c
import
'dart:typed_data'
;
import
'package:firebase_auth/firebase_auth.dart'
;
import
'package:firebase_auth/firebase_auth.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:cloud_firestore/cloud_firestore.dart'
;
import
'package:cloud_firestore/cloud_firestore.dart'
;
import
'package:image_picker/image_picker.dart'
;
import
'package:image_picker/image_picker.dart'
;
import
'package:firebase_storage/firebase_storage.dart'
;
import
'package:firebase_storage/firebase_storage.dart'
;
import
'dart:io'
;
import
'../colors.dart'
;
import
'../colors.dart'
;
import
'../services/google_auth_service.dart'
;
import
'../services/google_auth_service.dart'
;
...
@@ -18,15 +19,16 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -18,15 +19,16 @@ class _ProfileScreenState extends State<ProfileScreen> {
User
?
_user
;
User
?
_user
;
bool
_isLoading
=
false
;
bool
_isLoading
=
false
;
bool
_isEditing
=
false
;
bool
_isEditing
=
false
;
// Profile editing controllers
// Profile editing controllers
final
TextEditingController
_nameController
=
TextEditingController
();
final
TextEditingController
_nameController
=
TextEditingController
();
final
TextEditingController
_phoneController
=
TextEditingController
();
final
TextEditingController
_phoneController
=
TextEditingController
();
final
TextEditingController
_bioController
=
TextEditingController
();
final
TextEditingController
_bioController
=
TextEditingController
();
final
TextEditingController
_companyController
=
TextEditingController
();
final
TextEditingController
_companyController
=
TextEditingController
();
String
?
_profileImageUrl
;
String
?
_profileImageUrl
;
File
?
_selectedImage
;
XFile
?
_selectedImage
;
Uint8List
?
_selectedImageBytes
;
// GraphGo specific stats
// GraphGo specific stats
int
_totalRoutes
=
0
;
int
_totalRoutes
=
0
;
...
@@ -80,9 +82,11 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -80,9 +82,11 @@ class _ProfileScreenState extends State<ProfileScreen> {
}
catch
(
e
)
{
}
catch
(
e
)
{
print
(
'Error loading user data:
$e
'
);
print
(
'Error loading user data:
$e
'
);
}
finally
{
}
finally
{
setState
(()
{
if
(
mounted
)
{
_isLoading
=
false
;
setState
(()
{
});
_isLoading
=
false
;
});
}
}
}
}
}
...
@@ -126,12 +130,14 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -126,12 +130,14 @@ class _ProfileScreenState extends State<ProfileScreen> {
totalEfficiency
+=
(
routeData
[
'efficiency'
]
??
0.0
).
toDouble
();
totalEfficiency
+=
(
routeData
[
'efficiency'
]
??
0.0
).
toDouble
();
}
}
setState
(()
{
if
(
mounted
)
{
_totalRoutes
=
totalRoutes
;
setState
(()
{
_totalDeliveries
=
totalDeliveries
;
_totalRoutes
=
totalRoutes
;
_totalDistance
=
totalDistance
;
_totalDeliveries
=
totalDeliveries
;
_averageEfficiency
=
totalRoutes
>
0
?
totalEfficiency
/
totalRoutes
:
0.0
;
_totalDistance
=
totalDistance
;
});
_averageEfficiency
=
totalRoutes
>
0
?
totalEfficiency
/
totalRoutes
:
0.0
;
});
}
}
}
}
catch
(
e
)
{
}
catch
(
e
)
{
print
(
'Error loading user stats:
$e
'
);
print
(
'Error loading user stats:
$e
'
);
...
@@ -149,12 +155,15 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -149,12 +155,15 @@ class _ProfileScreenState extends State<ProfileScreen> {
);
);
if
(
image
!=
null
)
{
if
(
image
!=
null
)
{
final
bytes
=
await
image
.
readAsBytes
();
setState
(()
{
setState
(()
{
_selectedImage
=
File
(
image
.
path
);
_selectedImage
=
image
;
_selectedImageBytes
=
bytes
;
});
});
}
}
}
catch
(
e
)
{
}
catch
(
e
)
{
print
(
'Error picking image:
$e
'
);
print
(
'Error picking image:
$e
'
);
if
(!
mounted
)
return
;
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'Error selecting image:
$e
'
)),
SnackBar
(
content:
Text
(
'Error selecting image:
$e
'
)),
);
);
...
@@ -162,7 +171,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -162,7 +171,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
}
}
Future
<
void
>
_uploadProfileImage
()
async
{
Future
<
void
>
_uploadProfileImage
()
async
{
if
(
_selectedImage
==
null
)
return
;
if
(
_selectedImage
==
null
||
_selectedImageBytes
==
null
)
return
;
try
{
try
{
setState
(()
{
setState
(()
{
...
@@ -175,24 +184,29 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -175,24 +184,29 @@ class _ProfileScreenState extends State<ProfileScreen> {
.
child
(
'profile_images'
)
.
child
(
'profile_images'
)
.
child
(
fileName
);
.
child
(
fileName
);
UploadTask
uploadTask
=
storageRef
.
put
File
(
_selectedImage
!);
UploadTask
uploadTask
=
storageRef
.
put
Data
(
_selectedImageBytes
!);
TaskSnapshot
snapshot
=
await
uploadTask
;
TaskSnapshot
snapshot
=
await
uploadTask
;
String
downloadUrl
=
await
snapshot
.
ref
.
getDownloadURL
();
String
downloadUrl
=
await
snapshot
.
ref
.
getDownloadURL
();
setState
(()
{
if
(
mounted
)
{
_profileImageUrl
=
downloadUrl
;
setState
(()
{
});
_profileImageUrl
=
downloadUrl
;
});
}
print
(
'✅ Profile image uploaded:
$downloadUrl
'
);
print
(
'✅ Profile image uploaded:
$downloadUrl
'
);
}
catch
(
e
)
{
}
catch
(
e
)
{
print
(
'Error uploading profile image:
$e
'
);
print
(
'Error uploading profile image:
$e
'
);
if
(!
mounted
)
return
;
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'Error uploading image:
$e
'
)),
SnackBar
(
content:
Text
(
'Error uploading image:
$e
'
)),
);
);
}
finally
{
}
finally
{
setState
(()
{
if
(
mounted
)
{
_isLoading
=
false
;
setState
(()
{
});
_isLoading
=
false
;
});
}
}
}
}
}
...
@@ -203,7 +217,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -203,7 +217,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
});
});
// Upload profile image if selected
// Upload profile image if selected
if
(
_selectedImage
!=
null
)
{
if
(
_selectedImage
Bytes
!=
null
)
{
await
_uploadProfileImage
();
await
_uploadProfileImage
();
}
}
...
@@ -220,25 +234,30 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -220,25 +234,30 @@ class _ProfileScreenState extends State<ProfileScreen> {
'updatedAt'
:
FieldValue
.
serverTimestamp
(),
'updatedAt'
:
FieldValue
.
serverTimestamp
(),
});
});
setState
(()
{
if
(
mounted
)
{
_isEditing
=
false
;
setState
(()
{
});
_isEditing
=
false
;
});
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
const
SnackBar
(
content:
Text
(
'✅ Profile updated successfully!'
),
content:
Text
(
'✅ Profile updated successfully!'
),
backgroundColor:
Colors
.
green
,
backgroundColor:
Colors
.
green
,
),
),
);
);
}
}
catch
(
e
)
{
}
catch
(
e
)
{
print
(
'Error saving profile:
$e
'
);
print
(
'Error saving profile:
$e
'
);
if
(!
mounted
)
return
;
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'Error saving profile:
$e
'
)),
SnackBar
(
content:
Text
(
'Error saving profile:
$e
'
)),
);
);
}
finally
{
}
finally
{
setState
(()
{
if
(
mounted
)
{
_isLoading
=
false
;
setState
(()
{
});
_isLoading
=
false
;
});
}
}
}
}
}
...
@@ -280,7 +299,6 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -280,7 +299,6 @@ class _ProfileScreenState extends State<ProfileScreen> {
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
if
(
_isLoading
)
{
if
(
_isLoading
)
{
return
Scaffold
(
return
Scaffold
(
appBar:
AppBar
(
appBar:
AppBar
(
...
@@ -320,7 +338,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -320,7 +338,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
setState
(()
{
setState
(()
{
_isEditing
=
!
_isEditing
;
_isEditing
=
!
_isEditing
;
if
(!
_isEditing
)
{
if
(!
_isEditing
)
{
// Reset to original values
_selectedImage
=
null
;
_selectedImageBytes
=
null
;
_loadUserData
();
_loadUserData
();
}
}
});
});
...
@@ -345,12 +364,12 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -345,12 +364,12 @@ class _ProfileScreenState extends State<ProfileScreen> {
children:
[
children:
[
CircleAvatar
(
CircleAvatar
(
radius:
60
,
radius:
60
,
backgroundImage:
_selectedImage
!=
null
backgroundImage:
_selectedImage
Bytes
!=
null
?
FileImage
(
_selectedImage
!)
?
MemoryImage
(
_selectedImageBytes
!)
:
(
_profileImageUrl
!=
null
:
(
_profileImageUrl
!=
null
?
NetworkImage
(
_profileImageUrl
!)
as
ImageProvider
?
NetworkImage
(
_profileImageUrl
!)
as
ImageProvider
:
null
),
:
null
),
child:
_selectedImage
==
null
&&
_profileImageUrl
==
null
child:
_selectedImage
Bytes
==
null
&&
_profileImageUrl
==
null
?
const
Icon
(
Icons
.
person
,
size:
60
)
?
const
Icon
(
Icons
.
person
,
size:
60
)
:
null
,
:
null
,
),
),
...
@@ -375,7 +394,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -375,7 +394,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
),
),
),
const
SizedBox
(
height:
16
),
const
SizedBox
(
height:
16
),
// User Name
// User Name
if
(
_isEditing
)
if
(
_isEditing
)
TextField
(
TextField
(
...
@@ -398,7 +417,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -398,7 +417,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
fontWeight:
FontWeight
.
bold
,
fontWeight:
FontWeight
.
bold
,
),
),
),
),
// User Email
// User Email
Text
(
Text
(
_user
?.
email
??
'No email'
,
_user
?.
email
??
'No email'
,
...
@@ -410,9 +429,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -410,9 +429,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
],
],
),
),
),
),
const
SizedBox
(
height:
24
),
const
SizedBox
(
height:
24
),
// GraphGo Statistics
// GraphGo Statistics
Card
(
Card
(
child:
Padding
(
child:
Padding
(
...
@@ -434,7 +453,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -434,7 +453,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
],
],
),
),
const
SizedBox
(
height:
16
),
const
SizedBox
(
height:
16
),
Row
(
Row
(
children:
[
children:
[
_buildStatCard
(
_buildStatCard
(
...
@@ -467,9 +486,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -467,9 +486,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
),
),
),
),
),
const
SizedBox
(
height:
16
),
const
SizedBox
(
height:
16
),
// Profile Details
// Profile Details
Card
(
Card
(
child:
Padding
(
child:
Padding
(
...
@@ -485,7 +504,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -485,7 +504,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
),
),
),
const
SizedBox
(
height:
16
),
const
SizedBox
(
height:
16
),
// Company
// Company
Row
(
Row
(
children:
[
children:
[
...
@@ -513,9 +532,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -513,9 +532,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
),
],
],
),
),
const
SizedBox
(
height:
16
),
const
SizedBox
(
height:
16
),
// Phone Number
// Phone Number
Row
(
Row
(
children:
[
children:
[
...
@@ -543,9 +562,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -543,9 +562,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
),
],
],
),
),
const
SizedBox
(
height:
16
),
const
SizedBox
(
height:
16
),
// Bio
// Bio
Row
(
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
...
@@ -579,16 +598,15 @@ class _ProfileScreenState extends State<ProfileScreen> {
...
@@ -579,16 +598,15 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
),
),
),
),
),
const
SizedBox
(
height:
24
),
const
SizedBox
(
height:
24
),
// Action Buttons
// Action Buttons
Row
(
Row
(
children:
[
children:
[
Expanded
(
Expanded
(
child:
ElevatedButton
.
icon
(
child:
ElevatedButton
.
icon
(
onPressed:
()
{
onPressed:
()
{
// Navigate to route history
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Route history coming soon!'
)),
const
SnackBar
(
content:
Text
(
'Route history coming soon!'
)),
);
);
...
...
lib/services/firestore_service.dart
View file @
101cfa5c
...
@@ -16,6 +16,16 @@ class FirestoreService {
...
@@ -16,6 +16,16 @@ class FirestoreService {
return
_db
.
collection
(
_collectionPath
).
doc
(
address
.
id
).
set
(
address
.
toJson
());
return
_db
.
collection
(
_collectionPath
).
doc
(
address
.
id
).
set
(
address
.
toJson
());
}
}
// Save a list of addresses from a CSV
Future
<
void
>
saveAddressesFromCsv
(
List
<
DeliveryAddress
>
addresses
)
async
{
final
batch
=
_db
.
batch
();
for
(
final
address
in
addresses
)
{
final
docRef
=
_db
.
collection
(
_collectionPath
).
doc
(
address
.
id
);
batch
.
set
(
docRef
,
address
.
toJson
());
}
await
batch
.
commit
();
}
// Delete an address
// Delete an address
Future
<
void
>
deleteAddress
(
String
addressId
)
{
Future
<
void
>
deleteAddress
(
String
addressId
)
{
return
_db
.
collection
(
_collectionPath
).
doc
(
addressId
).
delete
();
return
_db
.
collection
(
_collectionPath
).
doc
(
addressId
).
delete
();
...
...
pubspec.lock
View file @
101cfa5c
...
@@ -193,6 +193,14 @@ packages:
...
@@ -193,6 +193,14 @@ packages:
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "1.0.2"
version: "1.0.2"
csv:
dependency: "direct main"
description:
name: csv
sha256: c6aa2679b2a18cb57652920f674488d89712efaf4d3fdf2e537215b35fc19d6c
url: "https://pub.dev"
source: hosted
version: "6.0.0"
cupertino_icons:
cupertino_icons:
dependency: "direct main"
dependency: "direct main"
description:
description:
...
@@ -233,6 +241,14 @@ packages:
...
@@ -233,6 +241,14 @@ packages:
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "7.0.1"
version: "7.0.1"
file_picker:
dependency: "direct main"
description:
name: file_picker
sha256: "1bbf65dd997458a08b531042ec3794112a6c39c07c37ff22113d2e7e4f81d4e4"
url: "https://pub.dev"
source: hosted
version: "6.2.1"
file_selector_linux:
file_selector_linux:
dependency: transitive
dependency: transitive
description:
description:
...
@@ -1156,6 +1172,14 @@ packages:
...
@@ -1156,6 +1172,14 @@ packages:
url: "https://pub.dev"
url: "https://pub.dev"
source: hosted
source: hosted
version: "3.1.0"
version: "3.1.0"
win32:
dependency: transitive
description:
name: win32
sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03"
url: "https://pub.dev"
source: hosted
version: "5.14.0"
xdg_directories:
xdg_directories:
dependency: transitive
dependency: transitive
description:
description:
...
...
pubspec.yaml
View file @
101cfa5c
...
@@ -36,6 +36,8 @@ dependencies:
...
@@ -36,6 +36,8 @@ dependencies:
http
:
^1.1.0
http
:
^1.1.0
uuid
:
^4.2.1
uuid
:
^4.2.1
image_picker
:
^1.0.4
image_picker
:
^1.0.4
file_picker
:
^6.2.0
csv
:
^6.0.0
dev_dependencies
:
dev_dependencies
:
flutter_test
:
flutter_test
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment