-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fix: 기존에 잘못된 url 주소 변경 * feat: carousel 구현 * fix: api 요청 방법 변경 * fix: image post api 수정 * feat: image 불러오기 위한 기능 구현 * fix: 스크롤바가 보이지 않도록 변경 * design: Carousel 디자인 변경 * fix: 사진 추가 버튼 커스텀 * feat: images 불러오는 api 추가 * feat: Carousel component 구현 완료 * feat: 사진 추가 페이지 구현 * feat: 요청으로 불러오는 Images 타입 선언 * feat: 홈에서 이미지를 확인할 수 있는 기능 추가 * fix: 행사 생성 시 다른 query들 초기화하도록 변경 * fix: style이 제대로 적용되지 않던 문제 해결 * style: lint 적용 * fix: mock url 변경 * feat: imageDelete api 추가 * fix: service type 수정 * refactor: AddImagesPage 구조 변경 및 delete api 추가 * fix: 불필요한 z-index 제거₩ * fix: merge 충돌 해결
- Loading branch information
Showing
34 changed files
with
673 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export const BASE_URL = { | ||
HD: process.env.API_BASE_URL, | ||
S3: process.env.S3_URL, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import {EventId, Images} from 'types/serviceType'; | ||
|
||
import {BASE_URL} from '@apis/baseUrl'; | ||
import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; | ||
import {requestDelete, requestGet, requestPostWithoutResponse} from '@apis/fetcher'; | ||
import {WithEventId} from '@apis/withId.type'; | ||
|
||
export interface RequestPostImages { | ||
formData: FormData; | ||
} | ||
|
||
export const requestPostImages = async ({eventId, formData}: WithEventId<RequestPostImages>) => { | ||
// return await requestPostWithoutResponse({ | ||
// baseUrl: BASE_URL.HD, | ||
// endpoint: `${ADMIN_API_PREFIX}/${eventId}/images`, | ||
// headers: { | ||
// 'Content-Type': 'multipart/form-data', | ||
// }, | ||
// body: formData, | ||
// }); | ||
|
||
// TODO: (@todari): 기존의 request 방식들은 기본적으로 | ||
// header를 Content-Type : application/json 으로 보내주고 있음 | ||
// multipart/form-data 요청을 보내기 위해선 header Content-Type을 빈 객체로 전달해야 함 | ||
fetch(`${BASE_URL.HD}${ADMIN_API_PREFIX}/${eventId}/images`, { | ||
credentials: 'include', | ||
// headers: { | ||
// 'Content-Type': 'multipart/form-data', | ||
// }, | ||
method: 'POST', | ||
body: formData, | ||
}); | ||
}; | ||
|
||
export const requestGetImages = async ({eventId}: WithEventId) => { | ||
return await requestGet<Images>({ | ||
baseUrl: BASE_URL.HD, | ||
endpoint: `${USER_API_PREFIX}/${eventId}/images`, | ||
}); | ||
}; | ||
|
||
export interface RequestDeleteImage { | ||
imageId: number; | ||
} | ||
|
||
export const requestDeleteImage = async ({eventId, imageId}: WithEventId<RequestDeleteImage>) => { | ||
return await requestDelete({ | ||
baseUrl: BASE_URL.HD, | ||
endpoint: `${ADMIN_API_PREFIX}/${eventId}/images/${imageId}`, | ||
}); | ||
}; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions
27
client/src/components/Design/components/Carousel/Carousel.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import type {Meta, StoryObj} from '@storybook/react'; | ||
|
||
import Carousel from './Carousel'; | ||
|
||
const meta = { | ||
title: 'Components/Carousel', | ||
component: Carousel, | ||
tags: ['autodocs'], | ||
parameters: { | ||
layout: 'centered', | ||
width: 430, | ||
}, | ||
argTypes: {}, | ||
args: { | ||
urls: [ | ||
'https://wooteco-crew-wiki.s3.ap-northeast-2.amazonaws.com/%EC%BF%A0%ED%82%A4(6%EA%B8%B0)/image.png', | ||
'https://wooteco-crew-wiki.s3.ap-northeast-2.amazonaws.com/%EC%BF%A0%ED%82%A4%286%EA%B8%B0%29/4tyq1x19rsn.jpg', | ||
'https://img.danawa.com/images/descFiles/5/896/4895281_1_16376712347542321.gif', | ||
], | ||
}, | ||
} satisfies Meta<typeof Carousel>; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof meta>; | ||
|
||
export const Playground: Story = {}; |
94 changes: 94 additions & 0 deletions
94
client/src/components/Design/components/Carousel/Carousel.style.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import {css} from '@emotion/react'; | ||
|
||
import {Theme} from '@components/Design/theme/theme.type'; | ||
|
||
export const carouselWrapperStyle = css` | ||
position: relative; | ||
overflow: hidden; | ||
display: flex; | ||
`; | ||
|
||
interface ImageCardContainerStyleProps { | ||
currentIndex: number; | ||
length: number; | ||
translateX: number; | ||
isDragging: boolean; | ||
} | ||
|
||
export const imageCardContainerStyle = ({ | ||
currentIndex, | ||
length, | ||
translateX, | ||
isDragging, | ||
}: ImageCardContainerStyleProps) => css` | ||
display: flex; | ||
gap: 1rem; | ||
margin-inline: 2rem; | ||
transform: translateX( | ||
calc( | ||
(100vw - 3rem) * ${-currentIndex} + | ||
${(currentIndex === 0 && translateX > 0) || (currentIndex === length - 1 && translateX < 0) ? 0 : translateX}px | ||
) | ||
); | ||
transition: ${isDragging ? 'none' : '0.2s'}; | ||
transition-timing-function: cubic-bezier(0.7, 0.62, 0.62, 1.16); | ||
`; | ||
|
||
interface ImageCardStyleProps { | ||
theme: Theme; | ||
} | ||
|
||
export const imageCardStyle = ({theme}: ImageCardStyleProps) => css` | ||
position: relative; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
clip-path: inset(0 round 1rem); | ||
background-color: ${theme.colors.gray}; | ||
`; | ||
|
||
export const imageStyle = css` | ||
width: calc(100vw - 4rem); | ||
aspect-ratio: 3/4; | ||
object-fit: contain; | ||
`; | ||
|
||
export const deleteButtonStyle = css` | ||
position: absolute; | ||
top: 1rem; | ||
right: 1rem; | ||
padding: 0.5rem; | ||
opacity: 0.48; | ||
background-color: rgba(0, 0, 0, 0.5); | ||
border-radius: 50%; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
`; | ||
|
||
export const indicatorContainerStyle = css` | ||
position: absolute; | ||
left: 50%; | ||
bottom: 1rem; | ||
transform: translateX(-50%); | ||
display: flex; | ||
gap: 0.25rem; | ||
width: 8rem; | ||
`; | ||
|
||
interface IndicatorStyleProps { | ||
index: number; | ||
currentIndex: number; | ||
theme: Theme; | ||
} | ||
|
||
export const indicatorStyle = ({index, currentIndex, theme}: IndicatorStyleProps) => css` | ||
width: 100%; | ||
height: 0.125rem; | ||
border-radius: 0.0625rem; | ||
opacity: ${index !== currentIndex ? 0.48 : 1}; | ||
background-color: ${index !== currentIndex ? theme.colors.lightGrayContainer : theme.colors.primary}; | ||
transition: 0.2s; | ||
transition-timing-function: cubic-bezier(0.7, 0.62, 0.62, 1.16); | ||
content: ' '; | ||
`; |
36 changes: 36 additions & 0 deletions
36
client/src/components/Design/components/Carousel/Carousel.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** @jsxImportSource @emotion/react */ | ||
import {CarouselProps} from './Carousel.type'; | ||
import CarouselIndicator from './CarouselIndicator'; | ||
import CarouselDeleteButton from './CarouselDeleteButton'; | ||
import {carouselWrapperStyle, imageCardContainerStyle, imageCardStyle, imageStyle} from './Carousel.style'; | ||
import useCarousel from './useCarousel'; | ||
|
||
const Carousel = ({urls, onClickDelete}: CarouselProps) => { | ||
const {handleDragStart, handleDrag, handleDragEnd, theme, currentIndex, translateX, isDragging, handleClickDelete} = | ||
useCarousel({urls, onClickDelete}); | ||
|
||
return ( | ||
<div css={carouselWrapperStyle}> | ||
<div | ||
css={imageCardContainerStyle({currentIndex, length: urls.length, translateX, isDragging})} | ||
onMouseDown={handleDragStart} | ||
onMouseMove={handleDrag} | ||
onMouseUp={handleDragEnd} | ||
onTouchStart={handleDragStart} | ||
onTouchMove={handleDrag} | ||
onTouchEnd={handleDragEnd} | ||
> | ||
{urls && | ||
urls.map((url, index) => ( | ||
<div key={url} css={imageCardStyle({theme})}> | ||
<img src={url} alt={`업로드된 이미지 ${index + 1}`} css={imageStyle} /> | ||
{onClickDelete && <CarouselDeleteButton onClick={() => handleClickDelete(index)} />} | ||
</div> | ||
))} | ||
</div> | ||
{urls.length !== 1 && <CarouselIndicator length={urls.length} currentIndex={currentIndex} />} | ||
</div> | ||
); | ||
}; | ||
|
||
export default Carousel; |
4 changes: 4 additions & 0 deletions
4
client/src/components/Design/components/Carousel/Carousel.type.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export interface CarouselProps { | ||
urls: string[]; | ||
onClickDelete?: (index: number) => void; | ||
} |
17 changes: 17 additions & 0 deletions
17
client/src/components/Design/components/Carousel/CarouselDeleteButton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import Icon from '../Icon/Icon'; | ||
|
||
import {deleteButtonStyle} from './Carousel.style'; | ||
|
||
interface Props { | ||
onClick: () => void; | ||
} | ||
|
||
const CarouselDeleteButton = ({onClick}: Props) => { | ||
return ( | ||
<button css={deleteButtonStyle} onClick={onClick}> | ||
<Icon iconType="x" /> | ||
</button> | ||
); | ||
}; | ||
|
||
export default CarouselDeleteButton; |
22 changes: 22 additions & 0 deletions
22
client/src/components/Design/components/Carousel/CarouselIndicator.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import {useTheme} from '@components/Design/theme/HDesignProvider'; | ||
|
||
import {indicatorContainerStyle, indicatorStyle} from './Carousel.style'; | ||
|
||
interface Props { | ||
length: number; | ||
currentIndex: number; | ||
} | ||
|
||
const CarouselIndicator = ({length, currentIndex}: Props) => { | ||
const {theme} = useTheme(); | ||
|
||
return ( | ||
<div css={indicatorContainerStyle}> | ||
{Array.from({length}).map((_, index) => ( | ||
<div key={index} css={indicatorStyle({index, currentIndex, theme})} /> | ||
))} | ||
</div> | ||
); | ||
}; | ||
|
||
export default CarouselIndicator; |
48 changes: 48 additions & 0 deletions
48
client/src/components/Design/components/Carousel/useCarousel.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import {useRef, useState} from 'react'; | ||
|
||
import {useTheme} from '@components/Design/theme/HDesignProvider'; | ||
|
||
import {CarouselProps} from './Carousel.type'; | ||
|
||
const useCarousel = ({urls, onClickDelete}: CarouselProps) => { | ||
const startX = useRef(0); | ||
const [translateX, setTranslateX] = useState(0); | ||
const [isDragging, setIsDragging] = useState(false); | ||
const [currentIndex, setCurrentIndex] = useState(0); | ||
const {theme} = useTheme(); | ||
|
||
const handleDragStart = (e: React.TouchEvent | React.MouseEvent) => { | ||
setIsDragging(true); | ||
startX.current = 'touches' in e ? e.touches[0].clientX : e.clientX; | ||
}; | ||
|
||
const handleDrag = (e: React.TouchEvent | React.MouseEvent) => { | ||
if (!isDragging) return; | ||
const currentX = 'touches' in e ? e.touches[0].clientX : e.clientX; | ||
const deltaX = currentX - startX.current; | ||
setTranslateX(deltaX); | ||
}; | ||
|
||
const threshold = window.screen.width / 10; | ||
|
||
const handleDragEnd = () => { | ||
setIsDragging(false); | ||
if (-translateX > threshold) { | ||
setCurrentIndex(prev => (prev !== urls.length - 1 ? prev + 1 : prev)); | ||
} | ||
if (+translateX > threshold) { | ||
setCurrentIndex(prev => (prev !== 0 ? prev - 1 : prev)); | ||
} | ||
setTranslateX(0); | ||
}; | ||
|
||
const handleClickDelete = (index: number) => { | ||
if (!onClickDelete) return; | ||
onClickDelete(index); | ||
if (urls.length !== 1 && index === urls.length - 1) setCurrentIndex(prev => prev - 1); | ||
}; | ||
|
||
return {handleDragStart, handleDrag, handleDragEnd, theme, currentIndex, translateX, isDragging, handleClickDelete}; | ||
}; | ||
|
||
export default useCarousel; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,5 +21,4 @@ export type FlexProps = React.HTMLAttributes<HTMLDivElement> & { | |
minHeight?: string; | ||
|
||
cssProp?: CSSObject; | ||
} | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.