Spaces:
Running
Running
File size: 3,789 Bytes
806d445 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | import React, { useState, useEffect } from 'react';
import Background from './components/Background';
import HomeView from './views/HomeView';
import ResultsView from './views/ResultsView';
import FavoritesView from './views/FavoritesView';
import BookDetailsModal from './components/BookDetailsModal';
import Footer from './components/Footer';
function App() {
const [popularBooks, setPopularBooks] = useState([]);
const [recommendations, setRecommendations] = useState([]);
const [selectedBook, setSelectedBook] = useState(null);
const [loading, setLoading] = useState(false);
const [view, setView] = useState('home'); // 'home' or 'results' or 'favorites'
const [method, setMethod] = useState('hybrid');
const [bookTitle, setBookTitle] = useState('');
const [modalBook, setModalBook] = useState(null); // For book details modal
const [isModalOpen, setIsModalOpen] = useState(false);
useEffect(() => {
fetch('/api/popular')
.then(res => res.json())
.then(data => setPopularBooks(data))
.catch(err => console.error(err));
}, []);
const handleRecommend = async (title, selectedMethod) => {
setLoading(true);
setMethod(selectedMethod);
setBookTitle(title);
try {
const formData = new FormData();
formData.append('book_title', title);
formData.append('method', selectedMethod);
const resp = await fetch('/api/recommend', {
method: 'POST',
body: formData,
});
const data = await resp.json();
setRecommendations(data.recommendations);
setSelectedBook(data.selected_book);
setView('results');
window.scrollTo({ top: 0, behavior: 'smooth' });
} catch (err) {
console.error(err);
} finally {
setLoading(false);
}
};
const handleBack = () => {
setView('home');
setRecommendations([]);
setSelectedBook(null);
window.scrollTo({ top: 0, behavior: 'smooth' });
};
const handleViewDetails = (book) => {
setModalBook(book);
setIsModalOpen(true);
};
const handleCloseModal = () => {
setIsModalOpen(false);
setModalBook(null);
};
return (
<div className="relative min-h-screen text-text-primary bg-bg-body font-inter selection:bg-accent/30">
<Background />
{loading && (
<div className="fixed inset-0 z-[100] bg-white/60 backdrop-blur-sm flex items-center justify-center">
<div className="flex flex-col items-center gap-4">
<span className="loading loading-spinner loading-lg text-accent"></span>
<p className="text-accent font-bold animate-pulse uppercase tracking-widest text-xs">Finding matches...</p>
</div>
</div>
)}
<main className="relative z-10">
{view === 'home' ? (
<HomeView
popularBooks={popularBooks}
onRecommend={handleRecommend}
onViewDetails={handleViewDetails}
onViewFavorites={() => setView('favorites')}
/>
) : view === 'favorites' ? (
<FavoritesView
onRecommend={handleRecommend}
onViewDetails={handleViewDetails}
onBack={() => setView('home')}
/>
) : (
<ResultsView
bookTitle={bookTitle}
selectedBook={selectedBook}
recommendations={recommendations}
method={method}
onBack={handleBack}
onRecommend={handleRecommend}
onViewDetails={handleViewDetails}
/>
)}
</main>
{isModalOpen && modalBook && (
<BookDetailsModal
book={modalBook}
onClose={handleCloseModal}
onRecommend={handleRecommend}
/>
)}
<Footer />
</div>
);
}
export default App;
|