diff --git a/.vscode/extensions.json b/.vscode/extensions.json index c99c624..1d7ac85 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,3 @@ { - "recommendations": [ - "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode" - ] -} \ No newline at end of file + "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] +} diff --git a/components/Book.tsx b/components/Book.tsx index 3d81233..842d6a4 100644 --- a/components/Book.tsx +++ b/components/Book.tsx @@ -1,29 +1,61 @@ -import React from 'react'; -import styles from '../styles/book.module.css'; +import Image from "next/image"; +import React from "react"; -const Book = React.memo(({ book, isFavorite, handleFavorite }) => { - const handleFavoriteClick = (e) => { - e.stopPropagation(); - handleFavorite(book); +import styles from "../styles/book.module.css"; +import type { BookProps } from "./appContext"; + +const Book = React.memo(function Book({ + book, + isFavorite, + handleFavorite, +}: BookProps) { + const handleFavoriteClick = (e: React.MouseEvent) => { + e.stopPropagation(); + handleFavorite(book); }; return (

{book.title}

-

by {book.authors.map(author => author.name).join(', ')}

-
+

+ by {book.authors.map((author) => author.name).join(", ")} +

+
- - Read + + Read +
); }); -export default Book; - +export { Book }; diff --git a/components/BookSearch.tsx b/components/BookSearch.tsx index 6a8429b..fb0b7ee 100644 --- a/components/BookSearch.tsx +++ b/components/BookSearch.tsx @@ -1,125 +1,152 @@ -import React, { useState, useEffect } from 'react'; -import Book from './Book'; -import styles from '../styles/book-search.module.css'; +import React, { useEffect, useState } from "react"; -const baseUrl = 'https://gutendex.com/books'; -export const languages = ['pl', 'en', 'fr']; +import styles from "../styles/book-search.module.css"; +import { Book } from "./Book"; +import type { AppContextType, Book_t, JsonResponse } from "./appContext"; +const baseUrl = "https://gutendex.com/books"; +export const languages = ["pl", "en", "fr"]; -export function toggleStringInList(string, list) { +const DELAY = 300; + +export function toggleStringInList(string: string, list: string[]): string[] { const index = list.indexOf(string); if (index === -1) { - // String not found in the list, so add it - list.push(string); + // String not found in the list, so add it + list.push(string); } else { - // String found in the list, so remove it - list.splice(index, 1); + // String found in the list, so remove it + list.splice(index, 1); } return list; } - -function BooksSearch({ favorites, handleFavorite}) { - const [books, setBooks] = useState(null); - const [searchQuery, setSearchQuery] = useState(''); +function BooksSearch({ favorites, handleFavorite }: AppContextType) { + const [books, setBooks] = useState(null); + const [searchQuery, setSearchQuery] = useState(""); const [currUrl, setCurrUrl] = useState(baseUrl); const [prevUrl, setPrevUrl] = useState(""); const [nextUrl, setNextUrl] = useState(""); - const [filterTags, setFilterdTags] = useState([]); - console.log(filterTags); - - + const [filterTags, setFilterdTags] = useState([]); useEffect(() => { - const delay = searchQuery ? 300 : 0; // no delay for initial fetch - const getBooksByDebouncing = setTimeout(async () => { - const url = new URL(currUrl); - if (searchQuery) { - url.searchParams.append('search', searchQuery); - } - console.log(filterTags); - - if(filterTags.length >= 1){ - url.searchParams.append('languages', filterTags.join(',')); - } - - console.log(url); - - try { - const response = await fetch(url); - const data = await response.json(); - const booksWithHtml = data.results.map(book => { - return { - ...book, - htmlLink: book.formats['text/html'] - }; - }); - setBooks(booksWithHtml); - setPrevUrl(data.previous); - setNextUrl(data.next); - } catch (error) { - console.error('An error occured:', error); - } + const delay = searchQuery ? DELAY : 0; // no delay for initial fetch + const getBooksByDebouncing = setTimeout(() => { + const fetchData = async () => { + const url = new URL(currUrl); + if (searchQuery) { + url.searchParams.append("search", searchQuery); + } + + if (filterTags.length >= 1) { + url.searchParams.append("languages", filterTags.join(",")); + } + + try { + const response = await fetch(url); + const data = (await response.json()) as JsonResponse; + const booksWithHtml = data.results.map((book) => { + return { + ...book, + htmlLink: book.formats["text/html"], + }; + }); + setBooks(booksWithHtml); + setPrevUrl(data.previous); + setNextUrl(data.next); + } catch (error) { + // eslint-disable-next-line no-console + console.error("Error fetching books", error); + } + }; + void fetchData(); }, delay); - return () => clearTimeout(getBooksByDebouncing) - - }, [searchQuery, currUrl, filterTags]); - + return () => { + clearTimeout(getBooksByDebouncing); + }; + }, [searchQuery, currUrl, filterTags]); - if(!books ){ + if (!books) { return
Loading books...
; } return (
-
+
+
+ { + setCurrUrl(baseUrl); + setSearchQuery(e.target.value); + }} + placeholder="Search for books..." + /> +
+ +
+ {languages.map((clickedLanguage) => ( + + ))} +
+ +
+ {prevUrl ? ( +
+ +
+ ) : null} + {nextUrl ? ( +
+ +
+ ) : null} +
+
- { setCurrUrl(baseUrl); setSearchQuery(e.target.value); }} - placeholder="Search for books..." - /> + {books.map((book) => ( + f.id === book.id)} + handleFavorite={handleFavorite} + /> + ))}
- -
- { - languages.map(clickedLanguage => ( - - )) - } -
- -
- {prevUrl &&
} - {nextUrl &&
} -
- - - -
- - -
- {books.map(book => ( - f.id === book.id)} - handleFavorite={handleFavorite} - /> - ))} -
); } -export default BooksSearch; +export { BooksSearch }; diff --git a/components/Favorites.tsx b/components/Favorites.tsx index 46ddb1f..1ce2cf9 100644 --- a/components/Favorites.tsx +++ b/components/Favorites.tsx @@ -1,74 +1,103 @@ -import React, { useState, useEffect } from 'react'; -import Book from './Book'; -import styles from '../styles/book-search.module.css'; -import { languages, toggleStringInList } from './BookSearch'; +import React, { useEffect, useState } from "react"; -function Favorites({ favorites, handleFavorite }) { - const [favoriteBooks, setFavoriteBooks] = useState([]); - const [searchQuery, setSearchQuery] = useState(''); - const [filterTags, setFilterdTags] = useState([]); +import styles from "../styles/book-search.module.css"; +import { Book } from "./Book"; +import { languages, toggleStringInList } from "./BookSearch"; +import type { AppContextType, Book_t } from "./appContext"; + +function Favorites({ favorites, handleFavorite }: AppContextType) { + const [favoriteBooks, setFavoriteBooks] = useState([]); + const [searchQuery, setSearchQuery] = useState(""); + const [filterTags, setFilterdTags] = useState([]); const [isFirstLoad, setIsFirstLoad] = useState(true); useEffect(() => { - setIsFirstLoad(false); - const savedFavorites = JSON.parse(localStorage.getItem('favorites')) || favorites; + const savedFavoritesJSON = localStorage.getItem("favorites"); + const savedFavorites = + savedFavoritesJSON !== null + ? (JSON.parse(savedFavoritesJSON) as Book_t[]) + : []; - const filtered = savedFavorites.filter(book => { - const matchesSearchQuery = book.title.toLowerCase().includes(searchQuery.toLowerCase()); - const matchesLanguage = filterTags.length == 0 || book.languages.some(language => filterTags.includes(language)); - - return matchesSearchQuery && matchesLanguage; - }); + const filtered = savedFavorites.filter((book) => { + const matchesSearchQuery = book.title + .toLowerCase() + .includes(searchQuery.toLowerCase()); + const matchesLanguage = + filterTags.length === 0 || + book.languages.some((language) => filterTags.includes(language.name)); + return matchesSearchQuery && matchesLanguage; + }); setFavoriteBooks(filtered); }, [favorites, searchQuery, filterTags]); - if ((!favoriteBooks.length && !searchQuery && !filterTags.length && isFirstLoad) || JSON.parse(localStorage.getItem('favorites')).length == 0){ + const hasNoFavorites = () => { + const savedFavoritesJSON = localStorage.getItem("favorites"); + if (savedFavoritesJSON !== null) { + const savedFavorites = JSON.parse(savedFavoritesJSON) as Book_t[]; + return savedFavorites.length === 0; + } + return true; + }; + + if ( + (!favoriteBooks.length && + !searchQuery && + !filterTags.length && + isFirstLoad) || + hasNoFavorites() + ) { return
Brak ulubionych książek.
; } return ( -
-
-
- { setSearchQuery(e.target.value); }} - placeholder="Search for books..." - /> -
- -
- { - languages.map(clickedLanguage => ( - - )) - } +
+
+
+ { + setSearchQuery(e.target.value); + }} + placeholder="Search for books..." + /> +
+
+ {languages.map((clickedLanguage) => ( + + ))} +
-
-
- {favoriteBooks.map(book => ( - - ))} +
+ {favoriteBooks.map((book: Book_t) => ( + + ))} +
-
); } -export default Favorites; +export { Favorites }; diff --git a/components/Footer.tsx b/components/Footer.tsx index 7130e0a..bce98cd 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -1,6 +1,4 @@ - - -import styles from '../styles/footer.module.css'; +import styles from "../styles/footer.module.css"; const Footer = () => { return ( @@ -10,6 +8,4 @@ const Footer = () => { ); }; -export default Footer; - - \ No newline at end of file +export { Footer }; diff --git a/components/Hero.tsx b/components/Hero.tsx index 60c967e..192f1da 100644 --- a/components/Hero.tsx +++ b/components/Hero.tsx @@ -1,15 +1,16 @@ -import styles from '../styles/hero.module.css'; +import styles from "../styles/hero.module.css"; const Hero = () => { return (

Welcome to the Online Reading Room

-

Find your next adventure in a book

+

+ Find your next adventure in a book +

); }; -export default Hero; - +export { Hero }; diff --git a/components/NavBar.tsx b/components/NavBar.tsx index 7625716..65aed71 100644 --- a/components/NavBar.tsx +++ b/components/NavBar.tsx @@ -1,32 +1,22 @@ -import Link from 'next/link'; -import React from 'react'; -import styles from '../styles/navbar.module.css'; +import Link from "next/link"; +import React from "react"; -const NavBar = () => { +import styles from "../styles/navbar.module.css"; + +export const NavBar = () => { return ( ); }; - -export default NavBar; - - - diff --git a/components/appContext.tsx b/components/appContext.tsx index 6a4fda6..01295f2 100644 --- a/components/appContext.tsx +++ b/components/appContext.tsx @@ -1,13 +1,50 @@ -import { createContext, useContext } from 'react'; +import { createContext, useContext } from "react"; +import type { ReactNode } from "react"; -const AppContext = createContext(); +export interface BookProps { + book: Book_t; + isFavorite: boolean; + handleFavorite: (book: Book_t) => void; +} + +export interface AppContextType { + favorites: Book_t[]; + handleFavorite: (book: Book_t) => void; +} + +const AppContext = createContext({ + favorites: [], + // eslint-disable-next-line @typescript-eslint/no-empty-function + handleFavorite: () => {}, +}); + +export interface Book_t { + id: string; + title: string; + authors: Array<{ name: string }>; + formats: { "text/html": string }; + htmlLink: string; + languages: Array<{ name: string }>; +} -export function AppContextProvider({ children, value }) { +interface AppContextProviderProps { + children: ReactNode; + value: AppContextType; +} + +export interface JsonResponse { + results: Book_t[]; + previous: string; + next: string; +} + +export function AppContextProvider({ + children, + value, +}: AppContextProviderProps) { return {children}; } export function useAppContext() { return useContext(AppContext); } - -//elo zelo diff --git a/package-lock.json b/package-lock.json index 95c6b36..1c711fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,13 +7,12 @@ "dependencies": { "next": "latest", "react": "18.2.0", - "react-dom": "18.2.0", - "styled-components": "^6.1.8" + "react-dom": "18.2.0" }, "devDependencies": { "@alergeek-ventures/eslint-config": "^9.0.17", "@trivago/prettier-plugin-sort-imports": "^4.3.0", - "@types/react": "18.3.1", + "@types/react": "^18.3.1", "@typescript-eslint/parser": "^7.6.0", "eslint": "8.57.0", "eslint-config-next": "14.2.1", @@ -847,24 +846,6 @@ "node": ">=18" } }, - "node_modules/@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", - "dependencies": { - "@emotion/memoize": "^0.8.1" - } - }, - "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" - }, - "node_modules/@emotion/unitless": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", - "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" - }, "node_modules/@ericcornelissen/bash-parser": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@ericcornelissen/bash-parser/-/bash-parser-0.5.2.tgz", @@ -1565,11 +1546,6 @@ "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, - "node_modules/@types/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-n4sx2bqL0mW1tvDf/loQ+aMX7GQD3lc3fkCMC55VFNDu/vBOabO+LTIeXKM14xK0ppk5TUGcWRjiSpIlUpghKw==" - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.8.0.tgz", @@ -2238,14 +2214,6 @@ "node": ">=6" } }, - "node_modules/camelize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", - "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001609", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001609.tgz", @@ -2526,28 +2494,11 @@ "node": ">=18" } }, - "node_modules/css-color-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", - "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", - "engines": { - "node": ">=4" - } - }, - "node_modules/css-to-react-native": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", - "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", - "dependencies": { - "camelize": "^1.0.0", - "css-color-keywords": "^1.0.0", - "postcss-value-parser": "^4.0.2" - } - }, "node_modules/csstype": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", + "dev": true }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -5958,11 +5909,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6349,11 +6295,6 @@ "node": ">= 0.4" } }, - "node_modules/shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -6647,38 +6588,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/styled-components": { - "version": "6.1.8", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.8.tgz", - "integrity": "sha512-PQ6Dn+QxlWyEGCKDS71NGsXoVLKfE1c3vApkvDYS5KAK+V8fNWGhbSUEo9Gg2iaID2tjLXegEW3bZDUGpofRWw==", - "dependencies": { - "@emotion/is-prop-valid": "1.2.1", - "@emotion/unitless": "0.8.0", - "@types/stylis": "4.2.0", - "css-to-react-native": "3.2.0", - "csstype": "3.1.2", - "postcss": "8.4.31", - "shallowequal": "1.1.0", - "stylis": "4.3.1", - "tslib": "2.5.0" - }, - "engines": { - "node": ">= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/styled-components" - }, - "peerDependencies": { - "react": ">= 16.8.0", - "react-dom": ">= 16.8.0" - } - }, - "node_modules/styled-components/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" - }, "node_modules/styled-jsx": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", @@ -6701,11 +6610,6 @@ } } }, - "node_modules/stylis": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", - "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==" - }, "node_modules/summary": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/summary/-/summary-2.1.0.tgz", diff --git a/package.json b/package.json index 3ea5250..44db2b9 100644 --- a/package.json +++ b/package.json @@ -14,13 +14,12 @@ "dependencies": { "next": "latest", "react": "18.2.0", - "react-dom": "18.2.0", - "styled-components": "^6.1.8" + "react-dom": "18.2.0" }, "devDependencies": { "@alergeek-ventures/eslint-config": "^9.0.17", "@trivago/prettier-plugin-sort-imports": "^4.3.0", - "@types/react": "18.3.1", + "@types/react": "^18.3.1", "@typescript-eslint/parser": "^7.6.0", "eslint": "8.57.0", "eslint-config-next": "14.2.1", diff --git a/pages/_app.tsx b/pages/_app.tsx index e1215d3..0157e09 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,35 +1,43 @@ -import '../styles/global.css'; +import type { AppProps } from "next/app"; +import React, { useEffect, useState } from "react"; -import React, { useState, useEffect } from 'react'; -import { AppContextProvider } from '../components/appContext'; +import type { Book_t } from "../components/appContext"; +import { AppContextProvider } from "../components/appContext"; +import "../styles/global.css"; -function MyApp({ Component, pageProps }) { - const [favorites, setFavorites] = useState([]); +function MyApp({ Component, pageProps }: AppProps) { + const [favorites, setFavorites] = useState([]); useEffect(() => { - const savedFavorites = JSON.parse(localStorage.getItem('favorites')) || []; + const savedFavoritesJSON = localStorage.getItem("favorites"); + const savedFavorites = + savedFavoritesJSON !== null + ? (JSON.parse(savedFavoritesJSON) as Book_t[]) + : []; setFavorites(savedFavorites); }, []); useEffect(() => { - localStorage.setItem('favorites', JSON.stringify(favorites)); + localStorage.setItem("favorites", JSON.stringify(favorites)); }, [favorites]); - const handleFavorite = (book) => { + const handleFavorite = (book: Book_t) => { setFavorites((prevFavorites) => { - const isAlreadyFavorite = prevFavorites.some(f => f.id === book.id); + const isAlreadyFavorite = prevFavorites.some( + (f: Book_t) => f.id === book.id, + ); const updatedFavorites = isAlreadyFavorite - ? prevFavorites.filter(f => f.id !== book.id) + ? prevFavorites.filter((f: Book_t) => f.id !== book.id) : [...prevFavorites, book]; - localStorage.setItem('favorites', JSON.stringify(updatedFavorites)); + localStorage.setItem("favorites", JSON.stringify(updatedFavorites)); return updatedFavorites; }); }; return ( - - - + + + ); } diff --git a/pages/books.tsx b/pages/books.tsx index 20237fb..b1a0e99 100644 --- a/pages/books.tsx +++ b/pages/books.tsx @@ -1,8 +1,6 @@ - - -import NavBar from '../components/NavBar'; -import { useAppContext } from '../components/appContext'; -import BooksSearch from '../components/BookSearch'; +import { BooksSearch } from "../components/BookSearch"; +import { NavBar } from "../components/NavBar"; +import { useAppContext } from "../components/appContext"; function Books() { const { favorites, handleFavorite } = useAppContext(); @@ -16,5 +14,3 @@ function Books() { } export default Books; - - diff --git a/pages/favorites.tsx b/pages/favorites.tsx index aac1984..d9e8eb8 100644 --- a/pages/favorites.tsx +++ b/pages/favorites.tsx @@ -1,18 +1,18 @@ -import React from 'react'; -import Favorites from '../components/Favorites'; -import NavBar from '../components/NavBar'; +import React from "react"; -import { useAppContext } from '../components/appContext'; +import { Favorites } from "../components/Favorites"; +import { NavBar } from "../components/NavBar"; +import { useAppContext } from "../components/appContext"; const Fav = () => { - const { favorites, handleFavorite } = useAppContext(); + const { favorites, handleFavorite } = useAppContext(); - return ( -
- - -
- ) -} + return ( +
+ + +
+ ); +}; -export default Fav; \ No newline at end of file +export default Fav; diff --git a/pages/index.tsx b/pages/index.tsx index 037c50e..8d0a468 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,15 +1,16 @@ -'use client'; +"use client"; -import React from 'react'; -import NavBar from '../components/NavBar'; -import Footer from '../components/Footer'; -import styles from '../styles/Home.module.css'; -import Hero from '../components/Hero'; +import React from "react"; + +import { Footer } from "../components/Footer"; +import { Hero } from "../components/Hero"; +import { NavBar } from "../components/NavBar"; +import styles from "../styles/Home.module.css"; const Page = () => { return ( -
-
+
+
@@ -19,4 +20,4 @@ const Page = () => { ); }; -export default Page; \ No newline at end of file +export default Page; diff --git a/styles/Home.module.css b/styles/Home.module.css index d0784c9..97fe082 100644 --- a/styles/Home.module.css +++ b/styles/Home.module.css @@ -1,4 +1,3 @@ - .page_container { position: relative; background-size: cover; @@ -7,17 +6,16 @@ z-index: 1000; } - .form_container { - background: rgba(255, 255, 255, 0.9); + background: rgba(255, 255, 255, 0.9); border-radius: 8px; padding: 20px; - max-width: 500px; - margin: 0 auto; + max-width: 500px; + margin: 0 auto; } .background_container { - background-image: url('/background.jpg'); + background-image: url("/background.jpg"); background-size: cover; background-position: center; position: relative; @@ -33,6 +31,6 @@ right: 0; bottom: 0; left: 0; - background-color: rgba(255, 255, 255, 0.5); + background-color: rgba(255, 255, 255, 0.5); z-index: 0; } diff --git a/styles/book-search.module.css b/styles/book-search.module.css index 7f67df9..f69a5c9 100644 --- a/styles/book-search.module.css +++ b/styles/book-search.module.css @@ -1,4 +1,3 @@ - .box_field { display: flex; flex-direction: column; @@ -6,108 +5,106 @@ } .content_container { - display: flex; - align-items: center; - justify-content: flex-start; - gap: 10px; + display: flex; + align-items: center; + justify-content: flex-start; + gap: 10px; } -.nav_pages{ +.nav_pages { margin-left: auto; display: flex; - justify-content: flex-end; + justify-content: flex-end; align-items: center; } .page_button { padding: 10px 15px; margin: 0 5px; - border: 2px solid #007BFF; + border: 2px solid #007bff; background-color: white; - color: #007BFF; + color: #007bff; font-size: 16px; cursor: pointer; - transition: background-color 0.3s, color 0.3s; - border-radius: 5px; + transition: + background-color 0.3s, + color 0.3s; + border-radius: 5px; user-select: none; } .page_button:hover { - box-shadow: 0 2px 5px 0 rgba(0,123,255,0.5); + box-shadow: 0 2px 5px 0 rgba(0, 123, 255, 0.5); } .page_button:focus { outline: none; - box-shadow: 0 0 0 3px rgba(0,123,255,0.3); + box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.3); } - .language_button { padding: 10px 15px; margin: 0 5px; - border: 2px solid #007BFF; + border: 2px solid #007bff; background-color: white; - color: #007BFF; + color: #007bff; font-size: 16px; cursor: pointer; - transition: background-color 0.3s, color 0.3s; - border-radius: 5px; - user-select: none; + transition: + background-color 0.3s, + color 0.3s; + border-radius: 5px; + user-select: none; } .language_button.active { - background-color: #007BFF; - color: white; - border-color: #0056b3; + background-color: #007bff; + color: white; + border-color: #0056b3; } - .language_button:hover { - box-shadow: 0 2px 5px 0 rgba(0,123,255,0.5); + box-shadow: 0 2px 5px 0 rgba(0, 123, 255, 0.5); } - .language_button:focus { outline: none; - box-shadow: 0 0 0 3px rgba(0,123,255,0.3); + box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.3); } - .search_box { padding: 10px 15px; - width: 100%; - max-width: 400px; - border: 2px solid #007BFF; - border-radius: 25px; - outline: none; - font-size: 16px; - color: #333; - transition: border-color 0.3s; + width: 100%; + max-width: 400px; + border: 2px solid #007bff; + border-radius: 25px; + outline: none; + font-size: 16px; + color: #333; + transition: border-color 0.3s; } -.search_box::placeholder { - color: #888; +.search_box::placeholder { + color: #888; } -.search_box:focus { +.search_box:focus { border-color: #0056b3; - box-shadow: 0 0 5px rgba(0,123,255,0.5); + box-shadow: 0 0 5px rgba(0, 123, 255, 0.5); } - - .loading { display: flex; justify-content: center; align-items: center; - height: 100vh; - width: 100vw; - font-size: 24px; - font-family: 'Arial', sans-serif; - color: #555; + height: 100vh; + width: 100vw; + font-size: 24px; + font-family: "Arial", sans-serif; + color: #555; background-color: rgba(255, 255, 255, 0.8); - position: fixed; + position: fixed; top: 0; left: 0; - z-index: 0; -} \ No newline at end of file + z-index: 0; +} diff --git a/styles/book.module.css b/styles/book.module.css index 2371980..ac8bbb4 100644 --- a/styles/book.module.css +++ b/styles/book.module.css @@ -1,64 +1,56 @@ - - .book_item { - position: relative; - display: flex; - justify-content: space-between; - align-items: center; - padding: 10px; - margin: 10px 0; - background-color: white; - box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); - border-radius: 4px; - } - + position: relative; + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; + margin: 10px 0; + background-color: white; + box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); + border-radius: 4px; +} + .book_title { - color: #333; - font-size: 1.2em; - font-weight: 600; + color: #333; + font-size: 1.2em; + font-weight: 600; } - + .book_author { - color: #666; - font-size: 1em; - margin-top: 4px; + color: #666; + font-size: 1em; + margin-top: 4px; } .heart_icon { - display: flex; - width: 24px; - height: auto; - cursor: pointer; - align-items: right; + display: flex; + width: 24px; + height: auto; + cursor: pointer; + align-items: right; } - .favorite_container { - padding: 0; - border: none; - background: none; - + padding: 0; + border: none; + background: none; } .book_link { - text-decoration: none; - color: inherit; - display: flex; - justify-content: flex-end; - margin-right: 20px; - margin-left: 20px; - transition: color 0.3s; + text-decoration: none; + color: inherit; + display: flex; + justify-content: flex-end; + margin-right: 20px; + margin-left: 20px; + transition: color 0.3s; } .book_link:hover { - color: #007bff; + color: #007bff; } - .book_actions { - display: flex; - align-items: center; + display: flex; + align-items: center; } - - - diff --git a/styles/books-page.module.css b/styles/books-page.module.css index fc3e3c4..70e5591 100644 --- a/styles/books-page.module.css +++ b/styles/books-page.module.css @@ -1,19 +1,17 @@ .background_container { - background-image: url('/background.jpg'); - background-size: cover; - background-position: center; - position: relative; - z-index: 0; - } - - .background_overlay { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - background-color: rgba(255, 255, 255, 0.5); - z-index: 0; - } - + background-image: url("/background.jpg"); + background-size: cover; + background-position: center; + position: relative; + z-index: 0; +} +.background_overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: rgba(255, 255, 255, 0.5); + z-index: 0; +} diff --git a/styles/footer.module.css b/styles/footer.module.css index 0ec714e..981b8fd 100644 --- a/styles/footer.module.css +++ b/styles/footer.module.css @@ -1,8 +1,7 @@ .footer { - background-color: rgba(255, 255, 255, 0); - color: white; - text-align: center; - padding: 20px 0; - margin-top: auto; - } - \ No newline at end of file + background-color: rgba(255, 255, 255, 0); + color: white; + text-align: center; + padding: 20px 0; + margin-top: auto; +} diff --git a/styles/global.css b/styles/global.css index 355f74b..07519f0 100644 --- a/styles/global.css +++ b/styles/global.css @@ -17,9 +17,7 @@ body { sans-serif; font-size: 16px; height: 100vh; -} */ - - +} a { color: inherit; text-decoration: none; @@ -34,7 +32,6 @@ img { height: auto; } - :root { --background-color: #fff; --text-color: #000; @@ -49,4 +46,3 @@ body { background-color: var(--background-color); color: var(--text-color); } - diff --git a/styles/hero.module.css b/styles/hero.module.css index b693141..ca28380 100644 --- a/styles/hero.module.css +++ b/styles/hero.module.css @@ -1,22 +1,20 @@ +.hero-content { + position: absolute; + text-align: center; +} - .hero-content { - position: absolute; - text-align: center; - } - - .hero h1 { - font-size: 3rem; - margin-bottom: 1rem; - } - - .hero p { - font-size: 1.5rem; - } - +.hero h1 { + font-size: 3rem; + margin-bottom: 1rem; +} - .hero { - text-align: center; - padding: 50px 0; - color: white; - font: 1em sans-serif; - } \ No newline at end of file +.hero p { + font-size: 1.5rem; +} + +.hero { + text-align: center; + padding: 50px 0; + color: white; + font: 1em sans-serif; +} diff --git a/styles/navbar.module.css b/styles/navbar.module.css index 0a3f65f..273af31 100644 --- a/styles/navbar.module.css +++ b/styles/navbar.module.css @@ -1,7 +1,7 @@ .navbar { z-index: 1000; position: relative; - background-color: rgba(255, 255, 255, 0); /* przezroczyste tło */ + background-color: rgba(255, 255, 255, 0); overflow: hidden; display: flex; flex-direction: column; @@ -11,29 +11,29 @@ } .navLinks { - list-style: none; /* usuwa wypunktowanie */ + list-style: none; display: flex; justify-content: center; - padding: 0; /* usuwa domyślne paddingi dla listy */ - margin: 0; /* usuwa domyślne marginesy dla listy */ + padding: 0; + margin: 0; } .navLinkItem { - margin-right: 30px; /* odstępy między linkami, ostatni link nie potrzebuje marginesu */ - text-decoration: none; /* usuwa podkreślenie */ - color: #333; /* kolor tekstu */ + margin-right: 30px; + text-decoration: none; + color: #333; } .navLinkItem:last-child { - margin-right: 0; /* usuwa margines z ostatniego elementu, aby nie było przesunięcia */ + margin-right: 0; } .navLinkItem a { - text-decoration: none; /* usuwa podkreślenie z linków */ - color: inherit; /* spowoduje, że linki będą miały ten sam kolor co element rodzica */ - transition: color 0.3s; /* płynna zmiana koloru przy hover */ + text-decoration: none; + color: inherit; + transition: color 0.3s; } .navLinkItem a:hover { - color: #007bff; /* kolor tekstu linków po najechaniu kursorem */ + color: #007bff; }