Commit e953b7df authored by Adam Bruck's avatar Adam Bruck

Updated Post

parent c08d00b7
This diff is collapsed.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class BookDetailsPage extends StatelessWidget {
final QueryDocumentSnapshot book;
BookDetailsPage({required this.book});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(book['title'])),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: book['imageUrl'] != null
? Image.network(book['imageUrl'], height: 200, fit: BoxFit.cover)
: Icon(Icons.book, size: 100),
),
SizedBox(height: 20),
Text("Title: ${book['title']}", style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
Text("Author: ${book['author']}", style: TextStyle(fontSize: 18)),
Text("ISBN: ${book['isbn']}", style: TextStyle(fontSize: 16)),
Text("Price: \$${book['price']}", style: TextStyle(fontSize: 16, color: Colors.green)),
SizedBox(height: 10),
Text("Description:", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
Text(book['description'] ?? 'No description available', style: TextStyle(fontSize: 16)),
],
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'book_detail_page.dart';
class MyBooksPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Get current user ID
String userId = FirebaseAuth.instance.currentUser?.uid ?? "";
return Scaffold(
appBar: AppBar(title: Text('My Books')),
appBar: AppBar(title: Text("My Books")),
body: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('books').snapshots(),
stream: FirebaseFirestore.instance
.collection('books')
.where('userId', isEqualTo: userId) // 🔹 Filter by logged-in user ID
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (!snapshot.hasData || snapshot.data!.docs.isEmpty) {
return Center(child: Text('No books found.'));
}
if (!snapshot.hasData) return Center(child: CircularProgressIndicator());
var books = snapshot.data!.docs;
if (books.isEmpty) {
return Center(child: Text("No books posted yet."));
}
return ListView.builder(
itemCount: books.length,
itemBuilder: (context, index) {
var book = books[index].data() as Map<String, dynamic>;
var book = books[index];
return ListTile(
title: Text(book['title'] ?? 'No Title'),
subtitle: Text(book['author'] ?? 'Unknown Author'),
trailing: Text("\$${book['price']}"),
leading: book['imageUrl'] != null
? Image.network(book['imageUrl'], width: 50, height: 50, fit: BoxFit.cover)
: Icon(Icons.book),
title: Text(book['title']),
subtitle: Text(book['author']),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BookDetailsPage(book: book),
),
);
},
);
},
);
......
import 'dart:convert';
import 'dart:io';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
......@@ -11,10 +14,10 @@ class PostBookPage extends StatefulWidget {
class _PostBookPageState extends State<PostBookPage> {
final TextEditingController titleController = TextEditingController();
final TextEditingController descriptionController = TextEditingController();
final TextEditingController priceController = TextEditingController();
final TextEditingController isbnController = TextEditingController();
final TextEditingController authorController = TextEditingController();
final TextEditingController descriptionController = TextEditingController();
File? _imageFile;
// Function to pick an image from camera or gallery
......@@ -30,32 +33,77 @@ class _PostBookPageState extends State<PostBookPage> {
}
}
Future<String?> fetchBookDescription(String isbn) async {
final String url = "https://www.googleapis.com/books/v1/volumes?q=isbn:$isbn";
// Function to upload book data to Firebase
Future<bool> uploadBook() async {
try {
// Store book details in Firestore
await FirebaseFirestore.instance.collection('books').add({
'title': titleController.text,
'description': descriptionController.text,
'price': priceController.text,
'isbn': isbnController.text,
'author': authorController.text,
'imageUrl': '', // Remove Firebase Storage dependency
'createdAt': Timestamp.now(),
});
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
if (data['totalItems'] > 0) {
return data['items'][0]['volumeInfo']['description'] ?? 'No description available';
}
}
} catch (e) {
print("Error fetching book details: $e");
}
return null; // Return null if no description is found
}
return true;
Future<String?> uploadImageToImgur(File imageFile) async {
try {
final uri = Uri.parse('https://api.imgur.com/3/upload');
final request = http.MultipartRequest('POST', uri)
..headers['Authorization'] = '00caf989adf38fa'
..files.add(await http.MultipartFile.fromPath('image', imageFile.path));
final response = await request.send();
if (response.statusCode == 200) {
final responseData = await response.stream.bytesToString();
final jsonData = json.decode(responseData);
return jsonData['data']['link']; // The image URL from Imgur
} else {
print('Failed to upload image to Imgur');
return null;
}
} catch (e) {
print('Error uploading book: $e');
return false;
print('Error uploading image: $e');
return null;
}
}
// Function to upload book data to Firebase
Future<bool> uploadBook() async {
try {
User? user = FirebaseAuth.instance.currentUser;
if (user == null) return false; // Ensure user is logged in
String? imageUrl;
if (_imageFile != null) {
imageUrl = await uploadImageToImgur(_imageFile!);
if (imageUrl == null) return false; // Upload and get URL
}
await FirebaseFirestore.instance.collection('books').add({
'title': titleController.text,
'author': authorController.text,
'isbn': isbnController.text,
'price': priceController.text,
'description': descriptionController.text,
'userId': user.uid, // 🔹 Save logged-in user's ID
'imageUrl': imageUrl ?? "", // Optional image
});
return true;
} catch(e) {
print("Error uploading book: $e");
return false;
}
}
// Function to handle book posting
Future<void> _postBook() async {
if (titleController.text.isEmpty || descriptionController.text.isEmpty ||
if (titleController.text.isEmpty ||
priceController.text.isEmpty || isbnController.text.isEmpty ||
authorController.text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
......@@ -63,6 +111,10 @@ class _PostBookPageState extends State<PostBookPage> {
);
return;
}
String? description = await fetchBookDescription(isbnController.text);
descriptionController.text = description ?? 'No description available';
bool success = await uploadBook();
if (success) {
Navigator.pushReplacementNamed(context, '/mybooks');
......@@ -91,13 +143,7 @@ class _PostBookPageState extends State<PostBookPage> {
),
SizedBox(height: 10),
// Description Input
TextField(
controller: descriptionController,
decoration: InputDecoration(labelText: 'Description'),
maxLines: 3,
),
SizedBox(height: 10),
// Price Input
TextField(
......
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