Add further work to Book Detail page

This commit is contained in:
Ray 2023-11-14 09:23:56 +00:00 committed by GitHub
parent f137be055d
commit 258483b023
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 136 additions and 94 deletions

View File

@ -2,17 +2,23 @@ import { FirebaseConfig } from "./config/Config"
import { initializeApp } from "firebase/app" import { initializeApp } from "firebase/app"
import { Routes, Route } from "react-router-dom" import { Routes, Route } from "react-router-dom"
import { useState, useEffect } from "react" import { useState, useEffect } from "react"
import { getAuth, import {
getAuth,
createUserWithEmailAndPassword, createUserWithEmailAndPassword,
onAuthStateChanged, onAuthStateChanged,
signOut, signOut,
signInWithEmailAndPassword } from "firebase/auth"; signInWithEmailAndPassword
import { getFirestore, } from "firebase/auth";
collection, import {
query, getFirestore,
where, collection,
getDocs } from "firebase/firestore"; query,
import {getStorage} from "firebase/storage" where,
getDoc,
getDocs,
doc
} from "firebase/firestore";
import { getStorage } from "firebase/storage"
import { Header } from "./components/Header" import { Header } from "./components/Header"
import './App.css' import './App.css'
@ -34,8 +40,8 @@ function App() {
const FBauth = getAuth(FBapp) const FBauth = getAuth(FBapp)
const FBdb = getFirestore(FBapp) const FBdb = getFirestore(FBapp)
const FBstorage = getStorage(FBapp) const FBstorage = getStorage(FBapp)
// navigation array // navigation array
const navItems = [ const navItems = [
{ label: "Home", link: "/" }, { label: "Home", link: "/" },
@ -49,35 +55,35 @@ function App() {
{ label: "Home", link: "/" }, { label: "Home", link: "/" },
{ label: "About", link: "/about" }, { label: "About", link: "/about" },
{ label: "Contact", link: "/contact" }, { label: "Contact", link: "/contact" },
] ]
/// application states /// application states
const [nav, setNav] = useState(navItems) const [nav, setNav] = useState(navItems)
const [auth, setAuth] = useState(false) const [auth, setAuth] = useState(false)
const [data, setData] = useState([]) const [data, setData] = useState([])
const [ fetching , setFetching ] = useState( false ) const [fetching, setFetching] = useState(false)
useEffect( () => { useEffect(() => {
if( data.length === 0 && fetching === false ) { if (data.length === 0 && fetching === false) {
readData() readData()
setFetching( true ) setFetching(true)
} }
}, [data]) }, [data])
// authentication observer // authentication observer
onAuthStateChanged(FBauth, (user) => { onAuthStateChanged(FBauth, (user) => {
if( user ) { if (user) {
// currently authenticated // currently authenticated
setAuth( user ) setAuth(user)
setNav( AuthnavItems ) setNav(AuthnavItems)
} }
else { else {
// currently unauthenticated // currently unauthenticated
setAuth( false ) setAuth(false)
setNav( navItems ) setNav(navItems)
} }
}) })
@ -89,64 +95,73 @@ function App() {
// signing up a user // signing up a user
const signUp = (email, password) => { const signUp = (email, password) => {
createUserWithEmailAndPassword(FBauth, email, password) createUserWithEmailAndPassword(FBauth, email, password)
.then( (userCredential) => { .then((userCredential) => {
// do something // do something
}) })
.catch((error) => console.log(error.message)) .catch((error) => console.log(error.message))
}
const logOut = () => {
signOut(FBauth).then( () => {
// user is signed out
})
}
const signIn = (email, password) => {
return new Promise((resolve, reject) => {
signInWithEmailAndPassword(FBauth, email, password)
.then(() => {
// user is signed in
resolve(true)
})
.catch((error) => {
console.log(error)
reject( error.code )
})
})
}
// function to get data
const readData = async () => {
const querySnapshot = await getDocs( collection(FBdb, "books") )
let listdata = []
querySnapshot.forEach( (doc) => {
let item = doc.data()
item.id = doc.id
listdata.push( item )
})
setData( listdata )
}
return (
<div className="App">
<Header items={nav} user={auth} />
<AuthContext.Provider value={auth}>
<StorageContext.Provider value={FBstorage}>
<Routes>
<Route path="/" element={<Home items = {data} />} />
<Route path="/about" element={<About greeting="Hey you, this is about page!" handler={saySomething} />} />
<Route path="/contact" element={<Contact greeting="Hey you, this is contact page!" />} />
<Route path="/signup" element={ <Signup handler={signUp}/> } />
<Route path="/signout" element={ <Signout handler={logOut}/> } />
<Route path="/signin" element={ <Signin handler={signIn} authstate={auth}/> } />
<Route path="/detail/:id" element={<Detail/>} />
</Routes>
</StorageContext.Provider>
</AuthContext.Provider>
</div>
);
} }
export default App; const logOut = () => {
signOut(FBauth).then(() => {
// user is signed out
})
}
const signIn = (email, password) => {
return new Promise((resolve, reject) => {
signInWithEmailAndPassword(FBauth, email, password)
.then(() => {
// user is signed in
resolve(true)
})
.catch((error) => {
console.log(error)
reject(error.code)
})
})
}
// function to get data
const readData = async () => {
const querySnapshot = await getDocs(collection(FBdb, "books"))
let listdata = []
querySnapshot.forEach((doc) => {
let item = doc.data()
item.id = doc.id
listdata.push(item)
})
setData(listdata)
}
// function to get a single item
const getDocument = async (itemId) => {
const docRef = doc(FBdb, "books", itemId)
const docSnap = await getDoc(docRef)
let book = docSnap.data()
book.id = itemId
return book
}
return (
<div className="App">
<Header items={nav} user={auth} />
<AuthContext.Provider value={auth}>
<StorageContext.Provider value={FBstorage}>
<Routes>
<Route path="/" element={<Home items={data} />} />
<Route path="/about" element={<About greeting="Hey you, this is about page!" handler={saySomething} />} />
<Route path="/contact" element={<Contact greeting="Hey you, this is contact page!" />} />
<Route path="/signup" element={<Signup handler={signUp} />} />
<Route path="/signout" element={<Signout handler={logOut} />} />
<Route path="/signin" element={<Signin handler={signIn} authstate={auth} />} />
<Route path="/detail/:id" element={<Detail handler={getDocument} />} />
</Routes>
</StorageContext.Provider>
</AuthContext.Provider>
</div>
);
}
export default App;

View File

@ -1,22 +1,49 @@
import Row from 'react-bootstrap/Row'; import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col'; import Col from 'react-bootstrap/Col';
import Container from "react-bootstrap/Container"; import Container from "react-bootstrap/Container";
import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { ItemImage } from '../components/ItemImage';
export function Detail(props) { export function Detail(props) {
const [bookData, setBookData] = useState()
let { id } = useParams(); let { id } = useParams();
return(
<Container> useEffect( () => {
<Row> if( !bookData ) {
<Col md={6}> props.handler(id).then( (book) => setBookData(book) )
<h1>Image</h1> }
</Col> }, [id])
<Col md={6}>
<h2>Details</h2>
<p>{id}</p> if( bookData ) {
</Col> return(
</Row> <Container>
</Container> <Row>
) <Col>
<h1>{bookData.book_title}</h1>
</Col>
</Row>
<Row>
<Col md={6}>
<ItemImage source={bookData.cover_image} />
</Col>
<Col md={6}>
<h2>More information</h2>
<h3>Summary</h3>
<p>{bookData.summary}</p>
<h3>Author</h3>
<p>{bookData.author}</p>
<h3>ISBN</h3>
<p>ISBN10 {bookData.isbn10}</p>
<p>ISBN13 {bookData.isbn13}</p>
</Col>
</Row>
</Container>
)
}
else {
return null
}
} }

View File

@ -18,7 +18,7 @@ export function Home(props) {
const ItemCards = books.map( ( book, itemkey ) => { const ItemCards = books.map( ( book, itemkey ) => {
const itemLink = `/detail/${book.id}` const itemLink = `/detail/${book.id}`
return( return(
<Col md={4} className="mb-4"> <Col md={4} className="mb-4" key={itemkey}>
<Card key={itemkey} className="position-relative"> <Card key={itemkey} className="position-relative">
<a href={itemLink} className="position-absolute" style={{top:0, left:0, right:0, bottom:0}}> <a href={itemLink} className="position-absolute" style={{top:0, left:0, right:0, bottom:0}}>
</a> </a>