Skip to content

Commit 97ee4e2

Browse files
committed
Add logic to render list of book recommended by user
1 parent 023287b commit 97ee4e2

File tree

5 files changed

+58
-3
lines changed

5 files changed

+58
-3
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class Api::V1::UsersController < ApplicationController
2+
def show
3+
user = User.find(params[:id])
4+
recommended_books = user.recommended_books
5+
render json: { data: recommended_books.map { |book| BookSerializer.new(book).serializable_hash } }
6+
end
7+
end

app/javascript/components/App.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import BookDetail from './pages/BookDetail';
55
import AddBook from './pages/AddBook';
66
import EditBook from './pages/EditBook';
77
import Home from './pages/Home';
8+
import RecommenderBooks from './pages/RecommenderBooks';
89

910
const App = () => {
1011
return (
@@ -15,6 +16,7 @@ const App = () => {
1516
<Route path="/books/:id" element={<BookDetail />} />
1617
<Route path="/books/new" element={<AddBook />} />
1718
<Route path="/books/:id/edit" element={<EditBook />} />
19+
<Route path="/recommender/:id" element={<RecommenderBooks />} />
1820
</Routes>
1921
</Router>
2022
);

app/javascript/components/pages/BookDetail.jsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import React, { useEffect, useState } from 'react';
2-
import { useParams } from 'react-router-dom';
2+
import { Link, useParams } from 'react-router-dom';
33

44
const BookDetail = () => {
55
const { id } = useParams();
66
const [book, setBook] = useState(null);
77
const [recommender, setRecommender] = useState(null);
8-
const [error, setError] = useState(null);
98

109
useEffect(() => {
1110
const fetchBook = async () => {
@@ -30,7 +29,14 @@ const BookDetail = () => {
3029
<hr />
3130
{recommender && (
3231
<p className="text-muted">
33-
Recommended by: {recommender?.attributes.email}
32+
Recommended by:
33+
<Link
34+
to={`/recommender/${recommender?.attributes.id}`}
35+
className="btn btn-info btn-lg mb-5"
36+
role="button"
37+
>
38+
{recommender?.attributes.email}
39+
</Link>
3440
</p>
3541
)}
3642
</div>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { useParams } from 'react-router-dom';
3+
4+
const RecommenderBooks = () => {
5+
const { id } = useParams();
6+
const [recommendedBooks, setRecommendedBooks] = useState([]);
7+
8+
useEffect(() => {
9+
const fetchBook = async () => {
10+
const response = await fetch(`http://localhost:3000/api/v1/users/${id}`);
11+
12+
const bookData = await response.json();
13+
setRecommendedBooks(bookData.data);
14+
};
15+
16+
fetchBook();
17+
}, [id]);
18+
19+
return (
20+
<div className="container my-5">
21+
<h2>Recommended Books</h2>
22+
<ul className="list-group">
23+
{recommendedBooks.length === 0 ? (
24+
<li className="list-group-item">No books recommended yet.</li>
25+
) : (
26+
recommendedBooks.map((book) => (
27+
<li key={book.data.id} className="list-group-item">
28+
<h4>{book.data.attributes.title}</h4>
29+
<p>{book.data.attributes.author}</p>
30+
<p>{book.data.attributes.description}</p>
31+
</li>
32+
))
33+
)}
34+
</ul>
35+
</div>
36+
);
37+
};
38+
39+
export default RecommenderBooks;

config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace :api do
44
namespace :v1 do
55
resources :books
6+
resources :users, only: [ :show ]
67
end
78
end
89
get "up" => "rails/health#show", as: :rails_health_check

0 commit comments

Comments
 (0)