diff --git a/src/Detail/components/BigLecueNote/BigLecueNote.style.ts b/src/Detail/components/BigLecueNote/BigLecueNote.style.ts index 9f24aaba..a2ba5cc3 100644 --- a/src/Detail/components/BigLecueNote/BigLecueNote.style.ts +++ b/src/Detail/components/BigLecueNote/BigLecueNote.style.ts @@ -1,8 +1,7 @@ import styled from '@emotion/styled'; export const BigLecueNoteWrapper = styled.div<{ - noteBackgroundColor: number; - noteBackgroundImage: string; + noteBackground: string; noteTextColor: number; }>` width: 100%; @@ -10,36 +9,16 @@ export const BigLecueNoteWrapper = styled.div<{ padding: 2rem 1.1rem 1.7rem 1.9rem; border-radius: 0.6rem; - background: ${({ theme, noteBackgroundColor, noteBackgroundImage }) => { - if (noteBackgroundColor === -1) { - return `url(${noteBackgroundImage})`; + ${({ noteBackground }) => { + if (noteBackground.substring(0, 1) === '#') { + return `background-color: ${noteBackground}`; } else { - switch (noteBackgroundColor) { - case 1: - return theme.colors.sub_pink; - case 2: - return theme.colors.sub_blue; - case 3: - return theme.colors.sub_green; - case 4: - return theme.colors.sub_purple; - case 5: - return theme.colors.sub_yellow; - case 6: - return theme.colors.sub_ivory; - default: - return 'transparent'; - } + return `background: url(${noteBackground})`; } }}; background-size: cover; - color: ${({ theme, noteTextColor }) => { - switch (noteTextColor) { - case 0: - return theme.colors.white; - case 1: - return theme.colors.BG; - } + color: ${({ noteTextColor }) => { + return noteTextColor; }}; `; diff --git a/src/Detail/components/BigLecueNote/index.tsx b/src/Detail/components/BigLecueNote/index.tsx index 7bb04427..9fa75b7f 100644 --- a/src/Detail/components/BigLecueNote/index.tsx +++ b/src/Detail/components/BigLecueNote/index.tsx @@ -5,8 +5,7 @@ interface BigLecueNoteProps { noteDate: string; noteNickname: string; noteTextColor: number; - noteBackgroundColor: number; - noteBackgroundImage: string; + noteBackground: string; } function BigLecueNote({ @@ -14,13 +13,11 @@ function BigLecueNote({ noteDate, noteNickname, noteTextColor, - noteBackgroundColor, - noteBackgroundImage, + noteBackground, }: BigLecueNoteProps) { return ( {noteNickname} diff --git a/src/Detail/components/BookInfoBox/BookInfoBox.style.ts b/src/Detail/components/BookInfoBox/BookInfoBox.style.ts index 77c89392..2312e313 100644 --- a/src/Detail/components/BookInfoBox/BookInfoBox.style.ts +++ b/src/Detail/components/BookInfoBox/BookInfoBox.style.ts @@ -1,17 +1,18 @@ import styled from '@emotion/styled'; -export const BookInfoBoxWrapper = styled.div<{ backgroundColor: number }>` +export const BookInfoBoxWrapper = styled.div<{ backgroundColor: string }>` display: flex; width: 100%; height: 18.3em; background-color: ${({ theme, backgroundColor }) => { + backgroundColor; switch (backgroundColor) { - case 0: + case '#F5F5F5': return theme.colors.BG; - case 1: - return theme.colors.white; + case '#191919': + return theme.colors.background; } }}; `; @@ -48,44 +49,48 @@ export const BookInfoHeaderItemWrapper = styled.div` column-gap: 0.3rem; `; -export const BookInfoHeaderItem = styled.p<{ backgroundColor: number }>` +export const BookInfoHeaderItem = styled.p<{ backgroundColor: string }>` height: 1.8rem; padding-top: 0.4rem; color: ${({ theme, backgroundColor }) => { + backgroundColor; switch (backgroundColor) { - case 0: + case '#F5F5F5': return theme.colors.white30; - case 1: + case '#191919': return theme.colors.MG; } }}; + ${({ theme }) => theme.fonts.E_Caption_R_12}; `; -export const BookInfoTitle = styled.p<{ backgroundColor: number }>` +export const BookInfoTitle = styled.p<{ backgroundColor: string }>` margin-top: 0.7rem; color: ${({ theme, backgroundColor }) => { + backgroundColor; switch (backgroundColor) { - case 0: - return theme.colors.white; - case 1: + case '#F5F5F5': + return theme.colors.background; + case '#191919': return theme.colors.BG; } }}; ${({ theme }) => theme.fonts.Head2_SB_18}; `; -export const BookInfoContent = styled.p<{ backgroundColor: number }>` +export const BookInfoContent = styled.p<{ backgroundColor: string }>` height: 8.5rem; margin-top: 1rem; color: ${({ theme, backgroundColor }) => { + backgroundColor; switch (backgroundColor) { - case 0: + case '#F5F5F5': return theme.colors.white80; - case 1: + case '#191919': return theme.colors.BG; } }}; diff --git a/src/Detail/components/BookInfoBox/index.tsx b/src/Detail/components/BookInfoBox/index.tsx index 348ac5bb..2ce5db11 100644 --- a/src/Detail/components/BookInfoBox/index.tsx +++ b/src/Detail/components/BookInfoBox/index.tsx @@ -7,7 +7,7 @@ interface BookInfoBoxProps { bookNickname: string; title: string; description: string; - bookBackgroundColor: number; + bookBackgroundColor: string; } function BookInfoBox({ diff --git a/src/Detail/components/LecueNoteLIstHeader/LecueNoteListHeader.style.ts b/src/Detail/components/LecueNoteLIstHeader/LecueNoteListHeader.style.ts index 1c4dc714..eeb1d252 100644 --- a/src/Detail/components/LecueNoteLIstHeader/LecueNoteListHeader.style.ts +++ b/src/Detail/components/LecueNoteLIstHeader/LecueNoteListHeader.style.ts @@ -1,7 +1,7 @@ import styled from '@emotion/styled'; export const LecueNoteListHeaderWrapper = styled.div<{ - backgroundColor: number; + backgroundColor: string; }>` display: flex; position: sticky; @@ -14,7 +14,7 @@ export const LecueNoteListHeaderWrapper = styled.div<{ column-gap: 1rem; `; -export const LecueNoteCountBox = styled.div<{ backgroundColor: number }>` +export const LecueNoteCountBox = styled.div<{ backgroundColor: string }>` display: flex; justify-content: center; align-items: center; @@ -23,18 +23,19 @@ export const LecueNoteCountBox = styled.div<{ backgroundColor: number }>` border-radius: 7rem; background-color: ${({ theme, backgroundColor }) => { + backgroundColor; switch (backgroundColor) { - case 0: + case '#F5F5F5': return theme.colors.BG; - case 1: - return theme.colors.white; + case '#191919': + return theme.colors.background; } }}; color: ${({ theme, backgroundColor }) => { switch (backgroundColor) { - case 0: - return theme.colors.white; - case 1: + case '#F5F5F5': + return theme.colors.background; + case '#191919': return theme.colors.BG; } }}; diff --git a/src/Detail/components/LecueNoteLIstHeader/index.tsx b/src/Detail/components/LecueNoteLIstHeader/index.tsx index 132031d2..0a76120a 100644 --- a/src/Detail/components/LecueNoteLIstHeader/index.tsx +++ b/src/Detail/components/LecueNoteLIstHeader/index.tsx @@ -3,7 +3,7 @@ import * as S from './LecueNoteListHeader.style'; interface LecueNoteListHeaderProps { noteNum: number; - backgroundColor: number; + backgroundColor: string; isZigZagView: boolean; buttonOnClick: () => void; } diff --git a/src/Detail/components/LecueNoteListContainer/LecueNoteListContainer.style.ts b/src/Detail/components/LecueNoteListContainer/LecueNoteListContainer.style.ts index 1ece03d5..7beffc27 100644 --- a/src/Detail/components/LecueNoteListContainer/LecueNoteListContainer.style.ts +++ b/src/Detail/components/LecueNoteListContainer/LecueNoteListContainer.style.ts @@ -1,20 +1,15 @@ import styled from '@emotion/styled'; export const LecueNoteListContainerWrapper = styled.div<{ - backgroundColor: number; + backgroundColor: string; isEditable: boolean; }>` width: 100vw; padding: 0 1.6rem; padding-bottom: ${({ isEditable }) => isEditable && '12rem'}; - background-color: ${({ theme, backgroundColor }) => { - switch (backgroundColor) { - case 0: - return theme.colors.white; - case 1: - return theme.colors.BG; - } + background-color: ${({ backgroundColor }) => { + return backgroundColor; }}; flex: 1; diff --git a/src/Detail/components/LecueNoteListContainer/index.tsx b/src/Detail/components/LecueNoteListContainer/index.tsx index ce4efa3c..42f1bdae 100644 --- a/src/Detail/components/LecueNoteListContainer/index.tsx +++ b/src/Detail/components/LecueNoteListContainer/index.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { DraggableData, DraggableEvent } from 'react-draggable'; import { useLocation, useNavigate } from 'react-router-dom'; @@ -10,6 +10,7 @@ import { IcCaution, } from '../../../assets'; import Button from '../../../components/common/Button'; +import usePostStickerState from '../../../StickerAttach/hooks/usePostStickerState'; import { NoteType, postedStickerType } from '../../type/lecueBookType'; import LecueNoteListHeader from '../LecueNoteLIstHeader'; import LinearView from '../LinearView'; @@ -18,9 +19,11 @@ import * as S from './LecueNoteListContainer.style'; interface LecueNoteListContainerProps { noteNum: number; - backgroundColor: number; + backgroundColor: string; noteList: NoteType[]; postedStickerList: postedStickerType[]; + isEditable: boolean; + setEditableStateFalse: () => void; } function LecueNoteListContainer({ @@ -28,17 +31,19 @@ function LecueNoteListContainer({ backgroundColor, noteList, postedStickerList, + isEditable, + setEditableStateFalse, }: LecueNoteListContainerProps) { //hooks const location = useLocation(); const navigate = useNavigate(); + const scrollRef = useRef(document.createElement('div')); //storage const storedValue = sessionStorage.getItem('scrollPosition'); const savedScrollPosition = storedValue !== null ? parseInt(storedValue, 10) : 0; //state const [isZigZagView, setIsZigZagView] = useState(true); - const [isEditable, setIsEditable] = useState(true); const [stickerState, setStickerState] = useState({ postedStickerId: 0, stickerImage: '', @@ -48,8 +53,10 @@ function LecueNoteListContainer({ const { state } = location; + const postMutation = usePostStickerState(); + useEffect(() => { - // editable 상태 변경 + // state : 라우터 타고 온 스티커 값, 즉 스티커 값을 갖고 있는 상태라면 if (state) { window.scrollTo(0, savedScrollPosition); const { stickerId, stickerImage } = state.sticker; @@ -60,10 +67,9 @@ function LecueNoteListContainer({ })); } else { // editable 상태 변경 - setIsEditable(false); - navigate('/lecue-book'); + setEditableStateFalse(); } - }, [state]); + }, [state, isEditable]); // 스티커 위치 값 저장 const handleDrag = (_e: DraggableEvent, ui: DraggableData) => { @@ -75,22 +81,31 @@ function LecueNoteListContainer({ })); }; + // 스티커 버튼 클릭시 const handleClickStickerButton = () => { + // 현재 스크롤 위치 저장 sessionStorage.setItem('scrollPosition', window.scrollY.toString()); - setIsEditable(true); - navigate('/sticker-pack'); }; const handleClickWriteButton = () => { - alert('WriteBtn'); + navigate('/create-note'); }; const handleClickDone = () => { - setIsEditable(true); - sessionStorage.removeItem('scrollPosition'); - navigate('/lecue-book'); + // 다 붙였을 때 post 실행 + const { postedStickerId, positionX, positionY } = stickerState; + const bookId = 1; + + postMutation.mutate({ + postedStickerId: postedStickerId, + bookId: bookId, + positionX: positionX, + positionY: positionY, + }); + + setEditableStateFalse(); }; return ( @@ -107,11 +122,13 @@ function LecueNoteListContainer({ {isZigZagView ? ( ) : ( @@ -121,14 +138,14 @@ function LecueNoteListContainer({ {!isEditable && ( <> - {backgroundColor === 0 ? ( + {backgroundColor === '#F5F5F5' ? ( ) : ( )} - {backgroundColor === 0 ? ( + {backgroundColor === '#F5F5F5' ? ( ) : ( diff --git a/src/Detail/components/SmallLecueNote/SmallLecueNote.style.ts b/src/Detail/components/SmallLecueNote/SmallLecueNote.style.ts index f4fdc5c1..058a8c51 100644 --- a/src/Detail/components/SmallLecueNote/SmallLecueNote.style.ts +++ b/src/Detail/components/SmallLecueNote/SmallLecueNote.style.ts @@ -3,8 +3,7 @@ import styled from '@emotion/styled'; export const SmallLecueNoteWrapper = styled.div<{ renderType: number; noteTextColor: number; - noteBackgroundColor: number; - noteBackgroundImage: string; + noteBackground: string; }>` width: 15.2rem; height: 16.6rem; @@ -27,36 +26,16 @@ export const SmallLecueNoteWrapper = styled.div<{ }}; border-radius: 0.4rem; - background: ${({ theme, noteBackgroundColor, noteBackgroundImage }) => { - if (noteBackgroundColor === -1 && noteBackgroundImage) { - return `url(${noteBackgroundImage})`; + ${({ noteBackground }) => { + if (noteBackground.substring(0, 1) === '#') { + return `background-color: ${noteBackground}`; } else { - switch (noteBackgroundColor) { - case 1: - return theme.colors.sub_pink; - case 2: - return theme.colors.sub_blue; - case 3: - return theme.colors.sub_green; - case 4: - return theme.colors.sub_purple; - case 5: - return theme.colors.sub_yellow; - case 6: - return theme.colors.sub_ivory; - default: - return 'transparent'; - } + return `background: url(${noteBackground})`; } }}; background-size: cover; - color: ${({ theme, noteTextColor }) => { - switch (noteTextColor) { - case 0: - return theme.colors.white; - case 1: - return theme.colors.BG; - } + color: ${({ noteTextColor }) => { + return noteTextColor; }}; transform: ${({ renderType }) => { diff --git a/src/Detail/components/SmallLecueNote/index.tsx b/src/Detail/components/SmallLecueNote/index.tsx index 11519b80..8f194569 100644 --- a/src/Detail/components/SmallLecueNote/index.tsx +++ b/src/Detail/components/SmallLecueNote/index.tsx @@ -1,29 +1,18 @@ import { useState } from 'react'; +import { NoteType } from '../../type/lecueBookType'; import LecueNoteModal from '../LecueNoteModal'; import * as S from './SmallLecueNote.style'; -interface Note { - noteId: number; - renderType: number; - content: string; - noteDate: string; - noteNickname: string; - noteTextColor: number; - noteBackgroundColor: number; - noteBackgroundImage: string; -} - interface SmallLecueNoteProps { renderType: number; content: string; noteDate: string; noteNickname: string; noteTextColor: number; - noteBackgroundColor: number; - noteBackgroundImage: string; + noteBackground: string; noteId: number; - noteList: Note[]; + noteList: NoteType[]; } function SmallLecueNote({ @@ -32,8 +21,7 @@ function SmallLecueNote({ noteDate, noteNickname, noteTextColor, - noteBackgroundColor, - noteBackgroundImage, + noteBackground, noteId, noteList, }: SmallLecueNoteProps) { @@ -52,8 +40,7 @@ function SmallLecueNote({ {noteNickname} diff --git a/src/Detail/components/ZigZagView/ZigZagView.style.ts b/src/Detail/components/ZigZagView/ZigZagView.style.ts index 57031213..23bb906d 100644 --- a/src/Detail/components/ZigZagView/ZigZagView.style.ts +++ b/src/Detail/components/ZigZagView/ZigZagView.style.ts @@ -17,17 +17,25 @@ export const LecueNoteContainer = styled.div` export const StickerContainer = styled.div` position: absolute; - width: 100%; + width: 34.2rem; height: 100%; + padding: 0.4rem 0 2rem; `; -export const Sticker = styled.div<{ stickerImage: string }>` - background-image: ${({ stickerImage }) => `url(${stickerImage})`}; +export const Sticker = styled.div<{ + stickerImage: string; + isEditable?: boolean; +}>` + position: absolute; width: 10rem; height: 10rem; - background-repeat: no-repeat; + ${({ isEditable, theme }) => + isEditable && `border: solid 0.1rem ${theme.colors.key}`}; + border-radius: 0.4rem; background-position: center; + background-image: ${({ stickerImage }) => `url(${stickerImage})`}; + background-repeat: no-repeat; object-fit: cover; `; diff --git a/src/Detail/components/ZigZagView/index.tsx b/src/Detail/components/ZigZagView/index.tsx index 3ad1ab44..9876ee7c 100644 --- a/src/Detail/components/ZigZagView/index.tsx +++ b/src/Detail/components/ZigZagView/index.tsx @@ -1,4 +1,4 @@ -import { useRef } from 'react'; +import { forwardRef, useRef } from 'react'; import Draggable, { DraggableData, DraggableEvent } from 'react-draggable'; import { NoteType, postedStickerType } from '../../type/lecueBookType'; @@ -11,15 +11,20 @@ interface ZigZagViewProps { stickerState: postedStickerType; isEditable: boolean; postedStickerList: postedStickerType[]; + savedScrollPosition: number; } -function ZigZagView({ - noteList, - handleDrag, - stickerState, - isEditable, - postedStickerList, -}: ZigZagViewProps) { +const ZigZagView = forwardRef(function ZigZagView( + { + noteList, + handleDrag, + stickerState, + isEditable, + postedStickerList, + savedScrollPosition, + }: ZigZagViewProps, + ref: React.Ref, +) { const nodeRef = useRef(null); return ( @@ -29,35 +34,36 @@ function ZigZagView({ ))} - + + {isEditable && ( + + + + )} {postedStickerList.map((data) => ( false} nodeRef={nodeRef} key={data.postedStickerId} - positionOffset={{ x: data.positionX, y: data.positionY }} - onStart={() => false} + defaultPosition={{ x: data.positionX, y: data.positionY }} > ))} - {isEditable && ( - - - - - - )} ); -} - +}); export default ZigZagView; diff --git a/src/Detail/page/DetailPage/index.tsx b/src/Detail/page/DetailPage/index.tsx index 3867bb01..7e4c32ab 100644 --- a/src/Detail/page/DetailPage/index.tsx +++ b/src/Detail/page/DetailPage/index.tsx @@ -1,3 +1,5 @@ +import { useState } from 'react'; + import Header from '../../../components/common/Header'; import BookInfoBox from '../../components/BookInfoBox'; import LecueNoteListContainer from '../../components/LecueNoteListContainer'; @@ -7,15 +9,22 @@ import * as S from './DetailPage.style'; function DetailPage() { const { bookDetail } = useGetBookDetail(); + const [isEditable, setIsEditable] = useState(true); + + const setEditableStateFalse = () => { + setIsEditable(false); + }; return bookDetail ? ( -
+
) : ( //TODO 에러페이지로 route -
uuid가 틀려서 아무것도 안보임
+
에러에러에러에러
); } diff --git a/src/Detail/type/lecueBookType.ts b/src/Detail/type/lecueBookType.ts index a5ab7a7b..5b602421 100644 --- a/src/Detail/type/lecueBookType.ts +++ b/src/Detail/type/lecueBookType.ts @@ -12,6 +12,5 @@ export interface NoteType { noteDate: string; noteNickname: string; noteTextColor: number; - noteBackgroundColor: number; - noteBackgroundImage: string; + noteBackground: string; } diff --git a/src/StickerAttach/api/postStickerState.ts b/src/StickerAttach/api/postStickerState.ts new file mode 100644 index 00000000..471d4ee9 --- /dev/null +++ b/src/StickerAttach/api/postStickerState.ts @@ -0,0 +1,28 @@ +import { api } from '../../libs/api'; +import { postedStickerParams } from '../type/postStickerType'; + +export async function postStickerState({ + postedStickerId, + bookId, + positionX, + positionY, +}: postedStickerParams) { + console.log('api', postedStickerId, bookId, positionX, positionY); + + const data = await api.post( + '/api/stickers', + { + bookId: bookId, + stickerId: postedStickerId, + positionX: positionX, + positionY: positionY, + }, + { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${import.meta.env.VITE_APP_TOKEN}`, + }, + }, + ); + return data?.data?.data; +} diff --git a/src/StickerAttach/hooks/.gitkeep b/src/StickerAttach/hooks/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/StickerAttach/hooks/usePostStickerState.ts b/src/StickerAttach/hooks/usePostStickerState.ts new file mode 100644 index 00000000..2ef10f63 --- /dev/null +++ b/src/StickerAttach/hooks/usePostStickerState.ts @@ -0,0 +1,33 @@ +import { AxiosError } from 'axios'; +import { useMutation } from 'react-query'; +import { useNavigate } from 'react-router-dom'; + +import { postStickerState } from '../api/postStickerState'; +import { postedStickerParams } from '../type/postStickerType'; + +const usePostStickerState = () => { + const navigate = useNavigate(); + const mutation = useMutation({ + mutationFn: ({ + postedStickerId, + bookId, + positionX, + positionY, + }: postedStickerParams) => { + return postStickerState({ + postedStickerId, + bookId, + positionX, + positionY, + }); + }, + onSuccess: () => { + navigate('/lecue-book'); + }, + + onError: (err: AxiosError) => console.log(err), + }); + return mutation; +}; + +export default usePostStickerState; diff --git a/src/StickerAttach/type/postStickerType.ts b/src/StickerAttach/type/postStickerType.ts new file mode 100644 index 00000000..f1a4b42d --- /dev/null +++ b/src/StickerAttach/type/postStickerType.ts @@ -0,0 +1,6 @@ +export interface postedStickerParams { + postedStickerId: number; + bookId: number; + positionX: number; + positionY: number; +}