Skip to content

Commit

Permalink
Merge pull request #37 from TeamPiickle/feat/#36-filter_modal
Browse files Browse the repository at this point in the history
Feat/#36 filter modal
  • Loading branch information
henization committed Jul 15, 2022
2 parents c1f59dc + c134d59 commit 0a1870a
Show file tree
Hide file tree
Showing 14 changed files with 368 additions and 18 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"axios": "^0.26.0",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-range": "^1.8.13",
"react-router-dom": "^6.2.1",
"react-scripts": "5.0.1",
"react-slick": "^0.29.0",
Expand Down
2 changes: 2 additions & 0 deletions src/asset/icon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export { ReactComponent as IcFilterBtn } from "./filterBtn.svg";
export { ReactComponent as IcHamburger } from "./hamburger.svg";
export { ReactComponent as IcLogo } from "./logo.svg";
export { ReactComponent as IcMenuBarImg } from "./MenuBar Profile.svg";
export { ReactComponent as IcModalCloseBtn } from "./modalCloseBtn.svg";
export { ReactComponent as IcNextCardBtmn } from "./nextCardBtn.svg";
export { ReactComponent as IcNextCardBtn } from "./nextCardBtn.svg";
export { ReactComponent as IcVoteImg1 } from "./voteImg1.svg";
export { ReactComponent as IcVoteImg2 } from "./voteImg2.svg";
4 changes: 4 additions & 0 deletions src/asset/icon/modalCloseBtn.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 8 additions & 2 deletions src/components/CardCollection/CardSlider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import Card from "../Card";
import LastCard from "../Card/LastCard";
import { St } from "./style";

interface CardSliderProps {
openHandler: () => void;
}

const sliderSettings = {
className: "center",
centerMode: true,
Expand All @@ -17,7 +21,9 @@ const sliderSettings = {
slidesToScroll: 1,
};

export default function CardSlider() {
export default function CardSlider(props: CardSliderProps) {
const { openHandler } = props;

return (
<St.Wrapper>
<Slider {...sliderSettings}>
Expand All @@ -30,7 +36,7 @@ export default function CardSlider() {
<LastCard />
</Slider>
{/* 마지막 index에서는 필터버튼 없애주기 */}
<St.IcFilterBtn />
<St.IcFilterBtn onClick={openHandler} />
</St.Wrapper>
);
}
34 changes: 34 additions & 0 deletions src/components/CardCollection/FilterModal/IntimacySlider/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Range } from "react-range";

import { RangeTrack, St } from "./style";

interface IntimacySliderProps {
min: number;
max: number;
step: number;

price: number[];
onChange: (values: number[]) => void;
}

export default function IntimacySlider(props: IntimacySliderProps) {
const { min, max, step, price, onChange } = props;

return (
<St.IntimacySlider>
<Range
step={step}
min={min}
max={max}
values={price}
onChange={onChange}
renderTrack={({ props, children }) => (
<RangeTrack {...props} min={min} max={max} price={price}>
{children}
</RangeTrack>
)}
renderThumb={({ props }) => <St.RangeThumb {...props} />}
/>
</St.IntimacySlider>
);
}
44 changes: 44 additions & 0 deletions src/components/CardCollection/FilterModal/IntimacySlider/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { getTrackBackground } from "react-range";
import styled from "styled-components";

interface RangeTrackProps {
min: number;
max: number;
price: number[];
}

export const St = {
IntimacySlider: styled.div`
height: 2.2rem;
margin: 1.2rem 0 0.2rem;
padding: 0 1.5rem;
`,

RangeThumb: styled.div`
position: absolute;
top: 0;
width: 1.8em;
height: 1.8rem;
border-radius: 2.4rem;
background-color: ${({ theme }) => theme.colors.white};
box-shadow: 0 0.1rem 0.4rem 0.1rem rgba(0, 0, 0, 0.25);
`,
};

export const RangeTrack = styled.div`
position: relative;
height: 0.8rem;
width: 100%;
border-radius: 0.4rem;
background: ${(props: RangeTrackProps) =>
getTrackBackground({
values: props.price,
colors: ["#19BE7E", "#ffffff"],
min: props.min,
max: props.max,
})};
box-shadow: inset 0 0.1rem 0.1rem rgba(0, 0, 0, 0.25);
`;
99 changes: 99 additions & 0 deletions src/components/CardCollection/FilterModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React, { useEffect, useState } from "react";

import Modal from "../../common/Modal";
import IntimacySlider from "./IntimacySlider";
import { St } from "./style";

interface FilterModalProps {
closeHandler: () => void;
}

type FilterTags = {
type: string;
tags: string[];
};

const filterTags: FilterTags[] = [
{
type: "성별",
tags: ["남", "여"],
},
{
type: "연령대",
tags: ["10대", "20대", "30대"],
},
{
type: "술자리 유형",
tags: ["개인", "커플", "친구", "단체"],
},
];

const intimacyTags: string[] = ["상관없음", "새로워요", "친근해요", "절친해요"];

export default function FilterModal(props: FilterModalProps) {
const { closeHandler } = props;
const [checkedTags, setCheckedTags] = useState<Set<string>>(new Set()); // 체크한 태그들을 저장할 state
const [intimacyValues, setIntimacyValues] = useState<number[]>([0]); // 친밀도 value
// 태그를 눌렀을 때 함수
const toggleTag = (_tag: string) => {
const tempCheckedTags = new Set([...checkedTags]);
tempCheckedTags.has(_tag) ? tempCheckedTags.delete(_tag) : tempCheckedTags.add(_tag);
setCheckedTags(tempCheckedTags);
};
// 추천 시작하기를 눌렀을 때, 태그 정보들과 친밀도 정보를 담아주고 창닫기
const submitFilter = () => {
const tempCheckedTags = new Set(checkedTags);
tempCheckedTags.add(intimacyTags[intimacyValues[0]]);
setCheckedTags(tempCheckedTags);
closeHandler();
};

useEffect(() => {
console.log(checkedTags);
}, [checkedTags]);

return (
<Modal closeHandler={closeHandler}>
<St.ModalContentsWrapper>
{filterTags.map((filterTag, idx) => (
<React.Fragment key={`filter-${idx}`}>
<St.FilterTitle>{filterTag.type}</St.FilterTitle>
<St.FilterTagsWrapper>
{filterTag.tags.map((tag, index) => (
<St.FilterTag key={index} isactive={checkedTags.has(tag)} onClick={() => toggleTag(tag)}>
{tag}
</St.FilterTag>
))}
</St.FilterTagsWrapper>
</React.Fragment>
))}

<St.FilterIntimacyWrapper>
<St.FilterTitle>친밀도</St.FilterTitle>
<IntimacySlider
min={0}
max={3}
step={1}
price={intimacyValues}
onChange={(values: number[]) => {
setIntimacyValues(values);
}}
/>
<St.FilterIntimacyTagsWrapper>
{intimacyTags.map((tag, index) => (
<St.FilterIntimacyTag isactive={index === intimacyValues[0]} key={index}>
{tag}
</St.FilterIntimacyTag>
))}
</St.FilterIntimacyTagsWrapper>
</St.FilterIntimacyWrapper>
</St.ModalContentsWrapper>

<St.SubmitBtnWrapper>
<St.SubmitBtn onClick={submitFilter} type="submit">
추천 시작하기
</St.SubmitBtn>
</St.SubmitBtnWrapper>
</Modal>
);
}
81 changes: 81 additions & 0 deletions src/components/CardCollection/FilterModal/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import styled from "styled-components";

export const St = {
ModalContentsWrapper: styled.div`
padding-top: 3.6rem;
`,

CloseBtn: styled.button`
background-image: IcModalCloseBtn;
`,

FilterTitle: styled.strong`
${({ theme }) => theme.fonts.body7}
color: ${({ theme }) => theme.colors.black};
`,

FilterTagsWrapper: styled.ul`
display: flex;
align-items: center;
gap: 1rem;
margin: 0.8rem 0 2.2rem;
`,

FilterTag: styled.li<{ isactive: boolean }>`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 6.2rem;
height: 2.6rem;
${({ theme }) => theme.fonts.btn3}
background-color: ${({ isactive, theme }) => (isactive ? theme.colors.green : theme.colors.white)};
color: ${({ isactive, theme }) => (isactive ? theme.colors.white : theme.colors.black)};
border-radius: 6.3rem;
`,

FilterIntimacyWrapper: styled.div`
display: flex;
flex-direction: column;
margin-bottom: 4rem;
`,

FilterIntimacyRange: styled.input`
margin: 1.2rem 0 0.2rem;
`,

FilterIntimacyTagsWrapper: styled.ul`
display: flex;
justify-content: space-between;
`,

FilterIntimacyTag: styled.li<{ isactive: boolean }>`
${({ theme }) => theme.fonts.caption4}
color: ${({ isactive, theme }) => (isactive ? theme.colors.green : theme.colors.gray600)};
`,

SubmitBtnWrapper: styled.div`
display: flex;
justify-content: center;
`,

SubmitBtn: styled.button`
${({ theme }) => theme.fonts.btn2};
background-color: ${({ theme }) => theme.colors.black};
color: ${({ theme }) => theme.colors.white};
width: 17.1rem;
height: 3.3rem;
display: flex;
justify-content: center;
align-items: center;
border-radius: 6.6rem;
`,
};
15 changes: 14 additions & 1 deletion src/components/CardCollection/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
import { useState } from "react";

import Header from "../common/Header";
import CardSlider from "./CardSlider";
import FilterModal from "./FilterModal";
import { St } from "./style";

export default function CardCollection() {
const [isOpened, setIsOpened] = useState<boolean>(false);

const openModal = () => {
setIsOpened(true);
};
const closeModal = () => {
setIsOpened(false);
};

return (
<St.MainPage>
<Header />
<CardSlider />
<CardSlider openHandler={openModal} />
{isOpened && <FilterModal closeHandler={closeModal} />}
</St.MainPage>
);
}
2 changes: 0 additions & 2 deletions src/components/Main/MenuBar/style.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import styled from "styled-components";

import { IcCloseBtn } from "../../../asset/icon";

export const St = {
Root: styled.section`
background-color: ${({ theme }) => theme.colors.gray600};
Expand Down
20 changes: 20 additions & 0 deletions src/components/common/Modal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { IcModalCloseBtn } from "../../../asset/icon";
import { St } from "./style";

type ModalContents = {
closeHandler: () => void;
children: React.ReactNode;
};

export default function Modal({ closeHandler, children }: ModalContents) {
return (
<St.Root>
<St.Modal>
<St.CloseBtn type="button">
<IcModalCloseBtn aria-label="필터 모달 닫기" onClick={closeHandler} />
</St.CloseBtn>
<St.ModalContents>{children}</St.ModalContents>
</St.Modal>
</St.Root>
);
}
Loading

0 comments on commit 0a1870a

Please sign in to comment.