Skip to content

Commit

Permalink
Merge pull request #26 from BbeumbungE/feat/FRONT-318
Browse files Browse the repository at this point in the history
Feat: 주제별 그리기 페이지 구현
  • Loading branch information
sidsidsidsids authored Oct 5, 2023
2 parents f1c6863 + 157fdb0 commit 1fe0900
Show file tree
Hide file tree
Showing 13 changed files with 1,242 additions and 63 deletions.
54 changes: 54 additions & 0 deletions client/src/api/topic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { AxiosResponse } from 'axios';
import { api } from './api';

interface Status {
httpStatus: string;
code: number;
message: string;
}

interface Sketch {
sketchId: number;
sketchImageUrl: string;
}

interface Subject {
id: number;
subjectName: string;
subjectImage: string;
sketchList: Sketch[];
}

interface DetailContent {
id: number;
itemPrice: number;
hasItem: boolean;
subject: Subject;
}

interface ApiResponse {
status: Status;
content: DetailContent;
}

const getTopicDrawings = async (itemId: number): Promise<ApiResponse> => {
try {
const response = await api.get(`/api/items/${itemId}/subjects`);
return response.data;
} catch (error) {
console.log('그림 주제 상세조회 에러', error);
throw error;
}
};

const postTopicDrawing = async (canvasId: number): Promise<any> => {
try {
const response = await api.post(`/api/canvases/${canvasId}/posts`);
return response.data;
} catch (error) {
console.log('그림 게시물 생성 에러', error);
throw error;
}
};

export { getTopicDrawings, postTopicDrawing };
15 changes: 10 additions & 5 deletions client/src/components/atoms/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface ButtonProps {
transparencyButton?: boolean;
}

const StyledMenu = styled(NavLink)<{
const StyledMenu = styled(Link)<{
$bgColor: string;
$border: string;
to?: string | null;
Expand Down Expand Up @@ -85,7 +85,10 @@ function Menu({
}: ButtonProps) {
const navigate = useNavigate();
const { playBtnBright } = SoundEffects();
const handleClick = () => {

const handleDrawingNavigate = () => {
console.log('이동');
navigate('/draw/topic');
playBtnBright();
};
let bgColor = theme.menuColors.pink; // 기본값은 mainBlue
Expand Down Expand Up @@ -135,11 +138,13 @@ function Menu({
routeUrl = '/store';
break;
default:
routeUrl = '/';
routeUrl = '/draw/topic';
break;
}

return srcId !== 0 ? (
console.log('srdId:', srcId);

return srcId !== 0 && !transparencyButton ? (
<StyledMenu $bgColor={bgColor} $border={border}>
<MenuText dangerouslySetInnerHTML={{ __html: buttonText }} />
{svgSrc && <SvgImage src={svgSrc} alt="SVG Image" />}
Expand All @@ -163,7 +168,7 @@ function Menu({
to={routeUrl}
$bgColor={bgColor}
$border={border}
onClick={handleClick}
onClick={handleDrawingNavigate}
>
<MenuText dangerouslySetInnerHTML={{ __html: buttonText }} />
{svgSrc && <SvgImage src={svgSrc} alt="SVG Image" />}
Expand Down
25 changes: 22 additions & 3 deletions client/src/components/organisms/CheckingModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import styled, { keyframes } from 'styled-components';
import ProgressBar from '../atoms/ProgressBar';
import { ReactComponent as questionMarkIcon } from '../../assets/image/etc/questionMark.svg';

interface CheckingModalProps {
imgPath: string | undefined;
Expand Down Expand Up @@ -69,6 +70,7 @@ const TopImageSkeleton = styled.div`
`;

const InnerWrapper = styled.div`
position: relative;
max-width: 100%;
max-height: 100%;
display: flex;
Expand All @@ -79,17 +81,34 @@ const InnerWrapper = styled.div`
text-align: center;
`;

const QuestionIcon = styled(questionMarkIcon)`
width: 9.375rem;
height: 9.375rem;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 200;
filter: brightness(0.5);
`;

function CheckingModal({ imgPath }: CheckingModalProps) {
return (
<ModalWrapper>
<InnerWrapper>
<ModalText>AI가 그림을 확인중이에요</ModalText>
{imgPath ? (
<TopImage src={imgPath} alt="이 주의 인기 그림" />
<>
<TopImage src={imgPath} alt="이 주의 인기 그림" />
<ModalLightText>이 주의 인기 그림</ModalLightText>
</>
) : (
<TopImageSkeleton />
<>
<TopImageSkeleton />
<QuestionIcon />
<ModalLightText>인기 그림은 누가 될까요?</ModalLightText>
</>
)}
<ModalLightText>이 주의 인기 그림</ModalLightText>
<ProgressBar />
</InnerWrapper>
</ModalWrapper>
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/organisms/ExitBoxOnBlur.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const ExitBoxDiv = styled.div`
cursor: pointer;
`;

const ExitBox = ({ color, onClick }: ExitBoxProps) => {
const ExitBoxOnBlur = ({ color, onClick }: ExitBoxProps) => {
return (
<ExitBoxDiv onClick={onClick}>
<ExitArrow color={color} />
Expand All @@ -25,4 +25,4 @@ const ExitBox = ({ color, onClick }: ExitBoxProps) => {
);
};

export default ExitBox;
export default ExitBoxOnBlur;
204 changes: 204 additions & 0 deletions client/src/components/organisms/FinishDrawingModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/* eslint-disable react/jsx-no-bind */
import { useNavigate } from 'react-router-dom';
import styled, { keyframes } from 'styled-components';
import { useRecoilValue, useRecoilState } from 'recoil';
import { useEffect } from 'react';
import { UserProfileState } from '../../recoil/profile/atom';
import { UserRupeeState } from '../../recoil/rupee/atom';
import BlurBox from '../atoms/BlurBox';
import LevelStars from './LevelStars';
import { ReactComponent as Rupee } from '../../assets/image/etc/rupee.svg';
import Button from '../atoms/Button';
import theme from '../../style/theme';
import { postTopicDrawing } from '../../api/topic';

interface ModalProps {
canvasId: number;
canvasUrl: string;
}

const pulseAnimation = keyframes`
0% {
opacity: 0.4;
}
50% {
opacity: 0.7;
}
100% {
opacity: 0.4;
}
`;

const transpWhite = '#ffffff5e';

const sparkle = keyframes`
50% {
opacity: 0.4;
transform: scale(7);
box-shadow: 0px 0px 30px 20px ${transpWhite};
}
50% {
opacity: 1;
transform: scale(7);
box-shadow: 0px 0px 30px 20px white;
}
100% {
opacity: 0;
transform: scale(7.5);
box-shadow: 0px 0px 30px 20px ${transpWhite};
}
`;

const jumpAnimation = keyframes`
0% {
bottom: 0;
}
50% {
bottom: 20px;
}
100% {
bottom: 0;
}
`;

const Star = styled.div`
position: absolute;
width: 30px;
height: 30px;
background-color: white;
border-radius: 50%;
opacity: 0;
animation: ${sparkle} 4s infinite alternate;
z-index: 0;
margin-bottom: 250px;
`;

const ModalWrapper = styled.div`
position: fixed;
top: 45%;
left: 50%;
transform: translate(-50%, -50%);
margin-top: 50px;
width: 500px;
height: 660px;
border-radius: 25px;
position: relative;
z-index: 600;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
`;

const TopImage = styled.img`
width: 380px;
height: 380px;
margin-right: auto;
margin-left: auto;
margin-bottom: 15px;
border-radius: 25px;
position: relative;
z-index: 100;
`;

const TopImageSkeleton = styled.div`
width: 300px;
height: 300px;
background-color: #ccc;
margin-right: auto;
margin-left: auto;
margin-bottom: 15px;
animation: ${pulseAnimation} 1.5s infinite;
border-radius: 25px;
`;

const CharacterImage = styled.div<{
$bgImage: string | null;
$position: { left: number; bottom: number };
}>`
width: 500px;
height: 500px;
background-image: url(${(props) => props.$bgImage});
background-size: cover;
background-repeat: no-repeat;
position: absolute;
z-index: 500;
transition:
right 1s ease,
bottom 1s ease;
left: ${(props) => `${props.$position.left}px`};
bottom: ${(props) => `${props.$position.bottom}px`};
animation: ${jumpAnimation} 1s infinite;
`;

const ButtonWrapper = styled.div`
display: flex;
justify-content: center;
width: 700px;
`;

function FinishDrawingModal({ canvasId, canvasUrl }: ModalProps) {
const navigate = useNavigate();
const userProfile = useRecoilValue(UserProfileState);

const handleConfirm = async () => {
try {
const response = await postTopicDrawing(canvasId);
console.log('게시물 올리기 성공', response);
return response.data;
} catch (error) {
console.log('게시물 올리기 실패', error);
throw error;
}
};

function handleSave() {
fetch(canvasUrl)
.then((response) => response.blob())
.then((blob) => {
const blobUrl = URL.createObjectURL(blob);

const a = document.createElement('a');
a.href = blobUrl;
a.download = '변환된 그림.jpg';
document.body.appendChild(a);
a.click();
setTimeout((_) => {
window.URL.revokeObjectURL(blobUrl);
}, 60000);
a.remove();

console.log('이미지 다운로드 성공');
})
.catch((error) => {
console.error('이미지 다운로드 에러', error);
});
}

return (
<>
<ModalWrapper>
{canvasUrl ? (
<TopImage src={canvasUrl} alt="최종 변환된 그림" />
) : (
<TopImageSkeleton />
)}
<ButtonWrapper>
<Button buttonText="저장하기" color="green" onClick={handleSave} />
<Button
buttonText="랭킹 참여하기"
color="green"
onClick={handleConfirm}
/>
<Button buttonText="공유하기" color="green" onClick={handleConfirm} />
</ButtonWrapper>
</ModalWrapper>
<CharacterImage
$bgImage={userProfile.profileImg}
$position={{ left: 0, bottom: -100 }}
/>
</>
);
}

export default FinishDrawingModal;
Loading

0 comments on commit 1fe0900

Please sign in to comment.