diff --git a/README.md b/README.md index bd265cfe..a7760427 100644 --- a/README.md +++ b/README.md @@ -105,10 +105,10 @@ https://www.studay.me/ ## 팀원 -| Frontend | Frontend | Frontend | -|:--------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------:| -| | | | -| [김희석](https://github.com/HeeSeok-kim) | [김유진](https://github.com/eugene028) | [김지성](https://github.com/jisung24) | +| Frontend | Frontend | Frontend | Frontend | +|:--------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------:| +| | | | | +| [김희석](https://github.com/HeeSeok-kim) | [김유진](https://github.com/eugene028) | [김지성](https://github.com/jisung24) | [최예준](https://github.com/CHOIYEJUN) | ## 시연영상 diff --git a/src/assets/icon/Filter.svg b/src/assets/icon/Filter.svg index c3e86045..bfff99d6 100644 --- a/src/assets/icon/Filter.svg +++ b/src/assets/icon/Filter.svg @@ -1,5 +1,4 @@ - - - - + + + diff --git a/src/assets/icon/Home.svg b/src/assets/icon/Home.svg index 01beff13..d04cfec7 100644 --- a/src/assets/icon/Home.svg +++ b/src/assets/icon/Home.svg @@ -1,3 +1,5 @@ - - + + + + diff --git a/src/assets/icon/Info.svg b/src/assets/icon/Info.svg index 80a3aa64..b9516f77 100644 --- a/src/assets/icon/Info.svg +++ b/src/assets/icon/Info.svg @@ -1,5 +1,12 @@ - - - - + + + + + + + + + + + diff --git a/src/assets/icon/MyPageIcon.svg b/src/assets/icon/MyPageIcon.svg new file mode 100644 index 00000000..52f48588 --- /dev/null +++ b/src/assets/icon/MyPageIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/Search.svg b/src/assets/icon/Search.svg index a631e23f..0b1c6ff7 100644 --- a/src/assets/icon/Search.svg +++ b/src/assets/icon/Search.svg @@ -1,5 +1,4 @@ - - - - + + + diff --git a/src/assets/icon/SearchMap.svg b/src/assets/icon/SearchMap.svg index 7c9cf58c..706dd5d0 100644 --- a/src/assets/icon/SearchMap.svg +++ b/src/assets/icon/SearchMap.svg @@ -1,3 +1,3 @@ - - + + diff --git a/src/assets/icon/Timetable.svg b/src/assets/icon/Timetable.svg index 7b87cd9c..86774338 100644 --- a/src/assets/icon/Timetable.svg +++ b/src/assets/icon/Timetable.svg @@ -1,10 +1,14 @@ - - - - - - - - - + + + + + + + + + + + + + diff --git a/src/assets/icon/index.tsx b/src/assets/icon/index.tsx index f2119b26..c0e08525 100644 --- a/src/assets/icon/index.tsx +++ b/src/assets/icon/index.tsx @@ -35,3 +35,4 @@ export { ReactComponent as Spinner } from './Spinner.svg' export { ReactComponent as Logo } from './Logo.svg' export { ReactComponent as Save } from './Save.svg' export { ReactComponent as Marker } from './Marker.svg' +export { ReactComponent as MyPageIcon } from './MyPageIcon.svg' diff --git a/src/components/common/button/Button.stories.tsx b/src/components/common/button/Button.stories.tsx index 68956845..61090abc 100644 --- a/src/components/common/button/Button.stories.tsx +++ b/src/components/common/button/Button.stories.tsx @@ -19,7 +19,8 @@ const meta = { 'Round-blue-500', 'Round-blue-700', 'Square', - 'Floating' + 'Floating', + 'Text-Plain' ] }, width: { @@ -78,3 +79,11 @@ export const SquareButton: Story = { onClick: () => alert('square clicked!') } } + +export const TextPlainButton: Story = { + args: { + label: 'Text', + buttonType: 'Text-Plain', + onClick: () => alert('text clicked!') + } +} diff --git a/src/components/common/button/Button.tsx b/src/components/common/button/Button.tsx index 6b3adb89..fb32b230 100644 --- a/src/components/common/button/Button.tsx +++ b/src/components/common/button/Button.tsx @@ -69,6 +69,8 @@ const Button = ({ } ${height ? 'h-[56px]' : BUTTON_HEIGHT[height]} ${ BUTTON_BG_COLOR['blue700'] } ${BUTTON_TEXT_COLOR['white0']}` + : buttonType === 'Text-Plain' + ? `` : '' } ${FONT_STYLE['NSK']} diff --git a/src/components/common/button/ButtonType.ts b/src/components/common/button/ButtonType.ts index 37fd4e53..2b4686c3 100644 --- a/src/components/common/button/ButtonType.ts +++ b/src/components/common/button/ButtonType.ts @@ -12,6 +12,7 @@ export type ButtonType = | 'Floating' | 'Plain-disabled' | 'Plain-Onboarding-disabled' + | 'Text-Plain' export type ButtonBorderRadius = 'min' | 'middle' | 'max' export type ButtonWidth = 'SW' | 'MW' | 'LW' | 'XLW' export type ButtonHeight = 'SH' | 'MH' | 'LH' diff --git a/src/components/common/icon/Icons.tsx b/src/components/common/icon/Icons.tsx index 5c8070f9..988a43ce 100644 --- a/src/components/common/icon/Icons.tsx +++ b/src/components/common/icon/Icons.tsx @@ -34,7 +34,8 @@ import { Write, Logo, Save, - Marker + Marker, + MyPageIcon } from '@/assets/icon' const Icons = { Abacus, @@ -72,7 +73,8 @@ const Icons = { Write, Logo, Save, - Marker + Marker, + MyPageIcon } export default Icons diff --git a/src/components/common/new_navigationbar/NewNavigationBar.stories.tsx b/src/components/common/new_navigationbar/NewNavigationBar.stories.tsx new file mode 100644 index 00000000..d9e5f83b --- /dev/null +++ b/src/components/common/new_navigationbar/NewNavigationBar.stories.tsx @@ -0,0 +1,22 @@ +import { Meta, StoryObj } from '@storybook/react' +import NewNavigationBar from '@/components/common/new_navigationbar/NewNavigationBar.tsx' + +const meta: Meta = { + component: NewNavigationBar, + tags: ['autodocs'], + title: 'components/NewNavigationBar', + argTypes: { + selectIcon: { + control: 'select' + } + } +} + +export default meta +type NewStory = StoryObj + +export const Default: NewStory = { + args: { + selectIcon: 'Home' + } +} diff --git a/src/components/common/new_navigationbar/NewNavigationBar.tsx b/src/components/common/new_navigationbar/NewNavigationBar.tsx new file mode 100644 index 00000000..c17d8add --- /dev/null +++ b/src/components/common/new_navigationbar/NewNavigationBar.tsx @@ -0,0 +1,115 @@ +import { useCallback, useEffect, useState } from 'react' +import { useNavigate } from 'react-router-dom' +import Icon, { IconType } from '@/components/common/icon/Icon.tsx' +import { + NavigationBarProps, + NavigationStateType +} from '@/components/common/new_navigationbar/NewNavigationBarType.ts' +import { + DefaultIconFill, + DefaultText, + initNavigationList, + SelectIconFill, + SelectText, + SelectIconFillStroke +} from '@/components/common/new_navigationbar/constants.ts' + +const NewNavigationBar = ({ selectIcon }: NavigationBarProps) => { + const navigate = useNavigate() + + const [navigationState, setNavigationState] = useState( + initNavigationList.map((item) => ({ + ...item, + select: item.icon === selectIcon + })) + ) + + useEffect(() => { + setNavigationState((prevState) => + prevState.map((item) => ({ + ...item, + select: item.icon === selectIcon + })) + ) + }, [selectIcon]) + + const handleIconClick = useCallback( + (selectedIcon: IconType) => { + const updatedNavigationState = navigationState.map((item) => { + if (item.icon === selectedIcon) { + switch (item.icon) { + case 'SearchMap': { + navigate('/map') + break + } + case 'Home': { + navigate('/') + + break + } + case 'Info': { + navigate('/academies') + + break + } + case 'Timetable': { + navigate('/schedule') + + break + } + case 'MyPageIcon': { + navigate('/myPage') + + break + } + } + return { ...item, select: true } + } + return { ...item, select: false } + }) + + setNavigationState(updatedNavigationState) + }, + [navigationState] + ) + + return ( +
+ {navigationState && + navigationState.map((list, index) => ( +
+ handleIconClick(e.currentTarget.dataset.id as IconType) + }> + + + {list['text']} + +
+ ))} +
+ ) +} + +export default NewNavigationBar diff --git a/src/components/common/new_navigationbar/NewNavigationBarType.ts b/src/components/common/new_navigationbar/NewNavigationBarType.ts new file mode 100644 index 00000000..8c5ab224 --- /dev/null +++ b/src/components/common/new_navigationbar/NewNavigationBarType.ts @@ -0,0 +1,11 @@ +import { IconType } from '@/components/common/icon/Icon.tsx' + +export interface NavigationStateType { + icon: IconType + text: string + select: boolean +} + +export interface NavigationBarProps { + selectIcon: 'SearchMap' | 'Home' | 'Timetable' | 'Info' | 'MyPageIcon' +} diff --git a/src/components/common/new_navigationbar/constants.ts b/src/components/common/new_navigationbar/constants.ts new file mode 100644 index 00000000..284f9d5d --- /dev/null +++ b/src/components/common/new_navigationbar/constants.ts @@ -0,0 +1,35 @@ +import { NavigationStateType } from '@/components/common/new_navigationbar/NewNavigationBarType.ts' + +export const SelectText = 'text-green-50' +export const SelectIconFillStroke = 'fill-green-50 stroke-green-50' +export const SelectIconFill = 'fill-green-50' +export const DefaultText = 'text-gray-300' +export const DefaultIconFill = 'fill-gray-300 stroke-gray-300' + +export const initNavigationList: NavigationStateType[] = [ + { + icon: 'Home', + text: '홈', + select: true + }, + { + icon: 'SearchMap', + text: '지도', + select: false + }, + { + icon: 'Timetable', + text: '시간표', + select: false + }, + { + icon: 'Info', + text: '학원 정보', + select: false + }, + { + icon: 'MyPageIcon', + text: '마이페이지', + select: false + } +] diff --git a/src/components/common/searchBar/SearchBar.stories.tsx b/src/components/common/searchBar/SearchBar.stories.tsx new file mode 100644 index 00000000..41b93dea --- /dev/null +++ b/src/components/common/searchBar/SearchBar.stories.tsx @@ -0,0 +1,23 @@ +import { Meta, StoryObj } from '@storybook/react' +import SearchBar from '@/components/common/searchBar/SearchBar.tsx' + +const meta: Meta = { + component: SearchBar, + title: 'Components/SearchBar', + argTypes: { + fullWidth: { + control: 'boolean' + }, + placeholder: { control: 'text' } + } +} + +export default meta +type Story = StoryObj + +export const SearchInput: Story = { + args: { + fullWidth: true, + placeholder: '값을 입력해주세요' + } +} diff --git a/src/components/common/searchBar/SearchBar.tsx b/src/components/common/searchBar/SearchBar.tsx new file mode 100644 index 00000000..526e892b --- /dev/null +++ b/src/components/common/searchBar/SearchBar.tsx @@ -0,0 +1,97 @@ +import React, { useRef, useState } from 'react' +import Icon from '@/components/common/icon/Icon.tsx' +import { SearchBarType } from '@/components/common/searchBar/SearchBarType.ts' + +const SearchBar = ({ + fullWidth = false, + field = '', + width, + height, + name, + placeholder = '', + errorMessage, + onChange, + onSearch, // 새로 추가된 prop + ...props +}: SearchBarType) => { + const [searchInputValue, setSearchInputValue] = useState('') + const [isFocus, setIsFocus] = useState(false) + const inputRef = useRef(null) + const onChangeHandler = (e: React.ChangeEvent) => { + if (onChange) { + onChange(e) + } + setSearchInputValue(e.target.value) + } + + const handleSearch = () => { + if (onSearch) { + onSearch(searchInputValue) + } + } + + const handleClickClose = (e: any) => { + e.stopPropagation() + setSearchInputValue('') + inputRef.current?.focus() + } + + const handleFocus = () => setIsFocus(true) + const handleBlur = () => setIsFocus(false) + + return ( + <> +
+ {isFocus ? ( + + ) : ( + + )} + + + + {isFocus ? ( + + ) : ( + { + //필터 버튼 이벤트 만들어야 함 ㅠㅠ + }} + /> + )} +
+ {errorMessage && ( +

+ {errorMessage} +

+ )} + + ) +} + +export default SearchBar diff --git a/src/components/common/searchBar/SearchBarType.ts b/src/components/common/searchBar/SearchBarType.ts new file mode 100644 index 00000000..e16e126a --- /dev/null +++ b/src/components/common/searchBar/SearchBarType.ts @@ -0,0 +1,12 @@ +import { ComponentProps } from 'react' +export interface SearchBarType extends ComponentProps<'input'> { + fullWidth?: boolean + width?: string + height?: string + name?: string + typo?: string + field?: string + errorMessage?: string + placeholder?: string + onSearch?: (e: string) => void +}