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

[Feature] - 여행기 등록 페이지에 필요한 공통 컴포넌트 구현(리버) #89

Merged
merged 26 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7b8629d
feat: MultiImageUpload 컴포넌트 구현
0jenn0 Jul 22, 2024
954fab5
feat: ThumbnailUpload 컴포넌트 구현
0jenn0 Jul 22, 2024
818cc8c
fix: emotion css를 styled로 수정
0jenn0 Jul 22, 2024
a1301a8
test: ThumnailUpload 컴포넌트 storybook 추가
0jenn0 Jul 22, 2024
6769328
feat: MultiImageUpload 컴포넌트 이미지 삭제 기능 구현
0jenn0 Jul 22, 2024
2142f2d
refactor: MultiImageUpload 컴포넌트에서 함수명 코드 컨벤션에 맞게 수정
0jenn0 Jul 22, 2024
27689d5
feat: ThumbnailUpload 컴포넌트 썸네일 수정 기능 구현
0jenn0 Jul 22, 2024
2048f79
feat: ThumbnailUploadButton에 gap 수정
0jenn0 Jul 22, 2024
ad0108f
refactor: ThumbnailUpload 컴포넌트에서 중복 제거
0jenn0 Jul 22, 2024
e83895c
refactor: ThumbnailUpload 컴포넌트에서 화살표 함수로 단순화
0jenn0 Jul 22, 2024
cd77225
fix: MulitiImageUpload 컴포넌트에서 emotion css를 emotion styled로 수정
0jenn0 Jul 22, 2024
8d2b140
refactor: 이미지 업로드 로직을 useImageUpload로 분리
0jenn0 Jul 22, 2024
eb9f183
test: MultiImageUpload 컴포넌트 storybook 추가
0jenn0 Jul 22, 2024
e3cbc5c
fix: ThumbnailUpload 컴포넌트 storybook title 수정
0jenn0 Jul 22, 2024
e5c2396
fix: MultiImageUpload 컴포넌트 storybook title 수정
0jenn0 Jul 22, 2024
38a9424
refactor: ThumbnailUpload 컴포넌트 storybook에서 base64를 mageUrl로 수정
0jenn0 Jul 22, 2024
885c19e
feat: MultiImageUpload 컴포넌트의 이미지 렌더링 부분에 스크롤 추가
0jenn0 Jul 22, 2024
4c099c0
test: MultiImageUpload 컴포넌트 storybook에 이미지 많이 첨부한 경우 추가
0jenn0 Jul 22, 2024
de05de0
refactor: MultiImageUpload 컴포넌트 삭제 버튼에 svg 사용
0jenn0 Jul 22, 2024
b75fe8b
refactor: MultiImageUpload 컴포넌트에서 styled 컴포넌트명 수정
0jenn0 Jul 22, 2024
1ec7b38
feat: useDragScroll hook 구현
0jenn0 Jul 22, 2024
2bd3fc9
feat: MultiImageUpload 컴포넌트에 드래그 스크롤 기능 추가
0jenn0 Jul 22, 2024
f02c523
feat: MultiImageUpload 컴포넌트에 y축 스크롤 hidden 추가
0jenn0 Jul 22, 2024
46208c8
refactor: MultiImageUpload 컴포넌트에서 사진 추가 버튼 UI 수정
0jenn0 Jul 23, 2024
870257a
Merge branch 'develop/fe' into feature/fe/issue86
0jenn0 Jul 23, 2024
50965c4
Merge branch 'develop/fe' into feature/fe/issue86
jinyoung234 Jul 23, 2024
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
11 changes: 11 additions & 0 deletions frontend/src/assets/svg/camera-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions frontend/src/assets/svg/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export { default as DownArrow } from "./down-arrow.svg";
export { default as Marker } from "./marker.svg";
export { default as markerUrl } from "./marker.svg?url";
export { default as EmptyHeart } from "./empty-heart.svg";
export { default as PictureIcon } from "./picture-icon.svg";
export { default as XIcon } from "./x-icon.svg";
export { default as Tturi } from "./tturi.svg";
export { default as RecycleBin } from "./recycle-bin.svg";
export { default as ChevronsRight } from "./chevrons-right.svg";
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/assets/svg/picture-icon.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 frontend/src/assets/svg/x-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from "react";

import type { Meta, StoryObj } from "@storybook/react";

import MultiImageUpload from "./MultiImageUpload";

const meta = {
title: "common/MultiImageUpload",
component: MultiImageUpload,
decorators: [
(Story, context) => {
return (
<div style={{ width: "48rem" }}>
<Story args={{ ...context.args }} />
</div>
);
},
],
} satisfies Meta<typeof MultiImageUpload>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {};

export const WithImages: Story = {
decorators: [
(Story) => {
React.useEffect(() => {
const fetchAndCreateFile = async () => {
const imageUrl =
"https://api.allorigins.win/raw?url=https://i.pinimg.com/474x/df/6d/1a/df6d1a665685af3c0eb7e4c6a0c40169.jpg";
const file = new File([await fetch(imageUrl).then((r) => r.blob())], "example.png", {
type: "image/png",
});

const files = Array(3).fill(file);

const dataTransfer = new DataTransfer();

files.map((file) => dataTransfer.items.add(file));

const inputElement = document.querySelector('input[type="file"]') as HTMLInputElement;
if (inputElement) {
Object.defineProperty(inputElement, "files", {
value: dataTransfer.files,
});

const event = new Event("change", { bubbles: true });
inputElement.dispatchEvent(event);
}
};

fetchAndCreateFile();
}, []);

return <Story />;
},
],
};

export const WithManyImages: Story = {
decorators: [
(Story) => {
React.useEffect(() => {
const fetchAndCreateFile = async () => {
const imageUrl =
"https://api.allorigins.win/raw?url=https://i.pinimg.com/474x/df/6d/1a/df6d1a665685af3c0eb7e4c6a0c40169.jpg";
const file = new File([await fetch(imageUrl).then((r) => r.blob())], "example.png", {
type: "image/png",
});

const files = Array(7).fill(file);

const dataTransfer = new DataTransfer();

files.map((file) => dataTransfer.items.add(file));

const inputElement = document.querySelector('input[type="file"]') as HTMLInputElement;
if (inputElement) {
Object.defineProperty(inputElement, "files", {
value: dataTransfer.files,
});

const event = new Event("change", { bubbles: true });
inputElement.dispatchEvent(event);
}
};

fetchAndCreateFile();
}, []);

return <Story />;
},
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import styled from "@emotion/styled";

export const MultiImageUploadContainer = styled.div`
display: flex;
width: 100%;
justify-content: flex-start;
align-items: center;
gap: ${(props) => props.theme.spacing.m};
`;

export const MultiImageUploadButton = styled.button`
display: flex;
width: 100%;
padding: ${(props) => props.theme.spacing.s};
border: 1px solid ${(props) => props.theme.colors.border};
justify-content: center;
align-items: center;
gap: ${(props) => props.theme.spacing.xs};

${(props) => props.theme.typography.mobile.detailBold};
color: ${(props) => props.theme.colors.text.secondary};
border-radius: 0.4rem;
`;

export const MultiImageUploadPictureContainer = styled.div`
display: flex;
align-items: center;
flex: 1;
width: 100%;
overflow-x: auto-scroll;
justify-content: flex-start;
gap: ${(props) => props.theme.spacing.m};
`;

export const MultiImageUploadPictureWrapper = styled.div`
display: flex;
position: relative;

justify-content: flex-start;
gap: ${(props) => props.theme.spacing.m};
`;

export const MultiImageUploadPicture = styled.img`
width: 6rem;
height: 6rem;
object-fit: cover;
object-position: center;
border-radius: 0.4rem;
`;

export const MultiImageUploadPicturesInfo = styled.div`
display: flex;
width: 6rem;
height: 6rem;
border-radius: 0.4rem;
justify-content: center;
align-items: center;
border: 1px solid ${(props) => props.theme.colors.border};
flex-direction: column;
gap: ${(props) => props.theme.spacing.s};

p {
${(props) => props.theme.typography.mobile.detailBold}
color: ${(props) => props.theme.colors.text.secondary}
}
`;

export const MultiImageUploadPictureAddButton = styled.button<{ $hasPicture: boolean }>`
display: flex;
width: 6rem;
height: 6rem;
margin-top: ${({ $hasPicture }) => ($hasPicture ? "0" : "0.5rem")};
border-radius: 0.4rem;
justify-content: center;
align-items: center;
border: 1px solid ${(props) => props.theme.colors.border};
flex-direction: column;
gap: ${(props) => props.theme.spacing.s};

p {
${(props) => props.theme.typography.mobile.detailBold}
color: ${(props) => props.theme.colors.text.secondary}
}

svg {
width: 2rem;
}
`;

export const MultiImageUploadDeleteButton = styled.button`
display: flex;
position: absolute;
top: -1rem;
right: -1rem;
justify-content: center;
align-items: center;
width: 2rem;
height: 2rem;
border: 1px solid ${(props) => props.theme.colors.border};

background-color: #fff;
border-radius: 50%;

svg {
width: 0.8rem;
}
`;

export const MultiImageUploadHiddenInput = styled.input`
display: none;
`;

export const ImageScrollContainer = styled.div<{ $isDragging: boolean }>`
display: flex;
overflow: auto hidden;
width: 100%;
height: 7rem;
padding: 1rem 1rem 0 0;
padding-bottom: ${(props) => props.theme.spacing.s};
flex: 1;
justify-content: flex-start;
align-items: center;
gap: ${(props) => props.theme.spacing.m};
scrollbar-width: none;
cursor: ${({ $isDragging }) => ($isDragging ? "grab" : "pointer")};
`;

export const MultiImageUploadSVGWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
width: 2.5rem;
height: 2.5rem;

svg {
width: 2rem;
}
`;
Loading