Skip to content

Commit

Permalink
✨ 210903 룰렛 추가 완료
Browse files Browse the repository at this point in the history
## What is this PR? 🔍

#13 완료.

## Major Fix 🔌


## Minor Fix 🛠
  • Loading branch information
Sh031224 authored Sep 5, 2021
2 parents c758483 + 50163e8 commit 364b57e
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 39 deletions.
1 change: 1 addition & 0 deletions src/components/Main/Roulette/Roulette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const Roulette: React.FC = () => {
키워드를 클릭해서 랜덤으로 추천 게임을 받아보세요!
</RouletteSubTitle>
<RouletteSubTitleTooltip
unoptimized
src={tooltip}
onMouseEnter={handleOnMouseEnter}
/>
Expand Down
6 changes: 2 additions & 4 deletions src/components/Main/Roulette/RoulettePlay/RoulettePlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,16 @@ const RoulettePlay: React.FC = () => {
played,
skip,
waiting,
loading,
onClickReset,
onClickStart,
onClickSkip,
} = useRoulette();

return (
<RoulettePlayWrapper>
<RoulettePlayContainer>
<RoulettePlayIcons count={selectedCount} position="left" />
<RoulettePlayContent
{...{ skip, waiting, onClickSkip, item: roulette }}
/>
<RoulettePlayContent {...{ skip, waiting, loading, item: roulette }} />
<RoulettePlayIcons count={selectedCount} position="right" />
</RoulettePlayContainer>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,24 @@ export const RoulettePlayContentCircle = styled.div<{ isPlay: boolean }>`
isPlay ? "animate 3.5s 0s ease-in-out forwards" : "none"};
`;

export const RoulettePlayContentBox = styled.div`
width: 46rem;
height: 21.5rem;
display: flex;
opacity: 0;
transition: opacity 0.5s 0s;
position: absolute;
flex-direction: column;
align-items: center;
justify-content: center;
left: 0;
top: 50%;
transform: translate(0, calc(-50% + 0.5px));
background-color: #000000ac;
z-index: 3;
padding: 2rem;
`;

export const RoulettePlayContentRandom = styled.div`
position: absolute;
background-color: black;
Expand All @@ -51,8 +69,13 @@ export const RoulettePlayContentRandom = styled.div`
&:first-of-type {
left: 0;
top: 50%;
transform: translate(0, -50%);
transform: translate(0, calc(-50% + -0.5px));
z-index: 2;
&:hover {
${RoulettePlayContentBox} {
opacity: 1;
}
}
}
&:nth-child(2) {
Expand All @@ -73,3 +96,48 @@ export const RoulettePlayContentRandom = styled.div`
transform: translate(-50%, 10.75rem) rotate(270deg);
}
`;

export const RoulettePlayContentTitle = styled.h3`
color: ${({ theme }) => theme.palette.grayScale[100]};
font-weight: 500;
font-size: 28px;
line-height: 28px;
letter-spacing: -0.03em;
`;

export const RoulettePlayContentGenres = styled.div`
margin-top: 1.5rem;
display: flex;
flex-wrap: wrap;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 19px;
letter-spacing: -0.03em;
align-items: center;
justify-content: center;
color: ${({ theme }) => theme.palette.grayScale[100]};
span {
background-color: ${({ theme }) => theme.palette.primary.main};
border-radius: 14px;
min-width: 64px;
padding: 0.3rem 1rem;
display: inline-block;
margin: 0.5rem;
}
`;

export const RoulettePlayContentBtn = styled.span`
cursor: pointer;
margin-top: 2rem;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 28px;
letter-spacing: -0.03em;
color: #c7c7c7;
display: inline-block;
border: 2px solid #c7c7c7;
border-radius: 5px;
padding: 0.15rem 1.5rem;
`;
Original file line number Diff line number Diff line change
@@ -1,49 +1,67 @@
import Image from "next/image";
import Link from "next/link";

import { IRouletteState } from "types/IRouletteResult";

import loading from "assets/images/roulette/loading.gif";
import loadingGif from "assets/images/roulette/loading.gif";
import random from "assets/images/roulette/random.svg";

import {
RoulettePlayContentWrapper,
RoulettePlayContentRandom,
RoulettePlayContentCircle,
RoulettePlayContentGroup,
RoulettePlayContentBox,
RoulettePlayContentTitle,
RoulettePlayContentGenres,
RoulettePlayContentBtn,
} from "./RoulettePlayContent.style";

interface IRoulettePlayContentProps {
item: IRouletteState;
skip: boolean;
waiting: boolean;
onClickSkip: () => void;
loading: boolean;
}

const RoulettePlayContent: React.FC<IRoulettePlayContentProps> = ({
item,
skip,
waiting,
onClickSkip,
loading,
}) => {
const { error, data } = item;

return (
<RoulettePlayContentWrapper>
<RoulettePlayContentGroup>
<RoulettePlayContentCircle isPlay={!skip} onClick={onClickSkip}>
{data && !error ? (
<RoulettePlayContentCircle isPlay={!skip}>
{data && !error && !loading ? (
<RoulettePlayContentRandom>
<Image
unoptimized
src={data.header_image}
width={460}
height={215}
/>
<RoulettePlayContentBox>
<RoulettePlayContentTitle>
{data.name || "이름없음."}
</RoulettePlayContentTitle>
<RoulettePlayContentGenres>
{data.genres.map((v, i) => (
<span key={i}>{v}</span>
))}
</RoulettePlayContentGenres>
<Link href={`/about/${data.id}`} scroll={true}>
<RoulettePlayContentBtn>게임 상세보기</RoulettePlayContentBtn>
</Link>
</RoulettePlayContentBox>
</RoulettePlayContentRandom>
) : (
<RoulettePlayContentRandom>
{waiting ? (
<Image unoptimized src={loading} width={30} height={30} />
<Image unoptimized src={loadingGif} width={30} height={30} />
) : (
<Image unoptimized src={random} />
)}
Expand Down
3 changes: 0 additions & 3 deletions src/config/server.ts

This file was deleted.

80 changes: 55 additions & 25 deletions src/hooks/main/useRoulette.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { useMemo, useRef, useState } from "react";
import { useRecoilState } from "recoil";
import { useRecoilState, useRecoilValue } from "recoil";

import {
keywordsDefaultState,
keywordsState,
rouletteDefaultState,
rouletteState,
} from "atom/roulette.atom";
// import client from "lib/customAxios";
import client from "lib/customAxios";
import axios, { CancelTokenSource } from "axios";

const useRoulette = () => {
const [keywords, setKeywords] = useRecoilState(keywordsState);
const keywords = useRecoilValue(keywordsState);
const [roulette, setRoulette] = useRecoilState(rouletteState);

const [waiting, setWaiting] = useState(false);
Expand All @@ -19,11 +19,24 @@ const useRoulette = () => {

const loading = useRef(false);
const timeout = useRef<null | ReturnType<typeof setTimeout>>(null);
const callback = useRef<null | (() => void)>(null);
const source = useRef<CancelTokenSource | null>(null);

const selectedCount = useMemo(
() => keywords.filter((v) => v.isSelected).length,
[keywords]
);
const selectedKeywords = useMemo(
() =>
keywords.reduce(
(result: string[], { name, isSelected }) => [
...result,
...(isSelected ? [name] : []),
],
[]
),
[keywords]
);

const clear = () => {
if (timeout.current) {
Expand All @@ -34,19 +47,26 @@ const useRoulette = () => {

const onClickSkip = () => {
clear();
if (loading.current) {
setWaiting(true);
setSkip(true);
setWaiting(true);
setSkip(true);
if (callback.current) {
callback.current();
callback.current = null;
}
};

const onClickReset = () => {
setKeywords(keywordsDefaultState);
clear();
setPlayed(false);
setSkip(true);
setWaiting(false);
setRoulette(rouletteDefaultState);
clear();
callback.current = null;
loading.current = false;
if (source.current) {
source.current.cancel();
source.current = null;
}
};

const onClickStart = () => {
Expand All @@ -61,28 +81,38 @@ const useRoulette = () => {
setSkip(false);
}, 0);
setWaiting(false);
setRoulette({ ...rouletteDefaultState });
setRoulette(rouletteDefaultState);

// client.post('/api/roulette-recommendation')
setTimeout(() => {
setPlayed(true);
loading.current = false;
setRoulette({
...rouletteDefaultState,
data: {
id: 348800,
name: "test",
header_image:
"https://cdn.akamai.steamstatic.com/steam/apps/348800/header.jpg?t=1611266489",
genres: ["액션", "어드벤처", "인디"],
},
source.current = axios.CancelToken.source();
client
.post("api/roulette-recommendation", selectedKeywords, {
cancelToken: source.current.token,
})
.then((res) => {
const fn = () => {
setWaiting(false);
setPlayed(true);
setRoulette({ ...rouletteDefaultState, data: res.data.data });
loading.current = false;
};

if (timeout.current) {
callback.current = fn;
} else {
fn();
}
})
.catch(() => {
onClickReset();
});
}, 3000);

timeout.current = setTimeout(() => {
if (loading.current) {
setWaiting(true);
}
if (typeof callback.current === "function") {
callback.current();
}
}, 3000);
}
};
Expand All @@ -93,7 +123,7 @@ const useRoulette = () => {
played,
skip,
waiting,
onClickSkip,
loading: loading.current,
onClickReset,
onClickStart,
};
Expand Down
1 change: 1 addition & 0 deletions src/lib/customAxios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const client = axios.create({

client.defaults.headers = {
"Cache-Control": "no-cache",
"Accept-Language": "ko-KR",
Accept: "application/json",
Pragma: "no-cache",
Expires: "0",
Expand Down
1 change: 1 addition & 0 deletions src/style/GlobalStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const GlobalStyle = createGlobalStyle`
body {
min-width: 1024px;
background-color:#161623;
position: relative;
}
`;

Expand Down

0 comments on commit 364b57e

Please sign in to comment.