diff --git a/.stylelintrc.json b/.stylelintrc.json index e67f227e..e7750f1a 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -22,6 +22,7 @@ "noEmptyLineBetween": true, "properties": [ "display", + "gap", "justify-content", "align-items", "flex-direction", @@ -30,6 +31,12 @@ "flex-grow", "flex-shrink", "flex-basis", + "grid-template-columns", + "grid-area", + "grid-template-rows", + "grid-column", + "grid-template-areas", + "grid-gap", "position", "top", "right", @@ -77,6 +84,8 @@ "border-style", "background", "background-color", + "background-position", + "background-size", "color", "font-style", "font-weight", diff --git a/src/Router.tsx b/src/Router.tsx index 16e4af3a..43c60061 100644 --- a/src/Router.tsx +++ b/src/Router.tsx @@ -1,12 +1,14 @@ import { BrowserRouter, Route, Routes } from 'react-router-dom'; import HomePage from './Home/page/HomePage'; +import StickerPack from './StickerPack/page/StickerPack'; function Router() { return ( } /> + } /> ); diff --git a/src/StickerPack/api/getStickerPack.ts b/src/StickerPack/api/getStickerPack.ts new file mode 100644 index 00000000..e82a068a --- /dev/null +++ b/src/StickerPack/api/getStickerPack.ts @@ -0,0 +1,12 @@ +import { api } from '../../libs/api'; + +export async function getStickerPack(bookId: number) { + const data = await api.get(`/api/stickers/${bookId}`, { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${import.meta.env.VITE_APP_TOKEN}`, + }, + }); + + return data.data.data; +} diff --git a/src/StickerPack/components/StickerList/StickerList.style.ts b/src/StickerPack/components/StickerList/StickerList.style.ts new file mode 100644 index 00000000..a2555d72 --- /dev/null +++ b/src/StickerPack/components/StickerList/StickerList.style.ts @@ -0,0 +1,41 @@ +import styled from '@emotion/styled'; + +export const Wrapper = styled.section` + display: flex; + flex-direction: column; +`; + +export const Title = styled.header` + margin: 1.4rem 0; + + color: ${({ theme }) => theme.colors.BG}; + + ${({ theme }) => theme.fonts.Head2_SB_18}; +`; + +export const StickerGridWrapper = styled.article` + display: grid; + gap: 2.15rem 1.6rem; + grid-template-columns: repeat(3, 1fr); + + margin-bottom: 5rem; +`; + +export const ImageWrapper = styled.button<{ + isSelected: boolean; +}>` + width: 10rem; + height: 10rem; + + border: solid 0.1rem + ${({ theme, isSelected }) => + isSelected ? theme.colors.key : theme.colors.background}; + border-radius: 0.4rem; +`; + +export const ImageComponent = styled.img` + width: 10rem; + height: 10rem; + + object-fit: contain; +`; diff --git a/src/StickerPack/components/StickerList/index.tsx b/src/StickerPack/components/StickerList/index.tsx new file mode 100644 index 00000000..ab282aff --- /dev/null +++ b/src/StickerPack/components/StickerList/index.tsx @@ -0,0 +1,44 @@ +import { Fragment } from 'react'; + +import useGetStickerPack from '../../hooks/useGetStickerPack'; +import { stickerPackType } from '../../type/stickerPackType'; +import * as S from './StickerList.style'; + +interface StickerListProps { + isSelectedId: number | null; + handleStickerClick: (stickerId: number) => void; +} + +function StickerList(props: StickerListProps) { + const { isSelectedId, handleStickerClick } = props; + //TODO 임시 값 수정 + const { stickerPack } = useGetStickerPack(1); + + return ( + + {stickerPack?.length > 0 && + stickerPack.map((data: stickerPackType) => ( + + {data.stickerCategory} + + {data.stickerList.map((sticker) => ( + handleStickerClick(sticker.stickerId)} + isSelected={sticker.stickerId === isSelectedId} + > + + + ))} + + + ))} + + ); +} + +export default StickerList; diff --git a/src/StickerPack/constants/.gitkeep b/src/StickerPack/constants/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/src/StickerPack/hooks/useGetStickerPack.ts b/src/StickerPack/hooks/useGetStickerPack.ts new file mode 100644 index 00000000..ac406aa5 --- /dev/null +++ b/src/StickerPack/hooks/useGetStickerPack.ts @@ -0,0 +1,17 @@ +import { useQuery } from 'react-query'; + +import { getStickerPack } from '../api/getStickerPack'; + +export default function useGetStickerPack(bookId: number) { + const { data: stickerPack } = useQuery( + ['useGetStickerPack'], + () => getStickerPack(bookId), + { + onError: () => { + console.error; + }, + }, + ); + + return { stickerPack }; +} diff --git a/src/StickerPack/page/StickerPack/StickerPack.style.ts b/src/StickerPack/page/StickerPack/StickerPack.style.ts new file mode 100644 index 00000000..2d2a698e --- /dev/null +++ b/src/StickerPack/page/StickerPack/StickerPack.style.ts @@ -0,0 +1,18 @@ +import styled from '@emotion/styled'; + +export const Body = styled.article` + padding: 0 1.64rem; + padding-bottom: 5rem; + + background-color: ${({ theme }) => theme.colors.background}; +`; + +export const Wrapper = styled.section` + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + + width: 100vw; + height: 100dvh; +`; diff --git a/src/StickerPack/page/StickerPack/index.tsx b/src/StickerPack/page/StickerPack/index.tsx new file mode 100644 index 00000000..2f25afa2 --- /dev/null +++ b/src/StickerPack/page/StickerPack/index.tsx @@ -0,0 +1,41 @@ +import { useState } from 'react'; + +// component +import Button from '../../../components/common/Button/index.tsx'; +import Header from '../../../components/common/Header/index.tsx'; +import StickerList from '../../components/StickerList/index.tsx'; +// style +import * as S from './StickerPack.style.ts'; + +function StickerPack() { + const [isSelectedId, setIsSelectedId] = useState(null); + + const handleStickerClick = (stickerId: number) => { + setIsSelectedId(stickerId); + }; + + const handleClickDone = () => { + alert(`${isSelectedId}`); + }; + + return ( + <> +
+ + + + + + ); +} + +export default StickerPack; diff --git a/src/StickerPack/type/stickerPackType.ts b/src/StickerPack/type/stickerPackType.ts new file mode 100644 index 00000000..f2e513ed --- /dev/null +++ b/src/StickerPack/type/stickerPackType.ts @@ -0,0 +1,9 @@ +export interface stickerPackType { + stickerCategory: string; + stickerList: [ + { + stickerId: number; + stickerImage: string; + }, + ]; +} diff --git a/src/components/common/Button/Button.style.ts b/src/components/common/Button/Button.style.ts index 6db19e2d..830e734a 100644 --- a/src/components/common/Button/Button.style.ts +++ b/src/components/common/Button/Button.style.ts @@ -3,6 +3,9 @@ import styled from '@emotion/styled'; export type ButtonStyle = 'choose' | 'complete'; export const CustomButton = styled.button<{ variant: ButtonStyle }>` + position: fixed; + bottom: 2rem; + width: 34.4rem; height: 6rem;