Skip to content

Commit

Permalink
전체 모임 필터 작업 및 UI 수정 작업 (필터 모달 삭제) (#997)
Browse files Browse the repository at this point in the history
* feat: 공지 box 제거

* design: arrow 버튼 모양 변경

* feat: 전체 칩 추가

* feat: useMediaQuery 훅 추가, 카테고리 바깥으로 이동

* feat: 필요없는 ui 제거

* feat: 파트 드롭다운 필터 구현

* chore: 주석 제거

* fix: useMediaQuery 훅 삭제, useDisplay로 변경

* style: CATEGORY_OPTIONS 변경으로 인한 스타일 변경 처리
  • Loading branch information
ocahs9 authored Feb 5, 2025
1 parent 0b36357 commit 9ce8f38
Show file tree
Hide file tree
Showing 14 changed files with 128 additions and 38 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,4 @@
"workspaces": [
"packages/*"
]
}
}
27 changes: 18 additions & 9 deletions pages/list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import Filter from '@components/page/list/Filter';
import Search from '@components/page/list/Filter/Search';
import GridLayout from '@components/page/list/Grid/Layout';
import { MeetingListOfAll } from '@components/page/list/Grid/List';
import NoticeSlider from '@components/page/list/Slider/NoticeSlider/NoticeSlider';
import { SSRSafeSuspense } from '@components/util/SSRSafeSuspense';
import useModal from '@hooks/useModal';
import { playgroundLink } from '@sopt-makers/playground-common';
Expand All @@ -18,12 +17,15 @@ import { useRouter } from 'next/router';
import { useEffect } from 'react';
import { styled } from 'stitches.config';
import CrewTab from '@components/CrewTab';
import Chips from '@components/page/list/Filter/Modal/Chip';
import { CATEGORY_FILTER } from '@constants/option';

const Home: NextPage = () => {
const router = useRouter();
const { data: me } = useQueryMyProfile();
const { isModalOpened, handleModalOpen, handleModalClose } = useModal();
const { data: notices } = useNotices();

const categoryFilterStyle = { display: 'flex', alignItems: 'flex-start', gap: '$12', alignSelf: 'stretch' };

const handleMakeMeeting = () => {
if (!me?.hasActivities) {
Expand Down Expand Up @@ -61,12 +63,12 @@ const Home: NextPage = () => {
</SMakeMeetingButton>
</CrewTab>

{/*Notice 슬라이더*/}
<SNoticeWrapper>
<NoticeSlider notices={notices} />
</SNoticeWrapper>
{/*카테고리 필터 칩*/}
<SChipWrapper>
<Chips css={categoryFilterStyle} filter={CATEGORY_FILTER} />
</SChipWrapper>

{/*필터 - 필터, 모임 검색, 모임 신청 가이드, 필터 적용 후 생기는 FLEX 박스(chip 모임)*/}
{/*필터 - 모임 검색, 드롭다운, 토글, 모임 신청 가이드*/}
<SFilterWrapper>
<Filter />
</SFilterWrapper>
Expand Down Expand Up @@ -136,10 +138,10 @@ const SMobileButtonContainer = styled('div', {
});

const SFilterWrapper = styled('div', {
mt: '$40',
mt: '$20',
mb: '$64',
'@tablet': {
mt: '$32',
mt: '$16',
mb: '$24',
},
});
Expand All @@ -150,3 +152,10 @@ const SNoticeWrapper = styled('div', {
mt: '$28',
},
});

const SChipWrapper = styled('div', {
mt: '$45',
'@tablet': {
mt: '$32',
},
});
4 changes: 4 additions & 0 deletions public/assets/svg/arrow_right_circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 48 additions & 0 deletions src/components/page/list/Filter/DropDown/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ampli } from '@/ampli';
import { FilterType } from '@constants/option';
import { useQueryString } from '@hooks/queryString';
import { SelectV2 } from '@sopt-makers/ui';
import { useRouter } from 'next/router';
import React from 'react';
import { styled } from 'stitches.config';

interface DropDownFilterProps {
filter: FilterType;
}

function DropDownFilter({ filter }: DropDownFilterProps) {
const router = useRouter();
const selectedPartQuery = router.query.part as string;
const defaultValue = selectedPartQuery ? { label: selectedPartQuery, value: selectedPartQuery } : undefined;

const { subject, options } = filter;
const { value: selectedValue, setValue, deleteKey } = useQueryString(subject);

const setPartQuery = (value: string) => {
ampli.clickFilterPart({ group_part: value });

if (selectedValue === value) return deleteKey();
return setValue(value);
};

return (
<SDropDownContainer>
<SelectV2.Root type="text" visibleOptions={6} defaultValue={defaultValue} onChange={setPartQuery}>
<SelectV2.Trigger>
<SelectV2.TriggerContent placeholder={'대상 파트'} />
</SelectV2.Trigger>
<SelectV2.Menu>
{options.map(option => (
<SelectV2.MenuItem key={option} option={{ label: option, value: option }} />
))}
</SelectV2.Menu>
</SelectV2.Root>
</SDropDownContainer>
);
}

export default DropDownFilter;

const SDropDownContainer = styled('div', {
ml: '$16',
});
15 changes: 12 additions & 3 deletions src/components/page/list/Filter/Modal/Chip/ChipItem.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { ampli } from '@/ampli';
import { CATEGORY_FILTER, PART_FILTER, STATUS_FILTER } from '@constants/option';
import { useDisplay } from '@hooks/useDisplay';
import { Chip } from '@sopt-makers/ui';
import { styled } from 'stitches.config';

interface ChipItemProps {
Expand All @@ -8,10 +10,17 @@ interface ChipItemProps {
isSelected: boolean;
addValue: (val: string) => void;
deleteValue: (val: string) => void;
resetQuery: () => void;
}

function ChipItem({ label, value, isSelected, addValue, deleteValue }: ChipItemProps) {
function ChipItem({ label, value, isSelected, addValue, deleteValue, resetQuery }: ChipItemProps) {
const { isTablet } = useDisplay();
const toggle = () => {
if (value === '전체') {
resetQuery();
return;
}

switch (label) {
case CATEGORY_FILTER.label:
ampli.clickFilterCategory({ group_category: value });
Expand All @@ -28,9 +37,9 @@ function ChipItem({ label, value, isSelected, addValue, deleteValue }: ChipItemP
return addValue(value);
};
return (
<SOption isSelected={isSelected} onClick={toggle}>
<Chip size={isTablet ? 'sm' : 'md'} active={isSelected} onClick={toggle}>
{value}
</SOption>
</Chip>
);
}

Expand Down
16 changes: 10 additions & 6 deletions src/components/page/list/Filter/Modal/Chip/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,37 @@ import { useMultiQueryString } from '@hooks/queryString';
import { CSSType, styled } from 'stitches.config';
import ChipItem from './ChipItem';

interface ChipProps {
interface ChipsProps {
isLabel?: boolean;
css?: CSSType;
filter: FilterType;
}

function Chip({ css, filter }: ChipProps) {
function Chips({ isLabel, css, filter }: ChipsProps) {
//해당 Chip 선택시 Chip의 filter로 전달된 subject를 이용하여 쿼리 세팅
const { label, subject, options } = filter;
const { value: selectedValues, addValue, deleteValue } = useMultiQueryString(subject, true);
const { value: selectedValues, addValue, deleteValue, resetQuery } = useMultiQueryString(subject, true);

const isEntire = !selectedValues.length;
return (
<SChipWrapper css={{ ...css }}>
{label && <SLabel>{label}</SLabel>}
{isLabel && <SLabel>{label}</SLabel>}
{options.map(option => (
<ChipItem
key={option}
isSelected={selectedValues.includes(option)}
isSelected={selectedValues.includes(option) || (isEntire && option === '전체')}
label={label}
value={option}
addValue={addValue}
deleteValue={deleteValue}
resetQuery={resetQuery}
/>
))}
</SChipWrapper>
);
}

export default Chip;
export default Chips;

const SChipWrapper = styled('div', {});
const SLabel = styled('p', {
Expand Down
2 changes: 1 addition & 1 deletion src/components/page/list/Filter/Modal/Toggle/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Switch as HeadlessSwitch } from '@headlessui/react';
import { ampli } from '@/ampli';
interface ToggleProps {
css?: CSSType;
label: string;
label?: string;
}

function Toggle({ css, label }: ToggleProps) {
Expand Down
11 changes: 6 additions & 5 deletions src/components/page/list/Filter/Modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import DefaultModal from '@components/modal/DefaultModal';
import { CATEGORY_FILTER, PART_FILTER, STATUS_FILTER } from '@constants/option';
import { styled } from 'stitches.config';
import InitializationButton from '../Result/InitializationButton';
import Chip from './Chip';
import Chips from './Chip';
import Toggle from './Toggle';

interface FilterSelectModalProps {
isModalOpened: boolean;
handleModalClose: () => void;
}

//Notice: 현재 사용 중이지 않습니다.
function FilterSelectModal({ isModalOpened, handleModalClose }: FilterSelectModalProps) {
const filterSectionStyle = { mb: '$48', '@tablet': { mb: '$40' } };
return (
Expand All @@ -19,10 +20,10 @@ function FilterSelectModal({ isModalOpened, handleModalClose }: FilterSelectModa
titleLeft={<InitializationButton withText={false} size={24} />}
>
<SSelectWrapper>
<Chip css={filterSectionStyle} filter={CATEGORY_FILTER} />
<Chip css={filterSectionStyle} filter={STATUS_FILTER} />
<Chips css={filterSectionStyle} filter={CATEGORY_FILTER} isLabel={true} />
<Chips css={filterSectionStyle} filter={STATUS_FILTER} isLabel={true} />
<Toggle css={filterSectionStyle} label="대상 기수" />
<Chip css={filterSectionStyle} filter={PART_FILTER} />
<Chips css={filterSectionStyle} filter={PART_FILTER} isLabel={true} />
</SSelectWrapper>
</DefaultModal>
);
Expand Down
1 change: 1 addition & 0 deletions src/components/page/list/Filter/Result/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import InitializationButton from './InitializationButton';
import { styled } from 'stitches.config';
import { parseBool } from '@utils/parseBool';

//Notice: 현재 사용 중이지 않습니다.
function Result() {
//설정된 쿼리 파라미터의 값을 가져와서 OR 연산으로 필터링한 모임 렌더링
const { value: category, deleteValue: deleteCategoryValue } = useCategoryParams();
Expand Down
2 changes: 1 addition & 1 deletion src/components/page/list/Filter/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ function Search() {

export default Search;
const SSearchWrapper = styled(Flex, {
height: '$48',
py: '$15',
px: '$20',
border: '1px solid $gray600',
borderRadius: '14px',
ml: '$12',
'@tablet': {
display: 'none',
},
Expand Down
19 changes: 9 additions & 10 deletions src/components/page/list/Filter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { styled } from 'stitches.config';
import { Flex } from '@components/util/layout/Flex';
import { useSearchParams } from '@hooks/queryString/custom';
import Search from './Search';
import Result from './Result';
import ArrowSmallRightIcon from '@assets/svg/arrow_small_right.svg';
import FilterModalOpenButton from './Modal/OpenButton';
import ArrowRightCircleIcon from '@assets/svg/arrow_right_circle.svg';
import Toggle from './Modal/Toggle';
import { PART_FILTER } from '@constants/option';
import DropDownFilter from './DropDown';

function Filter() {
const { value: search } = useSearchParams();
Expand All @@ -13,8 +14,9 @@ function Filter() {
<>
<Flex align="center" justify="between">
<Flex>
<FilterModalOpenButton />
<Search />
<DropDownFilter filter={PART_FILTER} />
<Toggle />
</Flex>

<SGuideButton
Expand All @@ -23,13 +25,10 @@ function Filter() {
rel="noreferrer noopener"
>
모임 신청 가이드
<ArrowSmallRightIcon />
<ArrowRightCircleIcon />
</SGuideButton>
</Flex>

{/*필터 적용 결과 박스 (chip 모임)*/}
<Result />

{!!search && <SearchResultMessage>"{search}"에 대한 검색결과입니다.</SearchResultMessage>}
</>
);
Expand All @@ -38,13 +37,13 @@ function Filter() {
export default Filter;

const SGuideButton = styled('a', {
height: '$48',
flexType: 'verticalCenter',
gap: '$8',
color: '$gray10',
padding: '$18 $20',
border: '1px solid $gray10',
borderRadius: '14px',
fontAg: '18_medium_100',
fontAg: '18_semibold_100',
boxSizing: 'border-box',
'@tablet': {
padding: '$14 $12 $14 $16',
Expand Down
5 changes: 3 additions & 2 deletions src/constants/option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export const APPROVAL_STATUS_KOREAN_TO_ENGLISH: StringKeyObject = {
거절: 'REJECT',
};
export const APPLICATION_TYPE = ['신청', '초대'];
export const CATEGORY_OPTIONS = ['번쩍', '스터디', '세미나', '행사'];
export const CATEGORY_OPTIONS = ['스터디', '세미나', '행사', '번쩍'];
export const CATEGORY_FILTER_OPTIONS = ['전체', ...CATEGORY_OPTIONS];
export const PART_OPTIONS = ['기획', '디자인', 'Android', 'iOS', '웹', '서버'];
export const PART_VALUES = ['PM', 'DESIGN', 'ANDROID', 'IOS', 'WEB', 'SERVER'];
export const ACTION_STATUS = ['모집 전', '모집 중', '모집 마감', '활동 중', '활동 종료'];
Expand Down Expand Up @@ -53,7 +54,7 @@ export interface FilterType {
export const CATEGORY_FILTER = {
label: '카테고리',
subject: 'category',
options: CATEGORY_OPTIONS,
options: CATEGORY_FILTER_OPTIONS,
};
export const STATUS_FILTER = {
label: '모집 상태',
Expand Down
13 changes: 13 additions & 0 deletions src/hooks/queryString/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,24 @@ export function useMultiQueryString(key: string, withPage?: boolean) {
delete query[key];
pushQuery(query);
};

const resetQuery = () => {
router.replace(
{
pathname: router.pathname,
query: {},
},
undefined,
{ shallow: true }
);
};

return {
value: splitQueryOfKey, // , 로 구분된 해당 key의 value들을 배열 형태로 반환
setValue,
addValue,
deleteValue,
deleteKey,
resetQuery,
};
}
1 change: 1 addition & 0 deletions src/hooks/useDisplay.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useState } from 'react';
import { useMediaQuery } from 'react-responsive';
import useIsomorphicLayoutEffect from './useIsomorphicLayoutEffect';

export function useDisplay() {
const [isMobile, setIsMobile] = useState(false);
const [isTablet, setIsTable] = useState(false);
Expand Down

0 comments on commit 9ce8f38

Please sign in to comment.