Skip to content

Commit 196b106

Browse files
committed
Add intl package, update home page navigation, and refactor crop registration image upload
1 parent 51a9191 commit 196b106

16 files changed

+963
-154
lines changed

kisan/devtools_options.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
description: This file stores settings for Dart & Flutter DevTools.
2+
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
3+
extensions:

kisan/lib/main.dart

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class MyApp extends StatelessWidget {
1616
@override
1717
Widget build(BuildContext context) {
1818
return const MaterialApp(
19+
debugShowCheckedModeBanner: false,
1920
title: 'Kisan',
2021
home: AuthPage(), // Start with the AuthPage
2122
);

kisan/lib/models/register_crop.dart

+122-1
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,44 @@
1+
import 'dart:io';
12
import 'package:cloud_firestore/cloud_firestore.dart';
3+
import 'package:firebase_auth/firebase_auth.dart';
4+
import 'package:firebase_storage/firebase_storage.dart';
5+
import 'package:image_picker/image_picker.dart';
6+
import 'package:flutter/material.dart';
27

38
class RegisteredCrop {
9+
String? documentId; // New field to store Firestore document ID
410
String cropName;
511
String minBid;
612
String totalWeight;
713
String state;
814
String phoneNumber;
915
DateTime timestamp;
16+
List<String> imageUrls; // Added to store image URLs
1017

1118
// Constructor
1219
RegisteredCrop({
20+
this.documentId, // Optional since it's not always available during creation
1321
required this.cropName,
1422
required this.minBid,
1523
required this.totalWeight,
1624
required this.state,
1725
required this.phoneNumber,
1826
required this.timestamp,
27+
required this.imageUrls, // Pass image URLs
1928
});
2029

2130
// Factory constructor to create an instance from Firestore Document
22-
factory RegisteredCrop.fromFirestore(Map<String, dynamic> firestoreData) {
31+
factory RegisteredCrop.fromFirestore(DocumentSnapshot doc) {
32+
Map<String, dynamic> firestoreData = doc.data() as Map<String, dynamic>;
2333
return RegisteredCrop(
34+
documentId: doc.id, // Use the Firestore document ID
2435
cropName: firestoreData['cropName'] ?? '',
2536
minBid: firestoreData['minBid'] ?? '',
2637
totalWeight: firestoreData['totalWeight'] ?? '',
2738
state: firestoreData['state'] ?? '',
2839
phoneNumber: firestoreData['phoneNumber'] ?? '',
2940
timestamp: (firestoreData['timestamp'] as Timestamp).toDate(),
41+
imageUrls: List<String>.from(firestoreData['imageUrls'] ?? []), // Fetch image URLs
3042
);
3143
}
3244

@@ -39,6 +51,7 @@ class RegisteredCrop {
3951
'state': state,
4052
'phoneNumber': phoneNumber,
4153
'timestamp': Timestamp.fromDate(timestamp),
54+
'imageUrls': imageUrls, // Save image URLs
4255
};
4356
}
4457

@@ -57,4 +70,112 @@ class RegisteredCrop {
5770
print('Failed to register crop: $e');
5871
}
5972
}
73+
74+
// Method to upload images and return their URLs
75+
static Future<List<String>> _uploadImages(List<XFile>? imageFiles) async {
76+
List<String> imageUrls = [];
77+
try {
78+
User? currentUser = FirebaseAuth.instance.currentUser;
79+
if (currentUser == null) {
80+
print('No authenticated user found');
81+
return imageUrls;
82+
}
83+
84+
// Ensure there are files to upload
85+
if (imageFiles != null && imageFiles.isNotEmpty) {
86+
for (var file in imageFiles) {
87+
File imageFile = File(file.path);
88+
89+
// Check if the file exists
90+
if (!await imageFile.exists()) {
91+
print('File does not exist: ${file.path}');
92+
continue; // Skip this file and move to the next
93+
}
94+
95+
// Generate a unique file name for Firebase Storage
96+
String fileName = 'crop_images/${currentUser.uid}/${DateTime.now().millisecondsSinceEpoch}.jpg';
97+
98+
try {
99+
// Firebase Storage reference to upload the image
100+
Reference storageReference = FirebaseStorage.instance.ref().child(fileName);
101+
102+
// Upload task
103+
UploadTask uploadTask = storageReference.putFile(
104+
imageFile,
105+
SettableMetadata(contentType: 'image/jpeg'),
106+
);
107+
108+
// Wait for the upload task to complete
109+
TaskSnapshot snapshot = await uploadTask;
110+
111+
// Retrieve the download URL after upload
112+
String downloadUrl = await snapshot.ref.getDownloadURL();
113+
114+
// Add the image URL to the list
115+
imageUrls.add(downloadUrl);
116+
print('Successfully uploaded: $downloadUrl');
117+
} on FirebaseException catch (e) {
118+
// Handle Firebase errors
119+
print('Firebase Storage Error: ${e.code} - ${e.message}');
120+
}
121+
}
122+
} else {
123+
print('No images selected for upload');
124+
}
125+
} catch (e) {
126+
// Handle unexpected errors
127+
print('Unexpected error in image upload: $e');
128+
}
129+
130+
return imageUrls;
131+
}
132+
}
133+
134+
// Function to handle crop registration
135+
void _registerCrop(BuildContext context, List<XFile>? _imageFiles, TextEditingController _minBidController, TextEditingController _totalWeightController, TextEditingController _phoneNumberController, String? _selectedCrop, String? _selectedState) async {
136+
String cropName = _selectedCrop ?? 'Not Selected';
137+
String minBid = _minBidController.text;
138+
String totalWeight = _totalWeightController.text;
139+
String address = _selectedState ?? 'Not Selected';
140+
String phoneNumber = _phoneNumberController.text;
141+
142+
// Get the current user ID from FirebaseAuth
143+
String userId = FirebaseAuth.instance.currentUser?.uid ?? '';
144+
145+
print('Crop Name: $cropName');
146+
print('Min Bid: $minBid');
147+
print('Total Weight (Kg): $totalWeight');
148+
print('Address (State): $address');
149+
print('Phone Number: $phoneNumber');
150+
print('User ID: $userId'); // Print the user ID
151+
print('Image Files: $_imageFiles');
152+
153+
// Upload images and get their URLs
154+
List<String> imageUrls = await RegisteredCrop._uploadImages(_imageFiles);
155+
156+
try {
157+
// Create RegisteredCrop instance with the image URLs
158+
RegisteredCrop newCrop = RegisteredCrop(
159+
cropName: cropName,
160+
minBid: minBid,
161+
totalWeight: totalWeight,
162+
state: address,
163+
phoneNumber: phoneNumber,
164+
timestamp: DateTime.now(),
165+
imageUrls: imageUrls, // Pass image URLs to RegisteredCrop
166+
);
167+
168+
// Save data to Firestore
169+
await newCrop.saveToFirestore();
170+
171+
print('Crop registration successful!');
172+
ScaffoldMessenger.of(context).showSnackBar(
173+
const SnackBar(content: Text('Crop registration successful!')),
174+
);
175+
} catch (e) {
176+
print('Failed to register crop: $e');
177+
ScaffoldMessenger.of(context).showSnackBar(
178+
const SnackBar(content: Text('Failed to register crop.')),
179+
);
180+
}
60181
}

kisan/lib/pages/CropTypesPage.dart

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import 'package:flutter/material.dart';
2+
import 'crop_farmers_page.dart';
3+
4+
class CropTypesPage extends StatefulWidget {
5+
const CropTypesPage({Key? key}) : super(key: key);
6+
7+
@override
8+
_CropTypesPageState createState() => _CropTypesPageState();
9+
}
10+
11+
class _CropTypesPageState extends State<CropTypesPage> {
12+
// Predefined list of crops
13+
final List<Map<String, String>> cropTypes = [
14+
{'name': 'Wheat', 'image': 'assets/images/wheat.jpg', 'description': 'Staple food grain.'},
15+
{'name': 'Rice', 'image': 'assets/images/rice.jpg', 'description': 'Grown in paddy fields.'},
16+
{'name': 'Jawar', 'image': 'assets/images/jawar.jpg', 'description': 'Rich in dietary fiber.'},
17+
{'name': 'Bajra', 'image': 'assets/images/bajra.jpg', 'description': 'Nutritious millet crop.'},
18+
{'name': 'Maize', 'image': 'assets/images/maize.jpg', 'description': 'Used for food and fodder.'},
19+
{'name': 'Cotton', 'image': 'assets/images/cotton.jpg', 'description': 'Essential for textiles.'},
20+
];
21+
22+
@override
23+
Widget build(BuildContext context) {
24+
return Scaffold(
25+
backgroundColor: const Color(0xFFFEFAE0),
26+
appBar: AppBar(
27+
centerTitle: true,
28+
title: const Text(
29+
'Bidding Space',
30+
style: TextStyle(fontWeight: FontWeight.bold),
31+
),
32+
backgroundColor: const Color(0xFF798645),
33+
),
34+
body: ListView.builder(
35+
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 15),
36+
itemCount: cropTypes.length,
37+
itemBuilder: (context, index) {
38+
final crop = cropTypes[index];
39+
return Padding(
40+
padding: const EdgeInsets.symmetric(vertical: 8.0),
41+
child: Card(
42+
elevation: 4,
43+
shape: RoundedRectangleBorder(
44+
borderRadius: BorderRadius.circular(15),
45+
),
46+
child: InkWell(
47+
borderRadius: BorderRadius.circular(15),
48+
onTap: () {
49+
Navigator.push(
50+
context,
51+
MaterialPageRoute(
52+
builder: (context) => CropFarmersPage(cropType: crop['name']!),
53+
),
54+
);
55+
},
56+
child: Row(
57+
children: [
58+
// Crop Image
59+
Container(
60+
height: 100,
61+
width: 100,
62+
decoration: BoxDecoration(
63+
borderRadius: const BorderRadius.only(
64+
topLeft: Radius.circular(15),
65+
bottomLeft: Radius.circular(15),
66+
),
67+
image: DecorationImage(
68+
image: AssetImage(crop['image']!),
69+
fit: BoxFit.cover,
70+
),
71+
),
72+
),
73+
// Crop Details
74+
Expanded(
75+
child: Padding(
76+
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10),
77+
child: Column(
78+
crossAxisAlignment: CrossAxisAlignment.start,
79+
children: [
80+
Text(
81+
crop['name']!,
82+
style: const TextStyle(
83+
fontSize: 20,
84+
fontWeight: FontWeight.bold,
85+
color: Color(0xFF4A4A4A),
86+
),
87+
),
88+
const SizedBox(height: 6),
89+
Text(
90+
crop['description']!,
91+
style: const TextStyle(
92+
fontSize: 14,
93+
color: Colors.black54,
94+
),
95+
),
96+
],
97+
),
98+
),
99+
),
100+
// Navigate Icon
101+
const Padding(
102+
padding: EdgeInsets.only(right: 16.0),
103+
child: Icon(Icons.arrow_forward_ios, color: Colors.black45),
104+
),
105+
],
106+
),
107+
),
108+
),
109+
);
110+
},
111+
),
112+
);
113+
}
114+
}

kisan/lib/pages/bidding_space_page.dart

-62
This file was deleted.

0 commit comments

Comments
 (0)