Skip to content

Commit

Permalink
feat: PostFormDropdown 컴포넌트 추가 및 적용
Browse files Browse the repository at this point in the history
  • Loading branch information
ccwnc committed Mar 28, 2024
1 parent 32f7e8e commit 57d01c3
Show file tree
Hide file tree
Showing 5 changed files with 249 additions and 5 deletions.
139 changes: 139 additions & 0 deletions src/components/commons/inputs/PostFormDropdown.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
.dropdown {
@include column-flexbox(start, start, 0.8rem);

.label {
@include text-style(14, $white);
}

.select-group {
position: relative;
width: 100%;

&-select {
display: none;
}

&-input-group {
position: relative;

.input {
@include text-style(16, $gray10);

cursor: pointer;

width: 100%;
height: 4.8rem;
padding: 0 5.2rem 0 1.6rem;

background: $input-background;
border: 0.1rem solid $input-stroke;
border-radius: 0.8rem;

transition: $base-transition;

&::placeholder {
@include text-style(16, $gray50);
}

&.sm {
@include text-style-14;

height: 4rem;
padding-right: 4.4rem;
}

&.opened {
border-color: $purple;
}

&:disabled {
cursor: not-allowed;
background: $gray60;
}
}

.arrow-btn {
@include pos-center-y;

right: 1.2rem;
transition: $transition-6s;

&:disabled {
cursor: not-allowed;
}

&.rotate {
@include pos-center-y;

transform: translateY(-62%) rotate(180deg);
transition: $transition-6s;
}
}
}

&-container {
cursor: pointer;

position: absolute;
z-index: $dropdown-level;
top: 5.6rem;

display: none;

width: 100%;
max-height: 24.8rem;
padding: 0.8rem 0.4rem 0.8rem 0.8rem;

background: $input-background;
border: 0.1rem solid $input-stroke;
border-radius: 0.6rem;
box-shadow: $dropdown-shadow;

&.sm {
top: 4.8rem;
}

&.show {
display: block;
}

&-list {
@include column-flexbox(start, start, 0.4rem);
@include thin-scrollbar;

overflow-y: auto;
width: 100%;
max-height: 23rem;
padding-right: 0.4rem;

.item {
width: 100%;

.btn {
@include text-style(16, $gray50);

@include responsive(T) {
color: $gray50;
background: inherit;
border-radius: inherit;
}

width: 100%;
padding: 0.8rem;
text-align: left;

&:hover {
color: $gray10;
background: $black50;
border-radius: 0.4rem;
}

&.sm {
@include text-style(14);
}
}
}
}
}
}
}
104 changes: 104 additions & 0 deletions src/components/commons/inputs/PostFormDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import Image from 'next/image';

import { useState } from 'react';

import classNames from 'classnames/bind';
import { useFormContext } from 'react-hook-form';

import { SVGS } from '@/constants';

import useTogglePopup from '@/hooks/useTogglePopup';

import styles from './PostFormDropdown.module.scss';

const cx = classNames.bind(styles);

const { url: defaultUrl, alt: defaultAlt } = SVGS.arrow.down.default;
const { url: activeUrl, alt: activeAlt } = SVGS.arrow.down.active;

type PostFormDropdownProps = {
name: string;
options: { title: string; value: number | string }[];
label?: string;
isSmall?: boolean;
isDisabled?: boolean;
};

export const PostFormDropdown = ({
name,
label = '',
options,
isSmall = false,
isDisabled = false,
}: PostFormDropdownProps) => {
const { register, setValue } = useFormContext();
const { isOpen, popupRef, buttonRef, togglePopup } = useTogglePopup();
const [currentOptionTitle, setCurrentOptionTitle] = useState(options[0].title);

const handleOptionChange = (title: string, value: number | string) => {
setValue(name, value);
setCurrentOptionTitle(title);
togglePopup();
};

return (
<div className={cx('dropdown')} ref={popupRef}>
<span className={cx('label')}>{label}</span>
<div className={cx('select-group')}>
<select
className={cx('select-group-select')}
{...register(name, {
value: options[0].value,
})}
>
{options.map((option, index) => (
<option key={`dropdown-${index}`} value={option.value}>
{option.title}
</option>
))}
</select>

<div className={cx('select-group-input-group')}>
<input
className={cx('input', { sm: isSmall }, { opened: isOpen })}
type='text'
value={currentOptionTitle}
disabled={isDisabled}
onClick={togglePopup}
readOnly
/>
<button
className={cx('arrow-btn', { rotate: isOpen })}
ref={buttonRef}
type='button'
disabled={isDisabled}
onClick={togglePopup}
>
{isOpen ? (
<Image src={activeUrl} alt={activeAlt} width={24} height={24} />
) : (
<Image src={defaultUrl} alt={defaultAlt} width={24} height={24} />
)}
</button>
</div>

<div className={cx('select-group-container', { sm: isSmall }, { show: isOpen })}>
{isOpen && (
<ul className={cx('select-group-container-list')}>
{options.map((option, index) => (
<li className={cx('item')} key={`dropdown-item-${index}`}>
<button
className={cx('btn', { sm: isSmall })}
onClick={() => handleOptionChange(option.title, option.value)}
>
<label>{option.title}</label>
</button>
</li>
))}
</ul>
)}
</div>
</div>
</div>
);
};
1 change: 1 addition & 0 deletions src/components/commons/inputs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './FormDropdown';
export * from './SearchBar';
export * from './DateField';
export * from './ImageField';
export * from './PostFormDropdown';
4 changes: 2 additions & 2 deletions src/components/createPage/PostForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
import { convertTimeStringToNumber, createHeadcountOptions, joinTitleByDelimiter, navigateBack } from '@/utils';

import { BaseButton } from '@/components/commons/buttons';
import { FormDropdown, ImageField, InputField, InputRadio, TextField } from '@/components/commons/inputs';
import { ImageField, InputField, InputRadio, PostFormDropdown, TextField } from '@/components/commons/inputs';
import { ConfirmModal, ModalButton } from '@/components/commons/modals';
import Schedule from '@/components/createPage/Schedule';
import SelectedSchedule from '@/components/createPage/SelectedSchedule';
Expand Down Expand Up @@ -186,7 +186,7 @@ const PostForm = ({ type, category }: PostFormProps) => {
{recruitmentTypes.isOfflineOrOnline(price) && (
<fieldset className={cx('post-form-input-content-headcount')}>
<legend>참여 인원</legend>
<FormDropdown name='headcount' label='참여 인원' options={HEADCOUNT_OPTIONS[category]} />
<PostFormDropdown name='headcount' label='참여 인원' options={HEADCOUNT_OPTIONS[category]} />
</fieldset>
)}
</div>
Expand Down
6 changes: 3 additions & 3 deletions src/components/createPage/Schedule/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import classNames from 'classnames/bind';
import { createTimeRange } from '@/utils';

import { OperationButton } from '@/components/commons/buttons';
import { DateField, FormDropdown } from '@/components/commons/inputs';
import { DateField, PostFormDropdown } from '@/components/commons/inputs';

import styles from './Schedule.module.scss';

Expand All @@ -28,11 +28,11 @@ const Schedule = ({ isScheduleSelected, onClick }: ScheduleProps) => {
</div>
<div className={cx('schedules-time')}>
<div className={cx('schedules-time-start')}>
<FormDropdown name='startTime' label='시작 시간' options={SCHEDULES_TIME.start} />
<PostFormDropdown name='startTime' label='시작 시간' options={SCHEDULES_TIME.start} />
</div>
<div className={cx('schedules-time-hyphen')}>-</div>
<div className={cx('schedules-time-end')}>
<FormDropdown name='endTime' label='종료 시간' options={SCHEDULES_TIME.end} />
<PostFormDropdown name='endTime' label='종료 시간' options={SCHEDULES_TIME.end} />
</div>
</div>
</div>
Expand Down

0 comments on commit 57d01c3

Please sign in to comment.