-
Notifications
You must be signed in to change notification settings - Fork 2
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
[FE] π§ μλ£ μν νμ΄λ£Έ 1μ°¨ ꡬν #820
Changes from 13 commits
40370fa
973721f
063bae1
6f3eae2
0fd6f19
263cc64
763aabd
b3b8039
bc29475
768c13f
484fad0
8364f16
a220e54
4fe6aac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import styled from 'styled-components'; | ||
|
||
export const Layout = styled.div` | ||
display: flex; | ||
justify-content: space-between; | ||
gap: 1rem; | ||
|
||
width: 100%; | ||
`; | ||
|
||
export const Container = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
gap: 0.3rem; | ||
|
||
width: 100%; | ||
height: 6rem; | ||
|
||
cursor: pointer; | ||
|
||
img { | ||
width: 2rem; | ||
} | ||
`; | ||
|
||
export const ItemLayout = styled.div` | ||
display: flex; | ||
align-items: center; | ||
gap: 1rem; | ||
|
||
width: 100%; | ||
`; | ||
|
||
export const Item = styled.li<{ $isChecked: boolean }>` | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
|
||
width: 100%; | ||
height: 4.4rem; | ||
padding: 0 1rem; | ||
border: 1px solid ${({ theme }) => theme.color.black[50]}; | ||
border-radius: 0.5rem; | ||
|
||
background-color: ${({ theme, $isChecked }) => ($isChecked ? theme.color.primary[700] : theme.color.black[10])}; | ||
color: ${({ theme, $isChecked }) => ($isChecked ? theme.color.black[10] : theme.color.black[70])}; | ||
font-size: ${({ theme }) => theme.fontSize.md}; | ||
|
||
transition: all 0.2s ease-out; | ||
|
||
&:hover { | ||
background-color: ${({ theme }) => theme.color.primary[700]}; | ||
color: ${({ theme }) => theme.color.black[10]}; | ||
} | ||
|
||
&:active { | ||
background-color: ${({ theme }) => theme.color.primary[800]}; | ||
color: ${({ theme }) => theme.color.black[10]}; | ||
} | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { CheckBoxChecked, CheckBoxUnchecked } from '@/assets'; | ||
|
||
import * as S from './CategoryItem.styles'; | ||
|
||
interface CategoryItemProps { | ||
categoryName: string; | ||
categoryId: string; | ||
isChecked: boolean; | ||
closeModal: () => void; | ||
handleSelectCategory: (categoryId: string) => void; | ||
} | ||
|
||
const CategoryItem = ({ closeModal, categoryName, categoryId, isChecked, handleSelectCategory }: CategoryItemProps) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. νΉμ μ΄λ κ² There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. κΈνκ² μλ νμΌ κ΅¬μ‘° κ·Έλλ‘ λ°μ€λλΌ νμμλ κ΅¬μ‘°κ° μκ²Όλ€μ! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
return ( | ||
<S.Layout> | ||
<S.Container> | ||
<S.ItemLayout | ||
id={categoryId} | ||
onClick={(event: React.MouseEvent<HTMLElement, MouseEvent>) => { | ||
if (event.currentTarget.id === 'μΉ΄ν κ³ λ¦¬') return; | ||
if (isChecked) return; | ||
handleSelectCategory(event.currentTarget.id); | ||
closeModal(); | ||
}} | ||
> | ||
<img | ||
src={isChecked ? CheckBoxChecked : CheckBoxUnchecked} | ||
alt={isChecked ? '체ν¬λ 체ν¬λ°μ€' : '체ν¬λμ§ μμ 체ν¬λ°μ€'} | ||
/> | ||
|
||
<S.Item $isChecked={isChecked}> | ||
<p>{categoryName}</p> | ||
</S.Item> | ||
</S.ItemLayout> | ||
</S.Container> | ||
</S.Layout> | ||
); | ||
}; | ||
|
||
export default CategoryItem; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import styled, { css } from 'styled-components'; | ||
|
||
export const inputStyles = css` | ||
width: 100%; | ||
|
||
font-size: ${({ theme }) => theme.fontSize.md}; | ||
`; | ||
|
||
export const Header = styled.div` | ||
display: flex; | ||
align-items: center; | ||
gap: 1rem; | ||
|
||
color: ${({ theme }) => theme.color.black[80]}; | ||
font-size: ${({ theme }) => theme.fontSize.lg}; | ||
`; | ||
|
||
export const CategoryList = styled.ul` | ||
display: flex; | ||
flex-direction: column-reverse; | ||
gap: 1rem; | ||
|
||
width: 100%; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { FaFilter } from 'react-icons/fa'; | ||
|
||
import { Modal } from '@/components/common/Modal'; | ||
import CategoryItem from '@/components/CompletedPairRoom/ReferenceCard/CategoryManagementModal/CategoriesEditor/CategoryItem/CategoryItem'; | ||
import { Category } from '@/components/PairRoom/ReferenceCard/ReferenceCard.type'; | ||
|
||
import * as S from './CategoryManagementModal.styles'; | ||
|
||
interface CategoryManagementModalProps { | ||
isOpen: boolean; | ||
closeModal: () => void; | ||
categories: Category[]; | ||
isCategoryExist: (categoryName: string) => boolean; | ||
selectedCategory: string; | ||
handleSelectCategory: (categoryId: string) => void; | ||
} | ||
|
||
const CategoryManagementModal = ({ | ||
isOpen, | ||
closeModal, | ||
categories, | ||
selectedCategory, | ||
handleSelectCategory, | ||
}: CategoryManagementModalProps) => { | ||
return ( | ||
<Modal isOpen={isOpen} close={closeModal} size="45rem"> | ||
<Modal.Header> | ||
<S.Header> | ||
<FaFilter /> | ||
<p>μΉ΄ν κ³ λ¦¬ μ ν</p> | ||
</S.Header> | ||
</Modal.Header> | ||
<Modal.CloseButton close={closeModal} /> | ||
<Modal.Body> | ||
<S.CategoryList> | ||
{categories.map((category) => ( | ||
<CategoryItem | ||
closeModal={closeModal} | ||
key={category.id} | ||
categoryName={category.value} | ||
categoryId={category.id} | ||
isChecked={category.id === selectedCategory} | ||
handleSelectCategory={handleSelectCategory} | ||
/> | ||
))} | ||
</S.CategoryList> | ||
</Modal.Body> | ||
</Modal> | ||
); | ||
}; | ||
|
||
export default CategoryManagementModal; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import styled, { css } from 'styled-components'; | ||
|
||
export const buttonStyles = css` | ||
width: fit-content; | ||
min-width: 6rem; | ||
padding: 0 1rem; | ||
`; | ||
|
||
export const Layout = styled.div` | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
|
||
width: 100%; | ||
height: 6rem; | ||
padding: 2rem; | ||
|
||
font-size: ${({ theme }) => theme.fontSize.lg}; | ||
`; | ||
|
||
export const Container = styled.div` | ||
display: flex; | ||
align-items: center; | ||
gap: 0.8rem; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { IoIosLink } from 'react-icons/io'; | ||
|
||
import Button from '@/components/common/Button/Button'; | ||
|
||
import { theme } from '@/styles/theme'; | ||
|
||
import * as S from './Header.styles'; | ||
|
||
interface HeaderProps { | ||
selectedFilteringCategoryName: string; | ||
onButtonClick: () => void; | ||
} | ||
|
||
const Header = ({ selectedFilteringCategoryName, onButtonClick }: React.PropsWithChildren<HeaderProps>) => { | ||
return ( | ||
<S.Layout> | ||
<S.Container> | ||
<IoIosLink size={theme.fontSize.h6} color={theme.color.primary[600]} /> | ||
<p>λ§ν¬</p> | ||
</S.Container> | ||
<Button | ||
css={S.buttonStyles} | ||
size="sm" | ||
rounded={true} | ||
onClick={(event: React.MouseEvent<HTMLElement, MouseEvent>) => { | ||
event.stopPropagation(); | ||
onButtonClick(); | ||
}} | ||
> | ||
{selectedFilteringCategoryName} | ||
</Button> | ||
</S.Layout> | ||
); | ||
}; | ||
|
||
export default Header; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import styled from 'styled-components'; | ||
|
||
export const Layout = styled.div` | ||
min-width: 49rem; | ||
`; | ||
|
||
export const Body = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
overflow: hidden; | ||
height: calc(100vh - 20rem); | ||
border-top: 1px solid ${({ theme }) => theme.color.black[30]}; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { useState } from 'react'; | ||
|
||
import CategoryManagementModal from '@/components/CompletedPairRoom/ReferenceCard/CategoryManagementModal/CategoryManagementModal'; | ||
import Header from '@/components/CompletedPairRoom/ReferenceCard/Header/Header'; | ||
import ReferenceList from '@/components/CompletedPairRoom/ReferenceCard/ReferenceList/ReferenceList'; | ||
import { PairRoomCard } from '@/components/PairRoom/PairRoomCard'; | ||
|
||
import useModal from '@/hooks/common/useModal'; | ||
import useCategories, { DEFAULT_CATEGORY_ID, DEFAULT_CATEGORY_VALUE } from '@/hooks/PairRoom/useCategories'; | ||
|
||
import { useGetReference } from '@/queries/PairRoom/reference/query'; | ||
|
||
import * as S from './ReferenceCard.styles'; | ||
|
||
interface ReferenceCardProps { | ||
accessCode: string; | ||
} | ||
|
||
const ReferenceCard = ({ accessCode }: ReferenceCardProps) => { | ||
const [selectedFilteringCategoryId, setSelectedFilteringCategoryId] = useState(DEFAULT_CATEGORY_ID); | ||
const { isModalOpen, openModal, closeModal } = useModal(); | ||
|
||
const { categories, isCategoryExist, getCategoryNameById } = useCategories(accessCode); | ||
|
||
const { data: references } = useGetReference(selectedFilteringCategoryId, accessCode); | ||
const selectedFilteringCategoryName = getCategoryNameById(selectedFilteringCategoryId) || DEFAULT_CATEGORY_VALUE; | ||
|
||
return ( | ||
<> | ||
<S.Layout> | ||
<PairRoomCard> | ||
<Header selectedFilteringCategoryName={selectedFilteringCategoryName} onButtonClick={openModal} /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. μλ³Έ μ½λμ κ°μ μ΄λ¦μ΄λΌ 리ν©ν°λ§ν λ ν λ²μ κ³ μ³μΌ ν κ² κ°μμ π₯² There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. μ½λ λ€μ΄μ΄νΈκ° μκΈνκ΅°μ |
||
<S.Body> | ||
<ReferenceList references={references} /> | ||
</S.Body> | ||
</PairRoomCard> | ||
</S.Layout> | ||
|
||
<CategoryManagementModal | ||
isOpen={isModalOpen} | ||
closeModal={closeModal} | ||
categories={categories} | ||
isCategoryExist={isCategoryExist} | ||
selectedCategory={selectedFilteringCategoryId} | ||
handleSelectCategory={(categoryId: string) => setSelectedFilteringCategoryId(categoryId)} | ||
/> | ||
</> | ||
); | ||
}; | ||
|
||
export default ReferenceCard; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
μ»΄ν¬λνΈ μ΄λ¦ μ§μ§ μ€κ»νλ€μ π