-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ci: add a lot of linting #1
Changes from all commits
24e0ceb
d35e7b7
89c03d1
9a8a563
2f52f2a
5ae690f
ee4127c
36eb00f
6b2ddec
35f5230
580fe77
0e19d74
c30a558
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,3 @@ | ||
{ | ||
"recommendations": [ | ||
"dbaeumer.vscode-eslint", | ||
"esbenp.prettier-vscode" | ||
] | ||
} | ||
"recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<HTMLButtonElement>) => { | ||
e.stopPropagation(); | ||
handleFavorite(book); | ||
}; | ||
|
||
Comment on lines
+12
to
15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. byś nie musiał tego typować jakbyś to wrzucił bezpośrednio koło buttona <button
className={styles.favorite_container}
onClick={(e) => {
e.stopPropagation();
handleFavorite(book);
}}
> |
||
return ( | ||
<div className={styles.book_item}> | ||
<div className={styles.book_text}> | ||
<h3 className={styles.book_title}>{book.title}</h3> | ||
<p className={styles.book_author}>by {book.authors.map(author => author.name).join(', ')}</p> | ||
</div> | ||
<p className={styles.book_author}> | ||
by {book.authors.map((author) => author.name).join(", ")} | ||
</p> | ||
</div> | ||
<div className={styles.book_actions}> | ||
<button className={styles.favorite_container} onClick={handleFavoriteClick}> | ||
{isFavorite | ||
? <img src="/icons/heart-filled.svg" className={styles.heart_icon} alt="Remove from favorites" /> | ||
: <img src="/icons/heart-icon.svg" className={styles.heart_icon} alt="Add to favorites" />} | ||
<button | ||
className={styles.favorite_container} | ||
onClick={handleFavoriteClick} | ||
> | ||
{isFavorite ? ( | ||
<Image | ||
src="/icons/heart-filled.svg" | ||
className={styles.heart_icon} | ||
alt="Remove from favorites" | ||
width={500} | ||
height={500} | ||
/> | ||
) : ( | ||
<Image | ||
src="/icons/heart-icon.svg" | ||
className={styles.heart_icon} | ||
alt="Add to favorites" | ||
width={500} | ||
height={500} | ||
/> | ||
)} | ||
</button> | ||
<a href={book.htmlLink} target="_blank" rel="noreferrer" className={styles.book_link}>Read</a> | ||
<a | ||
href={book.htmlLink} | ||
target="_blank" | ||
rel="noreferrer" | ||
className={styles.book_link} | ||
> | ||
Read | ||
</a> | ||
</div> | ||
</div> | ||
); | ||
}); | ||
|
||
export default Book; | ||
|
||
export { Book }; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -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); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nie potrzebujesz tu typu
Suggested change
|
||||||
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<Book_t[] | null>(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<string[]>([]); | ||||||
|
||||||
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 <div className={styles.loading}>Loading books...</div>; | ||||||
} | ||||||
|
||||||
return ( | ||||||
<div> | ||||||
<div className={styles.content_container}> | ||||||
<div className={styles.content_container}> | ||||||
<div> | ||||||
<input | ||||||
className={styles.search_box} | ||||||
type="text" | ||||||
value={searchQuery} | ||||||
onChange={(e) => { | ||||||
setCurrUrl(baseUrl); | ||||||
setSearchQuery(e.target.value); | ||||||
}} | ||||||
placeholder="Search for books..." | ||||||
/> | ||||||
</div> | ||||||
|
||||||
<div> | ||||||
{languages.map((clickedLanguage) => ( | ||||||
<button | ||||||
key={clickedLanguage} // Unique key prop added here | ||||||
className={`${styles.language_button} ${filterTags.includes(clickedLanguage) ? styles.active : ""}`} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. xd, dobry komentarz |
||||||
onClick={() => { | ||||||
const newList = [...filterTags]; | ||||||
toggleStringInList(clickedLanguage, newList); | ||||||
setBooks(null); | ||||||
setCurrUrl(baseUrl); | ||||||
setFilterdTags(newList); | ||||||
}} | ||||||
> | ||||||
{clickedLanguage.toUpperCase()} | ||||||
</button> | ||||||
))} | ||||||
</div> | ||||||
|
||||||
<div className={styles.nav_pages}> | ||||||
{prevUrl ? ( | ||||||
<div> | ||||||
<button | ||||||
className={styles.page_button} | ||||||
onClick={() => { | ||||||
setBooks(null); | ||||||
setCurrUrl(prevUrl); | ||||||
}} | ||||||
> | ||||||
Previous | ||||||
</button> | ||||||
</div> | ||||||
) : null} | ||||||
{nextUrl ? ( | ||||||
<div> | ||||||
<button | ||||||
className={styles.page_button} | ||||||
onClick={() => { | ||||||
setBooks(null); | ||||||
setCurrUrl(nextUrl); | ||||||
}} | ||||||
> | ||||||
Next | ||||||
</button> | ||||||
</div> | ||||||
) : null} | ||||||
</div> | ||||||
</div> | ||||||
|
||||||
<div> | ||||||
<input className={styles.search_box} | ||||||
type="text" | ||||||
value={searchQuery} | ||||||
onChange={(e) => { setCurrUrl(baseUrl); setSearchQuery(e.target.value); }} | ||||||
placeholder="Search for books..." | ||||||
/> | ||||||
{books.map((book) => ( | ||||||
<Book | ||||||
key={book.id} | ||||||
book={book} | ||||||
isFavorite={favorites.some((f: Book_t) => f.id === book.id)} | ||||||
handleFavorite={handleFavorite} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
/> | ||||||
))} | ||||||
</div> | ||||||
|
||||||
<div> | ||||||
{ | ||||||
languages.map(clickedLanguage => ( | ||||||
<button className={`${styles.language_button} ${filterTags.includes(clickedLanguage) ? styles.active : ''}`} onClick={() => { | ||||||
var newList = [...filterTags]; | ||||||
toggleStringInList(clickedLanguage, newList); | ||||||
setBooks(null); | ||||||
setCurrUrl(baseUrl); | ||||||
setFilterdTags(newList); | ||||||
}}>{clickedLanguage.toUpperCase()}</button> | ||||||
)) | ||||||
} | ||||||
</div> | ||||||
|
||||||
<div className={styles.nav_pages}> | ||||||
{prevUrl && <div><button className={styles.page_button} onClick={() => {setBooks(null); setCurrUrl(prevUrl); }}>Previous</button></div>} | ||||||
{nextUrl && <div><button className={styles.page_button} onClick={() => {setBooks(null); setCurrUrl(nextUrl); }}>Next</button></div>} | ||||||
</div> | ||||||
|
||||||
|
||||||
|
||||||
</div> | ||||||
|
||||||
|
||||||
<div> | ||||||
{books.map(book => ( | ||||||
<Book | ||||||
key={book.id} | ||||||
book={book} | ||||||
isFavorite={favorites.some(f => f.id === book.id)} | ||||||
handleFavorite={handleFavorite} | ||||||
/> | ||||||
))} | ||||||
</div> | ||||||
</div> | ||||||
); | ||||||
} | ||||||
|
||||||
export default BooksSearch; | ||||||
export { BooksSearch }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
te memo i tak nie zadziała tutaj 😭, lepiej je wyrzucić