Switched from array to hash table as book list, some naming errors fixed
This commit is contained in:
parent
917b00ea18
commit
3ac74ef780
@ -3,8 +3,9 @@ import { useLibrary, UseLibraryReturnTuple } from "./hooks/useLibrary";
|
|||||||
import { IBook } from "./types/book";
|
import { IBook } from "./types/book";
|
||||||
|
|
||||||
export const BookListContext = React.createContext<UseLibraryReturnTuple>([
|
export const BookListContext = React.createContext<UseLibraryReturnTuple>([
|
||||||
[],
|
{},
|
||||||
(book: IBook) => {},
|
(book: IBook) => {},
|
||||||
|
[],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const BookListContextProvider: React.FC = ({ children }) => {
|
export const BookListContextProvider: React.FC = ({ children }) => {
|
||||||
|
@ -1,38 +1,46 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { IBook } from "~/types/book";
|
import { IBook } from "~/types/book";
|
||||||
import {
|
import {
|
||||||
getBookList,
|
getBookHT,
|
||||||
getTitleList,
|
getHashList,
|
||||||
setBook,
|
saveBook,
|
||||||
updateTitleList,
|
updateHashList,
|
||||||
} from "~/utils/localStorage";
|
} from "~/utils/localStorage";
|
||||||
|
|
||||||
export type AddBookFT = (book: IBook) => void;
|
export type AddBookFT = (book: IBook) => void;
|
||||||
|
|
||||||
export type UseLibraryReturnTuple = [IBook[], AddBookFT];
|
export type UseLibraryReturnTuple = [
|
||||||
|
Record<string, IBook>,
|
||||||
|
AddBookFT,
|
||||||
|
string[]
|
||||||
|
];
|
||||||
|
|
||||||
export const useLibrary = (): UseLibraryReturnTuple => {
|
export const useLibrary = (): UseLibraryReturnTuple => {
|
||||||
const [bookList, setBookList] = useState<IBook[]>([]);
|
const [library, setLibrary] = useState<Record<string, IBook>>({});
|
||||||
const [titleList, setTitleList] = useState<string[]>([]);
|
const [hashList, setHashList] = useState<string[]>([]);
|
||||||
|
|
||||||
const addBook: AddBookFT = (book) => {
|
const addBook: AddBookFT = (book) => {
|
||||||
const key = book.hash || Date.now().toString();
|
const key = book.hash || Date.now().toString();
|
||||||
if (key && !titleList.includes(key)) {
|
if (key && !hashList.includes(key)) {
|
||||||
setTitleList([key, ...titleList]);
|
setHashList([key, ...hashList]);
|
||||||
setBookList([book, ...bookList]);
|
setLibrary((prev) => ({ [key]: book, ...prev }));
|
||||||
|
|
||||||
setBook(key, book);
|
saveBook(key, book);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const receivedTitleList = getTitleList();
|
const receivedHashList = getHashList();
|
||||||
|
|
||||||
setTitleList(receivedTitleList);
|
setHashList(receivedHashList);
|
||||||
setBookList(getBookList(receivedTitleList));
|
setLibrary(getBookHT(receivedHashList));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => updateTitleList(titleList), [titleList]);
|
useEffect(() => updateHashList(hashList), [hashList]);
|
||||||
|
|
||||||
return [bookList, addBook];
|
useEffect(() => {
|
||||||
|
console.log(library);
|
||||||
|
}, [library]);
|
||||||
|
|
||||||
|
return [library, addBook, hashList];
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,7 @@ export const Bookshelf = () => {
|
|||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<div className={styles.scrollContainer}>
|
<div className={styles.scrollContainer}>
|
||||||
<AddBook />
|
<AddBook />
|
||||||
{books.map((book, index) => (
|
{Object.values(books).map((book, index) => (
|
||||||
<BookItem key={book.hash} {...book} />
|
<BookItem key={book.hash} {...book} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,7 +3,7 @@ import { useLocation } from "wouter";
|
|||||||
|
|
||||||
import plusIcon from "~/assets/plus.svg";
|
import plusIcon from "~/assets/plus.svg";
|
||||||
import styles from "./UploadForm.module.css";
|
import styles from "./UploadForm.module.css";
|
||||||
import { submitFile, validateResponse, validState } from "~/api";
|
import { submitFile, validateResponse, validState } from "~/utils/api";
|
||||||
import { BookListContext } from "~/context";
|
import { BookListContext } from "~/context";
|
||||||
|
|
||||||
export const UploadForm = () => {
|
export const UploadForm = () => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { IBook, requiredBookProps } from "~/types/book";
|
import { IBook, requiredBookProps } from "~/types/book";
|
||||||
|
|
||||||
import { API_URL } from "./constants";
|
import { API_URL } from "~/constants";
|
||||||
|
|
||||||
export const validState = (file: File | undefined): file is File => {
|
export const validState = (file: File | undefined): file is File => {
|
||||||
if (!file) throw new Error("Book file is required. Please, attach one");
|
if (!file) throw new Error("Book file is required. Please, attach one");
|
||||||
@ -42,8 +42,11 @@ export const submitFile = async (
|
|||||||
export const validateResponse = (content: unknown): content is IBook => {
|
export const validateResponse = (content: unknown): content is IBook => {
|
||||||
if (content && typeof content === "object")
|
if (content && typeof content === "object")
|
||||||
for (const key of requiredBookProps)
|
for (const key of requiredBookProps)
|
||||||
if (!(key in content))
|
if (!(key in content)) {
|
||||||
throw new Error(`${key} is not specified in server response`);
|
if (import.meta.env.NODE_ENV === "development")
|
||||||
|
console.log(`${key} is not specified in server response`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
@ -1,33 +1,31 @@
|
|||||||
import { IBook } from "~/types/book";
|
import { IBook } from "~/types/book";
|
||||||
import { isArrOfStr } from "~/types/utils";
|
import { isArrOfStr } from "~/types/utils";
|
||||||
import { validateResponse } from "~/api";
|
import { validateResponse } from "~/utils/api";
|
||||||
|
|
||||||
export const getTitleList = () => {
|
export const getHashList = () => {
|
||||||
const titleListStr = localStorage.getItem("list") || "[]";
|
const hashListStr = localStorage.getItem("list") || "[]";
|
||||||
const titleList: unknown = JSON.parse(titleListStr);
|
const hashList: unknown = JSON.parse(hashListStr);
|
||||||
|
|
||||||
if (isArrOfStr(titleList)) return titleList;
|
if (isArrOfStr(hashList)) return hashList;
|
||||||
else {
|
else {
|
||||||
localStorage.setItem("list", "[]");
|
localStorage.setItem("list", "[]");
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getBookList = (titleList: string[]) =>
|
export const getBookHT = (hashList: string[]) => {
|
||||||
titleList
|
const bookHT: Record<string, IBook> = {};
|
||||||
.map<unknown>((hash) => JSON.parse(localStorage.getItem(hash) || "{}"))
|
|
||||||
.filter((obj): obj is IBook => {
|
|
||||||
try {
|
|
||||||
return validateResponse(obj);
|
|
||||||
} catch (err) {
|
|
||||||
if (import.meta.env.NODE_ENV === "development")
|
|
||||||
console.log(err.message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export const setBook = (key: string, book: IBook) =>
|
hashList.forEach((hash) => {
|
||||||
|
const obj: unknown = JSON.parse(localStorage.getItem(hash) || "{}");
|
||||||
|
if (validateResponse(obj)) bookHT[hash] = obj;
|
||||||
|
});
|
||||||
|
|
||||||
|
return bookHT;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const saveBook = (key: string, book: IBook) =>
|
||||||
localStorage.setItem(key, JSON.stringify(book));
|
localStorage.setItem(key, JSON.stringify(book));
|
||||||
|
|
||||||
export const updateTitleList = (titleList: string[]) =>
|
export const updateHashList = (hashList: string[]) =>
|
||||||
localStorage.setItem("list", JSON.stringify(titleList));
|
localStorage.setItem("list", JSON.stringify(hashList));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user