-
-
+
+
+
+ {title}
+
+
{author}
+
+
+
-
-
-
- {title}
+
+ >
+ );
+ } else {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+ {title}
+
+
{author}
+
+
+
+ {bookKeywordList.map((keyword, idx) => {
+ return (
+
+ );
+ })}
+
-
{author}
-
-
-
-
-
-
-
-
-
+
+ >
+ );
+ }
+ };
+
+ return (
+ <>
+
{renderCard(cardType)}
>
);
};
diff --git a/src/components/BookListSlide.js b/src/components/BookListSlide.js
index cc11def..b5babc9 100644
--- a/src/components/BookListSlide.js
+++ b/src/components/BookListSlide.js
@@ -1,4 +1,6 @@
import { useState, useEffect } from 'react';
+import Slider from 'react-slick';
+import { Swiper, SwiperSlide } from 'swiper/react';
import axios from 'axios';
// COMPONENTS
@@ -7,23 +9,57 @@ import BookCard from './BookCard';
// STYLES
import styles from '../styles/BookListSlide.module.css';
+import 'slick-carousel/slick/slick.css';
+import 'slick-carousel/slick/slick-theme.css';
+import 'swiper/css';
+import 'swiper/css/navigation';
+import 'swiper/css/pagination';
+import { set } from 'react-hook-form';
+
+const BookListSlide = ({
+ list,
+ bigCategory,
+ midCategoryTitle,
+ title,
+ author,
+ imageUrl,
+}) => {
+ var settings = {
+ dots: true,
+ infinite: false,
+ speed: 500,
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ };
-const BookListSlide = ({ bigCategory, midCategoryTitle, author }) => {
return (
<>
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ {list.map((item) => {
+ return (
+
+
+
+ );
+ })}
+
+
-
+
>
);
};
diff --git a/src/components/Button.jsx b/src/components/Button.jsx
index f1934ba..487e0be 100644
--- a/src/components/Button.jsx
+++ b/src/components/Button.jsx
@@ -39,7 +39,7 @@ const Button = ({ text, type }) => {
};
const renderButton = (url, type) => {
- if (type === 'add' || type === 'delete') {
+ if (type === 'add' || type === 'delete' || type === 'exp') {
return
;
} else {
if (type === 'logout') {
diff --git a/src/components/FeedCard.js b/src/components/FeedCard.js
index c9d17f2..cbd42c1 100644
--- a/src/components/FeedCard.js
+++ b/src/components/FeedCard.js
@@ -3,23 +3,23 @@ import React from 'react';
//STYLES
import '../styles/FeedCard.css';
-const FeedCard = ({ book_name, book_author, user_nickname }) => {
+const FeedCard = ({ title, author, nickname, imgUrl, comment }) => {
return (
<>
-
- 죽는 날까지 하늘을 우러러 한 점 부끄럼이 없기를
-
+
{comment}
-
+
+
+
-
서시
-
윤동주
+
{title}
+
{author}
@@ -27,7 +27,7 @@ const FeedCard = ({ book_name, book_author, user_nickname }) => {
diff --git a/src/components/Modal/Experience.jsx b/src/components/Modal/Experience.jsx
new file mode 100644
index 0000000..beec330
--- /dev/null
+++ b/src/components/Modal/Experience.jsx
@@ -0,0 +1,75 @@
+import React, { useState, useEffect } from 'react';
+import { useSearchParams } from 'react-router-dom';
+
+// SERVICE
+import api from '../../services/api';
+
+// COMPONENTS
+import BookInfoCard from '../BookDetailCard';
+
+// STYLE
+import '../../styles/Experience.css';
+
+const Experience = ({ onClose }) => {
+ // 모달 창 닫는 함수
+ const handleClose = () => {
+ onClose?.();
+ };
+
+ const [bookInfo, setBookInfo] = useState([]);
+ const [searchParams, setSearchParams] = useSearchParams();
+
+ const getIsbn = () => {
+ let isbn = searchParams.get('isbn');
+
+ api.get(`/api/book/detail?isbn=${isbn}`).then((res) => {
+ setBookInfo(res.data);
+ });
+ };
+
+ useEffect(() => {
+ getIsbn();
+ }, []);
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default Experience;
diff --git a/src/components/Pagination.jsx b/src/components/Pagination.jsx
new file mode 100644
index 0000000..4b25e64
--- /dev/null
+++ b/src/components/Pagination.jsx
@@ -0,0 +1,51 @@
+import React from "react";
+import { Link } from "react-router-dom";
+import styled from "styled-components";
+
+const Pagination = ({ booksPerPage, totalBooks, paginate, bookTitle }) => {
+ const pageNumbers = [];
+ console.log(totalBooks, booksPerPage);
+ for (let i = 1; i <= Math.ceil(totalBooks / booksPerPage); i++) {
+ pageNumbers.push(i);
+ console.log(pageNumbers);
+ }
+
+ return (
+
+ );
+};
+
+export default Pagination;
+
+const PaginationContainer = styled.ul`
+ display: flex;
+ justify-content: center;
+`;
diff --git a/src/components/SearchBox.jsx b/src/components/SearchBox.jsx
new file mode 100644
index 0000000..6eb091b
--- /dev/null
+++ b/src/components/SearchBox.jsx
@@ -0,0 +1,145 @@
+import React, { useState } from 'react'
+import SearchResultListModal from './SearchResultListModal';
+
+// style
+import "../styles/SearchStyles.css";
+import styled from 'styled-components';
+
+const SearchBox = ({
+ input,
+ setInput,
+ searchType,
+ setSearchType,
+ searchBook,
+ isShow,
+ setIsShow,
+ searchData,
+}) => {
+
+
+ return (
+
{
+ e.stopPropagation();
+ // handleSearchResultShow();
+ setIsShow(true);
+ }}
+ >
+
+ {input.length > 0 && isShow && searchData.length > 0 ? (
+ // {
+ // e.stopPropagation();
+ // }}
+ // />
+ {
+ e.stopPropagation();
+ }}
+ />
+ ) : null}
+
+ );
+};
+
+export default SearchBox;
+
+const SearchInputWrap = styled.div`
+ width: 100%;
+ height: 60px;
+ box-shadow: 0px 2px 4px #00000033;
+ padding: 10px 0px 10px 1rem;
+ border-radius: 5px;
+ border: 1px solid #b0b0b0;
+ display: flex;
+ align-items: center;
+ font-size: 20px;
+ /* margin-bottom: 40px; */
+`;
+
+const SelectMenu = styled.select`
+ width: 140px;
+ font-size: 20px;
+ border: none;
+ /* padding-left: 10px; */
+ text-align: center;
+ &:focus {
+ outline: none;
+ }
+`;
+
+const SearchInput = styled.input`
+ border: none;
+ border-left: 1px solid #c0c0c0;
+ margin-left: 1rem;
+ padding-left: 1rem;
+ font-size: 20px;
+ width: 100%;
+ &:focus {
+ outline: none;
+ }
+`;
\ No newline at end of file
diff --git a/src/components/SearchResultList.jsx b/src/components/SearchResultList.jsx
index 252e637..67741ae 100644
--- a/src/components/SearchResultList.jsx
+++ b/src/components/SearchResultList.jsx
@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import '../styles/SearchResultList.css';
+// 구글 책 검색
const SearchResultList = ({ book, type, updateBook }) => {
let listType = ['myBook'].includes(type) ? type : 'search';
// console.log('book: ',book);
@@ -49,6 +50,7 @@ const SearchResultList = ({ book, type, updateBook }) => {
);
}
+ return null;
})}
>
diff --git a/src/components/SearchResultListModal.jsx b/src/components/SearchResultListModal.jsx
new file mode 100644
index 0000000..c77de4f
--- /dev/null
+++ b/src/components/SearchResultListModal.jsx
@@ -0,0 +1,66 @@
+import React from 'react'
+import "../styles/SearchResultList.css";
+import { Link } from 'react-router-dom';
+
+const SearchResultListModal = ({ book, type, updateBook, addInput }) => {
+ let listType = ["myBook"].includes(type) ? type : "search";
+
+ const updateBookTitle = (pickTitle) => {
+ updateBook(pickTitle);
+ };
+
+ return (
+ <>
+
+ {book.map((item) => {
+ console.log(item);
+ // 작가에서 누구 지음 이걸 빼주도록 하기 -> 작가 이름을 어떻게 필터링 처리를 할까?
+
+ let title = item && item.title;
+ let author = item && item.author;
+ let thumbnail = item && item.imageUrl;
+ let keyword = item && item.name;
+
+ // 책 제목 && 작가 UI
+ if (title !== undefined) {
+ return (
+
+ );
+ }
+
+ // 키워드 UI
+ if (keyword !== undefined) {
+ return (
+
addInput(`#${keyword}`)}
+ >
+ {keyword}
+
+ );
+ }
+ })}
+
+ >
+ );
+}
+
+SearchResultListModal.defaultProps = {
+ type: "search",
+};
+
+export default SearchResultListModal
\ No newline at end of file
diff --git a/src/components/Slider.jsx b/src/components/Slider.jsx
index 9549acb..e420533 100644
--- a/src/components/Slider.jsx
+++ b/src/components/Slider.jsx
@@ -1,49 +1,50 @@
-import React from "react";
-import { Swiper, SwiperSlide } from "swiper/react";
-import "swiper/css";
-import "../styles/Slider.css";
+import React from 'react';
+import { Swiper, SwiperSlide } from 'swiper/react';
+import 'swiper/css';
+import '../styles/Slider.css';
-import { Navigation, Pagination, Scrollbar, A11y } from "swiper/modules";
+import { Navigation, Pagination, Scrollbar, A11y } from 'swiper/modules';
-import "swiper/css";
-import "swiper/css/navigation";
-import "swiper/css/pagination";
-import "swiper/css/scrollbar";
+import 'swiper/css';
+import 'swiper/css/navigation';
+import 'swiper/css/pagination';
+import 'swiper/css/scrollbar';
const Slider = ({ title, subtitle, isBestSeller, bookTitle, bookAuthor }) => {
- const numberOfSlides = 10;
+ const numberOfSlides = 10;
- const slides = Array.from({ length: numberOfSlides }, (_, index) => (
-
-
-
-
-
{bookTitle}
-
{bookAuthor}
-
-
- {isBestSeller && {index + 1}
}
-
- ));
+ const slides = Array.from({ length: numberOfSlides }, (_, index) => (
+
+
+
+
+
{bookTitle}
+
{bookAuthor}
+
+
+ {isBestSeller && {index + 1}
}
+
+ ));
- return (
-
- );
-}
+ return (
+
+ );
+};
export default Slider;
diff --git a/src/pages/BookDetail.jsx b/src/pages/BookDetail.jsx
index bbf6405..266b1ba 100644
--- a/src/pages/BookDetail.jsx
+++ b/src/pages/BookDetail.jsx
@@ -1,4 +1,8 @@
-import React, { useRef } from 'react';
+import React, { useState, useRef, useEffect } from 'react';
+import { useParams, useSearchParams } from 'react-router-dom';
+
+// SERVICE
+import api from '../services/api';
// COMPONENTS
import Header from '../components/Header';
@@ -8,10 +12,12 @@ import Review from '../components/Review';
import Title from '../components/ArrowTitle';
import BookCard from '../components/BookCard';
import Footer from '../components/Footer';
+import ModalPortal from '../components/Modal/Portal';
+import ExpModal from '../components/Modal/Experience';
+import MyListModal from '../components/Modal/MyListModal';
// STYLES
import '../styles/BookDetail.css';
-import { Link } from 'react-router-dom';
const BookDetail = () => {
const scrollRef = useRef([]);
@@ -19,6 +25,32 @@ const BookDetail = () => {
ref.scrollIntoView({ behavior: 'smooth' });
};
+ const [modalOn, setModalOn] = useState(false);
+
+ const handleModal = () => {
+ setModalOn(!modalOn);
+ };
+
+ const [searchParams, setSearchParams] = useSearchParams();
+ const [bookInfo, setBookInfo] = useState([]);
+ const [bookKeywordList, setBookKeywordList] = useState([]);
+
+ const getIsbn = () => {
+ let isbn = searchParams.get('isbn');
+ // console.log(isbn);
+
+ api.get(`/api/book/detail?isbn=${isbn}`).then((res) => {
+ // console.log(res.data.title);
+ // console.log(res.data);
+ setBookInfo(res.data);
+ setBookKeywordList(res.data.bookKeywordList);
+ });
+ };
+
+ useEffect(() => {
+ getIsbn();
+ }, []);
+
return (
<>
@@ -26,25 +58,38 @@ const BookDetail = () => {
-
+
+
+
-
해리포터와 불의 잔
-
J. K. 롤링
+
{bookInfo.title}
+
{bookInfo.author}
-
-
-
-
+ {bookKeywordList.map((item) => {
+ return ;
+ })}
diff --git a/src/pages/BookList.jsx b/src/pages/BookList.jsx
index 93f91b5..51d9e2a 100644
--- a/src/pages/BookList.jsx
+++ b/src/pages/BookList.jsx
@@ -1,7 +1,11 @@
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
+import Slider from 'react-slick';
import axios from 'axios';
+// SERVICE
+import api from '../services/api';
+
// COMPONENTS
import Header from '../components/Header';
import Title from '../components/ArrowTitle';
@@ -11,157 +15,40 @@ import BookListSlide from '../components/BookListSlide';
// STYLES
import '../styles/BookList.css';
+import 'slick-carousel/slick/slick.css';
+import 'slick-carousel/slick/slick-theme.css';
const BookList = () => {
+ var settings = {
+ dots: true,
+ infinite: true,
+ speed: 500,
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ };
+
// 대분류
let { title } = useParams();
const [bigCategory, setBigCategory] = useState('');
// 중분류
const [midCategory, setMidCategory] = useState([]);
-
- const categories = [
- {
- 총류: [
- '도서학·서지학',
- '문헌정보학',
- '백과사전',
- '강연집·수필집·연설문집',
- '일반연속간행물',
- '일반학회·단체·협회·기관',
- '신문·언론·저널리즘',
- '일반전집·총서',
- '향토자료',
- ],
- 철학: [
- '형이상학',
- '인식론·인과론·인간학',
- '철학의 체계',
- '경학',
- '동양철학·7사상',
- '서양철학',
- '논리학',
- '심리학',
- '윤리학·도덕철학',
- ],
- 종교: [
- '비교종교',
- '불교',
- '기독교',
- '도교',
- '천도교',
- '신도',
- '힌두교·브라만교',
- '이슬람교(회교)',
- '기타 제종교',
- ],
- 사회과학: [
- '통계학',
- '경제학',
- '사회학·사회문제',
- '정치학',
- '행정학',
- '법학',
- '교육학',
- '풍속·예절·민속학',
- '국방·군사학',
- ],
- 자연과학: [
- '수학',
- '물리학',
- '화학',
- '천문학',
- '지학',
- '광물학',
- '생명과학',
- '식물학',
- '동물학',
- ],
- 기술과학: [
- '의학',
- '농업·농학',
- '공학·공업일반·토목공학·환경',
- '건축공학',
- '기계공학',
- '전기공학·전자공학',
- '화학공학',
- '제조업',
- '생활과학',
- ],
- 예술: [
- '건축물',
- '조각·조형예술',
- '공예·장식미술',
- '서예',
- '회화·도화',
- '사진예술',
- '음악',
- '공연예술·매체예술',
- '오락·스포츠',
- ],
- 언어: [
- '한국어',
- '중국어',
- '일본어·기타아시아제어',
- '영어',
- '독일어',
- '프랑스어',
- '스페인어·포르투갈어',
- '이탈리아어',
- '기타제어',
- ],
- 문학: [
- // smallCategory 페이지 api 테스트 위해서 한국문학 -> 한국소설로 바꿈
- '한국소설',
- '중국문학',
- '일본문학·기타아시아문학',
- '영미문학',
- '독일문학',
- '프랑스문학',
- '스페인·포르투갈문학',
- '이탈리아문학',
- '기타제문학',
- ],
- 역사: [
- '아시아',
- '유럽',
- '아프리카',
- '북아프리카',
- '남아메리카',
- '오세아니아',
- '양극지방',
- '지리',
- '전기',
- ],
- },
- ];
+ const [resMidBookList, setResMidBookList] = useState([]);
// 초기에 랜더링될 때 한 번만 실행
useEffect(() => {
// 대분류 지정
setBigCategory(title);
- // {
- // smallCategory.map((e) => {
- // console.log(e);
- // });
- // }
- // setCategory(category[title]);
- // console.log(smallCategory);
- // 중분류 가져오기
+ api.get('/api/category/big').then((res) => {
+ setMidCategory(res.data[title]);
+ });
- // categories.map((res) => {
- // console.log('대분류:', title);
- // setMidCategory(res[title]);
- // });
- axios
- .get(
- 'https://port-0-backend-book-pharmacy-umnqdut2blqqhv7sd.sel5.cloudtype.app/api/category/big',
- )
- .then((res) => {
- console.log(res.data[title]);
- setMidCategory(res.data[title]);
+ api.get(`/api/book/list/big?name=${title}`).then((res) => {
+ res.data.map(() => {
+ setResMidBookList(res.data);
});
+ });
}, []);
return (
@@ -171,23 +58,43 @@ const BookList = () => {
{bigCategory}
-
- {midCategory?.map((e) => {
- // console.log(e);
- // setNameList(e.name);
- return (
-
- );
- })}
-
+
+ {resMidBookList.map((list, idx) => {
+ return (
+ // 중분류 타이틀 렌더링
+
+
+
+
+
+
+
+
+ {/* 중분류에 해당하는 책 리스트 데이터 바인딩 */}
+ {/* {list.bookList.map((item) => {
+ return (
+
+ );
+ })} */}
+
+
+ );
+ })}
diff --git a/src/pages/Feed.jsx b/src/pages/Feed.jsx
index 4013942..f194a65 100644
--- a/src/pages/Feed.jsx
+++ b/src/pages/Feed.jsx
@@ -1,13 +1,91 @@
-import React from 'react';
+import React, { useState, useEffect } from 'react';
+import axios from 'axios';
+
+// SERVICES
+import api from '../services/api';
// COMPONENTS
import Header from '../components/Header';
import FeedGrid from '../components/FeedGrid';
+import FeedCard from '../components/FeedCard';
// STYLES
import '../styles/Feed.css';
const Feed = () => {
+ const [dogArr, setDogArr] = useState([]);
+ const [feedArr, setFeedArr] = useState([]);
+ const [page, setPage] = useState(0);
+ const [isLoading, setIsLoading] = useState(false);
+
+ // Intersection Observer 설정
+ const handleObserver = (entries) => {
+ // console.log(entries);
+ const target = entries[0];
+ if (target.isIntersecting && !isLoading) {
+ setPage((prevPage) => prevPage + 1);
+ }
+ };
+
+ useEffect(() => {
+ const observer = new IntersectionObserver(handleObserver, {
+ threshold: 0,
+ });
+ // 최하단 요소를 관찰 대상으로 지정함
+ const observerTarget = document.getElementById('observer');
+ // 관찰 시작
+ if (observerTarget) {
+ observer.observe(observerTarget);
+ }
+ }, []);
+
+ // page 변경 감지에 따른 API호출
+ useEffect(() => {
+ fetchData();
+ console.log(page);
+ }, [page]);
+
+ let feedFetchData = { page: { page }, size: 9 };
+
+ // API를 호출하는 부분
+ const fetchData = async () => {
+ setIsLoading(true);
+ try {
+ // api.get('/api/feeds/all', feedFetchData).then((res) => {
+ // // console.log(res.data.content);
+ // setFeedArr(res.data.content);
+ // setFeedArr((prevData) => [...prevData, ...res.data.content]);
+ // });
+ const API_URL =
+ 'https://port-0-backend-book-pharmacy-umnqdut2blqqhv7sd.sel5.cloudtype.app/api/feeds/all?page=0&size=9';
+
+ const response = await axios.get(API_URL, feedFetchData);
+ // .then((res) => {
+ // // console.log(res.data.content);
+ // setFeedArr(res.data.content);
+ // });
+
+ // const newData = response.data.map((dogImg) => ({
+ // id: dogImg.id,
+ // dogUrl: dogImg.url,
+ // }));
+
+ const newData = response.data.content.map((item) => ({
+ title: item.bookTitle,
+ author: item.bookAuthor,
+ comment: item.comment,
+ image: item.imgUrl,
+ nickName: item.clientNickname,
+ }));
+
+ // //불러온 데이터를 배열에 추가
+ setFeedArr((prevData) => [...prevData, ...newData]);
+ } catch (error) {
+ console.log(error);
+ }
+ setIsLoading(false);
+ };
+
return (
<>
@@ -16,8 +94,20 @@ const Feed = () => {
추천 피드
-
+ {feedArr.map((item, idx) => {
+ return (
+
+ );
+ })}
+
>
);
diff --git a/src/pages/Login.jsx b/src/pages/Login.jsx
index a493183..6ceaa52 100644
--- a/src/pages/Login.jsx
+++ b/src/pages/Login.jsx
@@ -201,8 +201,6 @@ const ImageContent = styled.div`
flex: 1;
max-width: 50%;
box-sizing: border-box;
- /* background-image: url('https://d3udu241ivsax2.cloudfront.net/v3/images/login/promotion_intro_bg.ac5237a5bed49b864cccee5224a464e4.jpg'); */
- /* background-image: url('https://www.flybook.kr/FlyBookSitePublishing/assets/img/main/top-banner.jpg'); */
background-image: url('../../public/Login-Banner.png');
background: url(${banner});
background-size: cover;
diff --git a/src/pages/Search.jsx b/src/pages/Search.jsx
index 098dad0..d1bacbc 100644
--- a/src/pages/Search.jsx
+++ b/src/pages/Search.jsx
@@ -1,311 +1,329 @@
-import { useContext, useEffect, useState } from 'react';
-import { Link } from 'react-router-dom';
-import axios from 'axios';
+import { useContext, useEffect, useState } from "react";
+import { Link, useNavigate } from "react-router-dom";
+import axios from "axios";
// COMPONENTS
-import Header from '../components/Header';
-import SearchResultList from '../components/SearchResultList';
+import Header from "../components/Header";
+import SearchResultListModal from "../components/SearchResultListModal";
// STYLES
-import '../styles/SearchStyles.css';
-import bookImg1 from '../assets/category-book-총류.jpg';
-import bookImg2 from '../assets/category-book-철학.jpg';
-import bookImg3 from '../assets/category-book-종교.jpg';
-import bookImg4 from '../assets/category-book-사회과학.jpg';
-import bookImg5 from '../assets/category-book-자연과학.jpg';
-import bookImg6 from '../assets/category-book-기술과학.jpg';
-import bookImg7 from '../assets/category-book-예술.jpg';
-import bookImg8 from '../assets/category-book-언어.jpg';
-import bookImg9 from '../assets/category-book-문학.png';
-import bookImg10 from '../assets/category-book-역사.jpg';
-import { LoginContext } from '../contexts/LoginContextProvider';
+import "../styles/SearchStyles.css";
+import bookImg1 from "../assets/category-book-총류.jpg";
+import bookImg2 from "../assets/category-book-철학.jpg";
+import bookImg3 from "../assets/category-book-종교.jpg";
+import bookImg4 from "../assets/category-book-사회과학.jpg";
+import bookImg5 from "../assets/category-book-자연과학.jpg";
+import bookImg6 from "../assets/category-book-기술과학.jpg";
+import bookImg7 from "../assets/category-book-예술.jpg";
+import bookImg8 from "../assets/category-book-언어.jpg";
+import bookImg9 from "../assets/category-book-문학.png";
+import bookImg10 from "../assets/category-book-역사.jpg";
+import { LoginContext } from "../contexts/LoginContextProvider";
+import api from "../services/api";
+
const Search = () => {
- const baseURL = 'https://api.bookpharmacy.store/api';
- const [input, setInput] = useState(''); // 검색 데이터
- const [searchData, setSearchData] = useState([]); // 검색 결과 데이터
- const [categories, setCategories] = useState([]); // 카테고리 데이터
- const [isShow, setIsShow] = useState(false); // 검색창 모달창
+ const baseURL = "https://api.bookpharmacy.store/api";
+ const navigate = useNavigate();
+ const [input, setInput] = useState(""); // 검색 데이터
+ const [inputKeyword, setInputKeyword] = useState([]); // 키워드 검색 데이터
+ const [searchData, setSearchData] = useState([]); // 검색 결과 데이터
+ const [categories, setCategories] = useState([]); // 카테고리 데이터
+ const [isShow, setIsShow] = useState(false); // 검색창 모달창
+ const [searchType, setSearchType] = useState("title"); // 검색 유형 상태
+
+ const { userId, userPwd } = useContext(LoginContext);
+ const loginData = { username: userId, password: userPwd };
+
+ // 카테고리 배경 색상(10개) && 카테고리별 대표 책 이미지 정보
+ const categoriesInfo = [
+ { color: "#D4F4FF", image: bookImg1 },
+ { color: "#FFF2EC", image: bookImg2 },
+ { color: "#FFE3B5", image: bookImg3 },
+ { color: "#FFF4B6", image: bookImg4 },
+ { color: "#D6D6D6", image: bookImg5 },
+ { color: "#C2E2FF", image: bookImg6 },
+ { color: "#FFCACD", image: bookImg7 },
+ { color: "#DFFFF8", image: bookImg8 },
+ { color: "#CBD4F0", image: bookImg9 },
+ { color: "#D6CABC", image: bookImg10 },
+ ];
- const { userId, userPwd } = useContext(LoginContext);
- const loginData = { username: userId, password: userPwd };
- // 카테고리 배경 색상(10개) && 카테고리별 대표 책 이미지 정보
- const categoriesInfo = [
- { color: '#D4F4FF', image: bookImg1 },
- { color: '#FFF2EC', image: bookImg2 },
- { color: '#FFE3B5', image: bookImg3 },
- { color: '#FFF4B6', image: bookImg4 },
- { color: '#D6D6D6', image: bookImg5 },
- { color: '#C2E2FF', image: bookImg6 },
- { color: '#FFCACD', image: bookImg7 },
- { color: '#DFFFF8', image: bookImg8 },
- { color: '#CBD4F0', image: bookImg9 },
- { color: '#D6CABC', image: bookImg10 },
- ];
- const setCategory = async (res) => {
- const fetchedCategories = res.data;
- const transformedCategories = Object.keys(fetchedCategories).map(
- (key, index) => {
- const { color, image } = categoriesInfo[index % categoriesInfo.length]; // 객체에서 색상과 이미지를 가져옴
- return {
- title: key,
- subtitle: fetchedCategories[key].join(', '),
- image: image,
- color: color,
- };
- },
- );
- setCategories(transformedCategories);
- };
+ // 카테고리 대분류, 중분류 GET 요청 및 요청 데이터 사용하기 쉽게 처리
+ useEffect(() => {
+ let username = localStorage.getItem("id");
+ let password = localStorage.getItem("password");
- // 카테고리 대분류, 중분류 GET 요청 및 요청 데이터 사용하기 쉽게 처리
- useEffect(() => {
- let username = localStorage.getItem('id');
- let password = localStorage.getItem('password');
+ const fetchCategories = async () => {
+ try {
+ axios
+ .post(
+ "https://api.bookpharmacy.store/login",
+ { username: username, password: password },
+ { withCredentials: true }
+ )
+ .then(async () => {
+ // console.log('성공');
+ axios
+ .get("https://api.bookpharmacy.store/api/category/big", {
+ withCredentials: true,
+ })
+ .then((res) => {
+ setCategories(res.data);
+ });
+ })
+ .catch((err) => {
+ console.log(err);
+ });
+ axios
+ .get("https://api.bookpharmacy.store/api/category/big", {
+ withCredentials: true,
+ })
+ .then((res) => {
+ setCategories(res.data);
+ });
+ } catch (error) {
+ console.error("Error fetching categories:", error);
+ }
+ };
- const fetchCategories = async () => {
- try {
- axios
- .post(
- 'https://api.bookpharmacy.store/login',
- { username: username, password: password },
- { withCredentials: true },
- )
- .then(async () => {
- // console.log('성공');
- axios
- .get('https://api.bookpharmacy.store/api/category/big', {
- // withCredentials: true,
- })
- .then((res) => {
- setCategories(res.data);
- });
- })
- .catch((err) => {
- console.log(err);
- });
- } catch (error) {
- console.error('Error fetching categories:', error);
- }
- };
+ fetchCategories();
+ }, []);
- fetchCategories();
- }, []);
+ // 카테고리 아이템을 렌더링 함수
+ const renderCategoryItem = ({ title, subtitle, image, color }, index) => (
+
+
+
+
+
{title}
+ {subtitle}
+
+
+
+
+
+ );
- // 카테고리 아이템을 렌더링 함수
- const renderCategoryItem = ({ title, subtitle, image, color }, index) => (
-
-
-
-
-
{title}
- {subtitle}
-
-
-
-
-
- );
+ // 함수로 추천 키워드 리스트를 생성하는 함수
+ const renderKeywordList = (title, keywords) => (
+
+ {title}
+
+ {keywords.map((keyword, index) => (
+ -
+ {keyword}
+
+ ))}
+
+
+ );
- // 함수로 추천 키워드 리스트를 생성하는 함수
- const renderKeywordList = (title, keywords) => (
-
- {title}
-
- {keywords.map((keyword, index) => (
- -
- {keyword}
-
- ))}
-
-
- );
+ // 추천 검색어 리스트
+ const recommendedSearchKeywords = [
+ "감정",
+ "해리포터",
+ "화장품",
+ "하늘 높이 비상",
+ "감정",
+ // Add more keywords as needed
+ ];
- // 추천 검색어 리스트
- const recommendedSearchKeywords = [
- '감정',
- '해리포터',
- '화장품',
- '하늘 높이 비상',
- '감정',
- '해리포터',
- '화장품',
- '하늘 높이 비상',
- '감정',
- '해리포터',
- '화장품',
- '하늘 높이 비상',
- '감정',
- '해리포터',
- '화장품',
- '하늘 높이 비상',
- '감정',
- '해리포터',
- '화장품',
- '하늘 높이 비상',
- '감정',
- '해리포터',
- '화장품',
- '하늘 높이 비상',
- // Add more keywords as needed
- ];
+ // 사용자 추천 키워드 리스트
+ const userRecommendedKeywords = [
+ "#감정",
+ "#해리포터",
+ "#화장품",
+ "#하늘 높이 비상",
+ // Add more keywords as needed
+ ];
- // 사용자 추천 키워드 리스트
- const userRecommendedKeywords = [
- '#감정',
- '#해리포터',
- '#화장품',
- '#하늘 높이 비상',
- '#감정',
- '#해리포터',
- '#화장품',
- '#하늘 높이 비상',
- '#감정',
- '#해리포터',
- '#화장품',
- '#하늘 높이 비상',
- '#감정',
- '#해리포터',
- '#화장품',
- '#하늘 높이 비상',
- // Add more keywords as needed
- ];
+ // 검색할 때, 0.1초 딜레이 걸기 -> 끊기는 느낌을 방지
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ fetchBooks(input);
+ }, 100);
- // 검색할 때, 0.1초 딜레이 걸기 -> 끊기는 느낌을 방지
- useEffect(() => {
- const timer = setTimeout(() => {
- fetchBooks(input);
- }, 100);
+ // cleanup 함수를 반환하여 컴포넌트가 언마운트될 때 타이머를 해제합니다.
+ return () => clearTimeout(timer);
+ }, [input]);
- // cleanup 함수를 반환하여 컴포넌트가 언마운트될 때 타이머를 해제합니다.
- return () => clearTimeout(timer);
- }, [input]);
+ const fetchBooks = async (searchInput) => {
+ if (input.trim() === "") return; // 빈 문자열일 때 API 호출 방지
- const fetchBooks = async (searchInput) => {
- if (input.trim() === '') return; // 빈 문자열일 때 API 호출 방지
+ let endpoint = "";
+ if (searchType === "title") {
+ endpoint = `/api/search/book?title=${searchInput}&target=modal`;
+ }
+ if (searchType === "author") {
+ endpoint = `/api/search/book?author=${searchInput}&target=modal`;
+ }
+ if (searchType === "keyword") {
+ endpoint = `/api/search/keyword?name=${searchInput}&target=modal`;
+ }
- try {
- const response = await axios.get(
- `https://www.googleapis.com/books/v1/volumes?q=${searchInput}&key=AIzaSyDUtFpAVpNPHCEW-pxSxpTHSACNjko_MCc&maxResults=10`,
- );
- const booksData = response.data.items
- ? response.data.items.slice(0, 6)
- : []; // 검색창에서 6개의 데이터만 보여줌
+ try {
+ const response = await api.get(
+ endpoint
+ );
+ console.log("test", searchType,response.data);
+ setSearchData(response.data);
+ } catch (error) {
+ console.error("Failed to fetch books:", error);
+ }
+ };
- setSearchData(booksData);
- } catch (error) {
- console.error('Failed to fetch books:', error);
- }
- };
+ // 검색창 엔터 및 버튼 이벤트 처리
- // 검색창 엔터 및 버튼 이벤트 처리
+ const searchBook = (evt) => {
+ if (evt.key === "Enter") {
+ fetchBooks(input);
+ navigate(`/search/result/${input}`)
+ }
+ };
- const searchBook = (evt) => {
- if (evt.key === 'Enter' || evt.target.name === 'search-button') {
- fetchBooks(input);
- }
- };
+ const handleSearchResultClose = () => {
+ setIsShow(false);
+ };
- const handleSearchResultClose = () => {
- setIsShow(false);
- };
+ const handleSearchResultShow = () => {
+ setIsShow(true);
+ };
- const handleSearchResultShow = () => {
- setIsShow(true);
- };
+ const handleSelectChange = (e) => {
+ setSearchType(e.target.value);
+ setInput("");
+ };
- return (
-
-
+ return (
+
+
- {/* 검색 페이지 전체 */}
-
- {/* 검색 창 */}
-
+ {/* 검색 페이지 전체 */}
+
+ {/* 검색 창 */}
+
- {/* 추천 검색어 */}
- {renderKeywordList('추천검색어', recommendedSearchKeywords)}
+ {/* 추천 검색어 */}
+ {renderKeywordList("추천검색어", recommendedSearchKeywords)}
- {/* 사용자 추천 키워드 */}
- {renderKeywordList('사용자 추천 키워드', userRecommendedKeywords)}
+ {/* 사용자 추천 키워드 */}
+ {renderKeywordList("사용자 추천 키워드", userRecommendedKeywords)}
- {/* 카테고리 */}
-
- 카테고리
-
- {Object.keys(categories).map((key, index) => {
- const title = key;
- const subtitle = categories[key].join(', ');
- const infoIndex = index % categoriesInfo.length; // 나머지로 0~9만 접근하도록 길이제한
- const color = categoriesInfo[infoIndex].color;
- const image = categoriesInfo[infoIndex].image;
- return renderCategoryItem(
- { title, subtitle, color, image },
- index,
- );
- })}
-
-
-
-
- );
+ {/* 카테고리 */}
+
+ 카테고리
+
+ {Object.keys(categories).map((key, index) => {
+ const title = key;
+ const subtitle = categories[key].join(", ");
+ const infoIndex = index % categoriesInfo.length; // 나머지로 0~9만 접근하도록 길이제한
+ const color = categoriesInfo[infoIndex].color;
+ const image = categoriesInfo[infoIndex].image;
+ return renderCategoryItem(
+ { title, subtitle, color, image },
+ index
+ );
+ })}
+
+
+
+
+ );
};
export default Search;
diff --git a/src/pages/SearchResult.jsx b/src/pages/SearchResult.jsx
new file mode 100644
index 0000000..ca55c50
--- /dev/null
+++ b/src/pages/SearchResult.jsx
@@ -0,0 +1,584 @@
+import React, { useEffect, useState } from "react";
+import { Link, useNavigate, useParams } from "react-router-dom";
+import Header from "../components/Header";
+import styled from "styled-components";
+import closeIcon from "../assets/closeIconRound.svg";
+import starIcon from "../assets/icons8-별-30 (1).png";
+import api from "./../services/api";
+import Pagination from "../components/Pagination";
+import SearchBox from "../components/SearchBox";
+
+const SearchResult = () => {
+ const navigate = useNavigate();
+ const { title } = useParams(); // path로 책 제목 가져오기
+ const [viewMode, setViewMode] = useState(true); // 책 뷰 선택(리스트/카드)
+ const [books, setBooks] = useState([]); // 책 정보
+ const [currentPage, setCurrentPage] = useState(1); // 현재 페이지
+ const [booksPerPage, setBooksPerPage] = useState(10); // 페이지당 책 수
+ const [loading, setLoading] = useState(false); // 로딩
+
+ const [input, setInput] = useState(""); // 검색 데이터
+ const [searchType, setSearchType] = useState("title"); // 검색 유형 상태
+ const [searchData, setSearchData] = useState([]); // 검색 결과 데이터
+ const [isShow, setIsShow] = useState(false); // 검색창 모달창
+
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ fetchBooks(input);
+ }, 100);
+
+ // cleanup 함수를 반환하여 컴포넌트가 언마운트될 때 타이머를 해제합니다.
+ return () => clearTimeout(timer);
+ }, [input]);
+
+ const fetchBooks = async (searchInput) => {
+ if (input.trim() === "") return; // 빈 문자열일 때 API 호출 방지
+
+ let endpoint = "";
+ if (searchType === "title") {
+ endpoint = `/api/search/book?title=${searchInput}&target=modal`;
+ }
+ if (searchType === "author") {
+ endpoint = `/api/search/book?author=${searchInput}&target=modal`;
+ }
+ if (searchType === "keyword") {
+ endpoint = `/api/search/keyword?name=${searchInput}&target=modal`;
+ }
+
+ try {
+ const response = await api.get(endpoint);
+ console.log("test", searchType, response.data);
+ setSearchData(response.data);
+ } catch (error) {
+ console.error("Failed to fetch books:", error);
+ }
+ };
+
+ const searchBook = (evt) => {
+ if (evt.key === "Enter") {
+ fetchBooks(input);
+ if (input.length > 0) navigate(`/search/result/${input}`);
+ setIsShow(false);
+ }
+ };
+
+ // 현재 책들 정보
+ const indexOfLastBook = currentPage * booksPerPage;
+ const indexOfFirstBook = indexOfLastBook - booksPerPage;
+ console.log(indexOfFirstBook, indexOfLastBook);
+ const currentBooks = books.slice(indexOfFirstBook, indexOfLastBook);
+
+ // 페이지 변경
+ const paginate = (pageNumber) => setCurrentPage(pageNumber);
+
+ console.log(books.length);
+ console.log(currentBooks);
+
+ useEffect(() => {
+ const getSearchResults = async () => {
+ setLoading(true);
+ try {
+ const response = await api.get(
+ // `/api/search/book?title=${title}&target=page&page=${currentPage-1}&size=${booksPerPage}`
+ `/api/search/book?title=${title}&target=page&page=0&size=999`
+ );
+ console.log(response.data);
+ setBooks(response.data);
+ setLoading(false);
+ } catch (error) {
+ console.error("책 데이터 GET 요청 실패", error);
+ }
+ };
+ getSearchResults();
+ }, [title]);
+
+ let searchResultsCount = books.length;
+ searchResultsCount = searchResultsCount.toLocaleString();
+ let searchResultsKeywordCount = 123;
+ let reviewCount = 123;
+
+ const handleSizeChange = (event) => {
+ setBooksPerPage(event.target.value);
+ };
+
+ return (
+ <>
+
+
setIsShow(false)}>
+ {/* 검색창 컴포넌트 만들어야함 */}
+ {/*
+
+
+
+
+
+
+ */}
+
+
+
+
+ "{title}" 에 대한
+
+ {" "}
+ {searchResultsCount} 개의 검색 결과
+
+
+
+
+
+
+
+
+ {/* 헤더 영역 */}
+
+
+ 전체{" "}
+
+ {searchResultsKeywordCount}건
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* 키워드 영역 */}
+
+
+
+ {/* 저주
*/}
+ 저주
+
+
+
+
+
+ {/* 콘텐츠 영역 */}
+
+ {viewMode ? (
+
+ {/* {books.map((book, index) => ( */}
+ {currentBooks.map((book, index) => (
+
+
+
+
+
+
+ {book.title}
+
+
+ {book.author}
+
+
+
+
+ {
+ e.preventDefault();
+ navigate(
+ `/search/result/${book.middleCategoryName}`
+ );
+ }}
+ >
+ {book.middleCategoryName}
+
+ {book.bookKeywordList.map((keyword, index) => {
+ return (
+ {
+ e.preventDefault();
+ navigate(
+ `/search/result/${keyword.name}`
+ );
+ }}
+ >
+ {keyword.name}
+
+ );
+ })}
+
+
+
+ 평균 ★{book.rating}{" "}
+
+ ({reviewCount})
+
+
+
+
+
+
+ ))}
+
+ ) : (
+
+ {/* {books.map((book, index) => ( */}
+ {currentBooks.map((book, index) => (
+
+
+
+
+
+ {book.title}
+
+ {book.author}
+
+
+ 평균 ★{book.rating}{" "}
+ ({reviewCount})
+
+
+
+ {/* 별 컴포넌트 */}
+
+
+ ))}
+
+ )}
+
+
+
+
+
+ >
+ );
+};
+
+export default SearchResult;
+
+const Main = styled.main`
+ padding: 48px 52px 0px 52px;
+ max-width: 1440px;
+ margin: 0 auto;
+`;
+
+const SearchInputWrap = styled.div`
+ width: 100%;
+ height: 60px;
+ box-shadow: 0px 2px 4px #00000033;
+ padding: 10px 0px 10px 1rem;
+ border-radius: 5px;
+ border: 1px solid #b0b0b0;
+ display: flex;
+ align-items: center;
+ font-size: 20px;
+ margin-bottom: 40px;
+`;
+
+const SelectMenu = styled.select`
+ width: 140px;
+ font-size: 20px;
+ border: none;
+ /* padding-left: 10px; */
+ text-align: center;
+ &:focus {
+ outline: none;
+ }
+`;
+
+const SearchInput = styled.input`
+ border: none;
+ border-left: 1px solid #c0c0c0;
+ margin-left: 1rem;
+ padding-left: 1rem;
+ font-size: 20px;
+ width: 100%;
+ &:focus {
+ outline: none;
+ }
+`;
+
+const ContentsWrap = styled.div`
+ display: flex;
+`;
+
+const ContentTitle = styled.h2`
+ font-size: 20px;
+ font-weight: bold;
+`;
+
+const SearchKeyword = styled.li`
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ height: 29px;
+ line-height: 27px;
+ padding: 0px 0px 0px 12px;
+ background-color: #c8edf2;
+ border-radius: 15px;
+ margin-right: 10px;
+`;
+
+const BookKeyword = styled.li`
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ height: 29px;
+ padding: 0px 12px;
+ background-color: #c8edf2;
+ border-radius: 15px;
+ margin-right: 10px;
+`;
+
+const ListUIWrap = styled.ul``;
+
+const CardUIWrap = styled.ul`
+ padding: 36px 20px;
+ display: grid;
+ grid-template-columns: repeat(5, 1fr);
+ grid-gap: 10px;
+`;
+
+const BookTitle = styled.h2`
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2; /* 원하는 라인 수 */
+ overflow: hidden;
+ text-overflow: ellipsis;
+ font-size: 20px;
+ font-weight: bold;
+ margin-bottom: 5px;
+`;
diff --git a/src/pages/Signup2.jsx b/src/pages/Signup2.jsx
index 6671eae..145b884 100644
--- a/src/pages/Signup2.jsx
+++ b/src/pages/Signup2.jsx
@@ -2,6 +2,9 @@ import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { useForm, rules } from 'react-hook-form';
+// SERVICE
+import api from '../services/api';
+
// ASSETS
import banner from '../assets/Login-Banner.png';
@@ -274,6 +277,9 @@ const Signup2 = () => {
const [emailDomain, setEmailDomain] = useState('');
const [isInputEnabled, setIsInputEnabled] = useState(false);
+ // 직업 정보
+ const [job, setJob] = useState('');
+
// 모든 것을 작성해야 가입하기 버튼 클릭 활성화
const [isButtonEnabled, setIsButtonEnabled] = useState(true);
@@ -323,6 +329,11 @@ const Signup2 = () => {
setBirthDate(e.target.value);
};
+ const handleJobChange = (e) => {
+ // console.log(e.target.value);
+ setJob(e.target.value);
+ };
+
const handleGenderButtonClick = (gender) => {
if (gender === 'male') {
setIsMaleClicked(true);
@@ -358,7 +369,27 @@ const Signup2 = () => {
// setEmailDomain이 변경될 때마다 실행
setEmail(`${emailUsername}@${emailDomain}`);
}, [emailUsername, emailDomain]);
- console.log(emailDomain);
+ // console.log(emailDomain);
+
+ const signUpData = {
+ username: id,
+ password: pwd,
+ name: name,
+ nickname: nickname,
+ email: email,
+ gender: gender,
+ occupation: job,
+ };
+
+ const postSignup = () => {
+ api
+ .post('/signup', signUpData, {
+ withCredentials: true,
+ })
+ .then((res) => {
+ console.log(res.data);
+ });
+ };
return (
@@ -541,7 +572,7 @@ const Signup2 = () => {
직업 선택
-
+
@@ -554,8 +585,8 @@ const Signup2 = () => {
-
- 네, 동의합니다
+
+ {/* 네, 동의합니다 */}
diff --git a/src/pages/SmallCategory.jsx b/src/pages/SmallCategory.jsx
index 0d06234..464322c 100644
--- a/src/pages/SmallCategory.jsx
+++ b/src/pages/SmallCategory.jsx
@@ -1,11 +1,9 @@
import React, { useState, useEffect } from 'react';
-import { useParams, useSearchParams } from 'react-router-dom';
+import { useParams } from 'react-router-dom';
import axios from 'axios';
// COMPONENTS
import Header from '../components/Header';
-import Footer from '../components/Footer';
-import Btn from '../components/Button';
import Card from '../components/BookDetailCard';
// STYLES
@@ -28,12 +26,9 @@ const SmallCategory = () => {
)
.then((res) => {
setSmCategoryBookList(res.data);
- console.log(res.data);
});
}, []);
- const [searchParams, setSearchParams] = useSearchParams();
-
return (
<>
@@ -48,33 +43,18 @@ const SmallCategory = () => {
{smCategoryBookList.map((data) => {
- // console.log(data);
return (
{
- // setSearchParams({
- // title: data[title],
- // author: data[author],
- // });
- // }}
+ bookKeywordList={data.bookKeywordList}
/>
);
})}
- {/*
-
-
-
-
-
-
-
-
-
*/}
>
diff --git a/src/services/books.js b/src/services/books.js
new file mode 100644
index 0000000..b3a770c
--- /dev/null
+++ b/src/services/books.js
@@ -0,0 +1,7 @@
+import React from 'react'
+
+export const books = (page, limit) => {
+ let array = [];
+
+ return
+}
diff --git a/src/services/login.js b/src/services/login.js
index 1c46c06..830f7ed 100644
--- a/src/services/login.js
+++ b/src/services/login.js
@@ -4,7 +4,7 @@ export const login = async (username, password) => {
const result = await axios.post(
"https://port-0-backend-book-pharmacy-umnqdut2blqqhv7sd.sel5.cloudtype.app/login",
{ username, password }, // 키와 값이 같아서 생략함
- { withCredentials: true }
+ { withCredentials: true } // 쿠키를 브라우저에 자동 저장 및 보내기
);
console.log("result", result);
return result;
diff --git a/src/styles/ArrowTitle.module.css b/src/styles/ArrowTitle.module.css
index dc344ef..f16f105 100644
--- a/src/styles/ArrowTitle.module.css
+++ b/src/styles/ArrowTitle.module.css
@@ -33,7 +33,7 @@
}
.default_wrapper {
- width: 1338px;
+ width: 100%;
height: 55px;
display: flex;
justify-content: space-between;
diff --git a/src/styles/BookCard.module.css b/src/styles/BookCard.module.css
index 39cdba0..4d55c2d 100644
--- a/src/styles/BookCard.module.css
+++ b/src/styles/BookCard.module.css
@@ -12,6 +12,7 @@
display: flex;
flex-direction: column;
align-items: center;
+ cursor: pointer;
}
.book_img {
@@ -21,6 +22,11 @@
background: #d9d9d9;
}
+.book_thumbnail {
+ width: 148px;
+ height: 210px;
+}
+
.book_info_wrapper {
width: 148px;
display: flex;
diff --git a/src/styles/BookDetailCard.css b/src/styles/BookDetailCard.css
index c15183b..0e45a7e 100644
--- a/src/styles/BookDetailCard.css
+++ b/src/styles/BookDetailCard.css
@@ -84,3 +84,88 @@
padding-top: 60px;
overflow: auto;
}
+
+/* 경험 추가하기 모달창 */
+
+.expModal_bookCard_container {
+ width: 639px;
+ height: 200px;
+ background: #ffffff;
+ margin: 10px;
+
+ /* Drop Shadow */
+ /* box-shadow: 6px 6px 30px rgba(119, 119, 119, 0.466667); */
+ box-shadow: 0px 1px 13px rgba(119, 119, 119, 0.466667);
+ border-radius: 15px;
+}
+
+/* .expModal_bookCard_container:hover {
+ background: #a4d6dd;
+} */
+
+.expModal_bookCard_wrapper {
+ display: flex;
+ align-items: center;
+ padding: 14px 10px;
+}
+
+.expModal_bookCard_left_wrapper {
+ padding-left: 5px;
+}
+
+.expModal_left_img_wrapper {
+ height: 170px;
+ box-shadow: 2px 2px 4px rgba(119, 119, 119, 0.25);
+ border-radius: 5px;
+}
+
+.expModal_img_wrapper_thumbnail {
+ width: 120px;
+ height: 170px;
+ border-radius: 5px;
+}
+
+.expModal_bookCard_right_wrapper {
+ height: 170px;
+ display: flex;
+ flex-direction: column;
+ margin-left: 20px;
+}
+
+.expModal_bookCard_right_up_wrapper {
+ display: flex;
+ flex-direction: column;
+}
+
+.expModal_right_up_title {
+ width: 260px;
+
+ /* Font */
+ font-family: var(--basic-font);
+ font-style: normal;
+ font-weight: 700;
+ font-size: 18px;
+ line-height: 21px;
+ color: #000;
+
+ /* 말 줄임 */
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.expModal_right_up_author {
+ font-family: var(--basic-font);
+ font-style: normal;
+ font-weight: 500;
+ font-size: 16px;
+ line-height: 29px;
+ color: #868686;
+}
+
+.expModal_bookCard_right_bottom_wrapper {
+ width: 260px;
+ height: 130px;
+ padding-top: 60px;
+ overflow: auto;
+}
diff --git a/src/styles/BookList.css b/src/styles/BookList.css
index 5ab75da..d40d3d0 100644
--- a/src/styles/BookList.css
+++ b/src/styles/BookList.css
@@ -32,3 +32,11 @@
width: 1338px;
margin: 0 auto;
}
+
+.bookList_title_wrapper {
+ margin-top: 30px;
+}
+
+.bookList_slide_wrapper {
+ /* overflow-x: scroll; */
+}
diff --git a/src/styles/BookListSlide.module.css b/src/styles/BookListSlide.module.css
index a81bbdb..bf38d89 100644
--- a/src/styles/BookListSlide.module.css
+++ b/src/styles/BookListSlide.module.css
@@ -8,14 +8,25 @@
.container {
padding: 0;
- margin-top: 56px;
- width: 1338px;
+ margin-top: 16px;
+ width: 200px;
font-family: 'Pretendard-Regular';
font-weight: 700;
+ /* display: grid;
+ grid-template-columns: repeat(8, 1fr); */
+ width: 100%;
}
.slide {
- display: flex;
justify-content: space-around;
margin-top: 20px;
+ width: 500px;
+}
+
+.swiper-container .swiper {
+ padding: 0;
+}
+
+#my-swiper .swiper {
+ padding-left: 0;
}
diff --git a/src/styles/Experience.css b/src/styles/Experience.css
new file mode 100644
index 0000000..bede7c7
--- /dev/null
+++ b/src/styles/Experience.css
@@ -0,0 +1,141 @@
+.expModal_overlay {
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: rgba(0, 0, 0, 0.2);
+ z-index: 9999;
+}
+
+.expModal_wrapper {
+ width: 690px;
+ height: 600px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 30px 30px;
+ border-radius: 15px;
+ background-color: #fff;
+ position: absolute;
+ top: 53%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+}
+
+.expModal_title_wrapper {
+ display: flex;
+ width: 630px;
+ justify-content: space-between;
+
+ /* Font */
+ font-family: var(--basic-font);
+ font-style: normal;
+ font-weight: 600;
+ font-size: 24px;
+ line-height: 0px;
+}
+
+.expModal_title_wrapper .close_btn {
+ cursor: pointer;
+
+ /* Font */
+ font-family: var(--basic-font);
+ font-style: normal;
+ font-weight: 200;
+ font-size: 24px;
+ line-height: 0px;
+ color: #575757;
+}
+
+.expModal_content_wrapper {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 660px;
+ height: 570px;
+ margin-top: 20px;
+}
+
+.bookInfo_content_wrapper {
+ width: 100%;
+}
+
+.inputReview_wrapper {
+ display: flex;
+ flex-direction: column;
+ margin-top: 35px;
+}
+
+.inputReview_title {
+ /* Font */
+ font-family: var(--basic-font);
+ font-style: normal;
+ font-weight: 600;
+ font-size: 18px;
+ line-height: 21px;
+}
+
+.inputReview_box {
+ width: 640px;
+ height: 125px;
+ border: 1px solid #868686;
+ border-radius: 5px;
+ margin-top: 15px;
+ padding: 10px 10px;
+ resize: none;
+ overflow: auto;
+
+ /* Font */
+ font-family: var(--basic-font);
+ font-style: normal;
+ font-weight: 700;
+ font-size: 14px;
+ line-height: 1.5em;
+}
+
+.inputReview_box::-webkit-scrollbar {
+ width: 10px;
+}
+
+.inputReview_box::-webkit-scrollbar-button {
+ display: none;
+}
+
+.inputReview_box::-webkit-scrollbar-thumb {
+ background-color: #67b6c1;
+ border-radius: 20px;
+ background-clip: padding-box;
+ border: 2px solid transparent;
+}
+
+.inputReview_box::-webkit-scrollbar-track {
+ background-color: #fff;
+ border-radius: 20px;
+ box-shadow: inset 0px 0px 5px #fff;
+}
+
+.expModal_button_wrapper {
+ display: flex;
+ justify-content: space-around;
+ width: 100%;
+ margin-top: 40px;
+}
+
+.review_btn,
+.later_btn {
+ width: 300px;
+ height: 60px;
+ background-color: #c8edf2;
+ border-radius: 10px;
+
+ /* Font */
+ text-align: center;
+ font-family: var(--basic-font);
+ font-size: 20px;
+ font-weight: 600;
+ font-style: normal;
+ line-height: 0px;
+}
diff --git a/src/styles/Feed.css b/src/styles/Feed.css
index 175c5c7..d1a024d 100644
--- a/src/styles/Feed.css
+++ b/src/styles/Feed.css
@@ -10,20 +10,20 @@
margin: 0 auto;
max-width: 1440px;
padding: 24px;
- height: 1000vh;
+ /* height: 108vh; */
display: flex;
flex-direction: column;
}
.feed_title_wrapper {
- width: auto;
+ width: 100%;
height: 50px;
padding: 10px;
}
.feed_title {
color: #000;
- font-family: 'Pretendard-Regular';
+ font-family: var(--basic-font);
font-size: 24px;
font-style: normal;
font-weight: 700;
@@ -31,8 +31,10 @@
}
.feed_content_wrapper {
- max-width: 1440px;
- height: 500px;
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ width: 1440px;
+ /* height: 860px; */
-ms-flex-align: center;
align-items: center;
margin-left: auto;
diff --git a/src/styles/FeedCard.css b/src/styles/FeedCard.css
index a7d612b..ed0da25 100644
--- a/src/styles/FeedCard.css
+++ b/src/styles/FeedCard.css
@@ -9,7 +9,7 @@
.FeedCardContainer {
position: static;
box-sizing: border-box;
- width: 310px;
+ width: 340px;
height: 280px;
/* border-radius: 10px;
background: linear-gradient(111deg, #cafadf 0%, #d5e0ff 100%);
@@ -20,17 +20,17 @@
/* Drop Shadow */
box-shadow: 2px 2px 4px 0px rgba(119, 119, 119, 0.25);
+ margin-top: 20px;
}
.feed_up_wrapper {
display: flex;
- width: 310px;
+ width: 340px;
height: 240px;
}
.feed_review_wrapper {
display: flex;
- flex-direction: column;
align-items: center;
}
@@ -55,7 +55,7 @@
.review_book_wrapper {
position: absolute;
display: flex;
- width: 310px;
+ width: 340px;
height: 115px;
background: rgba(255, 255, 255, 0.35);
margin-top: 160px;
@@ -64,12 +64,19 @@
z-index: 1;
}
+.feed_book_img_wrapper {
+ width: 74px;
+ height: 106px;
+ background: #6f6f6f;
+ border-radius: 5px;
+}
+
.feed_book_img {
width: 74px;
height: 106px;
flex-shrink: 0;
border-radius: 5px;
- background: #6f6f6f;
+ object-fit: fill;
}
.feed_book_text_wrapper {
@@ -166,7 +173,7 @@
position: absolute;
z-index: 2;
display: flex;
- width: 311px;
+ width: 341px;
height: 40px;
padding: 4px 0;
align-items: center;
diff --git a/src/styles/HomeStyles.css b/src/styles/HomeStyles.css
index 001bef6..f4e7b8a 100644
--- a/src/styles/HomeStyles.css
+++ b/src/styles/HomeStyles.css
@@ -16,7 +16,7 @@
width: 100%;
z-index: 100;
background-color: hsla(0, 0%, 100%, 0.9);
- /* top: 0; */
+ top: 0;
}
.home_header {
diff --git a/src/styles/SearchResultList.css b/src/styles/SearchResultList.css
index 9380bf1..a0f8d59 100644
--- a/src/styles/SearchResultList.css
+++ b/src/styles/SearchResultList.css
@@ -6,7 +6,7 @@
box-sizing: border-box;
border-radius: 16px;
width: 1440px;
- padding: 29px 29px 39px;
+ padding: 29px 29px;
/* border: 1px solid #000; */
margin-top: 10px;
background-color: #fff;
@@ -25,6 +25,8 @@
}
.search-result-list img {
+ width: 70px;
+ background-color: rgb(192, 192, 192);
border: 1px solid #d6d6d6;
}
diff --git a/src/styles/SearchStyles.css b/src/styles/SearchStyles.css
index 2f8aff7..428c1bd 100644
--- a/src/styles/SearchStyles.css
+++ b/src/styles/SearchStyles.css
@@ -26,11 +26,20 @@
border-radius: 0.5rem;
}
-.search-button {
+/* .search-button {
width: 32px;
height: 32px;
background: url("../assets/search-icon.svg");
margin-top: 4px;
+} */
+
+.search-select {
+ border: none;
+ font-size: large;
+}
+
+.search-select:focus {
+ outline: none;
}
.search-input {
@@ -49,8 +58,8 @@
width: 50px;
height: 40px;
font-size: 1.5rem;
- position: relative;
- right: 0;
+ position: absolute;
+ right: 70px;
background-color: #fff;
}
diff --git a/src/styles/Slider.css b/src/styles/Slider.css
index a603afd..c98ad52 100644
--- a/src/styles/Slider.css
+++ b/src/styles/Slider.css
@@ -39,27 +39,27 @@
/* background-color: aqua; */
}
-.swiper-button-prev,
-.swiper-button-next {
+#slider-swiper .swiper-button-prev,
+#slider-swiper .swiper-button-next {
color: #575757 !important;
}
-.swiper-button-prev:after,
-.swiper-button-next:after {
+#slider-swiper .swiper-button-prev:after,
+#slider-swiper .swiper-button-next:after {
font-size: 2rem !important;
font-weight: 1000 !important;
margin-bottom: 40px;
}
-.swiper-button-prev:after {
+#slider-swiper .swiper-button-prev:after {
margin-left: -25px;
}
-.swiper-button-next:after {
+#slider-swiper .swiper-button-next:after {
margin-right: -20px;
}
-.swiper {
+#slider-swiper .swiper {
padding-left: 30px;
cursor: grab;
-}
\ No newline at end of file
+}
diff --git a/yarn.lock b/yarn.lock
index d073109..77ec5ac 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3543,6 +3543,11 @@ cjs-module-lexer@^1.0.0:
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107"
integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==
+classnames@^2.2.5:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
+ integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
+
clean-css@^5.2.2:
version "5.3.3"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd"
@@ -4408,6 +4413,11 @@ enhanced-resolve@^5.15.0:
graceful-fs "^4.2.4"
tapable "^2.2.0"
+enquire.js@^2.1.6:
+ version "2.1.6"
+ resolved "https://registry.yarnpkg.com/enquire.js/-/enquire.js-2.1.6.tgz#3e8780c9b8b835084c3f60e166dbc3c2a3c89814"
+ integrity sha512-/KujNpO+PT63F7Hlpu4h3pE3TokKRHN26JYmQpPyjkRD/N57R7bPDNojMXdi7uveAKjYB7yQnartCxZnFWr0Xw==
+
entities@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4"
@@ -6758,6 +6768,13 @@ json-stable-stringify-without-jsonify@^1.0.1:
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
+json2mq@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/json2mq/-/json2mq-0.2.0.tgz#b637bd3ba9eabe122c83e9720483aeb10d2c904a"
+ integrity sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==
+ dependencies:
+ string-convert "^0.2.0"
+
json5@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593"
@@ -8599,6 +8616,17 @@ react-scripts@5.0.1:
optionalDependencies:
fsevents "^2.3.2"
+react-slick@^0.30.2:
+ version "0.30.2"
+ resolved "https://registry.yarnpkg.com/react-slick/-/react-slick-0.30.2.tgz#b28e992f9c519bb516a0af8d37e82cb59fee08ce"
+ integrity sha512-XvQJi7mRHuiU3b9irsqS9SGIgftIfdV5/tNcURTb5LdIokRA5kIIx3l4rlq2XYHfxcSntXapoRg/GxaVOM1yfg==
+ dependencies:
+ classnames "^2.2.5"
+ enquire.js "^2.1.6"
+ json2mq "^0.2.0"
+ lodash.debounce "^4.0.8"
+ resize-observer-polyfill "^1.5.0"
+
react@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
@@ -8768,6 +8796,11 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
+resize-observer-polyfill@^1.5.0:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
+ integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
+
resolve-cwd@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
@@ -9156,6 +9189,11 @@ slash@^4.0.0:
resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7"
integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==
+slick-carousel@^1.8.1:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/slick-carousel/-/slick-carousel-1.8.1.tgz#a4bfb29014887bb66ce528b90bd0cda262cc8f8d"
+ integrity sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA==
+
sockjs@^0.3.24:
version "0.3.24"
resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce"
@@ -9296,6 +9334,11 @@ stop-iteration-iterator@^1.0.0:
dependencies:
internal-slot "^1.0.4"
+string-convert@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97"
+ integrity sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==
+
string-length@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"