Skip to content

Commit 1b669db

Browse files
committed
feat(hooks): create useBooks hook for fetching and managing books
1 parent ec16fa0 commit 1b669db

1 file changed

Lines changed: 122 additions & 0 deletions

File tree

src/hooks/useBooks.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { useState, useEffect } from 'react';
2+
3+
const BASE_URL = import.meta.env.VITE_API_URL;
4+
5+
export function useBooks() {
6+
const [books, setBooks] = useState([]);
7+
const [showForm, setShowForm] = useState(false);
8+
const [editingBook, setEditingBook] = useState(null);
9+
const [isLoading, setIsLoading] = useState(true);
10+
11+
const addBook = async (bookData) => {
12+
await createBook(bookData);
13+
setShowForm(false);
14+
};
15+
16+
const handleUpdateBook = async (bookData) => {
17+
await updateBook({ ...bookData, id: editingBook.id });
18+
setEditingBook(null);
19+
setShowForm(false);
20+
};
21+
22+
async function fetchBooks() {
23+
setIsLoading(true);
24+
try {
25+
const response = await fetch(`${BASE_URL}/books`);
26+
const data = await response.json();
27+
setBooks(data);
28+
} catch (error) {
29+
console.error('Fail to fetch book:', error);
30+
} finally {
31+
setIsLoading(false);
32+
}
33+
}
34+
35+
async function createBook(book) {
36+
setIsLoading(true);
37+
try {
38+
const response = await fetch(`${BASE_URL}/books`, {
39+
method: 'POST',
40+
headers: {
41+
'Content-Type': 'application/json',
42+
},
43+
body: JSON.stringify(book),
44+
});
45+
const newBook = await response.json();
46+
setBooks((prevBooks) => [...prevBooks, newBook]);
47+
} catch (error) {
48+
console.error('Fail to create book:', error);
49+
} finally {
50+
setIsLoading(false);
51+
}
52+
}
53+
54+
async function updateBook(book) {
55+
setIsLoading(true);
56+
try {
57+
const response = await fetch(`${BASE_URL}/books/${book.id}`, {
58+
method: 'PUT',
59+
headers: {
60+
'Content-Type': 'application/json',
61+
},
62+
body: JSON.stringify(book),
63+
});
64+
const updatedBook = await response.json();
65+
setBooks((prevBooks) =>
66+
prevBooks.map((b) => (b.id === book.id ? updatedBook : b))
67+
);
68+
setEditingBook(null);
69+
setShowForm(false);
70+
} catch (error) {
71+
console.error('Fail to update book:', error);
72+
} finally {
73+
setIsLoading(false);
74+
}
75+
}
76+
77+
async function deleteBook(id) {
78+
setIsLoading(true);
79+
try {
80+
await fetch(`${BASE_URL}/books/${id}`, {
81+
method: 'DELETE',
82+
});
83+
setBooks((prevBooks) => prevBooks.filter((book) => book.id !== id));
84+
} catch (error) {
85+
console.error('Fail to delete book:', error);
86+
} finally {
87+
setIsLoading(false);
88+
}
89+
}
90+
91+
useEffect(() => {
92+
fetchBooks();
93+
}, []);
94+
95+
const editBook = (book) => {
96+
setEditingBook(book);
97+
setShowForm(true);
98+
};
99+
100+
const cancelForm = () => {
101+
setShowForm(false);
102+
setEditingBook(null);
103+
};
104+
105+
const openAddForm = () => {
106+
setShowForm(true);
107+
};
108+
109+
return {
110+
books,
111+
isLoading,
112+
showForm,
113+
editingBook,
114+
addBook,
115+
updateBook: handleUpdateBook,
116+
deleteBook,
117+
editBook,
118+
cancelForm,
119+
openAddForm,
120+
refreshBooks: fetchBooks,
121+
};
122+
}

0 commit comments

Comments
 (0)