Skip to content

Commit

Permalink
Merge pull request #55 from team1-booklog/dev
Browse files Browse the repository at this point in the history
마지막 PR 반영 및 배포
  • Loading branch information
karpitony authored Oct 13, 2024
2 parents 02c4d9d + 903ff8f commit c169971
Show file tree
Hide file tree
Showing 13 changed files with 235 additions and 47 deletions.
2 changes: 2 additions & 0 deletions src/Routers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Register from './pages/Register.tsx'
import Editor from './pages/Editor.tsx'
import Book from './pages/Book.tsx'
import Article from './pages/Article.tsx'
import RequestLogin from './pages/RequestLogin.tsx'

export default function Routers() {
const router = createBrowserRouter([
Expand All @@ -21,6 +22,7 @@ export default function Routers() {
{ path: '/register', element: <Register /> },
{ path: '/editor', element: <Editor /> },
{ path: '/article/:articleSlug', element: <Article /> },
{ path: '/requestLogin', element: <RequestLogin /> },
],
},
{
Expand Down
68 changes: 60 additions & 8 deletions src/assets/images/SampleReviewImg.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion src/components/Editor/BookReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ export default function BookReportHeaderEditor(
</div>
</div>

<Search setBookIsbn={setBookIsbn}/>
<Search
bookIsbn={bookIsbn}
setBookIsbn={setBookIsbn}
/>
</div>
</div>
);
Expand Down
11 changes: 8 additions & 3 deletions src/components/Editor/BookReportHeader/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import MagnifyingGlass from '../../../assets/icons/MagnifyingGlass.svg';
import { searchBooks } from '../../../services/BackendBookApi';

interface SearchBarProps {
readBookTitle: string;
readBookTitle: string ;
onSearch: (searchText: string) => void;
setReadBookTitle: (value: string) => void;
isSearchOk: boolean;
}

export default function SearchBar({ readBookTitle, onSearch, setReadBookTitle }: SearchBarProps) {
export default function SearchBar({ readBookTitle, onSearch, setReadBookTitle, isSearchOk }: SearchBarProps) {
const inputRef = useRef<HTMLInputElement | null>(null);

const handleButtonClick = () => {
Expand All @@ -28,7 +29,8 @@ export default function SearchBar({ readBookTitle, onSearch, setReadBookTitle }:
return;
}
e.preventDefault();


if (isSearchOk) {
// 검색어를 부모 컴포넌트에 전달
onSearch(readBookTitle);

Expand All @@ -42,6 +44,9 @@ export default function SearchBar({ readBookTitle, onSearch, setReadBookTitle }:
}
}
searchBookFromBackend();
} else {
alert('검색할 수 없습니다.')
}
};

return (
Expand Down
37 changes: 35 additions & 2 deletions src/components/Editor/Search.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,52 @@
import { useState, useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { fetchBookId } from '../../services/IsbnBookIdService';
import SearchBar from './BookReportHeader/SearchBar';
import SearchResults from './BookReportHeader/SearchResults';

interface SearchProps {
bookIsbn: string;
setBookIsbn: (isbn: string) => void;
}

export default function Search({setBookIsbn}: SearchProps) {
export default function Search({bookIsbn, setBookIsbn}: SearchProps) {
const [readBookTitle, setReadBookTitle] = useState<string>('');
const [searchText, setSearchText] = useState<string>(''); // 검색어 상태 추가

const [presetReadBookTitle, setPresetReadBookTitle] = useState<string | undefined>('');
const [isSearchOk, setIsSearchOk] = useState<boolean>(true);
const location = useLocation();
const searchParams = new URLSearchParams(location.search);
const isbnFromUrl = searchParams.get('isbn');
const bookTitleFromUrl = searchParams.get('bookTitle');

useEffect(() => {
if (bookIsbn) {
setTimeout(() => {
const fetchBookId1 = async () => {
const bookData = await fetchBookId(bookIsbn);
const responseBookId = bookData?.id;
const responseBookTitle = bookData?.title;
if (responseBookId !== undefined) {
setPresetReadBookTitle(responseBookTitle);
console.log('책 제목:', responseBookTitle);
setIsSearchOk(false);
} else {
console.error('책 ID를 가져오는 중 오류가 발생했습니다.');
}
};
fetchBookId1();
}, 1000);
}
}, [bookIsbn]);

useEffect(() => {
if (presetReadBookTitle) {
setReadBookTitle(presetReadBookTitle);
console.log('사전 설정된 책제목 : ', presetReadBookTitle);
} else {
console.log('사전 설정된 책제목이 null');
}
}, [presetReadBookTitle]);

useEffect(() => {
if (isbnFromUrl) {
Expand Down Expand Up @@ -47,6 +79,7 @@ export default function Search({setBookIsbn}: SearchProps) {
readBookTitle={readBookTitle}
setReadBookTitle={setReadBookTitle}
onSearch={handleSearch}
isSearchOk={isSearchOk}
/>

{/* SearchResults 컴포넌트에 검색어 전달 */}
Expand Down
6 changes: 4 additions & 2 deletions src/components/auth/LoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import AuthBtn from './AuthBtn'
import { AuthCredentials } from '../../model/AuthCredentials'
import User from '../../assets/icons/User.svg'
import Lock from '../../assets/icons/Lock.svg'
import { useNavigate } from 'react-router-dom'
import { useNavigate, useLocation } from 'react-router-dom'
import { login } from '../../services/AuthService'
import { LoginRequest } from '../../model/LoginRequest'
import { useAuthStore } from '../../stores/UseCurrentUserStore'

export default function LoginForm() {
const navigate = useNavigate()
const location = useLocation()
const { setUsername, setAccessToken, setRefreshToken } = useAuthStore()

const {
Expand All @@ -28,13 +29,14 @@ export default function LoginForm() {

const onSubmit = async (data: AuthCredentials) => {
const loginRequestData = toLoginRequest(data)
const from = location.state?.from || '/'

try {
const response = await login(loginRequestData)
setAccessToken(response.accessToken)
setRefreshToken(response.refreshToken)
setUsername(loginRequestData.id)
navigate(-1)
navigate(from)
} catch (error) {
console.error('로그인 에러:', error)
}
Expand Down
45 changes: 30 additions & 15 deletions src/components/book/Review.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
import SampleReviewImg from '../../assets/images/SampleReviewImg.svg'
import cn from '../../libs/cn'
import { Review as ReviewType } from '../../model/ReviewListResponse'

// 예시 더미 데이터 하드코딩
export default function Review() {
interface reviewProps {
review: ReviewType
onClick?: () => void
}

export default function Review({ review, onClick }: reviewProps) {
return (
<>
<div
className={cn(
'md:w-36 lg:w-52 xl:w-72 lg:h-60 xl:h-80 flex flex-col bg-[#fafafa] shadow-lg rounded-2xl',
'md:w-36 lg:w-52 xl:w-72 lg:h-80 flex flex-col',
'bg-[#fafafa] shadow-lg rounded-2xl cursor-pointer',
'hover:bg-[#FAFAFA] hover:opacity-20 hover:border-2 hover:border-[#2B5877] hover:inset-0'
)}
onClick={onClick}
>
<img
src={SampleReviewImg}
alt="SampleReviewImg"
className="w-full md:h-auto xl:h-44 rounded-t-2xl"
/>
<p className="text-xs sm:text-lg xl:text-2xl text-[#2B5877] pt-2 px-3 lg:px-8">
생의 외침 속에서 찾는 진정한 나
{review.file ? (
<img
src={review.file.physicalPath}
alt={review.file.logicalName}
className="w-full md:h-auto xl:h-44 rounded-t-2xl object-cover"
/>
) : (
<img
src={SampleReviewImg}
alt="SampleReviewImg"
className="w-full md:h-auto xl:h-44 rounded-t-2xl"
/>
)}
<p className="text-xs sm:text-lg xl:text-2xl text-[#2B5877] pt-2 px-3 lg:px-8 lg:text-nowrap">
{review.title}
</p>
<div className="flex flex-grow pt-7 pb-3 lg:py-3 md:py-4 xl:py-8">
<p className="text-xs text-nowrap xl:text-sm text-[#2B5877] ml-3 lg:ml-8">
김해솔
<div className="flex flex-row pt-7 md:pb-3">
<p className="text-xs text-nowrap xl:text-sm text-[#2B5877] ml-3 lg:ml-8 lg:py-3 md:py-4 xl:py-8">
{review.userId}
</p>
<p className="text-xs text-nowrap xl:text-sm text-[#918F8F] pl-8 lg:pl-10 xl:pl-24">
2024. 10. 5.
<p className="w-full text-xs text-nowrap xl:text-sm text-[#918F8F] pl-8 lg:pl-10 xl:pl-24 lg:py-3 md:py-4 xl:py-8">
{review.updatedAt}
</p>
</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions src/hooks/UseBookDetail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import { useCurrentBookState } from '../stores/UseCurrentBookStore.ts'
import { getReviewsByBookId } from '../services/ReviewService.ts'
import { ReviewListResponse } from '../model/ReviewListResponse.ts'
import { ErrorResponse } from '../model/ReviewResponse.ts'
import { Review } from '../model/ReviewListResponse.ts'

export function useBookDetails() {
const { bookId, setBookId } = useCurrentBookState()
const { bookData } = useBook()
const navigate = useNavigate()
const [isAccessDenied, setIsAccessDenied] = useState(false)
const [isReviewed, setIsReviewed] = useState(false)
const [reviews, setReviews] = useState<Review[]>([])

useEffect(() => {
const fetchBookData = async () => {
Expand All @@ -35,6 +37,7 @@ export function useBookDetails() {

if ('reviews' in reviewsResponse) {
console.log('리뷰 응답 : ', reviewsResponse.reviews)
setReviews(reviewsResponse.reviews)
setIsReviewed(reviewsResponse.reviews.length > 0)
} else {
console.log('응답 없음 : ', reviewsResponse.message)
Expand All @@ -52,5 +55,6 @@ export function useBookDetails() {
bookData: isAccessDenied ? null : bookData,
isAccessDenied,
isReviewed,
reviews,
}
}
3 changes: 2 additions & 1 deletion src/model/ReviewResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface FileInfo {
// 책 정보 인터페이스
export interface BookInfo {
id: number
isbn: string
title: string
author: string
description: string
Expand All @@ -30,7 +31,7 @@ export interface ReviewDetailResponse {
content: string
name: string
file: FileInfo
book: BookInfo[]
book: BookInfo
createdAt: string
updatedAt: string
}
5 changes: 4 additions & 1 deletion src/pages/Article.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface ArticleData {
title: string;
thumbnail?: string;
context: string;
bookId: number;
bookIsbn: string;
date: string;
}
Expand All @@ -38,6 +39,7 @@ useEffect(() => {
setArticleData({
title: '스벨트는 우주 최강 프레임워크인 것 같다.',
context: '아무래도 리액트를 다 스벨트로 갈아엎어 버리고 싶다. 나는 스벨트를 할 줄 모른다.',
bookId: 64,
bookIsbn: '9791193926161',
date: '2021-01-01',
thumbnail: undefined,
Expand All @@ -56,7 +58,8 @@ useEffect(() => {
const tempData = {
title: response.title,
context: response.content,
bookIsbn: response.id.toString(),
bookId: response.id,
bookIsbn: response.book.isbn,
date: response.createdAt,
thumbnail: response.file?.physicalPath,
};
Expand Down
40 changes: 27 additions & 13 deletions src/pages/Book.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { useNavigate, useLocation } from 'react-router-dom'
import Review from '../components/book/Review.tsx'
import { getDisplayAuthor } from '../libs/AuthorUtils'
import cn from '../libs/cn.ts'
Expand All @@ -8,7 +8,7 @@ import { useAuthStore } from '../stores/UseCurrentUserStore.ts'
import { useBookDetails } from '../hooks/UseBookDetail.ts'

export default function Book() {
const { bookData, isAccessDenied, isReviewed } = useBookDetails()
const { bookData, isAccessDenied, isReviewed, reviews } = useBookDetails()
const navigate = useNavigate()
const { isLogin } = useAuthStore()

Expand All @@ -19,8 +19,22 @@ export default function Book() {
? `/editor?isbn=${encodeURIComponent(bookData.isbn)}&bookTitle=${encodeURIComponent(bookData.title)}`
: '/editor'
navigate(url)
} else if (!isLogin) {
navigate('/requestLogin', {
state: { from: location.pathname, action: '작성' },
})
}
}

const gotoArticle = (id: number) => {
const articleSlug = id.toString()

if (!isLogin) {
navigate('/requestLogin', {
state: { from: location.pathname, action: '감상' },
})
} else {
navigate('/login')
navigate(`/article/${articleSlug}`)
}
}

Expand Down Expand Up @@ -105,22 +119,22 @@ export default function Book() {
{isReviewed ? (
<div className="flex justify-center mt-11">
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6 mx-auto">
<Review />
<Review />
<Review />
<Review />
{reviews.map((review) => (
<Review
key={review.id}
review={review}
onClick={() => gotoArticle(review.id)}
/>
))}
</div>
</div>
) : (
<div className="flex flex-col px-20 pt-14 items-center">
<div className="mt-12 flex justify-center">
<img
src={NonReviwedBook}
alt="NonReviwedBook"
className="w-[136px] md:w-44 xl:w-52 h-auto "
alt="No Reviews"
className="h-44 md:h-60 lg:h-80"
/>
<p className="text-[16px] md:text-xl xl:text-2xl text-[#918f8f] mt-10 text-center text-nowrap">
아직 남겨진 독후감이 없습니다. <br /> 첫 번째 독후감을 남겨보세요!
</p>
</div>
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default function Editor() {
} else {
setTitle(response.title);
setContext(response.content);
setBookIsbn(response.id.toString());
setBookIsbn(response.book.isbn);
setThumbnail(response.file.physicalPath); // 수정: 썸네일이 URL로 제공될 경우 처리
setIsPostOk(true);
}
Expand Down
Loading

0 comments on commit c169971

Please sign in to comment.