Add further work to Book Detail page
This commit is contained in:
parent
f137be055d
commit
258483b023
165
src/App.js
165
src/App.js
|
@ -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'
|
||||||
|
@ -56,28 +62,28 @@ function App() {
|
||||||
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;
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue