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;