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

템플릿 CRUD 카테고리, 태그 추가 #275

Merged
merged 43 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
a63e31d
refactor(style): color dark <=> light 변수명 변경
Hain-tain Aug 5, 2024
51f82fa
feat(types): Tag, Category타입 추가 및 템플릿 타입에 적용
Hain-tain Aug 5, 2024
589f15d
refactor(mocks): 템플릿 mock data 카테고리, 태그 추가
Hain-tain Aug 5, 2024
f2c54d1
feat(mocks): 카테고리 mock data 생성
Hain-tain Aug 5, 2024
80a4be2
refactor(api): customFetch console.error(error) 추가
Hain-tain Aug 5, 2024
7d8ec71
feat(api): 카테고리 api 연결 함수 추가
Hain-tain Aug 5, 2024
4011665
refactor(api): 템플릿 등록 후 바로 페이지 이동을 위해 postTemplate return 추가
Hain-tain Aug 5, 2024
356eb5e
feat(Dropdown): Dropdown 구현
Hain-tain Aug 5, 2024
9e8de89
feat(src): HeaderContext 추가 및 headerRef 적용
Hain-tain Aug 5, 2024
ab824e8
refactor(style): GlobalStyle 버튼 css reset 추가
Hain-tain Aug 5, 2024
5402cd8
feat(utils): removeAllWhitespace
Hain-tain Aug 5, 2024
d57fc85
feat(asset): 태그 x 버튼 이미지 추가 및 index에서 export
Hain-tain Aug 5, 2024
843eeff
feat(TagInput): TagInput
Hain-tain Aug 5, 2024
9ba389c
refactor(Input): focus 상태일 때 placeholder color 유지되도록 변경
Hain-tain Aug 5, 2024
beb994e
refactor(SelectList): 색상 변경 및 반응형 추가
Hain-tain Aug 5, 2024
6121b3d
feat(hooks): useInput
Hain-tain Aug 5, 2024
696dd32
feat(hooks): useScrollToTargetElement
Hain-tain Aug 5, 2024
956e942
feat(hooks): useDropdown
Hain-tain Aug 5, 2024
1a79734
feat(hooks): useCategoryQuery
Hain-tain Aug 5, 2024
0da5791
refactor(hooks): useTemplateQuery, useTemplateUploadQuery, useTemplat…
Hain-tain Aug 5, 2024
f138bc1
feat(hooks): useCategory
Hain-tain Aug 5, 2024
72b9dec
feat(hooks): useCategoryUpload
Hain-tain Aug 5, 2024
277d545
feat(components): TemplateEdit 컴포넌트 생성 및 TemplateTitleInput 제거
Hain-tain Aug 5, 2024
e214e69
feat(hooks): useTemplate, useTemplateEdit, useTemplateUpload
Hain-tain Aug 5, 2024
fe58e9f
refactor(pages): 템플릿 생성, 수정 페이지에 TemplateEdit 컴포넌트 적용
Hain-tain Aug 5, 2024
1739792
refactor(TemplatePage): useTemplate 적용
Hain-tain Aug 5, 2024
846c346
feat(mocks): categoryHandlers 추가
Hain-tain Aug 5, 2024
d6e481c
chore: gitignore에 .env* 으로 변경
Hain-tain Aug 5, 2024
3992f50
feat(components): Toast
Hain-tain Aug 6, 2024
265fd47
feat(src): useCustonContext, ToastContext 생성 및 적용
Hain-tain Aug 6, 2024
cd84a35
feat(components): TagButton
Hain-tain Aug 6, 2024
1d0e6d1
refactor(SelectList): 배경색 변경 및 SelectList.style.ts 로 파일명 변경
Hain-tain Aug 6, 2024
514f8e4
feat(template): useTemplateEdit, useTemplateUpload에서 validate 함수 및 알림…
Hain-tain Aug 6, 2024
d7c1852
feat(template): 파일별 열림 여부 상태 및 상태 핸들러 추가
Hain-tain Aug 6, 2024
a3ba9fc
feat(TemplatePage): 복사 버튼, 태그, 파일 열림 여부 상태 추가
Hain-tain Aug 6, 2024
c93365b
feat(SnippetEditor): 파일명, 코드 input에 placeholder 추가
Hain-tain Aug 6, 2024
bbf46ae
feat(Input): xlarge 사이즈 추가
Hain-tain Aug 6, 2024
b519522
refactor(TagInput): borderBottom 삭제 및 placeholder 문구 변경
Hain-tain Aug 6, 2024
aa666a1
refactor(TemplateEdit): TagInput 위치 변경 및 제목 input xlarge로 변경
Hain-tain Aug 6, 2024
6b7ab4e
Merge branch 'dev/fe' of https://github.com/woowacourse-teams/2024-co…
Hain-tain Aug 6, 2024
a7cac5d
design(Button): 버튼 small size padding 1=> 0.5rem으로 변경
Hain-tain Aug 6, 2024
fd303d6
refactor(TemplateEdit): 버튼 사이즈 medium으로 변경
Hain-tain Aug 6, 2024
0220885
design(TemplatePage): 수정, 삭제 버튼 사이 gap 제거
Hain-tain Aug 6, 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
4 changes: 1 addition & 3 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,4 @@ node_modules

dist

.env
.env.development
.env.production
.env*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요거는 바뀌면 안될거 같아요@!

18 changes: 18 additions & 0 deletions frontend/src/api/category.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { CategoryList, CategoryRequest } from '@/types/category';
import { customFetch } from './customFetch';

const API_URL = process.env.REACT_APP_API_URL;

export const CATEGORY_API_URL = `${API_URL}/categories`;

export const getCategoryList = async (): Promise<CategoryList> =>
await customFetch({
url: `${CATEGORY_API_URL}`,
});

export const postCategory = async (newCategory: CategoryRequest) =>
await customFetch({
method: 'POST',
url: `${CATEGORY_API_URL}`,
body: JSON.stringify(newCategory),
});
1 change: 1 addition & 0 deletions frontend/src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { customFetch } from './customFetch';
export { QUERY_KEY } from './queryKeys';
export { TEMPLATE_API_URL, getTemplateList, getTemplate, postTemplate } from './templates';
export { CATEGORY_API_URL, getCategoryList, postCategory } from './category';
1 change: 1 addition & 0 deletions frontend/src/api/queryKeys.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const QUERY_KEY = {
TEMPLATE: 'template',
TEMPLATE_LIST: 'templateList',
CATEGORY: 'category',
LOGIN_STATE: 'loginState',
CHECK_EMAIL: 'checkEmail',
CHECK_USERNAME: 'userName',
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/api/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ export const getTemplate = async (id: number): Promise<Template> =>
url: `${TEMPLATE_API_URL}/${id}`,
});

export const postTemplate = async (newTemplate: TemplateUploadRequest): Promise<void> => {
export const postTemplate = async (newTemplate: TemplateUploadRequest) =>
await customFetch({
method: 'POST',
url: `${TEMPLATE_API_URL}`,
body: JSON.stringify(newTemplate),
});
};

export const editTemplate = async ({ id, template }: { id: number; template: TemplateEditRequest }): Promise<void> => {
await customFetch({
Expand Down
Binary file added frontend/src/assets/images/chevron.png
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/images/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ export { default as pencilIcon } from './pencil.png';
export { default as searchIcon } from './search.png';
export { default as trashcanIcon } from './trashcan.png';
export { default as userMenuIcon } from './userMenu_38x38.png';
export { default as chevron } from './chevron.png';
export { default as xCircle } from './x_circle.png';
export { default as passwordEyeIcon } from './passwordEye.png';
Binary file added frontend/src/assets/images/x_circle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion frontend/src/components/Button/Button.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const sizes = {
small: css`
gap: 0.25rem;
height: 1.75rem;
padding: 0 1rem;
padding: 0 0.5rem;
font-size: ${theme.font.size.text.xsmall};
`,
medium: css`
Expand Down
37 changes: 37 additions & 0 deletions frontend/src/components/Dropdown/Dropdown.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { Meta, StoryObj } from '@storybook/react';

import { useDropdown } from '@/hooks/utils/useDropdown';
import Dropdown from './Dropdown';

const meta: Meta<typeof Dropdown> = {
title: 'Dropdown',
component: Dropdown,
};

export default meta;

type Story = StoryObj<typeof Dropdown>;

export const Default: Story = {
args: {
currentValue: '',
},

render: () => {
const options = ['보기1', '보기2', '보기3'];
const { isOpen, toggleDropdown, currentValue, handleCurrentValue, dropdownRef } =
useDropdown<string>('선택해주세요');

const props = {
isOpen,
dropdownRef,
toggleDropdown,
options,
getOptionLabel: (string: string) => string,
currentValue,
handleCurrentValue,
};

return <Dropdown {...props} />;
},
};
45 changes: 45 additions & 0 deletions frontend/src/components/Dropdown/Dropdown.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import styled from '@emotion/styled';

export const DropdownContainer = styled.div`
font-size: '0.875rem';
`;

export const Wrapper = styled.div`
width: 10rem;
background-color: white;
border: 1px solid #788496;
border-radius: 8px;
`;

export const SelectedButton = styled.button`
display: flex;
align-items: center;
justify-content: space-between;

width: 100%;
padding: 0.75rem;

border-radius: 8px;
`;

export const OptionList = styled.ul`
position: absolute;
z-index: 1;

width: 10rem;
margin: 2px 0 0 0;

background-color: white;
border: 1px solid #788496;
border-radius: 8px;
`;

export const Option = styled.li`
width: 100%;
padding: 0.75rem;
border-radius: 7px;
&:hover {
color: ${({ theme }) => theme.color.light.white};
background-color: ${({ theme }) => theme.color.light.primary_500};
}
`;
Comment on lines +40 to +45
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(농담) 7px 말고 8px은 별로였나요 ㅋㅋㅋ

여기 color가 white라면 위에 background-color도 같은 theme 변수를 써도 좋았을거 같아요!

75 changes: 75 additions & 0 deletions frontend/src/components/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { chevron } from '@/assets/images';
import * as S from './Dropdown.style';

interface Props<T> {
dropdownRef: React.MutableRefObject<HTMLDivElement | null>;
isOpen: boolean;
toggleDropdown: () => void;
options: T[];
getOptionLabel: (option: T) => string;
currentValue: T;
handleCurrentValue: (value: T) => void;
replaceChildrenWhenIsOpen?: React.ReactNode;
}

const Dropdown = <T,>({
dropdownRef,
isOpen,
toggleDropdown,
options,
getOptionLabel,
currentValue,
handleCurrentValue,
replaceChildrenWhenIsOpen,
}: Props<T>) => (
<S.DropdownContainer ref={dropdownRef}>
<S.Wrapper>
{isOpen ? (
replaceChildrenWhenIsOpen || (
<SelectedButton
isOpen={isOpen}
toggleDropdown={toggleDropdown}
getOptionLabel={getOptionLabel}
currentValue={currentValue}
/>
)
) : (
<SelectedButton
isOpen={isOpen}
toggleDropdown={toggleDropdown}
getOptionLabel={getOptionLabel}
currentValue={currentValue}
/>
)}
</S.Wrapper>
{isOpen && (
<S.OptionList>
{options?.map((option, idx) => (
<S.Option key={idx} onClick={() => handleCurrentValue(option)}>
{getOptionLabel(option)}
</S.Option>
))}
Comment on lines +47 to +51
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 options가 옵셔널이 아닌거 같아요!

</S.OptionList>
)}
</S.DropdownContainer>
);

export default Dropdown;

type SelectedButtonProps<T> = Pick<Props<T>, 'toggleDropdown' | 'getOptionLabel' | 'currentValue' | 'isOpen'>;

const SelectedButton = <T,>({ toggleDropdown, getOptionLabel, currentValue, isOpen }: SelectedButtonProps<T>) => (
<S.SelectedButton onClick={toggleDropdown}>
{getOptionLabel(currentValue)}
<img
src={chevron}
width={24}
height={24}
alt=''
css={{
transition: 'transform 0.3s ease',
transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',
}}
/>
</S.SelectedButton>
);
4 changes: 2 additions & 2 deletions frontend/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { useCheckLoginState } from '@/hooks/authentication';
import { theme } from '../../style/theme';
import * as S from './Header.style';

const Header = () => {
const Header = ({ headerRef }: { headerRef: React.RefObject<HTMLDivElement> }) => {
useCheckLoginState();

return (
<S.HeaderContainer>
<S.HeaderContainer ref={headerRef}>
<S.HeaderContentContainer>
<Logo />
<Flex align='center' gap='2rem' flex='1'>
Expand Down
14 changes: 11 additions & 3 deletions frontend/src/components/Input/Input.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ const sizes = {
font-size: 1rem;
line-height: 100%;

border-radius: 12px;
`,
xlarge: css`
gap: 0.75rem;

height: 4rem;
padding: 1rem;

font-size: 2rem;
line-height: 100%;

border-radius: 12px;
`,
};
Expand Down Expand Up @@ -101,9 +112,6 @@ export const TextField = styled.input<TextFieldProps>`

&:focus {
outline: none;
&::placeholder {
color: transparent;
}
}

&:disabled {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import * as S from './Input.style';

export interface BaseProps extends HTMLAttributes<HTMLDivElement> {
size?: 'small' | 'medium' | 'large';
size?: 'small' | 'medium' | 'large' | 'xlarge';
variant?: 'filled' | 'outlined' | 'text';
isValid?: boolean;
}
Expand Down
29 changes: 21 additions & 8 deletions frontend/src/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import { useEffect, useRef } from 'react';
import { Outlet } from 'react-router-dom';

import { Header } from '@/components';
import { useHeaderHeight } from '@/hooks/utils/useHeaderHeight';
import * as S from './Layout.style';

const Layout = () => (
<S.LayoutContainer>
<Header />
<S.Wrapper>
<Outlet />
</S.Wrapper>
</S.LayoutContainer>
);
const Layout = () => {
const headerRef = useRef<HTMLDivElement>(null);
const { setHeaderHeight } = useHeaderHeight();

useEffect(() => {
if (headerRef.current) {
setHeaderHeight(headerRef.current.offsetHeight);
}
}, [setHeaderHeight]);

return (
<S.LayoutContainer>
<Header headerRef={headerRef} />
<S.Wrapper>
<Outlet />
</S.Wrapper>
</S.LayoutContainer>
);
};

export default Layout;
Loading