Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create deck api #102

Merged
merged 2 commits into from
Aug 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const deck = JSON_APIS({
/* deck Creations: Upload a deck of cards */
// Todo : change to session
createDeck: ({ createDeckDto }: { createDeckDto: CreateDeckDto }) =>
client.public.post<{ deck_id: string }>('decks', createDeckDto),
client.public.post<{ result: { deck_id: string } }>('decks', createDeckDto),
/* get Deck: Get card information by deck id */
// Todo : change to session
getDeck: ({ id }: { id: string }) => client.public.get<{ result: Deck | null }>(`decks/id=${id}`),
Expand Down
9 changes: 5 additions & 4 deletions packages/service-frontend/app/complete/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'

import Lottie from 'lottie-react'
import { useRouter } from 'next/navigation'
import { useRouter, useSearchParams } from 'next/navigation'
import { Button } from '@ppoba/ui'

import addDeckLottie from '@/public/lottie/addDeckLottie.json'
Expand All @@ -10,10 +10,11 @@ import { Header } from '../components/common'

export default function DeckCreateCompletePage(): JSX.Element {
const router = useRouter()

const searchParams = useSearchParams()
const deckId = searchParams.get('deckId')

const handleClick = () => {
// TODO: 실제 덱 아이디를 받아서 이동하도록 수정
router.push('/deck/1')
router.push(`/deck/${deckId}`)
}

return (
Expand Down
54 changes: 43 additions & 11 deletions packages/service-frontend/app/confirm-detail/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
'use client'
import { useState, type JSX, useCallback } from 'react'

import { useMutation } from '@tanstack/react-query'
import { useRouter } from 'next/navigation'
import { useRecoilState } from 'recoil'
import { api } from '@ppoba/api'
import { DeckCategory } from '@ppoba/types/src/dto/createDeckDto'
import { Icon, Button } from '@ppoba/ui'

import { Header } from '@/app/components'
import { deckFormAtomState } from '@/store/deck'

import GameKeywordBox from './GameKeywordBox'

Expand All @@ -20,32 +25,59 @@ const INITIAL_KEYWORDS = [
]

export default function ConfirmDetailPage(): JSX.Element {
const [keywords, setKeywords] = useState<string[]>(INITIAL_KEYWORDS)
const [isAdultGame, setIsAdultGame] = useState<boolean>(false)
const [selectedKeywords, setSelectedKeywords] = useState<string[]>([])

const [deck, setDeck] = useRecoilState(deckFormAtomState);
const router = useRouter()
const { mutate } = useMutation(api.deck.createDeck, {
onSuccess: (data) => {
const cardList = deck.cardList.filter((card) => card?.content !== undefined);
createCardMutate({
createCardDto: {
deckId: data.result.deck_id,
cardList: cardList,
}
})
},
onError: (error) => {
console.log('error', error)
}
});
const { mutate: createCardMutate } = useMutation(api.card.createCard, {
onSuccess: (_, variables) => {
const deckId = variables.createCardDto.deckId;
router.push(`/complete?deckId=${deckId}`)
},
onError: (error) => {
console.log('error', error)
}
});

const handleClick = () => {
router.push('/complete')
mutate({
createDeckDto: {
name: deck.name,
userId: "2931028309", // TODO: 실제 user id 넣기
category: deck.category as DeckCategory[],
}
});
}

const handleClickKeyword = useCallback(
(keyword: string) => {
const nextSelectedKeywords = [...selectedKeywords]
const nextSelectedKeywords = [...deck.category]
const targetIndex = nextSelectedKeywords.findIndex(
item => item === keyword,
)

if (targetIndex !== -1) {
// 기존에 선택했던 키워드라면 제거한다.
nextSelectedKeywords.splice(targetIndex, 1)
setSelectedKeywords(nextSelectedKeywords)
setDeck({ ...deck, category: nextSelectedKeywords })
} else {
setSelectedKeywords([...nextSelectedKeywords, keyword])
setDeck({ ...deck, category: [...nextSelectedKeywords, keyword] })
}
},
[selectedKeywords],
[deck.category],
)

return (
Expand All @@ -63,8 +95,8 @@ export default function ConfirmDetailPage(): JSX.Element {
</div>
{/* 키워드 선택 */}
<GameKeywordBox
keywords={keywords}
selectedKeywords={selectedKeywords}
keywords={INITIAL_KEYWORDS}
selectedKeywords={deck.category}
isAdultGame={isAdultGame}
onClickKeyword={handleClickKeyword}
onClickAdult={() => setIsAdultGame(prev => !prev)}
Expand All @@ -75,7 +107,7 @@ export default function ConfirmDetailPage(): JSX.Element {
size="large"
rightIcon="goWhite"
className="transition-all"
disabled={selectedKeywords.length === 0 && !isAdultGame}
disabled={deck.category.length === 0 && !isAdultGame}
onClick={handleClick}
>
업로드 하자
Expand Down
20 changes: 17 additions & 3 deletions packages/service-frontend/app/create-deck/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import React, { useState, useRef } from 'react'

import { useRouter } from 'next/navigation'
import { useRecoilState } from 'recoil'
import { Scrollbar } from 'swiper'
import { Swiper, SwiperSlide } from 'swiper/react'
import { Button, Icon, SecondaryButton } from '@ppoba/ui'
Expand All @@ -11,6 +12,7 @@ import 'swiper/css/scrollbar'

import { Header } from '@/app/components'
import { CardStyle } from '@/app/deck/[id]/play/constant'
import { deckFormAtomState } from '@/store/deck'

// DUMMY DATA
const DUMMY_DATA = ['1', '2', '3', '4', '5']
Expand All @@ -21,7 +23,7 @@ const bgColors: string[] = Object.values(CardStyle).map(
)

export default function CreateDeck(): JSX.Element {
const [text, setText] = useState('')
const [deck, setDeck] = useRecoilState(deckFormAtomState);
const router = useRouter()

const handleClick = () => {
Expand Down Expand Up @@ -59,10 +61,22 @@ export default function CreateDeck(): JSX.Element {
}`}
>
<textarea
value={text}
onChange={e => setText(e.target.value)}
value={deck.cardList[idx]?.content ?? ''}
placeholder="새로운 카드 내용을 입력해줘"
maxLength={50}
onChange={(e) => {
setDeck({
...deck,
cardList: deck.cardList.map((card, i) =>
i === idx
? {
...card,
content: e.target.value,
}
: card,
),
})
}}
className={`w-full h-[205px] headline-3 placeholder:text-[rgba(36,36,36,0.50)] bg-transparent text-center break-keep resize-none`}
/>
<button className="p-[14px] bg-white/20 rounded-full">
Expand Down
5 changes: 5 additions & 0 deletions packages/service-frontend/app/create-title/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
import React from 'react'

import { useRouter } from 'next/navigation'
import { useRecoilState } from 'recoil'
import { Button } from '@ppoba/ui'

import { Header } from '@/app/components'
import { deckFormAtomState } from '@/store/deck'

export default function CreateDeck(): JSX.Element {
const [deck, setDeck] = useRecoilState(deckFormAtomState);
const router = useRouter()

const handleClick = () => {
Expand All @@ -22,6 +25,8 @@ export default function CreateDeck(): JSX.Element {
placeholder="덱 이름을 알려줘 (최대 11자)"
className="headline-2 text-black text-center placeholder:text-grey-200 bg-transparent"
maxLength={11}
value={deck.name}
onChange={(e) => setDeck({ ...deck, name: e.target.value })}
/>
</div>
<Button size="large" rightIcon="goLight" onClick={handleClick}>
Expand Down
17 changes: 17 additions & 0 deletions packages/service-frontend/store/deck.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { atom } from "recoil";
import { CardList } from '@ppoba/types/src/dto/createCardDto';

type DeckFormAtomState = {
name: string;
category: string[];
cardList: CardList[];
}

export const deckFormAtomState = atom<DeckFormAtomState>({
key: "deckForm",
default: {
name: "",
category: [],
cardList: new Array(20).fill({}),
}
});