Skip to content

Commit

Permalink
Merge branch 'develop-FE' of https://github.com/woowacourse-teams/202…
Browse files Browse the repository at this point in the history
…3-map-befine into refactor/#593-swiper
  • Loading branch information
semnil5202 committed Oct 19, 2023
2 parents 01c6e88 + 4574c3a commit 12c0312
Show file tree
Hide file tree
Showing 10 changed files with 634 additions and 115 deletions.
71 changes: 37 additions & 34 deletions frontend/src/components/Layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Map from '../Map';
import Toast from '../Toast';
import Logo from './Logo';
import Navbar from './Navbar';
import ImageModalContext from '../../context/ImageModalContext';

type LayoutProps = {
children: React.ReactNode;
Expand Down Expand Up @@ -43,44 +44,46 @@ function Layout({ children }: LayoutProps) {
return (
<ToastProvider>
<ModalProvider>
<CoordinatesProvider>
<MarkerProvider>
<SeeTogetherProvider>
<TagProvider>
<MediaWrapper
$isAddPage={navbarHighlights.addMapOrPin}
$layoutWidth={width}
>
<LayoutFlex
$flexDirection="column"
$minWidth={width}
height="calc(var(--vh, 1vh) * 100)"
$backgroundColor="white"
<ImageModalContext>
<CoordinatesProvider>
<MarkerProvider>
<SeeTogetherProvider>
<TagProvider>
<MediaWrapper
$isAddPage={navbarHighlights.addMapOrPin}
$layoutWidth={width}
>
<LogoWrapper $layoutWidth={width}>
<Box>
<Logo />
<Space size={2} />
</Box>
</LogoWrapper>
<Flex
<LayoutFlex
$flexDirection="column"
height="inherit"
overflow="auto"
padding="0"
$minWidth={width}
height="calc(var(--vh, 1vh) * 100)"
$backgroundColor="white"
$layoutWidth={width}
>
{children}
</Flex>
<Navbar $layoutWidth={width} />
<Toast />
</LayoutFlex>
<Map />
</MediaWrapper>
</TagProvider>
</SeeTogetherProvider>
</MarkerProvider>
</CoordinatesProvider>
<LogoWrapper $layoutWidth={width}>
<Box>
<Logo />
<Space size={2} />
</Box>
</LogoWrapper>
<Flex
$flexDirection="column"
height="inherit"
overflow="auto"
padding="0"
>
{children}
</Flex>
<Navbar $layoutWidth={width} />
<Toast />
</LayoutFlex>
<Map />
</MediaWrapper>
</TagProvider>
</SeeTogetherProvider>
</MarkerProvider>
</CoordinatesProvider>
</ImageModalContext>
</ModalProvider>
</ToastProvider>
);
Expand Down
143 changes: 118 additions & 25 deletions frontend/src/components/PinImageContainer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
import { Swiper, Tab } from 'map-befine-swiper';
import { useState } from 'react';
import styled from 'styled-components';

import { ImageProps } from '../../types/Pin';
import Image from '../common/Image';
import RemoveImageButton from '../../assets/remove_image_icon.svg';
import useDelete from '../../apiHooks/useDelete';
import RemoveImageButton from '../../assets/remove_image_icon.svg';
import { ImageModal, useModalContext } from '../../context/ImageModalContext';
import useToast from '../../hooks/useToast';
import { ImageProps } from '../../types/Pin';
import Button from '../common/Button';
import Image from '../common/Image';
import Space from '../common/Space';

interface PinImageContainerProps {
images: ImageProps[];
getPinData: () => void;
}const NOT_FOUND_IMAGE =
'https://dr702blqc4x5d.cloudfront.net/2023-map-be-fine/icon/notFound_image.svg';
}
const NOT_FOUND_IMAGE =
'https://dr702blqc4x5d.cloudfront.net/2023-map-be-fine/icon/notFound_image.svg';

const PinImageContainer = ({ images, getPinData }: PinImageContainerProps) => {
function PinImageContainer({ images, getPinData }: PinImageContainerProps) {
const { fetchDelete } = useDelete();
const { showToast } = useToast();
const { isModalOpen, openModal, closeModal } = useModalContext();
const [modalImage, setModalImage] = useState<string>('');

const onRemovePinImage = (imageId: number) => {
const isRemoveImage = confirm('해당 이미지를 삭제하시겠습니까?');
Expand All @@ -24,45 +31,110 @@ const PinImageContainer = ({ images, getPinData }: PinImageContainerProps) => {
fetchDelete({
url: `/pins/images/${imageId}`,
errorMessage: '이미지 제거에 실패했습니다.',
isThrow: true,
onSuccess: () => {
showToast('info', '핀에서 이미지가 삭제 되었습니다.');
getPinData();
},
});
}
};
return (
<>

const onImageOpen = (imageUrl: string) => {
setModalImage(imageUrl);
openModal();
};

if (images.length <= 3) {
return (
<FilmList>
{images.map(
(image, index) =>
index < 3 && (
<ImageWrapper>
{images.map((image, index) => (
<Tab label={`${index}`} key={image.id}>
<ImageWrapper key={`image-${index}`}>
<div onClick={() => onImageOpen(image.imageUrl)}>
<Image
key={image.id}
height="100px"
width="100px"
src={image.imageUrl}
$errorDefaultSrc={NOT_FOUND_IMAGE}
/>
<RemoveImageIconWrapper
onClick={() => onRemovePinImage(image.id)}
>
<RemoveImageButton />
</RemoveImageIconWrapper>
</ImageWrapper>
),
</div>
<RemoveImageIconWrapper
onClick={() => onRemovePinImage(image.id)}
>
<RemoveImageButton />
</RemoveImageIconWrapper>
</ImageWrapper>
</Tab>
))}
{isModalOpen && (
<ImageModal closeModalHandler={closeModal}>
<ModalImageWrapper>
<ModalImage src={modalImage} />
<Space size={3} />
<Button variant="custom" onClick={closeModal}>
닫기
</Button>
</ModalImageWrapper>
</ImageModal>
)}
</FilmList>
</>
);
}

return (
<Wrapper>
<Swiper
as="ul"
width={330}
height={100}
$elementsOneTab={3}
swiper
swipeable
$isNotTabBoxShow
>
{images.map((image, index) => (
<Tab label={`${index}`} key={image.id}>
<ImageWrapper key={`image-${index}`}>
<div onClick={() => onImageOpen(image.imageUrl)}>
<Image
key={image.id}
height="100px"
width="100px"
src={image.imageUrl}
$errorDefaultSrc={NOT_FOUND_IMAGE}
/>
</div>
<RemoveImageIconWrapper
onClick={() => onRemovePinImage(image.id)}
>
<RemoveImageButton />
</RemoveImageIconWrapper>
</ImageWrapper>
</Tab>
))}
{isModalOpen && (
<ImageModal closeModalHandler={closeModal}>
<ModalImageWrapper>
<ModalImage src={modalImage} />
<Space size={3} />
<Button variant="custom" onClick={closeModal}>
닫기
</Button>
</ModalImageWrapper>
</ImageModal>
)}
</Swiper>
</Wrapper>
);
};
}

const FilmList = styled.ul`
const Wrapper = styled.div`
width: 330px;
`;

const FilmList = styled.ul`
display: flex;
flex-direction: row;
`;

const ImageWrapper = styled.li`
Expand All @@ -84,4 +156,25 @@ const RemoveImageIconWrapper = styled.div`
}
`;

const ModalImageWrapper = styled.div`
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
margin: 0 auto;
overflow: hidden;
`;

const ModalImage = styled.img`
width: 100%;
height: 100%;
min-width: 360px;
min-height: 360px;
display: block;
`;
export default PinImageContainer;
37 changes: 24 additions & 13 deletions frontend/src/components/TopicInfo/UpdatedTopicInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import useToast from '../../hooks/useToast';
import { TopicAuthorInfo } from '../../types/Topic';
import Button from '../common/Button';
import Flex from '../common/Flex';
import Image from '../common/Image';
import ImageCommon from '../common/Image';
import Space from '../common/Space';
import Text from '../common/Text';
import InputContainer from '../InputContainer';
Expand Down Expand Up @@ -135,6 +135,7 @@ function UpdatedTopicInfo({
) => {
const file = event.target.files && event.target.files[0];
const formData = new FormData();
const currentImage = new Image();

if (!file) {
showToast(
Expand All @@ -145,17 +146,27 @@ function UpdatedTopicInfo({
}

const compressedFile = await compressImage(file);
formData.append('image', compressedFile);

try {
await putApi(`/topics/images/${id}`, formData);
} catch {
showToast('error', '사용할 수 없는 이미지입니다.');
}

const updatedImageUrl = URL.createObjectURL(compressedFile);
setChangedImages(updatedImageUrl);
showToast('info', '지도 이미지를 수정하였습니다.');
currentImage.src = URL.createObjectURL(compressedFile);

currentImage.onload = async () => {
if (currentImage.width < 300) {
showToast(
'error',
'이미지의 크기가 너무 작습니다. 다른 이미지를 선택해 주세요.',
);
return;
}
formData.append('image', compressedFile);
try {
await putApi(`/topics/images/${id}`, formData);
} catch {
showToast('error', '사용할 수 없는 이미지입니다.');
}

const updatedImageUrl = URL.createObjectURL(compressedFile);
setChangedImages(updatedImageUrl);
showToast('info', '지도 이미지를 수정하였습니다.');
};
};

return (
Expand Down Expand Up @@ -293,7 +304,7 @@ const ImageInputButton = styled.input`
display: none;
`;

const TopicImage = styled(Image)`
const TopicImage = styled(ImageCommon)`
border-radius: ${({ theme }) => theme.radius.medium};
`;

Expand Down
35 changes: 35 additions & 0 deletions frontend/src/components/common/Input/ReplyComment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import SingleComment from './SingleComment';

interface ReplyCommentProps {
commentList: Comment[];
pageTotalCommentList: Comment[];
depth: number;
refetch: (pinId: number) => Promise<Comment[]>;
}

function ReplyComment({
commentList,
pageTotalCommentList,
depth,
refetch,
}: ReplyCommentProps) {
if (depth === 2) return null;
return (
<>
{commentList.length > 0 &&
commentList.map((comment) => (
<>
<SingleComment
comment={comment}
commentList={commentList}
totalList={pageTotalCommentList}
depth={depth}
refetch={refetch}
/>
</>
))}
</>
);
}

export default ReplyComment;
Loading

0 comments on commit 12c0312

Please sign in to comment.