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

[Fix] 카테고리 아이콘 연결 및 예외 처리 #216

Merged
merged 12 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<!-- <base href="https://tify-client.vercel.app/"> -->
<base href="https://tify-client.vercel.app/">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
<title>Vite + React + TS</title>
</head>
Expand Down
42 changes: 0 additions & 42 deletions src/assets/icons/HatIcon.tsx

This file was deleted.

29 changes: 7 additions & 22 deletions src/assets/icons/HatPinkIcon.tsx

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions src/assets/icons/HatPurpleIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const HatPurpleIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<g clipPath="url(#clip0_5121_13177)">
<path
d="M9.70395 3.17709C9.30065 3.20432 8.9448 3.2878 8.51251 3.45737C8.23486 3.56632 7.98445 3.68758 7.53371 3.93272C7.30966 4.05397 7.24991 4.07681 7.12514 4.08999C7.061 4.09702 6.83344 4.07154 6.56281 4.02761C6.09801 3.95292 5.90471 3.93623 5.48473 3.93623C5.1649 3.93623 5.03838 3.9459 4.87407 3.98104C4.67286 4.02409 4.45057 4.12074 4.29153 4.23233C4.18346 4.30877 3.87067 4.61981 3.78368 4.73667C3.34436 5.32887 3.10801 6.29274 3.04387 7.75743C3.03948 7.8655 3.0342 7.95512 3.03332 7.95688C3.03157 7.95776 2.96743 7.97269 2.89011 7.99027C2.46397 8.08516 2.02289 8.22662 1.60642 8.40059C1.21894 8.56226 1.02036 8.68703 0.786647 8.91371C0.561716 9.1325 0.488789 9.2309 0.432556 9.39345L0.403561 9.47604L0.400925 9.71679C0.399168 9.87055 0.401804 9.97862 0.407954 10.0155C0.422891 10.1016 0.463308 10.1974 0.523934 10.2888C0.589832 10.3889 0.801584 10.6095 0.935137 10.7167C1.54403 11.2061 2.79521 11.5813 4.55952 11.8036C5.47594 11.9195 6.29571 11.974 7.42564 11.9942C8.83761 12.0206 10.1969 11.9564 11.3865 11.8088C13.1139 11.5936 14.3572 11.2316 14.9907 10.7606C15.1216 10.6631 15.387 10.3969 15.4538 10.2949C15.5653 10.1262 15.582 10.0559 15.582 9.74754C15.582 9.48307 15.5741 9.4365 15.5082 9.30032C15.4546 9.18785 15.3852 9.10174 15.2156 8.93568C15.061 8.7828 14.9907 8.72569 14.8422 8.63167C14.4899 8.4085 13.758 8.13788 13.1087 7.99115L12.9417 7.95424L12.9312 7.74864C12.8512 6.18994 12.5657 5.05298 12.0675 4.30965C11.9612 4.1515 11.8821 4.05748 11.7037 3.8756C11.441 3.60938 11.3075 3.50833 11.0614 3.3862C10.862 3.28867 10.6555 3.22629 10.4156 3.19378C10.319 3.1806 9.8252 3.16918 9.70395 3.17709ZM10.1564 4.28769C10.3919 4.33601 10.5896 4.42563 10.7759 4.56533C10.8717 4.63738 10.934 4.70152 11.0149 4.81047C11.4419 5.38774 11.7108 6.3147 11.8162 7.57819C11.8426 7.88395 11.8654 8.35139 11.8654 8.56841V8.68L11.8109 8.71075C11.6106 8.82234 11.1792 8.95765 10.7302 9.04903C9.21279 9.35918 7.5671 9.40663 6.01367 9.18521C5.19565 9.06923 4.57709 8.91459 4.21509 8.73623C4.14568 8.70196 4.11581 8.68263 4.11229 8.66945C4.10614 8.64661 4.12108 8.05529 4.13338 7.84617C4.19401 6.7918 4.35743 6.03002 4.6263 5.56171C4.72119 5.39565 4.78884 5.30954 4.87495 5.24364C5.01641 5.13733 5.18511 5.06704 5.3828 5.03365C5.48209 5.01695 5.50142 5.01608 5.61828 5.02574C5.77116 5.03716 5.93371 5.05825 6.19818 5.09955C6.64541 5.16984 6.74909 5.17775 7.14799 5.17247C7.48978 5.16896 7.53722 5.16369 7.69889 5.11712C7.8096 5.08461 7.90537 5.04068 8.16106 4.90097C8.76644 4.57149 9.19521 4.39664 9.61081 4.30965C9.85683 4.25781 9.98862 4.25254 10.1564 4.28769ZM3.08165 9.15798C3.15106 9.29856 3.37424 9.527 3.57105 9.65792C3.75469 9.78005 4.05782 9.91185 4.36183 10.0015C4.55161 10.0577 4.67638 10.0876 4.91097 10.1341C5.642 10.2782 6.33788 10.3608 7.09439 10.3942C7.35447 10.4056 8.63289 10.4056 8.8956 10.3942C9.66968 10.36 10.4051 10.2712 11.1449 10.121C11.709 10.0067 12.172 9.83189 12.4664 9.6219C12.5463 9.56566 12.7203 9.40136 12.8011 9.30647C12.8319 9.27132 12.8706 9.21509 12.8881 9.1817C12.9066 9.14743 12.9259 9.12019 12.9321 9.12019C12.9672 9.12019 13.3398 9.23442 13.5436 9.30734C13.9161 9.4409 14.1815 9.56479 14.3722 9.69395C14.4328 9.73524 14.4486 9.75018 14.4468 9.76512C14.4424 9.79762 14.236 9.92415 14.0444 10.012C13.2044 10.3951 11.687 10.7026 9.98072 10.8335C8.63201 10.9363 7.3492 10.9363 6.00049 10.8335C4.21334 10.6965 2.63794 10.367 1.84013 9.96281C1.69779 9.89076 1.58709 9.82311 1.54667 9.78269C1.52382 9.75984 1.52382 9.75809 1.53876 9.74315C1.57918 9.70361 1.74436 9.60432 1.87967 9.53755C2.17929 9.38994 2.60806 9.2353 3.05793 9.11141C3.05881 9.11141 3.06935 9.1325 3.08165 9.15798Z"
fill="#7D40FF"
/>
</g>
<defs>
<clipPath id="clip0_5121_13177">
<rect width="16" height="16" fill="white" />
</clipPath>
</defs>
</svg>
)
}

export default HatPurpleIcon
25 changes: 7 additions & 18 deletions src/assets/icons/MittenIcon.tsx

Large diffs are not rendered by default.

25 changes: 7 additions & 18 deletions src/assets/icons/ScarfIcon.tsx

Large diffs are not rendered by default.

61 changes: 45 additions & 16 deletions src/components/atoms/Category/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,55 @@ import { Text } from '../Text'
import Svg from '../Svg'
import Plus from '@assets/icons/Plus'
import Gift from '@assets/icons/Gift'
import { SubCategoryName } from '@utils/apis/user/UserType'

/**
* @param categoryName 카테고리명을 나타냄
* @param isFriend 친구 프로필인지 내 프로필인지 여부를 나타냄
* @param children 보여줄 태그 컴포넌트 배열을 나타냄
* @param onButtonClick + / 선물 버튼 클릭 시 발생하는 이벤트를 넘겨주는 함수임
* @param onShowMorePreferencesClick 취향 더보기 버튼 클릭 시 발생하는 이벤트를 넘겨주는 함수임
* @param allCategoryAnswered + 아이콘을 보여줄지 말지를 나타냄 (모든 detailCategory를 다 답변했는지 여부를 나타냄)
* @param onPlusButtonClick + / 선물 버튼 클릭 시 발생하는 이벤트를 넘겨주는 함수임
*/
export type CategoryNameType =
| 'MAKEUP'
| 'FRAGRANCE'
| 'CLOTHES'
| 'FASHION_PRODUCT'
| 'DIGITAL_PRODUCT'
| 'BAG'
| 'ACCESSORY'
| 'COOKING'
| 'EXERCISE'

type CategoryPropsType = {
categoryName: string
categoryName: SubCategoryName
isFriend: boolean
children: React.ReactNode[]
onButtonClick?: () => void
allCategoryAnswered?: boolean
onPlusButtonClick?: () => void
onPresentButtonClick?: () => void
}

export const Category = ({
categoryName,
isFriend = false,
children,
onButtonClick,
allCategoryAnswered = false,
onPlusButtonClick,
onPresentButtonClick,
}: CategoryPropsType) => {
const renderIcon = () => {
if (isFriend) {
return <Svg children={<Gift />} onClick={onPresentButtonClick} />
} else {
if (!allCategoryAnswered) {
return <Svg children={<Plus />} onClick={onPlusButtonClick} />
} else {
return null
}
}
}

return (
<Wrapper>
<Heading>
Expand All @@ -35,17 +63,18 @@ export const Category = ({
color="white"
as="div"
/>
<RoundButton
variant="circle"
children={
<Svg
children={isFriend ? <Gift /> : <Plus />}
style={{ display: 'flex', alignItems: 'center' }}
height="fit-content"
/>
}
onClick={onButtonClick}
/>
{isFriend || !allCategoryAnswered ? (
<RoundButton
variant="circle"
children={
<Svg
children={renderIcon()}
style={{ display: 'flex', alignItems: 'center' }}
height="fit-content"
/>
}
/>
) : null}
</Heading>
<TagWrapper>
{children.map((child, index) => (
Expand Down
11 changes: 8 additions & 3 deletions src/components/atoms/GiftFilter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface FilterProps extends ButtonHTMLAttributes<HTMLButtonElement> {
selectedTags: SelectedTag[]
setSelectedTags: React.Dispatch<React.SetStateAction<SelectedTag[]>>
}

type Props = FilterProps & Partial<FilterProps>

export const GiftFilter = ({
Expand All @@ -18,7 +19,11 @@ export const GiftFilter = ({
selectedTags,
...props
}: Props) => {
const [selected, setSelected] = useState(selectedProps)
const [selected, setSelected] = useState<SelectedProps>(selectedProps)

useEffect(() => {
setSelected(selectedProps)
}, [selectedProps])

useEffect(() => {
const updatedTags = selected
Expand All @@ -30,8 +35,8 @@ export const GiftFilter = ({
return acc
}, [] as SelectedTag[])

setSelectedTags(updatedTags)
}, [selected])
setSelectedTags(updatedTags.length ? updatedTags : selectedTags)
}, [])

const handleClick = (id: number) => {
const updatedBtn = selected.map((item) => {
Expand Down
3 changes: 2 additions & 1 deletion src/components/atoms/Svg/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react'
import styled from '@emotion/styled'
import { HTMLAttributes } from 'react'
import { FlexBox } from '@components/layouts/FlexBox'

/**
* @param children 보여줄 SVG 이미지 컴포넌트를 나타냄
Expand All @@ -24,7 +25,7 @@ const Svg = ({
}: SvgProps) => {
return (
<SvgWrapper onClick={onClick} width={width} height={height} {...props}>
{children}
<FlexBox>{children}</FlexBox>
</SvgWrapper>
)
}
Expand Down
60 changes: 44 additions & 16 deletions src/components/friends/PresentRecommend.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { useEffect, useRef, useState } from 'react'
import { SelectedProps, SelectedTag } from '@utils/apis/user/UserType'
import { useEffect, useState } from 'react'
import {
SelectedProps,
SelectedTag,
SubCategoryName,
} from '@utils/apis/user/UserType'
import styled from '@emotion/styled'
import { ItemFilter } from '@assets/icons/ItemFilter'
import { Text } from '@components/atoms/Text'
import { FriendsApi } from '@utils/apis/friends/FriendsApi'
import { useOutsideClick } from '@libs/hooks/useOutsideClick'
import { GiftFilter } from '@components/atoms/GiftFilter'
import SortItem from './bottomsheet/SortItem'
import { useRecoilState, useRecoilValue } from 'recoil'
Expand All @@ -23,6 +26,8 @@ import cookingNull from '@assets/image/cookingNull.svg'
import exerciseNull from '@assets/image/exerciseNull.svg'
import BottomSheet from '@components/atoms/BottomSheet'
import useBottomSheet from '@libs/hooks/useBottomSheet'
import { friendState } from '@libs/store/friend'
import { CategoryNameType } from '@components/atoms/Category'

type DataType = {
productId: number
Expand All @@ -35,26 +40,28 @@ type DataType = {
smallCategory: string
}

function PresentRecommend() {
const selectedProps: SelectedProps = [
{ id: 1, active: false, name: '메이크업', value: 'MAKEUP' },
{ id: 2, active: false, name: '프레그런스', value: 'FRAGRANCE' },
{ id: 3, active: false, name: '의류', value: 'CLOTHES' },
{ id: 4, active: false, name: '패션소품', value: 'FASHION_PRODUCT' },
{ id: 5, active: false, name: '디지털 소품', value: 'DIGITAL_PRODUCT' },
{ id: 6, active: false, name: '가방', value: 'BAG' },
{ id: 7, active: false, name: '액세사리', value: 'ACCESSORY' },
{ id: 8, active: false, name: '요리', value: 'COOKING' },
{ id: 9, active: false, name: '운동', value: 'EXERCISE' },
]
const selectedPropsData: SelectedProps = [
{ id: 1, active: false, name: '메이크업', value: 'MAKEUP' },
{ id: 2, active: false, name: '프레그런스', value: 'FRAGRANCE' },
{ id: 3, active: false, name: '의류', value: 'CLOTHES' },
{ id: 4, active: false, name: '패션소품', value: 'FASHION_PRODUCT' },
{ id: 5, active: false, name: '디지털소품', value: 'DIGITAL_PRODUCT' },
{ id: 6, active: false, name: '가방', value: 'BAG' },
{ id: 7, active: false, name: '액세사리', value: 'ACCESSORY' },
{ id: 8, active: false, name: '요리', value: 'COOKING' },
{ id: 9, active: false, name: '운동', value: 'EXERCISE' },
]

function PresentRecommend() {
const [selectedProps, setSelectedProps] =
useState<SelectedProps>(selectedPropsData)
const [selectedTags, setSelectedTags] = useState<SelectedTag[]>([])
const [dataLoaded, setDataLoaded] = useState<boolean>(false)
const [products, setProducts] = useState<DataType[]>([])
const outsideRef = useRef()
const [isSortOpen, setIsSortOpen] = useRecoilState<string>(isFilterTypeState)
const selectedFilter = useRecoilValue(FilterState)
const selectedPrice = useRecoilValue(PriceState)
const friendStateData = useRecoilValue(friendState)

const selectedCategories = selectedTags.map((tag) => tag.value)
const selectedCategoriesString = selectedCategories
Expand Down Expand Up @@ -114,6 +121,26 @@ function PresentRecommend() {
})
}, [selectedTags, selectedFilter.filter, selectedPrice.price])

useEffect(() => {
const selectedOption = selectedProps.find(
(selectedProp) =>
selectedProp.value === friendStateData.presentRecommendFilterValue,
)

setSelectedProps((prevSelectedProps) =>
prevSelectedProps.map((prop) =>
prop.value === selectedOption?.value ? { ...prop, active: true } : prop,
),
)

setSelectedTags([
{
name: selectedOption?.name as SubCategoryName,
value: selectedOption?.value as CategoryNameType,
},
])
}, [friendStateData.presentRecommendFilterValue])

const handleFilterClick = () => {
setIsSortOpen('filter')
openBottomSheet()
Expand All @@ -132,6 +159,7 @@ function PresentRecommend() {
} = useBottomSheet({
initialState: false,
})

return (
<>
<FilterWrapper>
Expand Down
11 changes: 10 additions & 1 deletion src/components/profile/ProfileHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,16 @@ export const ProfileHeader = ({
(!userData.friend && auth.userProfile.userId !== userData.userId) ||
addFriend
) {
if (!userData.receivedApplication && !userData.sentApplication) {
if (userData.friend) {
return (
<SquareButton
variant="mediumSquare"
subVariant="default"
fullWidth={true}
children="수락됨"
/>
)
} else if (!userData.receivedApplication && !userData.sentApplication) {
return (
<SquareButton
variant="mediumSquare"
Expand Down
75 changes: 62 additions & 13 deletions src/components/profile/UserTagDataListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@ import { FlexBox } from '@components/layouts/FlexBox'
import { Spacing } from '@components/atoms/Spacing'
import { Category } from '@components/atoms/Category'
import { ColorIndexVariant, Tag } from '@components/atoms/Tag'
import { FilteredUserTag, SelectedProps } from '@utils/apis/user/UserType'
import {
FilteredUserTag,
SelectedProps,
SubCategoryName,
SubCategoryType,
} from '@utils/apis/user/UserType'
import { getTagAnswerData } from '@utils/getTagAnswerData'
import { useNavigate } from 'react-router-dom'
import { questionMenu } from '@utils/questionMenu'
import { useSetRecoilState } from 'recoil'
import { friendState } from '@libs/store/friend'

export interface UserTagDataProps {
selectedProps: SelectedProps
Expand All @@ -17,31 +26,71 @@ export const UserTagDataListItem = ({
userTagData,
isFriend,
}: UserTagDataProps) => {
const navigate = useNavigate()
const setFriendStateData = useSetRecoilState(friendState)

const handleClickPlusButton = (
categoryName: SubCategoryName,
smallCategory: string,
categoryValue: SubCategoryType,
) => {
if (categoryName === '프레그런스' && smallCategory === 'PERFUME') {
navigate(questionMenu[categoryValue][0])
} else if (categoryName === '프레그런스' && smallCategory === 'MOISTURE') {
navigate(questionMenu[categoryValue][1])
} else if (categoryName === '프레그런스' && smallCategory === 'PLACE') {
navigate(questionMenu[categoryValue][2])
} else {
navigate(questionMenu[categoryValue])
}
}

const handleClickPresentButton = (categoryValue: SubCategoryType) => {
setFriendStateData((prevStateData) => ({
...prevStateData,
presentRecommendFilterValue: categoryValue,
}))

navigate('/friends/presentRecommend')
}

const renderUserTagDataListItem = () => {
return getTagAnswerData(userTagData)
?.filter((tag) => tag.length !== 0)
?.map((tag, idx) => {
const matchingProp = selectedProps.find(
(selectedProp) => selectedProp.value === tag[0]?.smallCategory,
)
const categoryName = matchingProp ? matchingProp.name : ''
const categoryName = matchingProp
? matchingProp.name
: ('' as SubCategoryName)
const categoryValue = matchingProp?.value ?? ('' as SubCategoryType)
const smallCategory = tag[1].smallCategory ?? tag[0].smallCategory
const allCategoryAnswered = tag[0]?.allDetailCategoryAnswered

return (
<Category
key={idx}
categoryName={categoryName}
children={tag.map((tagData, index) => (
<Tag
key={index}
colorIndex={(index % 3) as ColorIndexVariant}
iconIndex={tagData.number}
children={tagData.answer}
smallCategory={tagData.smallCategory}
detailCategory={tagData.detailCategory}
answerNumber={tagData.number}
/>
))}
isFriend={isFriend}
allCategoryAnswered={allCategoryAnswered}
onPlusButtonClick={() =>
handleClickPlusButton(categoryName, smallCategory, categoryValue)
}
onPresentButtonClick={() => handleClickPresentButton(categoryValue)}
children={tag.map((tagData, index) =>
tagData.answer ? (
<Tag
key={index}
colorIndex={(index % 3) as ColorIndexVariant}
iconIndex={tagData.number}
children={tagData.answer}
smallCategory={tagData.smallCategory}
detailCategory={tagData.detailCategory}
answerNumber={tagData.number}
/>
) : null,
)}
/>
)
})
Expand Down
Loading
Loading