Skip to content

Commit

Permalink
Merge pull request #122 from DDD-Community/feature/119
Browse files Browse the repository at this point in the history
[Feature/119] 폴라로이드 상세 Carousel, 폴라로이드 삭제
  • Loading branch information
hwanheejung authored Sep 25, 2024
2 parents e62521d + 40ffa8c commit d2a39ce
Show file tree
Hide file tree
Showing 13 changed files with 232 additions and 43 deletions.
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"react": "^18",
"react-device-detect": "^2.2.3",
"react-dom": "^18",
"react-multi-carousel": "^2.8.5",
"tailwind-merge": "^2.3.0",
"tailwind-scrollbar-hide": "^1.1.7"
},
Expand Down
27 changes: 27 additions & 0 deletions public/icons/polaroid_fire.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icons/trash.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 14 additions & 12 deletions src/app/board/[boardId]/_components/PolaroidList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
'use client'

import { Polaroid } from '@/types'
import { useState } from 'react'
import PolaroidDetailModal from '@/components/Polaroid/PolaroidDetail'
import { Board } from '@/types'
import { useState } from 'react'
import PolaroidListItem from './PolaroidListItem'

interface PolaroidListProps {
polaroids: Polaroid[]
board: Board
boardId: string
}

const PolaroidList = ({ polaroids }: PolaroidListProps) => {
const PolaroidList = ({ boardId, board }: PolaroidListProps) => {
const [isModalOpen, setIsModalOpen] = useState(false)
const [selectedPolaroid, setSelectedPolaroid] = useState<Polaroid | null>(
null,
)
const [selectedIdx, setSelectedIdx] = useState<number>(0)

const openDetailModal = (polaroid: Polaroid) => {
setSelectedPolaroid(polaroid)
const openDetailModal = (idx: number) => {
setSelectedIdx(idx)
setIsModalOpen(true)
}

return (
<div className="mx-auto w-full flex-1 overflow-x-hidden overflow-y-scroll pb-10 scrollbar-hide">
<div className="grid grid-cols-2 gap-6 px-[20px] py-[10px]">
{polaroids.map((item) => (
{board.items.map((item, idx) => (
<PolaroidListItem
key={item.id}
item={item}
onClick={() => openDetailModal(item)}
onClick={() => openDetailModal(idx)}
/>
))}
</div>
<PolaroidDetailModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
polaroid={selectedPolaroid}
selectedIdx={selectedIdx}
polaroids={board.items}
boardId={boardId}
isBoardOwner={board.mine}
/>
</div>
)
Expand Down
1 change: 0 additions & 1 deletion src/app/board/[boardId]/_components/Tutorial/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ const Tutorial = ({
zIndex: 10,
boxShadow: '0 0 0 9999px rgba(0, 0, 0, 0.6)',
pointerEvents: 'none',
// border: '2px dotted red',
})

setTopBox({
Expand Down
2 changes: 1 addition & 1 deletion src/app/board/[boardId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const BoardPage = async ({ params }: BoardPageProps) => {
{board.items.length === 0 ? (
<Empty />
) : (
<PolaroidList polaroids={board.items} />
<PolaroidList board={board} boardId={boardId} />
)}

<ModalProvider>
Expand Down
51 changes: 51 additions & 0 deletions src/components/Polaroid/PolaroidDetail/PolaroidDeleteBtn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use client'

import Modal from '@/components/Modal'
import Icon from 'public/icons/polaroid_fire.svg'
import TrashIcon from 'public/icons/trash.svg'
import { useState } from 'react'

interface PolaroidDeleteBtnProps {
onDetailModalClose: () => void
onDelete: () => void
}

const PolaroidDeleteBtn = ({
onDetailModalClose,
onDelete,
}: PolaroidDeleteBtnProps) => {
const [showDeleteModal, setShowDeleteModal] = useState<boolean>(false)

const handleDelete = () => {
onDelete() // delete polaroid
setShowDeleteModal(false) // close delete modal
onDetailModalClose() // close polaroid detail modal
}

return (
<>
<button
type="button"
onClick={() => setShowDeleteModal(true)}
className="mx-auto rounded-full bg-gray-800 p-2.5"
aria-label="Delete"
>
<TrashIcon className="cursor-pointer text-gray-0" />
</button>
<Modal isOpen={showDeleteModal} onClose={() => setShowDeleteModal(false)}>
<Modal.CenterModal icon={<Icon />}>
<Modal.Close />
<Modal.Title>정말로 삭제하시겠습니까?</Modal.Title>
<Modal.Content>삭제된 폴라로이드는 되돌릴 수 없어요.</Modal.Content>
<Modal.CenterConfirmCancel
cancelText="아니요"
confirmText="예"
onConfirm={handleDelete}
/>
</Modal.CenterModal>
</Modal>
</>
)
}

export default PolaroidDeleteBtn
36 changes: 36 additions & 0 deletions src/components/Polaroid/PolaroidDetail/PolaroidItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Polaroid } from '@/types'
import PolaroidDescription from '../Base/PolaroidDescription'
import PolaroidFrame from '../Base/PolaroidFrame'
import PolaroidImage from '../Base/PolaroidImage'
import PolaroidMessage from '../Base/PolaroidMessage'
import PolaroidNickname from '../Base/PolaroidNickname'

interface PolaroidItemProps {
polaroid: Polaroid
}

const PolaroidItem = ({ polaroid }: PolaroidItemProps) => {
return (
<PolaroidFrame
className="mx-auto flex w-[272px] touch-pinch-zoom flex-col overflow-y-hidden"
themaKey={polaroid.options.THEMA}
fontKey={polaroid.options.FONT}
>
<div className="mt-5 px-3">
<PolaroidImage imageUrl={polaroid.imageUrl} />
</div>
<PolaroidDescription themaKey={polaroid.options.THEMA}>
<PolaroidMessage
className="min-h-6 text-xl"
message={polaroid.oneLineMessage}
/>
<PolaroidNickname
className="min-h-5 text-lg"
nickName={polaroid.nickname}
/>
</PolaroidDescription>
</PolaroidFrame>
)
}

export default PolaroidItem
109 changes: 81 additions & 28 deletions src/components/Polaroid/PolaroidDetail/index.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,100 @@
import Modal from '@/components/Modal'
import { deletePolaroid } from '@/lib'
import { Polaroid } from '@/types'
import PolaroidImage from '@/components/Polaroid/Base/PolaroidImage'
import PolaroidFrame from '@/components/Polaroid/Base/PolaroidFrame'
import PolaroidDescription from '@/components/Polaroid/Base/PolaroidDescription'
import PolaroidMessage from '@/components/Polaroid/Base/PolaroidMessage'
import PolaroidNickname from '@/components/Polaroid/Base/PolaroidNickname'
import CloseIcon from 'public/icons/close.svg'
import { useEffect, useRef, useState } from 'react'
import Carousel from 'react-multi-carousel'
import 'react-multi-carousel/lib/styles.css'
import PolaroidDeleteBtn from './PolaroidDeleteBtn'
import PolaroidItem from './PolaroidItem'

const responsive = {
all: {
breakpoint: { max: 3000, min: 0 },
items: 1,
partialVisibilityGutter: 0,
},
}

interface PolaroidDetailModalProps {
isOpen: boolean
onClose: () => void
polaroid: Polaroid | null
selectedIdx: number
polaroids: Polaroid[]
boardId: string
isBoardOwner: boolean
}

const PolaroidDetailModal = ({
isOpen,
onClose,
polaroid,
selectedIdx,
polaroids,
boardId,
isBoardOwner,
}: PolaroidDetailModalProps) => {
if (!polaroid) {
return null
const [currentSlide, setCurrentSlide] = useState(0)
const carouselRef = useRef<Carousel | null>(null)

useEffect(() => {
if (isOpen && carouselRef.current) {
carouselRef.current.goToSlide(selectedIdx + 1)
}
}, [selectedIdx, isOpen])

const onDelete = () => {
deletePolaroid(polaroids[currentSlide - 1].id, boardId)
}

return (
<Modal isOpen={isOpen} onClose={onClose}>
<PolaroidFrame
className="mx-auto flex w-[272px] touch-pinch-zoom flex-col overflow-y-hidden"
themaKey={polaroid.options.THEMA}
fontKey={polaroid.options.FONT}
>
<div className="mt-5 px-3">
<PolaroidImage imageUrl={polaroid.imageUrl} />
<Modal isOpen={isOpen} onClose={onClose} closeOnOutsideClick={false}>
<div className="relative mx-auto flex h-dvh max-w-md flex-1 touch-pan-x flex-col justify-center overflow-x-hidden py-10">
<CloseIcon
className="absolute left-5 top-5 cursor-pointer text-gray-0"
onClick={onClose}
/>

<div className="overflow-x-hidden">
<Carousel
ref={carouselRef}
swipeable
draggable
arrows={false}
additionalTransfrom={0}
ssr={false}
responsive={responsive}
customTransition="all .5"
centerMode
containerClass="-mx-28"
itemClass="my-auto"
beforeChange={(nextSlide) => {
setCurrentSlide(nextSlide)
}}
>
<div />
{polaroids.map((item) => (
<PolaroidItem polaroid={item} key={item.id} />
))}
</Carousel>
<div className="mt-4 text-center text-gray-400">
<span>
<span className="text-gray-100">
{currentSlide === 0 ? 1 : currentSlide}
</span>
{` / ${polaroids.length}`}
</span>
</div>
</div>
<PolaroidDescription themaKey={polaroid.options.THEMA}>
<PolaroidMessage
className="min-h-6 text-xl"
message={polaroid.oneLineMessage}
/>
<PolaroidNickname
className="min-h-5 text-lg"
nickName={polaroid.nickname}
/>
</PolaroidDescription>
</PolaroidFrame>

{isBoardOwner && (
<div className="absolute bottom-5 left-1/2 -translate-x-1/2">
<PolaroidDeleteBtn
onDetailModalClose={onClose}
onDelete={onDelete}
/>
</div>
)}
</div>
</Modal>
)
}
Expand Down
8 changes: 7 additions & 1 deletion src/lib/api/polaroid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { revalidateTag } from 'next/cache'
import { CreatePolaroidPayload, Polaroid } from '@/types'
import { get, post } from './base'
import { deleteApi, get, post } from './base'

export const getPolaroid = (id: string): Promise<Polaroid> => {
return get(`/api/v1/polaroids/${id}`, {
Expand All @@ -25,3 +25,9 @@ export const postPolaroid = async (

return result.data
}

export const deletePolaroid = async (polaroidId: number, boardId: string) => {
await deleteApi(`/api/v1/polaroids/${polaroidId}`)

revalidateTag(`board:${boardId}`)
}
1 change: 1 addition & 0 deletions src/types/board.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Polaroid } from './polaroid'
export interface Board {
title: string
items: Polaroid[]
mine: boolean
}

export interface CreateBoardPayload {
Expand Down
1 change: 1 addition & 0 deletions src/types/polaroid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export interface Polaroid {
imageUrl: string
oneLineMessage: string
nickname: string
mine: boolean
options: {
FONT: FontKeyType
THEMA: ThemaKeyType
Expand Down

0 comments on commit d2a39ce

Please sign in to comment.