Skip to content

Commit

Permalink
feat: 최근조회영화 추가기능 완성 (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
izone00 authored Feb 2, 2024
1 parent 04cd94f commit dcfbe92
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 4 deletions.
19 changes: 19 additions & 0 deletions src/assets/menu-svgrepo-com.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 0 additions & 2 deletions src/components/Content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import { Carousel } from "./Carousel";
import profileDefault from "../assets/user_default.jpg";
import StarRating from "./StarRating";
import CommentCard from "./CommentCard";

import { CommentsResType, CommentType, MovieType } from "../type";

import { MyStateType } from "../type";
import { Link, useOutletContext } from "react-router-dom";
import { defaultResponseHandler } from "../apis/custom";
Expand Down
122 changes: 122 additions & 0 deletions src/components/RecentlyViewedContents.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
@import "../utils/common.module.scss";

// 포지션 설정
.fixedPositionCon {
@include pageContainer;
position: fixed;
top: calc(62px + ((100vh - 62px) / 2));
left: 0;
right: 0;

.relativePostionCon {
position: relative;
width: 100%;

.absolutePostionCon {
position: absolute;
top: 50%;
left: 100%;
transform: translate(calc(-50%), -50%);

margin-left: 180px;
@media (max-width: #{$max-screen + 700}) {
margin-left: calc((100vw - 100%) / 4);
}
@media (max-width: #{$max-screen + 480}) {
margin-left: 120px;
}
@media (max-width: #{$max-screen + 240}) {
margin-left: 60px;
}
@media (max-width: #{$medium-screen + 100}) {
margin-left: 20px;
}
}
}
}

// 스타일 설정
.listOpenIcon {
width: 60px;
height: 60px;
border-radius: 50%;
background-image: url("../assets/menu-svgrepo-com.svg");
background-repeat: no-repeat;
background-position: center;
background-color: white;
box-shadow: 0 2px 10px #aaaaaa;
}

.cardListCon {
padding-right: 10px;

@media (max-width: #{$max-screen + 480}) {
transform: translate(calc(-10px - 50% + (100vw - 1560px) / 2));
}
@media (max-width: #{$max-screen + 240}) {
transform: translate(calc(-10px - 50% + (100vw - 1440px) / 2));
}
@media (max-width: #{$max-screen + 120}) {
transform: translate(calc(-50%));
}
}
.cardList {
width: 200px;
max-height: 80vh;
padding: 0 20px;
border: 1px solid $light-gray;
border-radius: 10px;
background-color: #eeeeee;
overflow-y: scroll;

@keyframes expandVertically {
0% {
transform: scaleY(0);
}
100% {
transform: scaleY(1);
}
}
animation: expandVertically 0.3s ease forwards;

&::-webkit-scrollbar {
width: 10px;
}
&::-webkit-scrollbar-track {
border-radius: 10px;
}
&::-webkit-scrollbar-thumb {
background: $light-gray;
border-radius: 10px;
}
&::-webkit-scrollbar-thumb:hover {
background: #bbbbbb;
}

header {
padding: 10px 0;
h2 {
font-size: 15px;
}
}
ul {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;

li {
list-style-type: none;

img {
width: 100%;
}
.contentTitleBox {
margin-top: -4px;
padding-bottom: 16px;
font-size: 14px;
font-weight: 500;
}
}
}
}
47 changes: 47 additions & 0 deletions src/components/RecentlyViewedContents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useState } from "react";
import styles from "./RecentlyViewedContents.module.scss";
import { Link } from "react-router-dom";
import useRecentContents from "../hooks/useRecentContents";

export default function RecentlyViewedContents() {
const [isOpenRecentContents, setIsOpenRecentContents] = useState(false);
const { recentContents } = useRecentContents();

return (
<div className={styles.fixedPositionCon}>
<div className={styles.relativePostionCon}>
<div className={styles.absolutePostionCon}>
{isOpenRecentContents ? (
<div
className={styles.cardListCon}
onMouseLeave={() => setIsOpenRecentContents(false)}
>
<div className={styles.cardList}>
<header>
<h2>최근 구경한 영화({recentContents.length}건)</h2>
</header>
<ul>
{recentContents.map((content) => (
<li key={content.movieCD}>
<Link to={`/contents/${content.movieCD}`}>
<img src={content.poster} alt="" />
<div className={styles.contentTitleBox}>
{`${content.title_ko} · ${content.directors?.[0].name}`}
</div>
</Link>
</li>
))}
</ul>
</div>
</div>
) : (
<div
className={styles.listOpenIcon}
onMouseEnter={() => setIsOpenRecentContents(true)}
></div>
)}
</div>
</div>
</div>
);
}
24 changes: 24 additions & 0 deletions src/hooks/useRecentContents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { MovieType } from "../type";

export default function useRecentContents() {
let recentContents: Partial<MovieType>[];
try {
recentContents = JSON.parse(localStorage.getItem("recentContents") ?? "[]");
} catch (e) {
localStorage.removeItem("recentContents");
recentContents = [];
}

function addRecentContent(newContent: Partial<MovieType>) {
recentContents = recentContents.filter(
(content) => content.movieCD !== newContent.movieCD
);
recentContents.push(newContent);
recentContents.length > 10 && recentContents.splice(0, 1);

localStorage.setItem("recentContents", JSON.stringify(recentContents));
}

// 순서를 뒤집어 return
return { recentContents: recentContents.reverse(), addRecentContent };
}
11 changes: 9 additions & 2 deletions src/pages/ContentPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import Content from "../components/Content";
import styles from "./ContentPage.module.scss";
import { useEffect, useState } from "react";
import { MovieType } from "../type";
// import { convertKeysToCamelCase } from "../utils/snackToCamel";
import { getContentRequest } from "../apis/content";
import { defaultResponseHandler } from "../apis/custom";
import { useAuthContext } from "../contexts/authContext";
import useChangeTitle from "../hooks/useChangeTitle";
import useRecentContents from "../hooks/useRecentContents";
import useMoveScrollToTop from "../hooks/useMoveScrollToTop";

export default function ContentPage() {
Expand All @@ -18,13 +18,15 @@ export default function ContentPage() {
const { setTitle } = useChangeTitle();
const [refetch, setRefetch] = useState(false);
const refetchContent = () => setRefetch(!refetch);
const { addRecentContent } = useRecentContents();

useMoveScrollToTop();

useEffect(() => {
id &&
getContentRequest(id, accessToken ?? undefined)
.then(defaultResponseHandler)
.then((content: MovieType) => {
console.log(content);
setTitle(content.title_ko + " - 와플피디아");
setContent(content);
})
Expand All @@ -33,6 +35,11 @@ export default function ContentPage() {
});
}, [id, accessToken, setTitle, refetch]);

// 최근조회영화 목록에 추가
useEffect(() => {
content && addRecentContent(content);
}, [id, content]);

return (
<div className={styles.container}>
{content && (
Expand Down
2 changes: 2 additions & 0 deletions src/pages/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useAuthContext } from "../contexts/authContext";
import { defaultResponseHandler } from "../apis/custom";
import SettingModal from "../components/user/SettingModal";
import UserEditModal from "../components/user/UserEditModal";
import RecentlyViewedContents from "../components/RecentlyViewedContents";

export type CurrentModalType =
| null
Expand Down Expand Up @@ -88,6 +89,7 @@ export default function Layout() {
} satisfies OutletContextType
}
/>
<RecentlyViewedContents />
<Footer />
</div>
</section>
Expand Down

0 comments on commit dcfbe92

Please sign in to comment.