Skip to content

Commit

Permalink
feat: EditPhotoList, EditPhotoItem 컴포넌트 추가 (#52)
Browse files Browse the repository at this point in the history
* feat(shared): EditPhotoItem에 사용되는 BiX svg 추가

* feat(shared): EditPhotoItem 컴포넌트 추가

* feat(shared): EditPhotoList에 사용되는 IoCamera svg 추가

* feat(shared): EditPhotoList, UploadPhotoItem 컴포넌트 추가
  • Loading branch information
sukvvon authored Nov 8, 2023
1 parent 6cc7128 commit 5e26275
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/shared/assets/icon_BiX.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/shared/assets/icon_IoCamera.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions packages/shared/components/EditPhotoItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { ImageProps } from '@chakra-ui/react';
import { Box, Image } from '@chakra-ui/react';
import { MouseEvent } from 'react';

import BiX from '../assets/icon_BiX.svg';

type UploadedPhotoItemProps = {
photoId: ImageProps['id'];
photoSrc: ImageProps['src'];
onDeletePhoto: (event: MouseEvent<HTMLDivElement>) => void;
};

export default function EditPhotoItem({
photoId,
photoSrc,
onDeletePhoto,
}: UploadedPhotoItemProps) {
return (
<Box
boxSize={100}
pos="relative"
overflow="hidden"
borderRadius="10px"
flexShrink={0}
>
<Box
id={photoId}
w={5}
h={5}
pos="absolute"
top={1}
right={1}
borderRadius={50}
border="1px solid"
borderColor="orange.400"
backgroundColor="white"
cursor="pointer"
onClick={onDeletePhoto}
>
<Image src={BiX} />
</Box>
<Image boxSize={100} fit="cover" src={photoSrc} />
</Box>
);
}
140 changes: 140 additions & 0 deletions packages/shared/components/EditPhotoList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import type { UseToastOptions } from '@chakra-ui/react';
import {
Box,
Flex,
HStack,
Image,
Input,
Text,
useToast,
} from '@chakra-ui/react';
import type { ChangeEvent, Dispatch, MouseEvent, SetStateAction } from 'react';

import IoIosCamera from '../assets/icon_IoCamera.svg';
import EditPhotoItem from './EditPhotoItem';

type EditPhotoListProps = {
urls: string[];
setUrls: Dispatch<SetStateAction<string[]>>;
};

type UploadPhotoItemProps = {
urlsCount: number;
onUploadPhoto: (event: ChangeEvent<HTMLInputElement>) => void;
};

export default function EditPhotoList({ urls, setUrls }: EditPhotoListProps) {
const toast = useToast();

const afterUploadToast = (
description: string,
status: UseToastOptions['status'],
) => {
toast({
description,
position: 'top',
status,
duration: 1500,
isClosable: true,
});
};

const deletePhoto = (event: MouseEvent<HTMLDivElement>) => {
const { id } = event.currentTarget;
const newUrls = urls.filter((url) => url !== id);

setUrls(newUrls);
};

const uploadPhoto = async (event: ChangeEvent<HTMLInputElement>) => {
if (urls.length === 5) {
afterUploadToast('사진을 더이상 추가할 수 없습니다', 'error');

return;
}

const formData = new FormData();
const { files } = event.currentTarget;
const uploadPhotoCount = (files?.length ?? 0) + urls.length;

if (uploadPhotoCount > 5) {
afterUploadToast(`${5 - urls.length}개 더 등록이 가능합니다`, 'error');

return;
}

if (files) {
Array.from(files).forEach((file) => {
formData.append('images', file);
});
}

// 아래는 api 함수로 받아왔다는 이미지들을 url 형식들로 받아왔다는 가정하에 진행하는 로직입니다

if (files) {
const imageUrls = Array.from(files).map((file) =>
URL.createObjectURL(file),
);

setUrls((prevUrls) => [...imageUrls, ...prevUrls]);
}
};

return (
<HStack
spacing={2}
overflowX="scroll"
sx={{
scrollbarWidth: 'none',
'&::-webkit-scrollbar': {
display: 'none',
},
}}
>
<UploadPhotoItem onUploadPhoto={uploadPhoto} urlsCount={urls.length} />
{urls.map((url, index) => (
<EditPhotoItem
key={index}
photoId={url}
photoSrc={url}
onDeletePhoto={deletePhoto}
/>
))}
</HStack>
);
}

function UploadPhotoItem({ urlsCount, onUploadPhoto }: UploadPhotoItemProps) {
return (
<Box as="label">
<Input
display="none"
type="file"
accept="image/*"
multiple
onChange={onUploadPhoto}
/>
<Flex
boxSize={100}
align="center"
justify="center"
border="1px solid"
borderColor="gray.200"
borderRadius="10px"
backgroundColor="inherit"
flexShrink={0}
>
<Flex flexDir="column" color="gray.400" justify="center">
<Image src={IoIosCamera} />
<Text display="flex" justifyContent="space-evenly" fontSize="14px">
<Text as="span" color={urlsCount === 0 ? 'gray.400' : 'orange.400'}>
{urlsCount}
</Text>
<Text as="span">/</Text>
<Text as="span">5</Text>
</Text>
</Flex>
</Flex>
</Box>
);
}

0 comments on commit 5e26275

Please sign in to comment.