\documentclass[10pt,a4paper]{article} % Packages \usepackage{fancyhdr} % For header and footer \usepackage{multicol} % Allows multicols in tables \usepackage{tabularx} % Intelligent column widths \usepackage{tabulary} % Used in header and footer \usepackage{hhline} % Border under tables \usepackage{graphicx} % For images \usepackage{xcolor} % For hex colours %\usepackage[utf8x]{inputenc} % For unicode character support \usepackage[T1]{fontenc} % Without this we get weird character replacements \usepackage{colortbl} % For coloured tables \usepackage{setspace} % For line height \usepackage{lastpage} % Needed for total page number \usepackage{seqsplit} % Splits long words. %\usepackage{opensans} % Can't make this work so far. Shame. Would be lovely. \usepackage[normalem]{ulem} % For underlining links % Most of the following are not required for the majority % of cheat sheets but are needed for some symbol support. \usepackage{amsmath} % Symbols \usepackage{MnSymbol} % Symbols \usepackage{wasysym} % Symbols %\usepackage[english,german,french,spanish,italian]{babel} % Languages % Document Info \author{sally sung} \pdfinfo{ /Title (full-stack-dev-with-js-final.pdf) /Creator (Cheatography) /Author (sally sung) /Subject (Full Stack Dev With JS - Final Cheat Sheet) } % Lengths and widths \addtolength{\textwidth}{6cm} \addtolength{\textheight}{-1cm} \addtolength{\hoffset}{-3cm} \addtolength{\voffset}{-2cm} \setlength{\tabcolsep}{0.2cm} % Space between columns \setlength{\headsep}{-12pt} % Reduce space between header and content \setlength{\headheight}{85pt} % If less, LaTeX automatically increases it \renewcommand{\footrulewidth}{0pt} % Remove footer line \renewcommand{\headrulewidth}{0pt} % Remove header line \renewcommand{\seqinsert}{\ifmmode\allowbreak\else\-\fi} % Hyphens in seqsplit % This two commands together give roughly % the right line height in the tables \renewcommand{\arraystretch}{1.3} \onehalfspacing % Commands \newcommand{\SetRowColor}[1]{\noalign{\gdef\RowColorName{#1}}\rowcolor{\RowColorName}} % Shortcut for row colour \newcommand{\mymulticolumn}[3]{\multicolumn{#1}{>{\columncolor{\RowColorName}}#2}{#3}} % For coloured multi-cols \newcolumntype{x}[1]{>{\raggedright}p{#1}} % New column types for ragged-right paragraph columns \newcommand{\tn}{\tabularnewline} % Required as custom column type in use % Font and Colours \definecolor{HeadBackground}{HTML}{333333} \definecolor{FootBackground}{HTML}{666666} \definecolor{TextColor}{HTML}{333333} \definecolor{DarkBackground}{HTML}{4269D4} \definecolor{LightBackground}{HTML}{F3F5FC} \renewcommand{\familydefault}{\sfdefault} \color{TextColor} % Header and Footer \pagestyle{fancy} \fancyhead{} % Set header to blank \fancyfoot{} % Set footer to blank \fancyhead[L]{ \noindent \begin{multicols}{3} \begin{tabulary}{5.8cm}{C} \SetRowColor{DarkBackground} \vspace{-7pt} {\parbox{\dimexpr\textwidth-2\fboxsep\relax}{\noindent \hspace*{-6pt}\includegraphics[width=5.8cm]{/web/www.cheatography.com/public/images/cheatography_logo.pdf}} } \end{tabulary} \columnbreak \begin{tabulary}{11cm}{L} \vspace{-2pt}\large{\bf{\textcolor{DarkBackground}{\textrm{Full Stack Dev With JS - Final Cheat Sheet}}}} \\ \normalsize{by \textcolor{DarkBackground}{sally sung} via \textcolor{DarkBackground}{\uline{cheatography.com/216190/cs/47975/}}} \end{tabulary} \end{multicols}} \fancyfoot[L]{ \footnotesize \noindent \begin{multicols}{3} \begin{tabulary}{5.8cm}{LL} \SetRowColor{FootBackground} \mymulticolumn{2}{p{5.377cm}}{\bf\textcolor{white}{Cheatographer}} \\ \vspace{-2pt}sally sung \\ \uline{cheatography.com/sally-sung} \\ \end{tabulary} \vfill \columnbreak \begin{tabulary}{5.8cm}{L} \SetRowColor{FootBackground} \mymulticolumn{1}{p{5.377cm}}{\bf\textcolor{white}{Cheat Sheet}} \\ \vspace{-2pt}Not Yet Published.\\ Updated 21st April, 2026.\\ Page {\thepage} of \pageref{LastPage}. \end{tabulary} \vfill \columnbreak \begin{tabulary}{5.8cm}{L} \SetRowColor{FootBackground} \mymulticolumn{1}{p{5.377cm}}{\bf\textcolor{white}{Sponsor}} \\ \SetRowColor{white} \vspace{-5pt} %\includegraphics[width=48px,height=48px]{dave.jpeg} Measure your website readability!\\ www.readability-score.com \end{tabulary} \end{multicols}} \begin{document} \raggedright \raggedcolumns % Set font size to small. Switch to any value % from this page to resize cheat sheet text: % www.emerson.emory.edu/services/latex/latex_169.html \footnotesize % Small font. \begin{multicols*}{2} \begin{tabularx}{8.4cm}{x{3.04 cm} x{4.96 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{8.4cm}}{\bf\textcolor{white}{Setup}} \tn % Row 0 \SetRowColor{LightBackground} React Client Setup & npm create vite@latest client -{}- -{}-template react \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} & cd client \tn % Row Count 4 (+ 1) % Row 2 \SetRowColor{LightBackground} & npm install axios bootstrap react-icons react-router-dom \tn % Row Count 7 (+ 3) % Row 3 \SetRowColor{white} & src \textgreater{} copy styles.css \tn % Row Count 8 (+ 1) % Row 4 \SetRowColor{LightBackground} & src / app.jsx \textgreater{} import './styles.css' \tn % Row Count 10 (+ 2) % Row 5 \SetRowColor{white} Node/Express Server setup & root \textgreater{} create a new folder named server \tn % Row Count 12 (+ 2) % Row 6 \SetRowColor{LightBackground} & cd server \tn % Row Count 13 (+ 1) % Row 7 \SetRowColor{white} & npm init -y \tn % Row Count 14 (+ 1) % Row 8 \SetRowColor{LightBackground} & create server.js file \tn % Row Count 15 (+ 1) % Row 9 \SetRowColor{white} Concurrently & root \textgreater{} npm i concurrently \tn % Row Count 17 (+ 2) \hhline{>{\arrayrulecolor{DarkBackground}}--} \SetRowColor{LightBackground} \mymulticolumn{2}{x{8.4cm}}{server \textgreater{} package.json \newline "scripts": \{ \newline "test": "echo \textbackslash{}"Error: no test specified\textbackslash{}" \&\& exit 1", \newline "start": "node server.js" \newline \}, \newline "type": "module" \newline \newline root \textgreater{} package.json \newline "scripts": \{ \newline "start": "concurrently \textbackslash{}"npm run server\textbackslash{}" \textbackslash{}"npm run client\textbackslash{}"", \newline "server": "cd server \&\& npm start", \newline "client": "cd client \&\& npm run dev" \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} src / config / api.js}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{export const API\_BASE\_URL = \seqsplit{(import.meta.env.VITE\_API\_BASE\_URL} || "http://localhost:3000").replace(/\textbackslash{}/\$/, ""); \newline % Row Count 3 (+ 3) export const API\_URLS = \{ \newline % Row Count 4 (+ 1) books: `\$\{API\_BASE\_URL\}/books`, \newline % Row Count 5 (+ 1) book: (bookId) =\textgreater{} `\$\{API\_BASE\_URL\}/books/\$\{bookId\}`, \newline % Row Count 7 (+ 2) \}; \newline % Row Count 8 (+ 1) export const BOOKS\_API\_URL = API\_URLS.books; \newline % Row Count 9 (+ 1) export const getBookUrl = API\_URLS.book;% Row Count 10 (+ 1) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} main.jsx}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{import \{ StrictMode \} from 'react' \newline % Row Count 1 (+ 1) import \{ createRoot \} from 'react-dom/client' \newline % Row Count 2 (+ 1) import './index.css' \newline % Row Count 3 (+ 1) import App from './App.jsx' \newline % Row Count 4 (+ 1) import \{BrowserRouter as Router\} from "react-router-dom" \newline % Row Count 6 (+ 2) import \seqsplit{"bootstrap/dist/css/bootstrap}.css" \newline % Row Count 7 (+ 1) \seqsplit{createRoot(document.getElementById('root')).render(} \newline % Row Count 9 (+ 2) \textless{}StrictMode\textgreater{} \newline % Row Count 10 (+ 1) \textless{}Router\textgreater{} \newline % Row Count 11 (+ 1) \textless{}App /\textgreater{} \newline % Row Count 12 (+ 1) \textless{}/Router\textgreater{} \newline % Row Count 13 (+ 1) \textless{}/StrictMode\textgreater{}, \newline % Row Count 14 (+ 1) )% Row Count 15 (+ 1) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} App.jsx}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{import \{ BOOKS\_API\_URL, getBookUrl \} from "./config/api"; \newline % Row Count 2 (+ 2) import './styles.css'; \newline % Row Count 3 (+ 1) const logError = (action, error) =\textgreater{} \{ \newline % Row Count 4 (+ 1) console.log(`ERROR in \$\{action\}: \$\{error.message\}`); \newline % Row Count 6 (+ 2) \}; \newline % Row Count 7 (+ 1) function App() \{ \newline % Row Count 8 (+ 1) const {[}books, setBooks{]} = useState({[}{]}); \newline % Row Count 9 (+ 1) useEffect(() =\textgreater{} \{ \newline % Row Count 10 (+ 1) const fetchBooks = async () =\textgreater{} \{ \newline % Row Count 11 (+ 1) try \{ \newline % Row Count 12 (+ 1) const \{ data \} = await \seqsplit{axios.get(BOOKS\_API\_URL);} \newline % Row Count 14 (+ 2) setBooks(data); \newline % Row Count 15 (+ 1) \} catch (err) \{ \newline % Row Count 16 (+ 1) logError("fetching books", err); \newline % Row Count 17 (+ 1) \} \newline % Row Count 18 (+ 1) \}; \newline % Row Count 19 (+ 1) fetchBooks(); \newline % Row Count 20 (+ 1) \}, {[}{]}); \newline % Row Count 21 (+ 1) const handleDelete = async (idToDelete) =\textgreater{} \{ \newline % Row Count 22 (+ 1) try \{ \newline % Row Count 23 (+ 1) await \seqsplit{axios.delete(getBookUrl(idToDelete));} \newline % Row Count 25 (+ 2) setBooks((currentBooks) =\textgreater{} \seqsplit{currentBooks.filter((book)} =\textgreater{} book.\_id !== idToDelete)); \newline % Row Count 27 (+ 2) \} catch (err) \{ \newline % Row Count 28 (+ 1) logError("deleting the book", err); \newline % Row Count 29 (+ 1) \} \newline % Row Count 30 (+ 1) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} App.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ \}; \newline % Row Count 1 (+ 1) const handleAdd = async (newBook) =\textgreater{} \{ \newline % Row Count 2 (+ 1) try \{ \newline % Row Count 3 (+ 1) const \{ data \} = await \seqsplit{axios.post(BOOKS\_API\_URL}, newBook); \newline % Row Count 5 (+ 2) setBooks((currentBooks) =\textgreater{} {[}...currentBooks, data{]}); \newline % Row Count 7 (+ 2) \} catch (err) \{ \newline % Row Count 8 (+ 1) logError("adding the book", err); \newline % Row Count 9 (+ 1) \} \newline % Row Count 10 (+ 1) \}; \newline % Row Count 11 (+ 1) const handleUpdate = async (updatedBook) =\textgreater{} \{ \newline % Row Count 12 (+ 1) try \{ \newline % Row Count 13 (+ 1) const \{ data \} = await \seqsplit{axios.put(getBookUrl(updatedBook.\_id)}, updatedBook); \newline % Row Count 15 (+ 2) setBooks((currentBooks) =\textgreater{} currentBooks.map((book) =\textgreater{} (book.\_id === data.\_id ? data : book))); \newline % Row Count 18 (+ 3) \} catch (err) \{ \newline % Row Count 19 (+ 1) logError("updating the book", err); \newline % Row Count 20 (+ 1) \} \newline % Row Count 21 (+ 1) \}; \newline % Row Count 22 (+ 1) const handleToggleLike = (bookToToggle) =\textgreater{} \{ \newline % Row Count 23 (+ 1) handleUpdate(\{ ...bookToToggle, like: !bookToToggle.like \}); \newline % Row Count 25 (+ 2) \}; \newline % Row Count 26 (+ 1) return ( \newline % Row Count 27 (+ 1) \textless{}div className="App"\textgreater{} \newline % Row Count 28 (+ 1) \textless{}NavBar /\textgreater{} \newline % Row Count 29 (+ 1) \textless{}Header /\textgreater{} \newline % Row Count 30 (+ 1) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} App.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ \textless{}Routes\textgreater{} \newline % Row Count 1 (+ 1) \textless{}Route \newline % Row Count 2 (+ 1) path="/" \newline % Row Count 3 (+ 1) element=\{\textless{}Books books=\{books\} onDelete=\{handleDelete\} onToggleLike=\{handleToggleLike\} /\textgreater{}\} \newline % Row Count 6 (+ 3) /\textgreater{} \newline % Row Count 7 (+ 1) \textless{}Route path="/addbook" element=\{\textless{}AddBook onAdd=\{handleAdd\} /\textgreater{}\} /\textgreater{} \newline % Row Count 9 (+ 2) \textless{}Route path="/updatebook/:id" element=\{\textless{}UpdateBook onUpdate=\{handleUpdate\} /\textgreater{}\} /\textgreater{} \newline % Row Count 11 (+ 2) \textless{}/Routes\textgreater{} \newline % Row Count 12 (+ 1) \textless{}Footer /\textgreater{} \newline % Row Count 13 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 14 (+ 1) ); \newline % Row Count 15 (+ 1) \} \newline % Row Count 16 (+ 1) export default App;% Row Count 17 (+ 1) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / books.jsx}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{import Book from "./book"; \newline % Row Count 1 (+ 1) const Books = (\{ books = {[}{]}, onDelete = (f) =\textgreater{} f, onToggleLike = (f) =\textgreater{} f \}) =\textgreater{} \{ \newline % Row Count 3 (+ 2) return ( \newline % Row Count 4 (+ 1) \textless{}section\textgreater{} \newline % Row Count 5 (+ 1) \{!books.length ? ( \newline % Row Count 6 (+ 1) \textless{}h2\textgreater{}There are no books available.\textless{}/h2\textgreater{} \newline % Row Count 8 (+ 2) ) : ( \newline % Row Count 9 (+ 1) \textless{}\textgreater{} \newline % Row Count 10 (+ 1) \textless{}h3\textgreater{}Showing \{books.length\} books.\textless{}/h3\textgreater{} \newline % Row Count 12 (+ 2) \textless{}table className="table"\textgreater{} \newline % Row Count 13 (+ 1) \textless{}thead\textgreater{} \newline % Row Count 14 (+ 1) \textless{}tr\textgreater{} \newline % Row Count 15 (+ 1) \textless{}th\textgreater{}Title\textless{}/th\textgreater{} \newline % Row Count 16 (+ 1) \textless{}th\textgreater{}Author\textless{}/th\textgreater{} \newline % Row Count 17 (+ 1) \textless{}th\textgreater{}Number in Stock\textless{}/th\textgreater{} \newline % Row Count 19 (+ 2) \textless{}th\textgreater{}Price\textless{}/th\textgreater{} \newline % Row Count 20 (+ 1) \textless{}th\textgreater{}Rating\textless{}/th\textgreater{} \newline % Row Count 21 (+ 1) \textless{}th\textgreater{}Publish Year\textless{}/th\textgreater{} \newline % Row Count 23 (+ 2) \textless{}th\textgreater{}Like\textless{}/th\textgreater{} \newline % Row Count 24 (+ 1) \textless{}th\textgreater{}Actions(s)\textless{}/th\textgreater{} \newline % Row Count 26 (+ 2) \textless{}/tr\textgreater{} \newline % Row Count 27 (+ 1) \textless{}/thead\textgreater{} \newline % Row Count 28 (+ 1) \textless{}tbody\textgreater{} \newline % Row Count 29 (+ 1) \{books.map((book) =\textgreater{} ( \newline % Row Count 31 (+ 2) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / books.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ \textless{}Book key=\{book.\_id\} book=\{book\} onDelete=\{onDelete\} onToggleLike=\{onToggleLike\} /\textgreater{} \newline % Row Count 3 (+ 3) ))\} \newline % Row Count 4 (+ 1) \textless{}/tbody\textgreater{} \newline % Row Count 5 (+ 1) \textless{}/table\textgreater{} \newline % Row Count 6 (+ 1) \textless{}/\textgreater{} \newline % Row Count 7 (+ 1) )\} \newline % Row Count 8 (+ 1) \textless{}/section\textgreater{} \newline % Row Count 9 (+ 1) ); \newline % Row Count 10 (+ 1) \}; \newline % Row Count 11 (+ 1) export default Books;% Row Count 12 (+ 1) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / book.jsx}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{import \{ FaHeart, FaRegHeart, FaTrash, FaEdit \} from "react-icons/fa"; \newline % Row Count 2 (+ 2) import \{ Link \} from "react-router-dom"; \newline % Row Count 3 (+ 1) const Book = (\{ book, onDelete = (f) =\textgreater{} f, onToggleLike = (f) =\textgreater{} f \}) =\textgreater{} \{ \newline % Row Count 5 (+ 2) const formatYear = () =\textgreater{} \{ \newline % Row Count 6 (+ 1) return new \seqsplit{Date(book.publishYear).toISOString().slice(0}, 10); \newline % Row Count 8 (+ 2) \}; \newline % Row Count 9 (+ 1) return ( \newline % Row Count 10 (+ 1) \textless{}tr\textgreater{} \newline % Row Count 11 (+ 1) \textless{}td\textgreater{}\{book.title\}\textless{}/td\textgreater{} \newline % Row Count 12 (+ 1) \textless{}td\textgreater{}\{book.author\}\textless{}/td\textgreater{} \newline % Row Count 13 (+ 1) \textless{}td\textgreater{}\{book.numberInStock\}\textless{}/td\textgreater{} \newline % Row Count 14 (+ 1) \textless{}td\textgreater{}\{book.price\}\textless{}/td\textgreater{} \newline % Row Count 15 (+ 1) \textless{}td\textgreater{}\{book.rating\}\textless{}/td\textgreater{} \newline % Row Count 16 (+ 1) \textless{}td\textgreater{}\{formatYear()\}\textless{}/td\textgreater{} \newline % Row Count 17 (+ 1) \textless{}td\textgreater{} \newline % Row Count 18 (+ 1) \textless{}button \newline % Row Count 19 (+ 1) type="button" \newline % Row Count 20 (+ 1) className="btn btn-link p-0 border-0" \newline % Row Count 22 (+ 2) onClick=\{() =\textgreater{} onToggleLike(book)\} \newline % Row Count 24 (+ 2) aria-label=\{book.like ? "Unlike book" : "Like book"\} \newline % Row Count 26 (+ 2) \textgreater{} \newline % Row Count 27 (+ 1) \{book.like ? \textless{}FaHeart color="red" /\textgreater{} : \textless{}FaRegHeart /\textgreater{}\} \newline % Row Count 29 (+ 2) \textless{}/button\textgreater{} \newline % Row Count 30 (+ 1) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / book.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ \textless{}/td\textgreater{} \newline % Row Count 1 (+ 1) \textless{}td\textgreater{} \newline % Row Count 2 (+ 1) \textless{}Link to=\{`/updatebook/\$\{book.\_id\}`\}\textgreater{} \newline % Row Count 4 (+ 2) \textless{}FaEdit /\textgreater{} \newline % Row Count 5 (+ 1) \textless{}/Link\textgreater{} \newline % Row Count 6 (+ 1) \textless{}/td\textgreater{} \newline % Row Count 7 (+ 1) \textless{}td\textgreater{} \newline % Row Count 8 (+ 1) \textless{}FaTrash onClick=\{() =\textgreater{} onDelete(book.\_id)\} /\textgreater{} \newline % Row Count 10 (+ 2) \textless{}/td\textgreater{} \newline % Row Count 11 (+ 1) \textless{}/tr\textgreater{} \newline % Row Count 12 (+ 1) ); \newline % Row Count 13 (+ 1) \}; \newline % Row Count 14 (+ 1) export default Book;% Row Count 15 (+ 1) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / addBook.jsx}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{import \{ useState \} from "react"; \newline % Row Count 1 (+ 1) import \{ useNavigate \} from "react-router-dom"; \newline % Row Count 2 (+ 1) const AddBook = (\{ onAdd = (f) =\textgreater{} f \}) =\textgreater{} \{ \newline % Row Count 3 (+ 1) const {[}book, setBook{]} = useState(\{ \newline % Row Count 4 (+ 1) title: "", \newline % Row Count 5 (+ 1) author: "", \newline % Row Count 6 (+ 1) numberInStock: "", \newline % Row Count 7 (+ 1) price: "", \newline % Row Count 8 (+ 1) rating: "", \newline % Row Count 9 (+ 1) publishYear: "", \newline % Row Count 10 (+ 1) like: "", \newline % Row Count 11 (+ 1) \}); \newline % Row Count 12 (+ 1) const navigate = useNavigate(); \newline % Row Count 13 (+ 1) const submitForm = (e) =\textgreater{} \{ \newline % Row Count 14 (+ 1) e.preventDefault(); \newline % Row Count 15 (+ 1) onAdd(book); \newline % Row Count 16 (+ 1) setBook(\{ \newline % Row Count 17 (+ 1) title: "", \newline % Row Count 18 (+ 1) author: "", \newline % Row Count 19 (+ 1) numberInStock: "", \newline % Row Count 20 (+ 1) price: "", \newline % Row Count 21 (+ 1) rating: "", \newline % Row Count 22 (+ 1) publishYear: "", \newline % Row Count 23 (+ 1) like: "", \newline % Row Count 24 (+ 1) \}); \newline % Row Count 25 (+ 1) navigate("/"); \newline % Row Count 26 (+ 1) \}; \newline % Row Count 27 (+ 1) return ( \newline % Row Count 28 (+ 1) \textless{}div\textgreater{} \newline % Row Count 29 (+ 1) \textless{}h1\textgreater{}Please enter the details of the new Book here..\textless{}/h1\textgreater{} \newline % Row Count 31 (+ 2) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / addBook.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ \textless{}form onSubmit=\{submitForm\} method="post"\textgreater{} \newline % Row Count 2 (+ 2) \textless{}div className="form-group"\textgreater{} \newline % Row Count 3 (+ 1) \textless{}label htmlFor="title" className="p-3"\textgreater{} \newline % Row Count 5 (+ 2) Book Title \newline % Row Count 6 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 7 (+ 1) \textless{}input \newline % Row Count 8 (+ 1) type="text" \newline % Row Count 9 (+ 1) name="title" \newline % Row Count 10 (+ 1) id="title" \newline % Row Count 11 (+ 1) className="form-control" \newline % Row Count 12 (+ 1) placeholder="Enter a Title" \newline % Row Count 14 (+ 2) onChange=\{(event) =\textgreater{} setBook(\{ ...book, title: event.target.value \})\} \newline % Row Count 16 (+ 2) value=\{book.title\} \newline % Row Count 17 (+ 1) required \newline % Row Count 18 (+ 1) /\textgreater{} \newline % Row Count 19 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 20 (+ 1) \textless{}div className="form-group"\textgreater{} \newline % Row Count 21 (+ 1) \textless{}label htmlFor="author" className="p-3"\textgreater{} \newline % Row Count 23 (+ 2) Book Author \newline % Row Count 24 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 25 (+ 1) \textless{}input \newline % Row Count 26 (+ 1) type="text" \newline % Row Count 27 (+ 1) name="author" \newline % Row Count 28 (+ 1) id="author" \newline % Row Count 29 (+ 1) className="form-control" \newline % Row Count 30 (+ 1) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / addBook.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ placeholder="Enter an Author" \newline % Row Count 2 (+ 2) onChange=\{(event) =\textgreater{} setBook(\{ ...book, author: event.target.value \})\} \newline % Row Count 4 (+ 2) value=\{book.author\} \newline % Row Count 5 (+ 1) required \newline % Row Count 6 (+ 1) /\textgreater{} \newline % Row Count 7 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 8 (+ 1) \textless{}div className="form-group"\textgreater{} \newline % Row Count 9 (+ 1) \textless{}label htmlFor="numberInStock" className="p-3"\textgreater{} \newline % Row Count 11 (+ 2) Number In Stock \newline % Row Count 12 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 13 (+ 1) \textless{}input \newline % Row Count 14 (+ 1) type="number" \newline % Row Count 15 (+ 1) name="numberInStock" \newline % Row Count 16 (+ 1) id="numberInStock" \newline % Row Count 17 (+ 1) className="form-control" \newline % Row Count 18 (+ 1) placeholder="Number In Stock" \newline % Row Count 20 (+ 2) onChange=\{(event) =\textgreater{} setBook(\{ ...book, numberInStock: event.target.value \})\} \newline % Row Count 23 (+ 3) value=\{book.numberInStock\} \newline % Row Count 25 (+ 2) required \newline % Row Count 26 (+ 1) /\textgreater{} \newline % Row Count 27 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 28 (+ 1) \textless{}div className="form-group"\textgreater{} \newline % Row Count 29 (+ 1) \textless{}label htmlFor="price" className="p-3"\textgreater{} \newline % Row Count 31 (+ 2) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / addBook.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ Book Price \newline % Row Count 1 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 2 (+ 1) \textless{}input \newline % Row Count 3 (+ 1) type="text" \newline % Row Count 4 (+ 1) name="price" \newline % Row Count 5 (+ 1) id="price" \newline % Row Count 6 (+ 1) className="form-control" \newline % Row Count 7 (+ 1) placeholder="Enter a Price" \newline % Row Count 9 (+ 2) onChange=\{(event) =\textgreater{} setBook(\{ ...book, price: event.target.value \})\} \newline % Row Count 11 (+ 2) value=\{book.price\} \newline % Row Count 12 (+ 1) required \newline % Row Count 13 (+ 1) /\textgreater{} \newline % Row Count 14 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 15 (+ 1) \textless{}div className="form-group"\textgreater{} \newline % Row Count 16 (+ 1) \textless{}label htmlFor="rating" className="p-3"\textgreater{} \newline % Row Count 18 (+ 2) Book Rating \newline % Row Count 19 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 20 (+ 1) \textless{}input \newline % Row Count 21 (+ 1) type="number" \newline % Row Count 22 (+ 1) name="rating" \newline % Row Count 23 (+ 1) id="rating" \newline % Row Count 24 (+ 1) className="form-control" \newline % Row Count 25 (+ 1) placeholder="Enter a Rating" \newline % Row Count 27 (+ 2) onChange=\{(event) =\textgreater{} setBook(\{ ...book, rating: event.target.value \})\} \newline % Row Count 29 (+ 2) value=\{book.rating\} \newline % Row Count 30 (+ 1) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / addBook.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ required \newline % Row Count 1 (+ 1) /\textgreater{} \newline % Row Count 2 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 3 (+ 1) \textless{}div className="form-group"\textgreater{} \newline % Row Count 4 (+ 1) \textless{}label htmlFor="publishYear" className="p-3"\textgreater{} \newline % Row Count 6 (+ 2) Book Publish Year \newline % Row Count 7 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 8 (+ 1) \textless{}input \newline % Row Count 9 (+ 1) type="date" \newline % Row Count 10 (+ 1) name="publishYear" \newline % Row Count 11 (+ 1) id="publishYear" \newline % Row Count 12 (+ 1) className="form-control" \newline % Row Count 13 (+ 1) placeholder="Enter a Publish Year" \newline % Row Count 15 (+ 2) onChange=\{(event) =\textgreater{} setBook(\{ ...book, publishYear: event.target.value \})\} \newline % Row Count 17 (+ 2) value=\{book.publishYear\} \newline % Row Count 18 (+ 1) required \newline % Row Count 19 (+ 1) /\textgreater{} \newline % Row Count 20 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 21 (+ 1) \textless{}div className="form-group"\textgreater{} \newline % Row Count 22 (+ 1) \textless{}label className="p-3 d-block"\textgreater{} \newline % Row Count 24 (+ 2) Like Status (True/False) \newline % Row Count 25 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 26 (+ 1) \textless{}div className="form-check form-check-inline"\textgreater{} \newline % Row Count 28 (+ 2) \textless{}input \newline % Row Count 29 (+ 1) type="radio" \newline % Row Count 30 (+ 1) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / addBook.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ name="like" \newline % Row Count 1 (+ 1) id="like-true" \newline % Row Count 2 (+ 1) \seqsplit{className="form-check-input"} \newline % Row Count 4 (+ 2) checked=\{book.like === true\} \newline % Row Count 6 (+ 2) onChange=\{() =\textgreater{} setBook(\{ ...book, like: true \})\} \newline % Row Count 8 (+ 2) required \newline % Row Count 9 (+ 1) /\textgreater{} \newline % Row Count 10 (+ 1) \textless{}label htmlFor="like-true" className="form-check-label"\textgreater{} \newline % Row Count 12 (+ 2) True \newline % Row Count 13 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 14 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 15 (+ 1) \textless{}div className="form-check form-check-inline"\textgreater{} \newline % Row Count 17 (+ 2) \textless{}input \newline % Row Count 18 (+ 1) type="radio" \newline % Row Count 19 (+ 1) name="like" \newline % Row Count 20 (+ 1) id="like-false" \newline % Row Count 21 (+ 1) \seqsplit{className="form-check-input"} \newline % Row Count 23 (+ 2) checked=\{book.like === false\} \newline % Row Count 25 (+ 2) onChange=\{() =\textgreater{} setBook(\{ ...book, like: false \})\} \newline % Row Count 27 (+ 2) required \newline % Row Count 28 (+ 1) /\textgreater{} \newline % Row Count 29 (+ 1) \textless{}label htmlFor="like-false" className="form-check-label"\textgreater{} \newline % Row Count 31 (+ 2) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / addBook.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ False \newline % Row Count 1 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 2 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 3 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 4 (+ 1) \textless{}button className="m-5 p-3 w-25"\textgreater{}ADD THE BOOK\textless{}/button\textgreater{} \newline % Row Count 6 (+ 2) \textless{}/form\textgreater{} \newline % Row Count 7 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 8 (+ 1) ); \newline % Row Count 9 (+ 1) \}; \newline % Row Count 10 (+ 1) export default AddBook;% Row Count 11 (+ 1) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / updateBook.jsx}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{import \{ getBookUrl \} from "../config/api"; \newline % Row Count 1 (+ 1) const UpdateBook = (\{ onUpdate = (f) =\textgreater{} f \}) =\textgreater{} \{ \newline % Row Count 2 (+ 1) const {[}book, setBook{]} = useState(\{ \newline % Row Count 3 (+ 1) title: "", \newline % Row Count 4 (+ 1) author: "", \newline % Row Count 5 (+ 1) numberInStock: "", \newline % Row Count 6 (+ 1) price: "", \newline % Row Count 7 (+ 1) rating: "", \newline % Row Count 8 (+ 1) publishYear: "", \newline % Row Count 9 (+ 1) like: "", \newline % Row Count 10 (+ 1) \}); \newline % Row Count 11 (+ 1) const \{ id \} = useParams(); \newline % Row Count 12 (+ 1) useEffect(() =\textgreater{} \{ \newline % Row Count 13 (+ 1) const fetchData = async () =\textgreater{} \{ \newline % Row Count 14 (+ 1) try \{ \newline % Row Count 15 (+ 1) const \{ data \} = await \seqsplit{axios.get(getBookUrl(id));} \newline % Row Count 17 (+ 2) const date = new \seqsplit{Date(data.publishYear).toISOString().slice(0}, 10); \newline % Row Count 19 (+ 2) setBook(\{ ...data, publishYear: date \}); //data is the existing book in the DB \newline % Row Count 21 (+ 2) \} catch (err) \{ \newline % Row Count 22 (+ 1) console.log(`There is an ERROR in fetching \$\{err.message\}`); \newline % Row Count 24 (+ 2) \} \newline % Row Count 25 (+ 1) \}; \newline % Row Count 26 (+ 1) fetchData(); \newline % Row Count 27 (+ 1) return () =\textgreater{} \{ \newline % Row Count 28 (+ 1) //clean up \newline % Row Count 29 (+ 1) \}; \newline % Row Count 30 (+ 1) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / updateBook.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ \}, {[}id{]}); \newline % Row Count 1 (+ 1) const navigate = useNavigate(); \newline % Row Count 2 (+ 1) const submitForm = (e) =\textgreater{} \{ \newline % Row Count 3 (+ 1) e.preventDefault(); \newline % Row Count 4 (+ 1) onUpdate(book); \newline % Row Count 5 (+ 1) setBook(\{ \newline % Row Count 6 (+ 1) title: "", \newline % Row Count 7 (+ 1) author: "", \newline % Row Count 8 (+ 1) numberInStock: "", \newline % Row Count 9 (+ 1) price: "", \newline % Row Count 10 (+ 1) rating: "", \newline % Row Count 11 (+ 1) publishYear: "", \newline % Row Count 12 (+ 1) like: "", \newline % Row Count 13 (+ 1) \}); \newline % Row Count 14 (+ 1) navigate("/"); \newline % Row Count 15 (+ 1) \}; \newline % Row Count 16 (+ 1) return ( \newline % Row Count 17 (+ 1) \textless{}div\textgreater{} \newline % Row Count 18 (+ 1) \textless{}h1\textgreater{}Please enter the details of the updated Book here..\textless{}/h1\textgreater{} \newline % Row Count 20 (+ 2) \textless{}form onSubmit=\{submitForm\} method="post"\textgreater{} \newline % Row Count 22 (+ 2) \textless{}div className="form-group"\textgreater{} \newline % Row Count 23 (+ 1) \textless{}label htmlFor="title" className="p-3"\textgreater{} \newline % Row Count 25 (+ 2) Book Title \newline % Row Count 26 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 27 (+ 1) \textless{}input \newline % Row Count 28 (+ 1) type="text" \newline % Row Count 29 (+ 1) name="title" \newline % Row Count 30 (+ 1) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / updateBook.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ id="title" \newline % Row Count 1 (+ 1) className="form-control" \newline % Row Count 2 (+ 1) placeholder="Enter a Title" \newline % Row Count 4 (+ 2) onChange=\{(event) =\textgreater{} setBook(\{ ...book, title: event.target.value \})\} \newline % Row Count 6 (+ 2) value=\{book.title\} \newline % Row Count 7 (+ 1) required \newline % Row Count 8 (+ 1) /\textgreater{} \newline % Row Count 9 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 10 (+ 1) \textless{}div className="form-group"\textgreater{} \newline % Row Count 11 (+ 1) \textless{}label htmlFor="author" className="p-3"\textgreater{} \newline % Row Count 13 (+ 2) Book Author \newline % Row Count 14 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 15 (+ 1) \textless{}input \newline % Row Count 16 (+ 1) type="text" \newline % Row Count 17 (+ 1) name="author" \newline % Row Count 18 (+ 1) id="author" \newline % Row Count 19 (+ 1) className="form-control" \newline % Row Count 20 (+ 1) placeholder="Enter an Author" \newline % Row Count 22 (+ 2) onChange=\{(event) =\textgreater{} setBook(\{ ...book, author: event.target.value \})\} \newline % Row Count 24 (+ 2) value=\{book.author\} \newline % Row Count 25 (+ 1) required \newline % Row Count 26 (+ 1) /\textgreater{} \newline % Row Count 27 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 28 (+ 1) \textless{}div className="form-group"\textgreater{} \newline % Row Count 29 (+ 1) \textless{}label htmlFor="numberInStock" className="p-3"\textgreater{} \newline % Row Count 31 (+ 2) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / updateBook.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ Number In Stock \newline % Row Count 1 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 2 (+ 1) \textless{}input \newline % Row Count 3 (+ 1) type="number" \newline % Row Count 4 (+ 1) name="numberInStock" \newline % Row Count 5 (+ 1) id="numberInStock" \newline % Row Count 6 (+ 1) className="form-control" \newline % Row Count 7 (+ 1) placeholder="Number In Stock" \newline % Row Count 9 (+ 2) onChange=\{(event) =\textgreater{} setBook(\{ ...book, numberInStock: event.target.value \})\} \newline % Row Count 12 (+ 3) value=\{book.numberInStock\} \newline % Row Count 14 (+ 2) required \newline % Row Count 15 (+ 1) /\textgreater{} \newline % Row Count 16 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 17 (+ 1) \textless{}div className="form-group"\textgreater{} \newline % Row Count 18 (+ 1) \textless{}label htmlFor="price" className="p-3"\textgreater{} \newline % Row Count 20 (+ 2) Book Price \newline % Row Count 21 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 22 (+ 1) \textless{}input \newline % Row Count 23 (+ 1) type="text" \newline % Row Count 24 (+ 1) name="price" \newline % Row Count 25 (+ 1) id="price" \newline % Row Count 26 (+ 1) className="form-control" \newline % Row Count 27 (+ 1) placeholder="Enter a Price" \newline % Row Count 29 (+ 2) onChange=\{(event) =\textgreater{} setBook(\{ ...book, price: event.target.value \})\} \newline % Row Count 31 (+ 2) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / updateBook.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ value=\{book.price\} \newline % Row Count 1 (+ 1) required \newline % Row Count 2 (+ 1) /\textgreater{} \newline % Row Count 3 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 4 (+ 1) \textless{}div className="form-group"\textgreater{} \newline % Row Count 5 (+ 1) \textless{}label htmlFor="rating" className="p-3"\textgreater{} \newline % Row Count 7 (+ 2) Book Rating \newline % Row Count 8 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 9 (+ 1) \textless{}input \newline % Row Count 10 (+ 1) type="number" \newline % Row Count 11 (+ 1) name="rating" \newline % Row Count 12 (+ 1) id="rating" \newline % Row Count 13 (+ 1) className="form-control" \newline % Row Count 14 (+ 1) placeholder="Enter a Rating" \newline % Row Count 16 (+ 2) onChange=\{(event) =\textgreater{} setBook(\{ ...book, rating: event.target.value \})\} \newline % Row Count 18 (+ 2) value=\{book.rating\} \newline % Row Count 19 (+ 1) required \newline % Row Count 20 (+ 1) /\textgreater{} \newline % Row Count 21 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 22 (+ 1) \textless{}div className="form-group"\textgreater{} \newline % Row Count 23 (+ 1) \textless{}label htmlFor="publishYear" className="p-3"\textgreater{} \newline % Row Count 25 (+ 2) Book Publish Year \newline % Row Count 26 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 27 (+ 1) \textless{}input \newline % Row Count 28 (+ 1) type="date" \newline % Row Count 29 (+ 1) name="publishYear" \newline % Row Count 30 (+ 1) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / updateBook.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ id="publishYear" \newline % Row Count 1 (+ 1) className="form-control" \newline % Row Count 2 (+ 1) placeholder="Enter a Publish Year" \newline % Row Count 4 (+ 2) onChange=\{(event) =\textgreater{} setBook(\{ ...book, publishYear: event.target.value \})\} \newline % Row Count 6 (+ 2) value=\{book.publishYear\} \newline % Row Count 7 (+ 1) required \newline % Row Count 8 (+ 1) /\textgreater{} \newline % Row Count 9 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 10 (+ 1) \textless{}div className="form-group"\textgreater{} \newline % Row Count 11 (+ 1) \textless{}label className="p-3 d-block"\textgreater{}Like Status (True/False)\textless{}/label\textgreater{} \newline % Row Count 13 (+ 2) \textless{}div className="form-check form-check-inline"\textgreater{} \newline % Row Count 15 (+ 2) \textless{}input \newline % Row Count 16 (+ 1) type="radio" \newline % Row Count 17 (+ 1) name="like" \newline % Row Count 18 (+ 1) id="like-true" \newline % Row Count 19 (+ 1) \seqsplit{className="form-check-input"} \newline % Row Count 21 (+ 2) checked=\{book.like === true\} \newline % Row Count 23 (+ 2) onChange=\{() =\textgreater{} setBook(\{ ...book, like: true \})\} \newline % Row Count 25 (+ 2) required \newline % Row Count 26 (+ 1) /\textgreater{} \newline % Row Count 27 (+ 1) \textless{}label htmlFor="like-true" className="form-check-label"\textgreater{} \newline % Row Count 29 (+ 2) True \newline % Row Count 30 (+ 1) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} components / updateBook.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ \textless{}/label\textgreater{} \newline % Row Count 1 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 2 (+ 1) \textless{}div className="form-check form-check-inline"\textgreater{} \newline % Row Count 4 (+ 2) \textless{}input \newline % Row Count 5 (+ 1) type="radio" \newline % Row Count 6 (+ 1) name="like" \newline % Row Count 7 (+ 1) id="like-false" \newline % Row Count 8 (+ 1) \seqsplit{className="form-check-input"} \newline % Row Count 10 (+ 2) checked=\{book.like === false\} \newline % Row Count 12 (+ 2) onChange=\{() =\textgreater{} setBook(\{ ...book, like: false \})\} \newline % Row Count 14 (+ 2) required \newline % Row Count 15 (+ 1) /\textgreater{} \newline % Row Count 16 (+ 1) \textless{}label htmlFor="like-false" className="form-check-label"\textgreater{} \newline % Row Count 18 (+ 2) False \newline % Row Count 19 (+ 1) \textless{}/label\textgreater{} \newline % Row Count 20 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 21 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 22 (+ 1) \textless{}button className="m-5 p-3 w-25"\textgreater{}UPDATE THE BOOK\textless{}/button\textgreater{} \newline % Row Count 24 (+ 2) \textless{}/form\textgreater{} \newline % Row Count 25 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 26 (+ 1) ); \newline % Row Count 27 (+ 1) \}; \newline % Row Count 28 (+ 1) export default UpdateBook;% Row Count 29 (+ 1) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} navBar.jsx}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{import \{ Link \} from "react-router-dom"; \newline % Row Count 1 (+ 1) const NavBar = () =\textgreater{} \{ \newline % Row Count 2 (+ 1) return ( \newline % Row Count 3 (+ 1) \textless{}nav className="navbar navbar-expand-lg navbar-light bg-light"\textgreater{} \newline % Row Count 5 (+ 2) \textless{}div className="collapse navbar-collapse" id="navbarNav"\textgreater{} \newline % Row Count 7 (+ 2) \textless{}ul className="navbar-nav"\textgreater{} \newline % Row Count 8 (+ 1) \textless{}li className="nav-item active"\textgreater{} \newline % Row Count 10 (+ 2) \textless{}Link className="nav-link" to="/"\textgreater{} \newline % Row Count 12 (+ 2) My Book Library \newline % Row Count 13 (+ 1) \textless{}/Link\textgreater{} \newline % Row Count 14 (+ 1) \textless{}/li\textgreater{} \newline % Row Count 15 (+ 1) \textless{}li className="nav-item"\textgreater{} \newline % Row Count 16 (+ 1) \textless{}Link className="nav-link" to="/"\textgreater{} \newline % Row Count 18 (+ 2) Books \newline % Row Count 19 (+ 1) \textless{}/Link\textgreater{} \newline % Row Count 20 (+ 1) \textless{}/li\textgreater{} \newline % Row Count 21 (+ 1) \textless{}li className="nav-item"\textgreater{} \newline % Row Count 22 (+ 1) \textless{}Link className="nav-link" to="addbook"\textgreater{} \newline % Row Count 24 (+ 2) Add a Book \newline % Row Count 25 (+ 1) \textless{}/Link\textgreater{} \newline % Row Count 26 (+ 1) \textless{}/li\textgreater{} \newline % Row Count 27 (+ 1) \textless{}/ul\textgreater{} \newline % Row Count 28 (+ 1) \textless{}/div\textgreater{} \newline % Row Count 29 (+ 1) \textless{}/nav\textgreater{} \newline % Row Count 30 (+ 1) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Client \textgreater{} navBar.jsx (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ ); \newline % Row Count 1 (+ 1) \}; \newline % Row Count 2 (+ 1) export default NavBar;% Row Count 3 (+ 1) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Server \textgreater{} config / db.js}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{import mongoose from "mongoose"; \newline % Row Count 1 (+ 1) import \{ url \} from "../atlas\_uri.js"; \newline % Row Count 2 (+ 1) export const connectDB = async () =\textgreater{} \{ \newline % Row Count 3 (+ 1) try \{ \newline % Row Count 4 (+ 1) await mongoose.connect(url); \newline % Row Count 5 (+ 1) console.log("Connected to DB"); \newline % Row Count 6 (+ 1) \} catch (err) \{ \newline % Row Count 7 (+ 1) console.log(`ERROR in connecting: \$\{err.message\}`); \newline % Row Count 9 (+ 2) process.exit(1); //exit in case of failure \newline % Row Count 11 (+ 2) \} \newline % Row Count 12 (+ 1) \}; \newline % Row Count 13 (+ 1) export const disconnectDB = async () =\textgreater{} \{ \newline % Row Count 14 (+ 1) await \seqsplit{mongoose.connection.close();} \newline % Row Count 15 (+ 1) console.log("Connection closed"); \newline % Row Count 16 (+ 1) \};% Row Count 17 (+ 1) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Server \textgreater{} models / books.js}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{import mongoose from "mongoose"; \newline % Row Count 1 (+ 1) const bookSchema = new mongoose.Schema(\{ \newline % Row Count 2 (+ 1) title: \{ \newline % Row Count 3 (+ 1) type: String, \newline % Row Count 4 (+ 1) required: {[}true, "Please check your entry, no title specified."{]}, \newline % Row Count 6 (+ 2) \}, \newline % Row Count 7 (+ 1) author: \{ \newline % Row Count 8 (+ 1) type: String, \newline % Row Count 9 (+ 1) required: {[}true, "Please check your entry, no author specified."{]}, \newline % Row Count 11 (+ 2) \}, \newline % Row Count 12 (+ 1) numberInStock: \{ \newline % Row Count 13 (+ 1) type: Number, \newline % Row Count 14 (+ 1) required: {[}true, "Number in Stock is missing. Please provide a value."{]}, \newline % Row Count 16 (+ 2) \}, \newline % Row Count 17 (+ 1) price: Number, \newline % Row Count 18 (+ 1) rating: \{ \newline % Row Count 19 (+ 1) type: Number, \newline % Row Count 20 (+ 1) min: 1, \newline % Row Count 21 (+ 1) max: 10, \newline % Row Count 22 (+ 1) required: {[}true, "The rating is required, please specify a value between 1-100."{]}, \newline % Row Count 24 (+ 2) \}, \newline % Row Count 25 (+ 1) publishYear: \{ \newline % Row Count 26 (+ 1) type: Date, \newline % Row Count 27 (+ 1) default: Date.now, // No parentheses to ensure execution at creation time \newline % Row Count 29 (+ 2) \}, \newline % Row Count 30 (+ 1) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Server \textgreater{} models / books.js (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ like: Boolean, \newline % Row Count 1 (+ 1) \}); \newline % Row Count 2 (+ 1) export const Book = mongoose.model("Book", bookSchema);% Row Count 4 (+ 2) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Server \textgreater{} server.js}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{import express from "express"; \newline % Row Count 1 (+ 1) import \{ connectDB \} from "./config/db.js"; \newline % Row Count 2 (+ 1) import router from \seqsplit{"./routes/basicRoutes.js";} \newline % Row Count 3 (+ 1) import cors from "cors"; \newline % Row Count 4 (+ 1) //1. create an express application \newline % Row Count 5 (+ 1) const app = express(); \newline % Row Count 6 (+ 1) //2. set up all the middlewares \newline % Row Count 7 (+ 1) app.use(express.urlencoded(\{ extended: true \})); \newline % Row Count 8 (+ 1) app.use(express.json()); \newline % Row Count 9 (+ 1) \seqsplit{app.use(express.static("public"));} \newline % Row Count 10 (+ 1) app.use(cors()); \newline % Row Count 11 (+ 1) //3. connect to the database \newline % Row Count 12 (+ 1) connectDB(); \newline % Row Count 13 (+ 1) //4. set up the routes \newline % Row Count 14 (+ 1) app.use("/", router); \newline % Row Count 15 (+ 1) //5. make your server listen to port 3000 \newline % Row Count 16 (+ 1) const PORT = process.env.PORT || 3000; \newline % Row Count 17 (+ 1) app.listen(PORT, () =\textgreater{} \{ \newline % Row Count 18 (+ 1) console.log(`The server is up and listening on PORT\$\{PORT\}`); \newline % Row Count 20 (+ 2) \});% Row Count 21 (+ 1) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Server \textgreater{} routes / basicRoutes.js}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{import express from "express"; \newline % Row Count 1 (+ 1) import \{ Book \} from "../models/books.js"; \newline % Row Count 2 (+ 1) const router = express.Router(); \newline % Row Count 3 (+ 1) //GET ALL BOOKS - READ OPERATION \newline % Row Count 4 (+ 1) router.get("/books", async (req, res) =\textgreater{} \{ \newline % Row Count 5 (+ 1) try \{ \newline % Row Count 6 (+ 1) const books = await Book.find(); \newline % Row Count 7 (+ 1) if (books.length === 0) \{ \newline % Row Count 8 (+ 1) return res.status(404).json(\{ error: "There are no books." \}); \newline % Row Count 10 (+ 2) \} \newline % Row Count 11 (+ 1) res.json(books); \newline % Row Count 12 (+ 1) \} catch (err) \{ \newline % Row Count 13 (+ 1) //500 -{}-\textgreater{} Internal Server Error \newline % Row Count 14 (+ 1) res.status(500).json(\{ error: err.message \}); \newline % Row Count 16 (+ 2) \} \newline % Row Count 17 (+ 1) \}); \newline % Row Count 18 (+ 1) //GET ONE BOOK - READ OPERATION \newline % Row Count 19 (+ 1) router.get("/books/:id", async (req, res) =\textgreater{} \{ \newline % Row Count 20 (+ 1) const \{ id \} = req.params; \newline % Row Count 21 (+ 1) try \{ \newline % Row Count 22 (+ 1) // const book = await Book.findById(id); \newline % Row Count 23 (+ 1) // const book = await Book.findOne(\{"title":"Eloquent JavaScript"\}); \newline % Row Count 25 (+ 2) const book = await Book.findOne(\{ \_id: id \}); \newline % Row Count 27 (+ 2) if (!book) \{ \newline % Row Count 28 (+ 1) return res.status(404).json(\{ error: "There are no such book." \}); \newline % Row Count 30 (+ 2) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Server \textgreater{} routes / basicRoutes.js (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ \} \newline % Row Count 1 (+ 1) res.json(book); \newline % Row Count 2 (+ 1) \} catch (err) \{ \newline % Row Count 3 (+ 1) //500 -{}-\textgreater{} Internal Server Error \newline % Row Count 4 (+ 1) res.status(500).json(\{ error: err.message \}); \newline % Row Count 6 (+ 2) \} \newline % Row Count 7 (+ 1) \}); \newline % Row Count 8 (+ 1) //POST BOOK - CREATE OPERATION \newline % Row Count 9 (+ 1) router.post("/books", async (req, res) =\textgreater{} \{ \newline % Row Count 10 (+ 1) try \{ \newline % Row Count 11 (+ 1) const book = new Book(req.body); \newline % Row Count 12 (+ 1) const savedBook = await book.save(); \newline % Row Count 13 (+ 1) \seqsplit{res.status(201).json(savedBook);} \newline % Row Count 14 (+ 1) \} catch (err) \{ \newline % Row Count 15 (+ 1) //500 -{}-\textgreater{} Internal Server Error \newline % Row Count 16 (+ 1) res.status(500).json(\{ error: err.message \}); \newline % Row Count 18 (+ 2) \} \newline % Row Count 19 (+ 1) \}); \newline % Row Count 20 (+ 1) //PUT BOOK - UPDATE OPERATION \newline % Row Count 21 (+ 1) router.put("/books/:id", async (req, res) =\textgreater{} \{ \newline % Row Count 22 (+ 1) const \{ id \} = req.params; \newline % Row Count 23 (+ 1) try \{ \newline % Row Count 24 (+ 1) const upatedBook = await \seqsplit{Book.findByIdAndUpdate(id}, req.body, \{ new: true, runValidators: true \}); \newline % Row Count 27 (+ 3) if (!upatedBook) \{ \newline % Row Count 28 (+ 1) return res.status(404).json(\{ error: "There are no such book." \}); \newline % Row Count 30 (+ 2) } \tn \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Server \textgreater{} routes / basicRoutes.js (cont)}} \tn \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{ \} \newline % Row Count 1 (+ 1) res.json(upatedBook); \newline % Row Count 2 (+ 1) \} catch (err) \{ \newline % Row Count 3 (+ 1) //500 -{}-\textgreater{} Internal Server Error \newline % Row Count 4 (+ 1) res.status(500).json(\{ error: err.message \}); \newline % Row Count 6 (+ 2) \} \newline % Row Count 7 (+ 1) \}); \newline % Row Count 8 (+ 1) //DELETE BOOK - DELETE OPERATION \newline % Row Count 9 (+ 1) \seqsplit{router.delete("/books/:id"}, async (req, res) =\textgreater{} \{ \newline % Row Count 10 (+ 1) const \{ id \} = req.params; \newline % Row Count 11 (+ 1) try \{ \newline % Row Count 12 (+ 1) const deletedBook = await \seqsplit{Book.findByIdAndDelete(id);} \newline % Row Count 14 (+ 2) if (!deletedBook) \{ \newline % Row Count 15 (+ 1) return res.status(404).json(\{ error: "There are no such book." \}); \newline % Row Count 17 (+ 2) \} \newline % Row Count 18 (+ 1) res.json(deletedBook); \newline % Row Count 19 (+ 1) \} catch (err) \{ \newline % Row Count 20 (+ 1) //500 -{}-\textgreater{} Internal Server Error \newline % Row Count 21 (+ 1) res.status(500).json(\{ error: err.message \}); \newline % Row Count 23 (+ 2) \} \newline % Row Count 24 (+ 1) \}); \newline % Row Count 25 (+ 1) export default router;% Row Count 26 (+ 1) } \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} % That's all folks \end{multicols*} \end{document}