Commit 9b79f5c0 authored by aleenaasghar's avatar aleenaasghar

Web Page for Admin Users

parent 23d89820
......@@ -79,7 +79,6 @@ app.*.map.json
coverage/
# Web related
lib/generated_plugin_registrant.dart
# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
\ No newline at end of file
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
......@@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.
version:
revision: "20f82749394e68bcfbbeee96bad384abaae09c13"
revision: "ac4e799d237041cf905519190471f657b657155a"
channel: "stable"
project_type: app
......@@ -13,26 +13,26 @@ project_type: app
migration:
platforms:
- platform: root
create_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
base_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
create_revision: ac4e799d237041cf905519190471f657b657155a
base_revision: ac4e799d237041cf905519190471f657b657155a
- platform: android
create_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
base_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
create_revision: ac4e799d237041cf905519190471f657b657155a
base_revision: ac4e799d237041cf905519190471f657b657155a
- platform: ios
create_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
base_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
create_revision: ac4e799d237041cf905519190471f657b657155a
base_revision: ac4e799d237041cf905519190471f657b657155a
- platform: linux
create_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
base_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
create_revision: ac4e799d237041cf905519190471f657b657155a
base_revision: ac4e799d237041cf905519190471f657b657155a
- platform: macos
create_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
base_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
create_revision: ac4e799d237041cf905519190471f657b657155a
base_revision: ac4e799d237041cf905519190471f657b657155a
- platform: web
create_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
base_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
create_revision: ac4e799d237041cf905519190471f657b657155a
base_revision: ac4e799d237041cf905519190471f657b657155a
- platform: windows
create_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
base_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
create_revision: ac4e799d237041cf905519190471f657b657155a
base_revision: ac4e799d237041cf905519190471f657b657155a
# User provided section
......
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'firebase_options.dart';
......@@ -8,15 +9,17 @@ import 'firebase_options.dart';
import 'providers/graph_provider.dart';
import 'providers/settings_provider.dart';
import 'providers/delivery_provider.dart';
import 'providers/auth_provider.dart';
// Screens
import 'screens/home_screen.dart';
import 'screens/map_screen.dart';
import 'screens/map_screen.dart';
import 'screens/settings_screen.dart';
import 'screens/profile_screen.dart';
import 'screens/login.dart';
import 'screens/signup.dart';
import 'screens/forgot_password.dart';
import 'screens/admin_dashboard_screen.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
......@@ -40,6 +43,7 @@ class MyApp extends StatelessWidget {
providers: [
ChangeNotifierProvider(create: (_) => GraphProvider()),
ChangeNotifierProvider(create: (_) => DeliveryProvider()),
ChangeNotifierProvider(create: (_) => AuthProvider()),
ChangeNotifierProvider.value(value: settingsProvider),
],
child: Consumer<SettingsProvider>(
......@@ -62,7 +66,7 @@ class MyApp extends StatelessWidget {
colorScheme: ColorScheme.dark(
primary: Colors.deepPurple.shade300,
surface: Colors.grey.shade800,
background: Colors.black,
background: Colors.black,
),
scaffoldBackgroundColor: Colors.black,
appBarTheme: const AppBarTheme(
......@@ -75,13 +79,12 @@ class MyApp extends StatelessWidget {
),
useMaterial3: true,
),
initialRoute: "/",
home: kIsWeb ? const AdminDashboardScreen() : const HomeScreen(),
routes: {
"/": (context) => const HomeScreen(),
"/login": (context) => const LoginPage(),
"/signup": (context) => const SignupPage(),
"/forgot": (context) => const ForgotPasswordPage(),
"/map": (context) => const MapScreen(),
"/map": (context) => const MapScreen(),
"/settings": (context) => const SettingsScreen(),
"/profile": (context) => const ProfileScreen(),
},
......
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
class AuthProvider with ChangeNotifier {
final FirebaseAuth _auth = FirebaseAuth.instance;
User? _user;
User? get user => _user;
AuthProvider() {
_auth.authStateChanges().listen((User? user) {
_user = user;
notifyListeners();
});
}
Future<void> signOut() async {
await _auth.signOut();
}
}
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import '../models/delivery_address.dart';
import '../services/google_auth_service.dart';
import '../services/firestore_service.dart';
import '../widgets/address_list.dart';
import '../widgets/add_edit_address_dialog.dart';
class AdminDashboardScreen extends StatefulWidget {
const AdminDashboardScreen({super.key});
@override
State<AdminDashboardScreen> createState() => _AdminDashboardScreenState();
}
class _AdminDashboardScreenState extends State<AdminDashboardScreen> {
final FirestoreService _firestoreService = FirestoreService();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final _formKey = GlobalKey<FormState>();
bool _isLoading = false;
User? _user;
@override
void initState() {
super.initState();
_user = FirebaseAuth.instance.currentUser;
FirebaseAuth.instance.authStateChanges().listen((user) {
if (mounted) {
setState(() {
_user = user;
});
}
});
}
void _showAddEditAddressDialog({DeliveryAddress? address}) {
showDialog(
context: context,
builder: (context) => AddEditAddressDialog(
address: address,
onSave: (address) => _firestoreService.saveAddress(address),
),
);
}
void _deleteAddress(String addressId) {
_firestoreService.deleteAddress(addressId);
}
Future<void> _loginWithEmail() async {
if (!_formKey.currentState!.validate()) return;
setState(() => _isLoading = true);
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
} on FirebaseAuthException catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Login Failed: ${e.message}")),
);
} finally {
if (mounted) {
setState(() => _isLoading = false);
}
}
}
Future<void> _loginWithGoogle() async {
setState(() => _isLoading = true);
try {
await GoogleAuthService.signInWithGoogle();
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Google Login Failed: ${e.toString()}")),
);
}
} finally {
if (mounted) {
setState(() => _isLoading = false);
}
}
}
void _logout() async {
await FirebaseAuth.instance.signOut();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.settings, color: Colors.white),
onPressed: () => Navigator.of(context).pushNamed('/settings'),
),
title: const Text('GraphGo Admin', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white)),
centerTitle: true,
actions: [
if (_user != null)
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Center(child: Text(_user!.email ?? '', style: const TextStyle(color: Colors.white))),
),
if (_user != null)
TextButton.icon(
onPressed: _logout,
icon: const Icon(Icons.logout, color: Colors.white, size: 18),
label: const Text('Logout', style: TextStyle(color: Colors.white)),
style: TextButton.styleFrom(foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 16.0)),
),
],
),
body: _user == null ? _buildLoginForm(context) : _buildLoggedInView(context),
);
}
Widget _buildLoggedInView(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
ElevatedButton.icon(
onPressed: () => _showAddEditAddressDialog(),
icon: const Icon(Icons.add),
label: const Text('Add Address'),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16)
),
),
const SizedBox(width: 16),
OutlinedButton.icon(
onPressed: null, // Disabled for now
icon: const Icon(Icons.upload_file),
label: const Text('Upload CSV'),
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16)
),
),
],
),
const SizedBox(height: 24),
Text(
'List of Addresses',
style: Theme.of(context).textTheme.headlineSmall,
),
Expanded(
child: AddressList(
onEdit: (address) => _showAddEditAddressDialog(address: address),
onDelete: _deleteAddress,
addressesStream: _firestoreService.getAddresses(),
),
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 20),
backgroundColor: Colors.green,
foregroundColor: Colors.white
),
child: const Text('Release to Drivers'),
),
),
],
),
);
}
Widget _buildLoginForm(BuildContext context) {
final ThemeData currentTheme = Theme.of(context);
final bool darkMode = currentTheme.brightness == Brightness.dark;
final Color welcomeTextColor = darkMode ? Colors.white : Colors.black87;
final Color sloganTextColor = darkMode ? Colors.grey[300]! : Colors.black54;
final Color iconColor = darkMode ? Colors.white : const Color(0xFF0D2B0D);
return Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(32.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.account_tree,
size: 100,
color: iconColor,
),
const SizedBox(height: 20),
Text(
'Welcome to GraphGo',
style: currentTheme.textTheme.headlineMedium?.copyWith(
fontSize: (currentTheme.textTheme.headlineMedium?.fontSize ?? 28) * 1.15,
fontWeight: FontWeight.bold,
color: welcomeTextColor,
),
),
const SizedBox(height: 10),
Text(
'Admin Panel Access',
style: currentTheme.textTheme.bodyLarge?.copyWith(
fontSize: (currentTheme.textTheme.bodyLarge?.fontSize ?? 16) * 1.1,
color: sloganTextColor,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 50),
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Column(
children: [
SizedBox(
width: double.infinity,
child: OutlinedButton.icon(
onPressed: _isLoading ? null : _loginWithGoogle,
icon: SvgPicture.asset('assets/icons/google_icon.svg', width: 20, height: 20),
label: const Text('Sign in with Google'),
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
),
),
),
const SizedBox(height: 20),
const Row(
children: [
Expanded(child: Divider()),
Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Text('OR'),
),
Expanded(child: Divider()),
],
),
const SizedBox(height: 20),
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: _emailController,
decoration: const InputDecoration(labelText: 'Email', border: OutlineInputBorder()),
keyboardType: TextInputType.emailAddress,
validator: (value) => value!.isEmpty ? "Enter your email" : null,
),
const SizedBox(height: 16),
TextFormField(
controller: _passwordController,
decoration: const InputDecoration(labelText: 'Password', border: OutlineInputBorder()),
obscureText: true,
validator: (value) => value!.isEmpty ? "Enter your password" : null,
),
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () {
Navigator.of(context).pushNamed('/forgot');
},
child: const Text('Forgot Password?'),
),
),
const SizedBox(height: 10),
_isLoading
? const CircularProgressIndicator()
: SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _loginWithEmail,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 20),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
child: const Text('Login with Email'),
),
),
],
),
),
const SizedBox(height: 20),
TextButton(
onPressed: () {
Navigator.of(context).pushNamed('/signup');
},
child: const Text("Don't have an account? Sign Up"),
),
],
),
),
],
),
),
);
}
}
import 'package:cloud_firestore/cloud_firestore.dart';
import '../models/delivery_address.dart';
class FirestoreService {
final FirebaseFirestore _db = FirebaseFirestore.instance;
final String _collectionPath = 'addresses';
// Get a stream of all addresses
Stream<List<DeliveryAddress>> getAddresses() {
return _db.collection(_collectionPath).snapshots().map((snapshot) =>
snapshot.docs.map((doc) => DeliveryAddress.fromJson(doc.data())).toList());
}
// Add or update an address
Future<void> saveAddress(DeliveryAddress address) {
return _db.collection(_collectionPath).doc(address.id).set(address.toJson());
}
// Delete an address
Future<void> deleteAddress(String addressId) {
return _db.collection(_collectionPath).doc(addressId).delete();
}
}
......@@ -17,7 +17,7 @@ class GoogleAuthService {
static Future<UserCredential?> signInWithGoogle() async {
try {
print('Starting Google Sign-In...');
// Trigger the authentication flow
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
......@@ -32,8 +32,6 @@ class GoogleAuthService {
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
print('Google auth tokens obtained');
print('Access token: ${googleAuth.accessToken?.substring(0, 20)}...');
print('ID token: ${googleAuth.idToken?.substring(0, 20)}...');
// Create a new credential
final credential = GoogleAuthProvider.credential(
......@@ -62,19 +60,6 @@ class GoogleAuthService {
} catch (e) {
print('Google Sign-In Error Details: $e');
print('Error type: ${e.runtimeType}');
// Handle specific type casting errors
if (e.toString().contains('PigeonUserDetails')) {
print('Type casting error detected - this is a known issue with google_sign_in package');
// Check if user is actually signed in despite the error
final user = _auth.currentUser;
if (user != null) {
print('User is already signed in: ${user.email}');
// Return null to indicate success but let the app handle the state
return null;
}
}
rethrow;
}
}
......
import 'package:flutter/material.dart';
import '../models/delivery_address.dart';
class AddEditAddressDialog extends StatefulWidget {
final DeliveryAddress? address;
final Function(DeliveryAddress) onSave;
const AddEditAddressDialog({super.key, this.address, required this.onSave});
@override
State<AddEditAddressDialog> createState() => _AddEditAddressDialogState();
}
class _AddEditAddressDialogState extends State<AddEditAddressDialog> {
final _formKey = GlobalKey<FormState>();
late TextEditingController _streetController;
late TextEditingController _cityController;
late TextEditingController _stateController;
late TextEditingController _zipController;
late TextEditingController _notesController;
@override
void initState() {
super.initState();
_streetController = TextEditingController(text: widget.address?.streetAddress ?? '');
_cityController = TextEditingController(text: widget.address?.city ?? '');
_stateController = TextEditingController(text: widget.address?.state ?? '');
_zipController = TextEditingController(text: widget.address?.zipCode ?? '');
_notesController = TextEditingController(text: widget.address?.notes ?? '');
}
@override
Widget build(BuildContext context) {
final isEditing = widget.address != null;
return AlertDialog(
title: Text(isEditing ? 'Edit Address' : 'Add Address'),
content: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
controller: _streetController,
decoration: const InputDecoration(labelText: 'Street Address'),
validator: (value) => value!.isEmpty ? 'Please enter a street address' : null,
),
const SizedBox(height: 16),
TextFormField(
controller: _cityController,
decoration: const InputDecoration(labelText: 'City'),
validator: (value) => value!.isEmpty ? 'Please enter a city' : null,
),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: TextFormField(
controller: _stateController,
decoration: const InputDecoration(labelText: 'State'),
validator: (value) => value!.isEmpty ? 'Please enter a state' : null,
),
),
const SizedBox(width: 16),
Expanded(
child: TextFormField(
controller: _zipController,
decoration: const InputDecoration(labelText: 'ZIP Code'),
validator: (value) => value!.isEmpty ? 'Please enter a ZIP code' : null,
),
),
],
),
const SizedBox(height: 16),
TextFormField(
controller: _notesController,
decoration: const InputDecoration(labelText: 'Notes (Optional)'),
),
],
),
),
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: _submit,
child: const Text('Save'),
),
],
);
}
void _submit() {
if (_formKey.currentState!.validate()) {
final address = DeliveryAddress(
id: widget.address?.id, // Keep original ID if editing
streetAddress: _streetController.text,
city: _cityController.text,
state: _stateController.text,
zipCode: _zipController.text,
notes: _notesController.text,
);
widget.onSave(address);
Navigator.of(context).pop();
}
}
}
import 'package:flutter/material.dart';
import '../models/delivery_address.dart';
class AddressList extends StatelessWidget {
final Stream<List<DeliveryAddress>> addressesStream;
final Function(DeliveryAddress) onEdit;
final Function(String) onDelete;
const AddressList({
super.key,
required this.addressesStream,
required this.onEdit,
required this.onDelete,
});
@override
Widget build(BuildContext context) {
return StreamBuilder<List<DeliveryAddress>>(
stream: addressesStream,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
if (!snapshot.hasData || snapshot.data!.isEmpty) {
return const Center(child: Text('No addresses found.'));
}
final addresses = snapshot.data!;
return ListView.builder(
itemCount: addresses.length,
itemBuilder: (context, index) {
final address = addresses[index];
return Card(
margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 4.0),
child: ListTile(
leading: CircleAvatar(child: Text('${index + 1}')),
title: Text(address.fullAddress),
subtitle: const Text('Status: Pending'),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: const Icon(Icons.edit, color: Colors.blue),
onPressed: () => onEdit(address),
),
IconButton(
icon: const Icon(Icons.delete, color: Colors.red),
onPressed: () => onDelete(address.id),
),
],
),
),
);
},
);
},
);
}
}
......@@ -13,10 +13,10 @@ packages:
dependency: transitive
description:
name: _flutterfire_internals
sha256: "37a42d06068e2fe3deddb2da079a8c4d105f241225ba27b7122b37e9865fd8f7"
sha256: "23d16f00a2da8ffa997c782453c73867b0609bd90435195671a54de38a3566df"
url: "https://pub.dev"
source: hosted
version: "1.3.35"
version: "1.3.62"
analyzer:
dependency: transitive
description:
......@@ -53,10 +53,10 @@ packages:
dependency: transitive
description:
name: build
sha256: "5b887c55a0f734b433b3b2d89f9cd1f99eb636b17e268a5b4259258bc916504b"
sha256: "825fed4d63050252a0b6e74f2d75844c4a85b664814be6993bd3493fb5239779"
url: "https://pub.dev"
source: hosted
version: "4.0.0"
version: "4.0.1"
build_config:
dependency: transitive
description:
......@@ -77,10 +77,10 @@ packages:
dependency: "direct dev"
description:
name: build_runner
sha256: "804c47c936df75e1911c19a4fb8c46fa8ff2b3099b9f2b2aa4726af3774f734b"
sha256: "4e54dbeefdc70691ba80b3bce3976af63b5425c8c07dface348dfee664a0edc1"
url: "https://pub.dev"
source: hosted
version: "2.8.0"
version: "2.9.0"
built_collection:
dependency: transitive
description:
......@@ -125,26 +125,26 @@ packages:
dependency: "direct main"
description:
name: cloud_firestore
sha256: a0f161b92610e078b4962d7e6ebeb66dc9cce0ada3514aeee442f68165d78185
sha256: af66aeffe5943d582c0f655ec860433dbd773ac4a4ffc62c11960b52a18833fe
url: "https://pub.dev"
source: hosted
version: "4.17.5"
version: "6.0.2"
cloud_firestore_platform_interface:
dependency: transitive
description:
name: cloud_firestore_platform_interface
sha256: "6a55b319f8d33c307396b9104512e8130a61904528ab7bd8b5402678fca54b81"
sha256: "494dd3d275a0259e3ba08b442b54e64839b0cf58352a50fe97eb67cacf3bad28"
url: "https://pub.dev"
source: hosted
version: "6.2.5"
version: "7.0.2"
cloud_firestore_web:
dependency: transitive
description:
name: cloud_firestore_web
sha256: "89dfa1304d3da48b3039abbb2865e3d30896ef858e569a16804a99f4362283a9"
sha256: "85b7b071c23eecbbbb47a9fbd2cfdb1b6af20f2323663fd90234d91a064f0584"
url: "https://pub.dev"
source: hosted
version: "3.12.5"
version: "5.0.2"
code_builder:
dependency: transitive
description:
......@@ -269,74 +269,74 @@ packages:
dependency: "direct main"
description:
name: firebase_auth
sha256: "279b2773ff61afd9763202cb5582e2b995ee57419d826b9af6517302a59b672f"
sha256: "735f857c9363376eeb585e7ba57e67e5f495202cd3f609902b8769795fd823bc"
url: "https://pub.dev"
source: hosted
version: "4.16.0"
version: "6.1.0"
firebase_auth_platform_interface:
dependency: transitive
description:
name: firebase_auth_platform_interface
sha256: a0270e1db3b2098a14cb2a2342b3cd2e7e458e0c391b1f64f6f78b14296ec093
sha256: "5badda0ea5048ffbb1726169cf5530539490de8055c3bd43f4f9cd5fcef8e556"
url: "https://pub.dev"
source: hosted
version: "7.3.0"
version: "8.1.2"
firebase_auth_web:
dependency: transitive
description:
name: firebase_auth_web
sha256: c7b1379ccef7abf4b6816eede67a868c44142198e42350f51c01d8fc03f95a7d
sha256: "07c889d2c56e648ed30225e819801d7e45542747a658d9c385520de35d312dec"
url: "https://pub.dev"
source: hosted
version: "5.8.13"
version: "6.0.3"
firebase_core:
dependency: "direct main"
description:
name: firebase_core
sha256: "26de145bb9688a90962faec6f838247377b0b0d32cc0abecd9a4e43525fc856c"
sha256: "4dd96f05015c0dcceaa47711394c32971aee70169625d5e2477e7676c01ce0ee"
url: "https://pub.dev"
source: hosted
version: "2.32.0"
version: "4.1.1"
firebase_core_platform_interface:
dependency: transitive
description:
name: firebase_core_platform_interface
sha256: "8bcfad6d7033f5ea951d15b867622a824b13812178bfec0c779b9d81de011bbb"
sha256: "5873a370f0d232918e23a5a6137dbe4c2c47cf017301f4ea02d9d636e52f60f0"
url: "https://pub.dev"
source: hosted
version: "5.4.2"
version: "6.0.1"
firebase_core_web:
dependency: transitive
description:
name: firebase_core_web
sha256: eb3afccfc452b2b2075acbe0c4b27de62dd596802b4e5e19869c1e926cbb20b3
sha256: "61a51037312dac781f713308903bb7a1762a7f92f7bc286a3a0947fb2a713b82"
url: "https://pub.dev"
source: hosted
version: "2.24.0"
version: "3.1.1"
firebase_storage:
dependency: "direct main"
description:
name: firebase_storage
sha256: b87029b506972987a827feaf296c21cd0fe1bb69c2595be1672253ba5205573e
sha256: "969e22fe91a2f846755869f82f5cb6872ce06568890059ffba2d5e5373a20077"
url: "https://pub.dev"
source: hosted
version: "11.6.5"
version: "13.0.2"
firebase_storage_platform_interface:
dependency: transitive
description:
name: firebase_storage_platform_interface
sha256: "4e18662e6a66e2e0e181c06f94707de06d5097d70cfe2b5141bf64660c5b5da9"
sha256: "6d1cf75721f614eb0ef44263de83215b9e898bd3c60b5b06e751fefe6c502274"
url: "https://pub.dev"
source: hosted
version: "5.1.22"
version: "5.2.13"
firebase_storage_web:
dependency: transitive
description:
name: firebase_storage_web
sha256: "9523c455521b0497ee436be8614aab52f719309d16147a5b11091e44e4c5aa0a"
sha256: "9fa0ed2ec6a973c99dd9e0a57704f12f68e5fc924f9c50f72b793540f19d32ea"
url: "https://pub.dev"
source: hosted
version: "3.6.22"
version: "3.10.20"
fixnum:
dependency: transitive
description:
......@@ -389,14 +389,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
url: "https://pub.dev"
source: hosted
version: "4.0.0"
fuchsia_remote_debug_protocol:
dependency: transitive
description: flutter
......@@ -462,10 +454,10 @@ packages:
dependency: transitive
description:
name: google_maps
sha256: "4d6e199c561ca06792c964fa24b2bac7197bf4b401c2e1d23e345e5f9939f531"
sha256: "5d410c32112d7c6eb7858d359275b2aa04778eed3e36c745aeae905fb2fa6468"
url: "https://pub.dev"
source: hosted
version: "8.1.1"
version: "8.2.0"
google_maps_flutter:
dependency: "direct main"
description:
......@@ -923,10 +915,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_android
sha256: bd14436108211b0d4ee5038689a56d4ae3620fd72fd6036e113bf1345bc74d9e
sha256: "0b0f98d535319cb5cdd4f65783c2a54ee6d417a2f093dbb18be3e36e4c3d181f"
url: "https://pub.dev"
source: hosted
version: "2.4.13"
version: "2.4.14"
shared_preferences_foundation:
dependency: transitive
description:
......@@ -1128,10 +1120,10 @@ packages:
dependency: transitive
description:
name: watcher
sha256: "5bf046f41320ac97a469d506261797f35254fa61c641741ef32dacda98b7d39c"
sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a"
url: "https://pub.dev"
source: hosted
version: "1.1.3"
version: "1.1.4"
web:
dependency: transitive
description:
......
......@@ -19,10 +19,10 @@ dependencies:
shared_preferences: ^2.2.3
# ✅ Firebase + Auth + Firestore + Storage
firebase_core: ^2.24.2
firebase_auth: ^4.15.3
cloud_firestore: ^4.13.6
firebase_storage: ^11.5.6
firebase_core:
firebase_auth:
cloud_firestore:
firebase_storage:
# ✅ Maps + Location
google_maps_flutter: ^2.5.0
......
......@@ -29,6 +29,8 @@
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
<meta name="google-signin-client_id" content="587913414359-2uk1aipv1vp60injam1i5i6rm3s9e7pi.apps.googleusercontent.com">
<title>graph_go</title>
<link rel="manifest" href="manifest.json">
</head>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment