{"version":3,"sources":["store.js","app.js","context/query-client.js","context/index.js","dev-tools/load.js","index.js","test/data/books.js","test/data/users.js","test/data/list-items.js","test/server/server-handlers.js","test/server/dev-server.js","styles/colors.js","utils/api-client.js","auth-provider.js","reducers/userSlice.js","components/lib.js","reducers/listItemSlice.js","components/profiler.js","styles/media-queries.js","assets/book-placeholder.svg","reducers/bookSlice.js","test/server/index.js"],"names":["logAllActionsMiddleware","storeAPI","next","action","console","group","type","log","getState","returnValue","groupEnd","store","configureStore","reducer","user","userSlice","book","bookSlice","listItem","listItemSlice","middleware","getDefaultMiddleware","concat","AuthenticatedApp","React","UnauthenticatedApp","a","userState","status","error","listItemState","listItems","auth","token","client","dispatch","refetchUser","refetchListItem","App","useSelector","selectUser","getRefetchData","isError","fallback","QueryClientProvider","children","queryClient","useConstant","initializer","QueryClient","defaultOptions","queries","useErrorBoundary","refetchOnWindowFocus","retry","failureCount","mutations","onError","err","variables","recover","window","__devtools","setQueryClient","AppProviders","loadDevTools","callback","url","URL","location","setInUrl","searchParams","has","urlEnabled","get","go","localStorageValue","localStorage","getItem","undefined","Cypress","then","devTools","install","ReactDOM","render","id","phases","document","getElementById","books","booksData","read","bookId","find","readManyNotInList","ids","filter","includes","query","search","matchSorter","keys","threshold","rankings","CONTAINS","key","usersKey","users","persist","setItem","JSON","stringify","load","Object","assign","parse","validateUserForm","username","password","Error","length","authenticate","hash","passwordHash","sanitizeUser","btoa","create","validateUser","str","i","charCodeAt","String","__bookshelf","purgeUsers","forEach","sleep","listItemsKey","authorize","userId","listItemId","ownerId","required","rating","notes","startDate","Date","now","finishDate","booksDB","validateListItem","update","updates","remove","readByOwner","values","li","ls","defaultVal","val","lsVal","Number","isFinite","purgeListItems","process","CI","Promise","resolve","t","Math","random","setTimeout","apiUrl","authUrl","handlers","rest","post","req","res","ctx","body","usersDB","json","userFields","message","getUser","getToken","listItemsDB","lis","all","map","listItemsAndBooks","fetch","matchingBooks","getBooksNotInUsersList","allBooks","slice","params","put","updatedListItem","success","handler","originalResolver","resolver","shouldFail","result","toString","failureRate","requestMatchesFailConfig","configMatches","requestMethod","urlMatch","method","match","pathname","matches","some","removeItem","headers","replace","atob","bookIdsInUsersList","fullUrl","homepage","server","setupWorker","start","quiet","serviceWorker","base","text","gray","gray10","gray20","gray80","indigo","indigoDarken10","yellow","green","danger","orange","apiURL","endpoint","data","customHeaders","customConfig","config","Authorization","response","reject","ok","localStorageKey","handleUserResponse","login","register","logout","authURL","Status","initialState","createAsyncThunk","form","createSlice","name","reducers","state","payload","resetError","extraReducers","builder","addCase","pending","fulfilled","rejected","actions","stateStore","spin","keyframes","transform","CircleButton","borderRadius","padding","width","height","lineHeight","display","alignItems","justifyContent","background","colors","color","border","cursor","BookListUL","Spinner","FaSpinner","animation","defaultProps","buttonVariants","primary","secondary","Button","variant","inputStyles","Input","Textarea","Dialog","ReachDialog","maxWidth","paddingBottom","boxShadow","margin","mq","FormGroup","FullPageSpinner","css","fontSize","flexDirection","Link","RouterLink","textDecoration","errorMessageVariants","stacked","inline","ErrorMessage","props","role","whiteSpace","marginBottom","FullPageErrorFallback","oldListItem","getListItem","addListItem","updateListItem","removeListItem","meta","arg","unshift","index","indexOf","splice","selectListItemState","selectStatusListItem","selectErrorListItem","queue","Profiler","metadata","onRender","reportProfile","phase","actualDuration","baseDuration","startTime","commitTime","interactions","push","setInterval","sendProfileQueue","queueToSend","small","loadingBook","title","author","coverImageUrl","bookPlaceholderSvg","publisher","synopsis","loadingBooks","Array","from","v","getBookListByQuery","encodeURIComponent","getBook","selectCurrentBook","selectError","selectBookState","module","exports","require"],"mappings":"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","file":"static/js/main.4947da96.chunk.js","sourcesContent":["import { configureStore } from '@reduxjs/toolkit';\nimport userSlice from 'reducers/userSlice';\nimport bookSlice from 'reducers/bookSlice';\nimport listItemSlice from 'reducers/listItemSlice';\n// middleware that log all actions\nconst logAllActionsMiddleware = (storeAPI) => (next) => (action) => {\n console.group(action.type);\n console.log('%c prev state', 'color: gray', storeAPI.getState());\n console.log('%c action', 'color: blue', action);\n const returnValue = next(action);\n console.log('%c next state', 'color: green', storeAPI.getState());\n console.groupEnd(action.type);\n return returnValue;\n};\n\nconst store = configureStore({\n reducer: {\n user: userSlice,\n book: bookSlice,\n listItem: listItemSlice,\n },\n middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logAllActionsMiddleware),\n});\n\nexport default store;\n","import * as React from 'react';\nimport { useSelector } from 'react-redux';\nimport { selectUser, refetchUser } from 'reducers/userSlice';\nimport { FullPageSpinner, FullPageErrorFallback } from 'components/lib';\n\nimport { client } from 'utils/api-client';\nimport store from 'store';\nimport * as auth from 'auth-provider';\nimport { refetchListItem } from 'reducers/listItemSlice';\n\nconst AuthenticatedApp = React.lazy(() => import(/* webpackPrefetch: true */ './authenticated-app'));\nconst UnauthenticatedApp = React.lazy(() => import('./unauthenticated-app'));\n\nasync function getRefetchData() {\n const userState = {\n status: 'pending', user: null, error: null,\n };\n const listItemState = {\n status: 'pending',\n listItems: [],\n };\n try {\n const token = await auth.getToken();\n if (token) {\n const { user, listItems } = await client('bootstrap', { token });\n userState.user = user;\n listItemState.listItems = listItems;\n }\n userState.status = 'resolved';\n listItemState.status = 'resolved';\n store.dispatch(refetchUser(userState));\n store.dispatch(refetchListItem(listItemState));\n } catch (error) {\n userState.status = 'rejectedApp';\n userState.error = error;\n store.dispatch(refetchUser(userState));\n }\n}\n\nfunction App() {\n const { status, user, error } = useSelector(selectUser);\n\n React.useEffect(() => {\n getRefetchData();\n }, []);\n\n const isIdle = status === 'idle';\n const isError = status === 'rejectedApp';\n if (isIdle) {\n return ;\n }\n\n if (isError) {\n return ;\n }\n\n return (\n }>\n {user ? : }\n \n );\n}\n\nexport { App };\n","import * as React from 'react';\nimport { QueryClient, QueryClientProvider as RQProvider } from 'react-query';\n\n/**\n * This is a clever little \"hack\" to make sure we make only one instance of\n * something for a given instance of the component. We store it in\n * lazily-initialized state and only return the state value and ignore the\n * state updater. This is the simplest way to do this.\n *\n * @param {Function} initializer A callback to initialize the value\n * @returns a constant value returned from the initializer\n */\nfunction useConstant(initializer) {\n return React.useState(initializer)[0];\n}\n\nfunction QueryClientProvider({ children }) {\n const queryClient = useConstant(() => {\n const client = new QueryClient({\n defaultOptions: {\n queries: {\n useErrorBoundary: true,\n refetchOnWindowFocus: false,\n retry(failureCount, error) {\n if (error.status === 404) return false;\n if (failureCount < 2) return true;\n return false;\n },\n },\n mutations: {\n onError: (err, variables, recover) => (typeof recover === 'function' ? recover() : null),\n },\n },\n });\n // let the devtools know about our new query client\n // if the devtools are installed:\n window.__devtools?.setQueryClient?.(client);\n return client;\n });\n\n return {children};\n}\n\nexport { QueryClientProvider };\n","import * as React from 'react';\nimport { BrowserRouter as Router } from 'react-router-dom';\nimport { Provider } from 'react-redux';\nimport store from 'store';\nimport { QueryClientProvider } from './query-client';\n\nfunction AppProviders({ children }) {\n return (\n \n \n \n {children}\n \n \n \n );\n}\n\nexport { AppProviders };\n","function loadDevTools(callback) {\n // check URL first\n const url = new URL(window.location);\n const setInUrl = url.searchParams.has('dev-tools');\n const urlEnabled = url.searchParams.get('dev-tools') === 'true';\n if (setInUrl) {\n if (urlEnabled) {\n return go();\n }\n return callback();\n }\n\n // the check localStorage\n const localStorageValue = window.localStorage.getItem('dev-tools');\n const setInLocalStorage = localStorageValue != undefined;\n const localStorageEnabled = localStorageValue === 'true';\n if (setInLocalStorage) {\n if (localStorageEnabled) {\n return go();\n }\n return callback();\n }\n\n // the default is off in Cypress\n if (window.Cypress) return callback();\n\n // the default is on in development\n if (process.env.NODE_ENV === 'development') return go();\n\n return callback();\n\n function go() {\n // use a dynamic import so the dev-tools code isn't bundled with the regular\n // app code so we don't worry about bundle size.\n import('./dev-tools')\n .then((devTools) => devTools.install())\n .finally(callback);\n }\n}\n\nexport { loadDevTools };\n\n/*\neslint\n eqeqeq: \"off\",\n*/\n","import './bootstrap';\nimport * as React from 'react';\nimport ReactDOM from 'react-dom';\nimport { Profiler } from 'components/profiler';\nimport { App } from './app';\nimport { loadDevTools } from './dev-tools/load';\nimport { AppProviders } from './context';\n\nloadDevTools(() => {\n ReactDOM.render(\n \n \n \n \n ,\n document.getElementById('root'),\n );\n});\n","import { matchSorter } from 'match-sorter';\nimport booksData from './books-data.json';\n\nlet books = [...booksData];\n\nasync function create(book) {\n books.push(book);\n return book;\n}\n\nasync function read(bookId) {\n return books.find((book) => book.id === bookId);\n}\n\nasync function readManyNotInList(ids) {\n return books.filter((book) => !ids.includes(book.id));\n}\n\nasync function query(search) {\n return matchSorter(books, search, {\n keys: [\n 'title',\n 'author',\n 'publisher',\n { threshold: matchSorter.rankings.CONTAINS, key: 'synopsis' },\n ],\n });\n}\n\nasync function reset() {\n books = [...booksData];\n}\n\nexport {\n create, query, read, readManyNotInList, reset,\n};\n","const usersKey = '__bookshelf_users__';\nlet users = {};\nconst persist = () => window.localStorage.setItem(usersKey, JSON.stringify(users));\nconst load = () => Object.assign(users, JSON.parse(window.localStorage.getItem(usersKey)));\n\n// initialize\ntry {\n load();\n} catch (error) {\n persist();\n // ignore json parse error\n}\n\nwindow.__bookshelf = window.__bookshelf || {};\nwindow.__bookshelf.purgeUsers = () => {\n Object.keys(users).forEach((key) => {\n delete users[key];\n });\n persist();\n};\n\nfunction validateUserForm({ username, password }) {\n if (!username) {\n const error = new Error('A username is required');\n error.status = 400;\n throw error;\n }\n if (!password) {\n const error = new Error('A password is required');\n error.status = 400;\n throw error;\n }\n if (password.length < 6) {\n const error = new Error('Password must be at least 6 characters');\n error.status = 400;\n throw error;\n }\n}\n\nasync function authenticate({ username, password }) {\n validateUserForm({ username, password });\n const id = hash(username);\n const user = users[id] || {};\n if (user.passwordHash === hash(password)) {\n return { ...sanitizeUser(user), token: btoa(user.id) };\n }\n const error = new Error('Invalid username or password');\n error.status = 400;\n throw error;\n}\n\nasync function create({ username, password }) {\n validateUserForm({ username, password });\n const id = hash(username);\n const passwordHash = hash(password);\n if (users[id]) {\n const error = new Error(\n `Cannot create a new user with the username \"${username}\"`,\n );\n error.status = 400;\n throw error;\n }\n users[id] = { id, username, passwordHash };\n persist();\n return read(id);\n}\n\nasync function read(id) {\n validateUser(id);\n return sanitizeUser(users[id]);\n}\n\nfunction sanitizeUser(user) {\n const { passwordHash, ...rest } = user;\n return rest;\n}\n\nasync function update(id, updates) {\n validateUser(id);\n Object.assign(users[id], updates);\n persist();\n return read(id);\n}\n\n// this would be called `delete` except that's a reserved word in JS :-(\nasync function remove(id) {\n validateUser(id);\n delete users[id];\n persist();\n}\n\nfunction validateUser(id) {\n load();\n if (!users[id]) {\n const error = new Error(`No user with the id \"${id}\"`);\n error.status = 404;\n throw error;\n }\n}\n\nfunction hash(str) {\n let hash = 5381;\n let i = str.length;\n\n while (i) {\n hash = (hash * 33) ^ str.charCodeAt(--i);\n }\n return String(hash >>> 0);\n}\n\nasync function reset() {\n users = {};\n persist();\n}\n\nexport {\n authenticate, create, read, update, remove, reset,\n};\n","import * as booksDB from './books';\n\nconst listItemsKey = '__bookshelf_list_items__';\nlet listItems = {};\nconst persist = () => window.localStorage.setItem(listItemsKey, JSON.stringify(listItems));\nconst load = () => Object.assign(\n listItems,\n JSON.parse(window.localStorage.getItem(listItemsKey)),\n);\n\n// initialize\ntry {\n load();\n} catch (error) {\n persist();\n // ignore json parse error\n}\n\nwindow.__bookshelf = window.__bookshelf || {};\nwindow.__bookshelf.purgeListItems = () => {\n Object.keys(listItems).forEach((key) => {\n delete listItems[key];\n });\n persist();\n};\n\nasync function authorize(userId, listItemId) {\n const listItem = await read(listItemId);\n if (listItem.ownerId !== userId) {\n const error = new Error('User is not authorized to view that list');\n error.status = 403;\n throw error;\n }\n}\n\nasync function create({\n bookId = required('bookId'),\n ownerId = required('ownerId'),\n rating = -1,\n notes = '',\n startDate = Date.now(),\n finishDate = null,\n}) {\n const id = hash(`${bookId}${ownerId}`);\n if (listItems[id]) {\n const error = new Error(\n 'This user cannot create new list item for that book',\n );\n error.status = 400;\n throw error;\n }\n const book = await booksDB.read(bookId);\n if (!book) {\n const error = new Error(`No book found with the ID of ${bookId}`);\n error.status = 400;\n throw error;\n }\n listItems[id] = {\n id, bookId, ownerId, rating, notes, finishDate, startDate,\n };\n persist();\n return read(id);\n}\n\nasync function read(id) {\n validateListItem(id);\n return listItems[id];\n}\n\nasync function update(id, updates) {\n validateListItem(id);\n Object.assign(listItems[id], updates);\n persist();\n return read(id);\n}\n\n// this would be called `delete` except that's a reserved word in JS :-(\nasync function remove(id) {\n validateListItem(id);\n delete listItems[id];\n persist();\n}\n\nasync function readMany(userId, listItemIds) {\n return Promise.all(\n listItemIds.map((id) => {\n authorize(userId, id);\n return read(id);\n }),\n );\n}\n\nasync function readByOwner(userId) {\n return Object.values(listItems).filter((li) => li.ownerId === userId);\n}\n\nfunction validateListItem(id) {\n load();\n if (!listItems[id]) {\n const error = new Error(`No list item with the id \"${id}\"`);\n error.status = 404;\n throw error;\n }\n}\n\nfunction hash(str) {\n let hash = 5381;\n let i = str.length;\n\n while (i) {\n hash = (hash * 33) ^ str.charCodeAt(--i);\n }\n return String(hash >>> 0);\n}\n\nfunction required(key) {\n const error = new Error(`${key} is required`);\n error.status = 400;\n throw error;\n}\n\nasync function reset() {\n listItems = {};\n persist();\n}\n\nexport {\n authorize, create, read, update, remove, readMany, readByOwner, reset,\n};\n","import { rest } from 'msw';\nimport { match } from 'node-match-path';\nimport * as booksDB from 'test/data/books';\nimport * as usersDB from 'test/data/users';\nimport * as listItemsDB from 'test/data/list-items';\n\nlet sleep;\nif (process.env.CI) {\n sleep = () => Promise.resolve();\n} else if (process.env.NODE_ENV === 'test') {\n sleep = () => Promise.resolve();\n} else {\n sleep = (\n t = Math.random() * ls('__bookshelf_variable_request_time__', 400)\n + ls('__bookshelf_min_request_time__', 400),\n ) => new Promise((resolve) => setTimeout(resolve, t));\n}\n\nfunction ls(key, defaultVal) {\n const lsVal = window.localStorage.getItem(key);\n let val;\n if (lsVal) {\n val = Number(lsVal);\n }\n return Number.isFinite(val) ? val : defaultVal;\n}\n\nconst apiUrl = process.env.REACT_APP_API_URL;\nconst authUrl = process.env.REACT_APP_AUTH_URL;\n\nconst handlers = [\n rest.post(`${authUrl}/login`, async (req, res, ctx) => {\n const { username, password } = req.body;\n const user = await usersDB.authenticate({ username, password });\n return res(ctx.json({ user }));\n }),\n\n rest.post(`${authUrl}/register`, async (req, res, ctx) => {\n const { username, password } = req.body;\n const userFields = { username, password };\n await usersDB.create(userFields);\n let user;\n try {\n user = await usersDB.authenticate(userFields);\n } catch (error) {\n return res(\n ctx.status(400),\n ctx.json({ status: 400, message: error.message }),\n );\n }\n return res(ctx.json({ user }));\n }),\n\n rest.get(`${apiUrl}/me`, async (req, res, ctx) => {\n const user = await getUser(req);\n const token = getToken(req);\n return res(ctx.json({ user: { ...user, token } }));\n }),\n\n rest.get(`${apiUrl}/bootstrap`, async (req, res, ctx) => {\n const user = await getUser(req);\n const token = getToken(req);\n const lis = await listItemsDB.readByOwner(user.id);\n const listItemsAndBooks = await Promise.all(\n lis.map(async (listItem) => ({\n ...listItem,\n book: await booksDB.read(listItem.bookId),\n })),\n );\n return res(ctx.json({ user: { ...user, token }, listItems: listItemsAndBooks }));\n }),\n\n rest.get(`${apiUrl}/books`, async (req, res, ctx) => {\n if (!req.url.searchParams.has('query')) {\n return ctx.fetch(req);\n }\n const query = req.url.searchParams.get('query');\n\n let matchingBooks = [];\n if (query) {\n matchingBooks = await booksDB.query(query);\n } else if (getToken(req)) {\n const user = await getUser(req);\n const allBooks = await getBooksNotInUsersList(user.id);\n // return a random assortment of 10 books not already in the user's list\n matchingBooks = allBooks.slice(0, 10);\n } else {\n const allBooks = await booksDB.readManyNotInList([]);\n matchingBooks = allBooks.slice(0, 10);\n }\n\n return res(ctx.json({ books: matchingBooks }));\n }),\n\n rest.get(`${apiUrl}/books/:bookId`, async (req, res, ctx) => {\n const { bookId } = req.params;\n const book = await booksDB.read(bookId);\n if (!book) {\n return res(\n ctx.status(404),\n ctx.json({ status: 404, message: 'Book not found' }),\n );\n }\n return res(ctx.json({ book }));\n }),\n\n rest.get(`${apiUrl}/list-items`, async (req, res, ctx) => {\n const user = await getUser(req);\n const lis = await listItemsDB.readByOwner(user.id);\n const listItemsAndBooks = await Promise.all(\n lis.map(async (listItem) => ({\n ...listItem,\n book: await booksDB.read(listItem.bookId),\n })),\n );\n return res(ctx.json({ listItems: listItemsAndBooks }));\n }),\n\n rest.post(`${apiUrl}/list-items`, async (req, res, ctx) => {\n const user = await getUser(req);\n const { bookId } = req.body;\n const listItem = await listItemsDB.create({\n ownerId: user.id,\n bookId,\n });\n const book = await booksDB.read(bookId);\n return res(ctx.json({ listItem: { ...listItem, book } }));\n }),\n\n rest.put(`${apiUrl}/list-items/:listItemId`, async (req, res, ctx) => {\n const user = await getUser(req);\n const { listItemId } = req.params;\n const updates = req.body;\n await listItemsDB.authorize(user.id, listItemId);\n const updatedListItem = await listItemsDB.update(listItemId, updates);\n const book = await booksDB.read(updatedListItem.bookId);\n return res(ctx.json({ listItem: { ...updatedListItem, book } }));\n }),\n\n rest.delete(`${apiUrl}/list-items/:listItemId`, async (req, res, ctx) => {\n const user = await getUser(req);\n const { listItemId } = req.params;\n await listItemsDB.authorize(user.id, listItemId);\n await listItemsDB.remove(listItemId);\n return res(ctx.json({ success: true }));\n }),\n\n rest.post(`${apiUrl}/profile`, async (req, res, ctx) => res(ctx.json({ success: true }))),\n].map((handler) => {\n const originalResolver = handler.resolver;\n handler.resolver = async function resolver(req, res, ctx) {\n try {\n if (shouldFail(req)) {\n throw new Error('Request failure (for testing purposes).');\n }\n const result = await originalResolver(req, res, ctx);\n return result;\n } catch (error) {\n const status = error.status || 500;\n return res(\n ctx.status(status),\n ctx.json({ status, message: error.message || 'Unknown Error' }),\n );\n } finally {\n await sleep();\n }\n };\n return handler;\n});\n\nfunction shouldFail(req) {\n if (JSON.stringify(req.body)?.includes('FAIL')) return true;\n if (req.url.searchParams.toString()?.includes('FAIL')) return true;\n if (process.env.NODE_ENV === 'test') return false;\n const failureRate = Number(\n window.localStorage.getItem('__bookshelf_failure_rate__') || 0,\n );\n if (Math.random() < failureRate) return true;\n if (requestMatchesFailConfig(req)) return true;\n\n return false;\n}\n\nfunction requestMatchesFailConfig(req) {\n function configMatches({ requestMethod, urlMatch }) {\n return (\n (requestMethod === 'ALL' || req.method === requestMethod)\n && match(urlMatch, req.url.pathname).matches\n );\n }\n try {\n const failConfig = JSON.parse(\n window.localStorage.getItem('__bookshelf_request_fail_config__') || '[]',\n );\n if (failConfig.some(configMatches)) return true;\n } catch (error) {\n window.localStorage.removeItem('__bookshelf_request_fail_config__');\n }\n return false;\n}\n\nconst getToken = (req) => req.headers.get('Authorization')?.replace('Bearer ', '');\n\nasync function getUser(req) {\n const token = getToken(req);\n if (!token) {\n const error = new Error('A token must be provided');\n error.status = 401;\n throw error;\n }\n let userId;\n try {\n userId = atob(token);\n } catch (e) {\n const error = new Error('Invalid token. Please login again.');\n error.status = 401;\n throw error;\n }\n const user = await usersDB.read(userId);\n return user;\n}\n\nasync function getBooksNotInUsersList(userId) {\n const bookIdsInUsersList = (await listItemsDB.readByOwner(userId)).map(\n (li) => li.bookId,\n );\n const books = await booksDB.readManyNotInList(bookIdsInUsersList);\n return books;\n}\n\nexport { handlers };\n","import { setupWorker } from 'msw';\nimport { handlers } from './server-handlers';\nimport { homepage } from '../../../package.json';\n\nconst fullUrl = new URL(homepage);\n\nconst server = setupWorker(...handlers);\n\nserver.start({\n quiet: true,\n serviceWorker: {\n url: `${fullUrl.pathname}mockServiceWorker.js`,\n },\n});\n\nexport * from 'msw';\nexport { server };\n","export const base = 'white';\nexport const text = '#434449';\nexport const gray = '#f1f2f7';\nexport const gray10 = '#f1f1f4';\nexport const gray20 = '#e4e5e9';\nexport const gray80 = '#6f7077';\nexport const indigo = '#3f51b5';\nexport const indigoDarken10 = '#364495';\nexport const indigoLighten80 = '#b7c1f8';\nexport const yellow = '#ffc107';\nexport const green = '#4caf50';\nexport const danger = '#ef5350';\nexport const orange = 'orange';\n","import * as auth from 'auth-provider';\n\nconst apiURL = process.env.REACT_APP_API_URL;\n\nasync function client(\n endpoint,\n {\n data, headers: customHeaders, ...customConfig\n } = {},\n) {\n const token = await auth.getToken();\n const config = {\n method: data ? 'POST' : 'GET',\n body: data ? JSON.stringify(data) : undefined,\n headers: {\n Authorization: token ? `Bearer ${token}` : undefined,\n 'Content-Type': data ? 'application/json' : undefined,\n ...customHeaders,\n },\n ...customConfig,\n };\n\n return window.fetch(`${apiURL}/${endpoint}`, config).then(async (response) => {\n if (response.status === 401) {\n await auth.logout();\n // refresh the page for them\n window.location.assign('/authentication');\n // eslint-disable-next-line prefer-promise-reject-errors\n return Promise.reject({ message: 'Please re-authenticate.' });\n }\n const data = await response.json();\n if (response.ok) {\n return data;\n }\n return Promise.reject(data);\n });\n}\n\nexport { client };\n","// pretend this is firebase, netlify, or auth0's code.\n// you shouldn't have to implement something like this in your own app\n\nconst localStorageKey = '__auth_provider_token__';\n\nasync function getToken() {\n // if we were a real auth provider, this is where we would make a request\n // to retrieve the user's token. (It's a bit more complicated than that...\n // but you're probably not an auth provider so you don't need to worry about it).\n return window.localStorage.getItem(localStorageKey);\n}\n\nfunction handleUserResponse({ user }) {\n window.localStorage.setItem(localStorageKey, user.token);\n return user;\n}\n\nfunction login({ username, password }) {\n return client('login', { username, password }).then(handleUserResponse);\n}\n\nfunction register({ username, password }) {\n return client('register', { username, password }).then(handleUserResponse);\n}\n\nasync function logout() {\n window.localStorage.removeItem(localStorageKey);\n}\n\n// an auth provider wouldn't use your client, they'd have their own\n// so that's why we're not just re-using the client\nconst authURL = process.env.REACT_APP_AUTH_URL;\n\nasync function client(endpoint, data) {\n const config = {\n method: 'POST',\n body: JSON.stringify(data),\n headers: { 'Content-Type': 'application/json' },\n };\n\n return window.fetch(`${authURL}/${endpoint}`, config).then(async (response) => {\n const data = await response.json();\n if (response.ok) {\n return data;\n }\n return Promise.reject(data);\n });\n}\n\nexport {\n getToken, login, register, logout, localStorageKey,\n};\n","import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';\nimport * as auth from 'auth-provider';\n\nconst Status = {\n IDLE: 'idle',\n PENDING: 'pending',\n RESOLVED: 'resolved',\n REJECTED: 'rejectedUnauthenticated',\n};\nconst initialState = {\n status: Status.IDLE,\n user: null,\n error: null,\n};\n\nconst login = createAsyncThunk('user/login', async (form) => {\n const user = await auth.login(form);\n return user;\n});\n\nconst register = createAsyncThunk('user/register', async (form) => {\n const user = await auth.register(form);\n return user;\n});\n\nexport const userSlice = createSlice({\n name: 'user',\n initialState,\n reducers: {\n refetchUser: (state, action) => {\n state.status = action.payload.status;\n state.user = action.payload.user;\n state.error = action.payload.error;\n },\n logout: (state) => {\n auth.logout();\n state.user = null;\n },\n resetError: (state) => {\n state.status = Status.RESOLVED;\n state.error = null;\n },\n },\n extraReducers: (builder) => {\n builder\n .addCase(login.pending, (state) => {\n state.status = Status.PENDING;\n state.error = null;\n })\n .addCase(register.pending, (state) => {\n state.status = Status.PENDING;\n state.error = null;\n })\n .addCase(login.fulfilled, (state, action) => {\n state.status = Status.RESOLVED;\n state.user = action.payload;\n })\n .addCase(register.fulfilled, (state, action) => {\n state.status = Status.RESOLVED;\n state.user = action.payload;\n })\n .addCase(login.rejected, (state, action) => {\n state.status = Status.REJECTED;\n state.error = action.error;\n })\n .addCase(register.rejected, (state, action) => {\n state.status = Status.REJECTED;\n state.error = action.error;\n });\n },\n});\n\nexport const { refetchUser, logout, resetError } = userSlice.actions;\n\nexport { login, register };\n\nexport const selectUser = (stateStore) => stateStore.user;\n\nexport default userSlice.reducer;\n","/** @jsx jsx */\nimport { jsx, keyframes } from '@emotion/core';\n\nimport { Link as RouterLink } from 'react-router-dom';\nimport styled from '@emotion/styled/macro';\nimport * as colors from 'styles/colors';\nimport * as mq from 'styles/media-queries';\nimport { Dialog as ReachDialog } from '@reach/dialog';\nimport { FaSpinner } from 'react-icons/fa';\n\nconst spin = keyframes({\n '0%': { transform: 'rotate(0deg)' },\n '100%': { transform: 'rotate(360deg)' },\n});\n\nconst CircleButton = styled.button({\n borderRadius: '30px',\n padding: '0',\n width: '40px',\n height: '40px',\n lineHeight: '1',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: colors.base,\n color: colors.text,\n border: `1px solid ${colors.gray10}`,\n cursor: 'pointer',\n});\n\nconst BookListUL = styled.ul({\n listStyle: 'none',\n padding: '0',\n display: 'grid',\n gridTemplateRows: 'repeat(auto-fill, minmax(100px, 1fr))',\n gridGap: '1em',\n});\n\nconst Spinner = styled(FaSpinner)({\n animation: `${spin} 1s linear infinite`,\n});\nSpinner.defaultProps = {\n 'aria-label': 'loading',\n};\n\nconst buttonVariants = {\n primary: {\n background: colors.indigo,\n color: colors.base,\n },\n secondary: {\n background: colors.gray,\n color: colors.text,\n },\n};\nconst Button = styled.button(\n {\n padding: '10px 15px',\n border: '0',\n lineHeight: '1',\n borderRadius: '3px',\n },\n ({ variant = 'primary' }) => buttonVariants[variant],\n);\n\nconst inputStyles = {\n border: '1px solid #f1f1f4',\n background: '#f1f2f7',\n padding: '8px 12px',\n};\n\nconst Input = styled.input({ borderRadius: '3px' }, inputStyles);\nconst Textarea = styled.textarea(inputStyles);\n\nconst Dialog = styled(ReachDialog)({\n maxWidth: '450px',\n borderRadius: '3px',\n paddingBottom: '3.5em',\n boxShadow: '0 10px 30px -5px rgba(0, 0, 0, 0.2)',\n margin: '20vh auto',\n [mq.small]: {\n width: '100%',\n margin: '10vh auto',\n },\n});\n\nconst FormGroup = styled.div({\n display: 'flex',\n flexDirection: 'column',\n});\n\nfunction FullPageSpinner() {\n return (\n \n \n \n );\n}\n\nconst Link = styled(RouterLink)({\n color: colors.indigo,\n ':hover': {\n color: colors.indigoDarken10,\n textDecoration: 'underline',\n },\n});\n\nconst errorMessageVariants = {\n stacked: { display: 'block' },\n inline: { display: 'inline-block' },\n};\n\nfunction ErrorMessage({ error, variant = 'stacked', ...props }) {\n return (\n \n There was an error: \n \n {error.message}\n \n \n );\n}\n\nfunction FullPageErrorFallback({ error }) {\n return (\n \n

Uh oh... There's a problem. Try refreshing the app.

\n

{error.message}

\n \n );\n}\n\nexport {\n FullPageErrorFallback,\n ErrorMessage,\n CircleButton,\n BookListUL,\n Spinner,\n Button,\n Input,\n Textarea,\n Dialog,\n FormGroup,\n FullPageSpinner,\n Link,\n};\n","import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';\nimport { client } from 'utils/api-client';\n\nlet oldListItem;\n\nconst Status = {\n IDLE: 'idle',\n PENDING: 'pending',\n RESOLVED: 'resolved',\n REJECTED: 'rejected',\n};\n\nconst initialState = {\n status: Status.IDLE,\n listItems: [],\n error: null,\n};\n\nconst getListItem = createAsyncThunk('listItems/getListItem', async () => {\n const { listItems } = await client('list-items');\n return listItems;\n});\n\nconst addListItem = createAsyncThunk('listItems/addListItem', async ({ bookId }) => {\n const { listItem } = await client('list-items', { data: { bookId } });\n return listItem;\n});\n\nconst updateListItem = createAsyncThunk('listItems/updateListItem', async (updates) => {\n const { listItem } = await client(`list-items/${updates.id}`, {\n method: 'PUT',\n data: updates,\n });\n return listItem;\n});\n\nconst removeListItem = createAsyncThunk('listItems/removeListItem', async ({ id }) => {\n await client(`list-items/${id}`, { method: 'DELETE' });\n return id;\n});\n\nexport const listItemSlice = createSlice({\n name: 'listItems',\n initialState,\n reducers: {\n refetchListItem: (state, action) => {\n state.status = action.payload.status;\n state.listItems = action.payload.listItems;\n },\n },\n extraReducers: (builder) => {\n builder\n .addCase(getListItem.pending, (state) => {\n state.status = Status.PENDING;\n })\n .addCase(addListItem.pending, (state) => {\n state.status = Status.PENDING;\n })\n .addCase(updateListItem.pending, (state, action) => {\n if (action.meta.arg.rating) {\n const { rating } = action.meta.arg;\n state.listItems = state.listItems.map((listItem) => {\n if (listItem.id === action.meta.arg.id) {\n oldListItem = listItem;\n return { ...listItem, rating };\n }\n return listItem;\n });\n }\n if (action.meta.arg.notes) {\n state.status = Status.PENDING;\n }\n })\n .addCase(removeListItem.pending, (state) => {\n state.status = Status.PENDING;\n })\n .addCase(getListItem.fulfilled, (state, action) => {\n state.status = Status.RESOLVED;\n state.listItems = action.payload;\n })\n .addCase(addListItem.fulfilled, (state, action) => {\n state.status = Status.RESOLVED;\n state.listItems.unshift(action.payload);\n })\n .addCase(updateListItem.fulfilled, (state, action) => {\n state.status = Status.RESOLVED;\n state.listItems = state.listItems.map((listItem) => (listItem.id === action.payload.id ? action.payload : listItem));\n })\n .addCase(removeListItem.fulfilled, (state, action) => {\n state.status = Status.RESOLVED;\n const index = state.listItems.map((listItem) => listItem.id).indexOf(action.payload);\n state.listItems.splice(index, 1);\n })\n .addCase(getListItem.rejected, (state, action) => {\n state.status = Status.REJECTED;\n state.error = action.error;\n })\n .addCase(addListItem.rejected, (state, action) => {\n state.status = Status.REJECTED;\n state.error = action.error;\n })\n .addCase(updateListItem.rejected, (state, action) => {\n if (action.meta.arg.rating) {\n state.listItems = state.listItems.map((listItem) => {\n if (listItem.id === action.meta.arg.id) {\n return { ...listItem, ...oldListItem };\n }\n return listItem;\n });\n }\n state.status = Status.REJECTED;\n state.error = action.error;\n })\n .addCase(removeListItem.rejected, (state, action) => {\n state.status = Status.REJECTED;\n state.error = action.error;\n })\n .addCase({ type: 'user/logout' }, (state) => {\n state.listItems = initialState.listItems;\n });\n },\n});\n\nexport const { refetchListItem } = listItemSlice.actions;\n\nexport {\n getListItem, addListItem, updateListItem, removeListItem,\n};\n\nexport const selectListItemState = (stateStore) => stateStore.listItem;\n\nexport const selectListItem = (stateStore) => stateStore.listItem.listItems;\n\nexport const selectStatusListItem = (stateStore) => stateStore.listItem.status;\n\nexport const selectErrorListItem = (stateStore) => stateStore.listItem.error;\n\nexport default listItemSlice.reducer;\n","import * as React from 'react';\nimport { client } from 'utils/api-client';\n\nlet queue = [];\n\nsetInterval(sendProfileQueue, 5000);\n\nfunction sendProfileQueue() {\n if (!queue.length) {\n return Promise.resolve({ success: true });\n }\n const queueToSend = [...queue];\n queue = [];\n return client('profile', { data: queueToSend });\n}\n\n// By wrapping the Profile like this, we can set the onRender to whatever\n// we want and we get the additional benefit of being able to include\n// additional data and filter phases\nfunction Profiler({ metadata, phases, ...props }) {\n function reportProfile(\n id, // the \"id\" prop of the Profiler tree that has just committed\n phase, // either \"mount\" (if the tree just mounted) or \"update\" (if it re-rendered)\n actualDuration, // time spent rendering the committed update\n baseDuration, // estimated time to render the entire subtree without memoization\n startTime, // when React began rendering this update\n commitTime, // when React committed this update\n interactions, // the Set of interactions belonging to this update\n ) {\n if (!phases || phases.includes(phase)) {\n queue.push({\n metadata,\n id,\n phase,\n actualDuration,\n baseDuration,\n startTime,\n commitTime,\n interactions,\n });\n }\n }\n return ;\n}\n\nexport { Profiler };\n","export const large = '@media (min-width: 1200px)';\nexport const medium = '@media (min-width: 992px) and (max-width: 1199px)';\nexport const small = '@media (max-width: 991px)';\n","export default __webpack_public_path__ + \"static/media/book-placeholder.0a37bda0.svg\";","import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';\nimport { client } from 'utils/api-client';\nimport bookPlaceholderSvg from 'assets/book-placeholder.svg';\n\nconst Status = {\n IDLE: 'idle',\n PENDING: 'pending',\n RESOLVED: 'resolved',\n REJECTED: 'rejected',\n};\n\nconst loadingBook = {\n title: 'Loading...',\n author: 'Loading...',\n coverImageUrl: bookPlaceholderSvg,\n publisher: 'Loading Publishing',\n synopsis: 'Loading...',\n loadingBook: true,\n};\n\nconst loadingBooks = Array.from({ length: 10 }, (v, index) => ({\n id: `loading-book-${index}`,\n ...loadingBook,\n}));\n\nconst initialState = {\n status: Status.IDLE,\n book: loadingBook,\n books: loadingBooks,\n error: null,\n};\n\nconst getBookListByQuery = createAsyncThunk('book/getBookListByQuery', async (query) => {\n const { books } = await client(`books?query=${encodeURIComponent(query)}`);\n return books;\n});\n\nconst getBook = createAsyncThunk('book/getBook', async (bookId) => {\n const { book } = await client(`books/${bookId}`);\n return book;\n});\n\nexport const bookSlice = createSlice({\n name: 'book',\n initialState,\n reducers: {\n },\n extraReducers: (builder) => {\n builder\n .addCase(getBookListByQuery.pending, (state) => {\n state.status = Status.PENDING;\n })\n .addCase(getBook.pending, (state) => {\n state.status = Status.PENDING;\n state.book = loadingBook;\n })\n .addCase(getBookListByQuery.fulfilled, (state, action) => {\n state.status = Status.RESOLVED;\n state.books = action.payload;\n })\n .addCase(getBook.fulfilled, (state, action) => {\n state.status = Status.RESOLVED;\n state.book = action.payload;\n })\n .addCase(getBookListByQuery.rejected, (state, action) => {\n state.status = Status.REJECTED;\n state.error = action.error;\n })\n .addCase(getBook.rejected, (state, action) => {\n state.status = Status.REJECTED;\n state.error = action.error;\n })\n .addCase({ type: 'user/logout' }, (state) => {\n state.books = initialState.books;\n state.book = initialState.book;\n });\n },\n});\n\nexport { getBookListByQuery, getBook };\n\nexport const selectCurrentBook = (stateStore) => stateStore.book.book;\n\nexport const selectBookList = (stateStore) => stateStore.book.books;\n\nexport const selectStatus = (stateStore) => stateStore.book.status;\n\nexport const selectError = (stateStore) => stateStore.book.error;\n\nexport const selectBookState = (stateStore) => stateStore.book;\n\nexport default bookSlice.reducer;\n","// dynamically export the server based on the environment\n// using CommonJS in this file because it's a bit simpler\n// even though mixing CJS and ESM is not typically recommended\n// It is possible to do this with ESM using `codegen.macro`\n// and you can take a look at an example of this here:\n// https://github.com/kentcdodds/bookshelf/blob/aef4f122428718ff422e203c6a68301dca50b396/src/test/server/index.js\n\nif (process.env.NODE_ENV === 'development') {\n module.exports = require('./dev-server');\n} else if (process.env.NODE_ENV === 'test') {\n module.exports = require('./test-server');\n} else {\n // in normal apps you'll not do anything in this case\n // but for this workshop app, we're actually going to\n // deploy our mock service worker to production\n // so normally, this condition would just look like this:\n\n // module.exports = \"\"\n\n // but for us, since we're shipping the dev server to prod\n // we'll do the same thing we did for development:\n module.exports = require('./dev-server');\n}\n"],"sourceRoot":""}