diff --git a/components/Toast/Toast.module.scss b/components/Toast/Toast.module.scss
new file mode 100644
index 0000000..ce038c1
--- /dev/null
+++ b/components/Toast/Toast.module.scss
@@ -0,0 +1,3 @@
+.toast {
+ @apply fixed bottom-5 left-1/2 transform -translate-x-1/2 bg-a1 text-white font-bold rounded-lg py-2 px-4 shadow-lg z-10 w-full h-[48px] text-center;
+}
\ No newline at end of file
diff --git a/components/Toast/Toast.tsx b/components/Toast/Toast.tsx
new file mode 100644
index 0000000..2063660
--- /dev/null
+++ b/components/Toast/Toast.tsx
@@ -0,0 +1,25 @@
+import React, { useState, useEffect } from 'react';
+import styles from './Toast.module.scss';
+
+interface ToastProps {
+ message: string;
+ duration?: number;
+ onVisibleChange: (visible: boolean) => void; // 새로운 콜백 함수 추가
+}
+
+export default function Toast({ message, duration = 3000, onVisibleChange }: ToastProps) {
+ const [visible, setVisible] = useState(true);
+
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ setVisible(false);
+ onVisibleChange(!onVisibleChange);
+ }, duration);
+
+ return () => {
+ clearTimeout(timer);
+ };
+ }, [duration, visible, onVisibleChange]);
+
+ return visible ?
{message}
: null;
+}
diff --git a/components/index.tsx b/components/index.tsx
index 9bf45e6..5a947de 100644
--- a/components/index.tsx
+++ b/components/index.tsx
@@ -16,3 +16,4 @@ export { default as Toggle } from '@/components/Toggle/Toggle.tsx';
export { default as Typography } from '@/components/Typography/Typography.tsx';
export { default as Space } from '@/components/Space.tsx';
export { default as LoginLayout } from '@/components/layouts/LoginLayout.tsx';
+export { default as Toast } from '@/components/Toast/Toast.tsx';
diff --git a/pages/index.tsx b/pages/index.tsx
index 3ef3b8e..23ad196 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -14,7 +14,6 @@ import { Chip, Typography } from '@/components/index.tsx';
import { FilterType } from '@/public/types/filter';
import Filter from '@/pages/room/filter.tsx';
import useModal from '@/hooks/useModal.ts';
-import { ModalSetterContext } from '@/context/ModalProvider';
import { FieldValues } from 'react-hook-form';
export const getStaticProps = async ({ locale }: GetStaticPropsContext) => ({
diff --git a/pages/room/filter.tsx b/pages/room/filter.tsx
index 3a107ea..d50f991 100644
--- a/pages/room/filter.tsx
+++ b/pages/room/filter.tsx
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useCallback } from 'react';
import { useTranslation } from 'next-i18next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { GetStaticPropsContext } from 'next';
-import { Chip, Select, Typography, Toggle, Checkbox, Space, Button, Input } from '@/components/index.tsx';
+import { Toast, Chip, Select, Typography, Toggle, Checkbox, Space, Button, Input } from '@/components/index.tsx';
import { FieldValues, SubmitHandler, useForm } from 'react-hook-form';
import { GuList, DongList } from '../../public/js/guDongList.ts';
@@ -35,12 +35,18 @@ export default function Filter({
label: '',
});
const [selectedOptions, setSelectedOptions] = useState([]);
+ const [showToast, setShowToast] = useState(false);
+ const [showMessage, setMessage] = useState('');
const filteredDongList = DongList.filter((v) => v.gu === guValue.value);
const onSubmit: SubmitHandler = (data) => {
getChildData(data);
closeModal();
};
+ const handleToastVisibleChange = (visible: boolean) => {
+ setShowToast(visible);
+ };
+
// 옵션 선택 시 실행될 함수, 유효성 검증
const handleOptionSelect = useCallback(() => {
if (!dongValue.label) return;
@@ -49,18 +55,25 @@ export default function Filter({
const option = dongValue.label;
setSelectedOptions((prevSelectedOptions) => {
const isExist = prevSelectedOptions.some((item) => item.includes(option));
+ // Location이 5개 이상 선택 될 경우 Toast 노출
+ if (prevSelectedOptions.length >= 5) {
+ setShowToast(true);
+ // TODO translation 사용해서 여기 나중에 바꿔줘야함
+ setMessage('You can select up to five');
+ return [...prevSelectedOptions];
+ }
+
if (!isExist) {
resultOptions = [...prevSelectedOptions, guValue?.label.concat(`, ${option}`)];
} else {
+ setShowToast(true);
+ // TODO translation 사용해서 여기 나중에 바꿔줘야함
+ setMessage('Already selected');
resultOptions = prevSelectedOptions;
}
return [...resultOptions];
});
}, [dongValue.label, guValue?.label]);
-
- useEffect(() => {
- handleOptionSelect();
- }, [dongValue.label, handleOptionSelect]);
/** Dong Select Component 변경될 경우 -> 일반 선언형 함수로 정의할 경우 Rendering 마다 새로운 인스턴스가 생성됨 */
const handleDongChange = useCallback(
(selectedValue: string, selectedLabel: string) => {
@@ -78,6 +91,9 @@ export default function Filter({
const handleOptionRemove = (option: string) => {
setSelectedOptions((prevSelectedOptions) => prevSelectedOptions.filter((item) => item !== option));
};
+ useEffect(() => {
+ handleOptionSelect();
+ }, [dongValue.label, handleOptionSelect]);
return (
@@ -330,6 +346,7 @@ export default function Filter({
+ {showToast && }
);
diff --git a/public/js/guDongList.ts b/public/js/guDongList.ts
index bab0e08..9d3a6a3 100644
--- a/public/js/guDongList.ts
+++ b/public/js/guDongList.ts
@@ -95,13 +95,13 @@ export const DongList: DongListItem[] = [
{ gu: '200', value: '570', label: 'Hangdangje 2-dong' },
{ gu: '200', value: '580', label: 'Eungbong-dong' },
{ gu: '200', value: '590', label: 'Kumho 1-ga-dong' },
- { gu: '200', value: '615', label: 'Kumho 2.3' },
- { gu: '200', value: '620', label: 'Kumho4 ga-dong' },
+ { gu: '200', value: '615', label: 'Kumho 2.3-ga-dong' },
+ { gu: '200', value: '620', label: 'Kumho4 4-ga-dong' },
{ gu: '200', value: '645', label: 'Oksu-dong' },
{ gu: '200', value: '650', label: 'Seongsu 1-gaje 1-dong' },
{ gu: '200', value: '660', label: 'Seongsu 1-gaje 2-dong' },
{ gu: '200', value: '670', label: 'Seongsu 2-gaje 1-dong' },
- { gu: '200', value: '690', label: 'Seongsu2gaje3dong' },
+ { gu: '200', value: '690', label: 'Seongsu2gaje 3-dong' },
{ gu: '200', value: '720', label: 'Songjeong-dong' },
{ gu: '200', value: '790', label: 'Yongdap-dong' },
{ gu: '215', value: '710', label: 'Hwayang-dong' },
diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index ab255fb..e7982be 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -9,5 +9,6 @@
"samePassword": "Please check again",
"next": "Next",
"complete": "Complete",
- "filters" : "Filters"
+ "filters" : "Filters",
+ "uptofive" : "You can select up to five"
}
diff --git a/public/locales/en/filter.json b/public/locales/en/filter.json
index 0f0cb87..c773e15 100644
--- a/public/locales/en/filter.json
+++ b/public/locales/en/filter.json
@@ -31,5 +31,6 @@
"kitchenette": "Kitchenette",
"reset": "Reset",
"apply": "Apply",
- "mmddyyyy": "MM-DD-YYYY"
+ "mmddyyyy": "MM-DD-YYYY",
+ "uptofive" : "You can select up to five"
}
diff --git a/public/locales/ko/filter.json b/public/locales/ko/filter.json
new file mode 100644
index 0000000..c773e15
--- /dev/null
+++ b/public/locales/ko/filter.json
@@ -0,0 +1,36 @@
+{
+ "location": "Location",
+ "gu": "Gu",
+ "koo": "Gu",
+ "dong": "Dong",
+ "deposit": "Deposit",
+ "viewRoomsWithoutDeposit": "View rooms without deposit",
+ "minMax": "Min 0 ₩ - Max 500,000,000 ₩ ",
+ "min": "Min",
+ "max": "Max",
+ "monthRent": "Monthly rent",
+ "includeMainFee": "Include maintenance fee",
+ "dateAvailable": "Date available",
+ "viewRoomsAvailable": "View rooms available now",
+ "typeOfHousing": "Type of housing",
+ "studio": "Studio",
+ "bedFlats ": "1bed flats",
+ "shareHouse": "Share house",
+ "furnishing": "Furnishing",
+ "bed": "Bed",
+ "wardrobe": "Wardrobe",
+ "tv": "TV",
+ "airconditioner": "Air conditioner",
+ "heater": "Heater",
+ "doorLock": "Door lock",
+ "refrigerator": "Refrigerator",
+ "stove": "Stove",
+ "washingMachine": "Washing machine",
+ "induction": "Induction",
+ "gasStove": "Gas stove",
+ "kitchenette": "Kitchenette",
+ "reset": "Reset",
+ "apply": "Apply",
+ "mmddyyyy": "MM-DD-YYYY",
+ "uptofive" : "You can select up to five"
+}