Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
P
PaperChase
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
PaperChase
Commits
e953b7df
Commit
e953b7df
authored
Mar 26, 2025
by
Adam Bruck
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated Post
parent
c08d00b7
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
137 additions
and
41 deletions
+137
-41
.flutter-plugins-dependencies
.flutter-plugins-dependencies
+1
-1
cache.dill.track.dill
build/cache.dill.track.dill
+0
-0
book_detail_page.dart
lib/book_detail_page.dart
+36
-0
mybooks.dart
lib/mybooks.dart
+30
-16
post.dart
lib/post.dart
+70
-24
No files found.
.flutter-plugins-dependencies
View file @
e953b7df
This diff is collapsed.
Click to expand it.
build/cache.dill.track.dill
View file @
e953b7df
No preview for this file type
lib/book_detail_page.dart
0 → 100644
View file @
e953b7df
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
)),
],
),
),
);
}
}
lib/mybooks.dart
View file @
e953b7df
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
),
),
);
},
);
},
);
...
...
lib/post.dart
View file @
e953b7df
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
"
;
try
{
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
}
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 image:
$e
'
);
return
null
;
}
}
// Function to upload book data to Firebase
Future
<
bool
>
uploadBook
()
async
{
try
{
// Store book details in Firestore
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
,
'description'
:
descriptionController
.
text
,
'price'
:
priceController
.
text
,
'isbn'
:
isbnController
.
text
,
'author'
:
authorController
.
text
,
'imageUrl'
:
''
,
// Remove Firebase Storage dependency
'createdAt'
:
Timestamp
.
now
(),
'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
'
);
}
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
(
...
...
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