From 043a65483aa55901b9aa758aae10075c86b07b91 Mon Sep 17 00:00:00 2001 From: jihunchoi Date: Tue, 21 May 2024 16:46:41 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20#50-=EC=82=AC=EC=9D=B4=EB=93=9C=20?= =?UTF-8?q?=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=20datepicker=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 101 ++++++++++++++++++ package.json | 2 + .../SideNavigation/datePickerPopup.js | 52 +++++++++ .../SideNavigation/sideNavigation.js | 56 +++++++++- src/components/SideNavigation/styles.js | 3 +- 5 files changed, 207 insertions(+), 7 deletions(-) create mode 100644 src/components/SideNavigation/datePickerPopup.js diff --git a/package-lock.json b/package-lock.json index ef884aa..d15d581 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,9 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "axios": "^1.6.8", + "date-fns": "^3.6.0", "react": "^18.2.0", + "react-datepicker": "^6.9.0", "react-dom": "^18.2.0", "react-modal": "^3.16.1", "react-router-dom": "^6.22.3", @@ -2400,6 +2402,54 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz", + "integrity": "sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==", + "dependencies": { + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz", + "integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==", + "dependencies": { + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.26.16", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.16.tgz", + "integrity": "sha512-HEf43zxZNAI/E781QIVpYSF3K2VH4TTYZpqecjdsFkjsaU1EbaWcM++kw0HXFffj7gDUcBFevX8s0rQGQpxkow==", + "dependencies": { + "@floating-ui/react-dom": "^2.1.0", + "@floating-ui/utils": "^0.2.0", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.0.tgz", + "integrity": "sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz", + "integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==" + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -6273,6 +6323,14 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -6974,6 +7032,15 @@ "node": ">=10" } }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -15034,6 +15101,22 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, + "node_modules/react-datepicker": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-6.9.0.tgz", + "integrity": "sha512-QTxuzeem7BUfVFWv+g5WuvzT0c5BPo+XTCNbMTZKSZQLU+cMMwSUHwspaxuIcDlwNcOH0tiJ+bh1fJ2yxOGYWA==", + "dependencies": { + "@floating-ui/react": "^0.26.2", + "clsx": "^2.1.0", + "date-fns": "^3.3.1", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.13.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17 || ^18", + "react-dom": "^16.9.0 || ^17 || ^18" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -15196,6 +15279,19 @@ "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18" } }, + "node_modules/react-onclickoutside": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.1.tgz", + "integrity": "sha512-LdrrxK/Yh9zbBQdFbMTXPp3dTSN9B+9YJQucdDu3JNKRrbdU+H+/TVONJoWtOwy4II8Sqf1y/DTI6w/vGPYW0w==", + "funding": { + "type": "individual", + "url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md" + }, + "peerDependencies": { + "react": "^15.5.x || ^16.x || ^17.x || ^18.x", + "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x" + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -16943,6 +17039,11 @@ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + }, "node_modules/tailwindcss": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", diff --git a/package.json b/package.json index b4f9101..43b9c41 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "axios": "^1.6.8", + "date-fns": "^3.6.0", "react": "^18.2.0", + "react-datepicker": "^6.9.0", "react-dom": "^18.2.0", "react-modal": "^3.16.1", "react-router-dom": "^6.22.3", diff --git a/src/components/SideNavigation/datePickerPopup.js b/src/components/SideNavigation/datePickerPopup.js new file mode 100644 index 0000000..6bccf66 --- /dev/null +++ b/src/components/SideNavigation/datePickerPopup.js @@ -0,0 +1,52 @@ +import React, { useRef, useEffect } from "react"; +import styled from "styled-components"; +import DatePicker from "react-datepicker"; +import "react-datepicker/dist/react-datepicker.css"; + +const PopupContainer = styled.div` + position: absolute; + z-index: 1000; + background: white; + border: 1px solid #ccc; + border-radius: 8px; + padding: 10px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); +`; + +const DatePickerPopup = ({ + startDate, + endDate, + onChange, + onClose, + position, +}) => { + const popupRef = useRef(null); + + useEffect(() => { + const handleClickOutside = (event) => { + if (popupRef.current && !popupRef.current.contains(event.target)) { + onClose(); + } + }; + + document.addEventListener("mousedown", handleClickOutside); + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [popupRef, onClose]); + + return ( + + + + ); +}; + +export default DatePickerPopup; diff --git a/src/components/SideNavigation/sideNavigation.js b/src/components/SideNavigation/sideNavigation.js index a54d5cd..9b497a2 100644 --- a/src/components/SideNavigation/sideNavigation.js +++ b/src/components/SideNavigation/sideNavigation.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useRef } from "react"; import { Checkbox, Item, @@ -10,13 +10,12 @@ import { SectionTitle, SectionTitleRow, Title, -} from "./styles"; -import { SearchInputContainer, SearchInput, SearchButton, SearchIcon, } from "./styles"; +import DatePickerPopup from "./datePickerPopup"; const SideNavigation = ({ categoryObject }) => { const initialMainCategoryStates = categoryObject.reduce((acc, category) => { @@ -46,6 +45,10 @@ const SideNavigation = ({ categoryObject }) => { const [subCategoryVisibility, setSubCategoryVisibility] = useState( initialSubCategoryVisibility, ); + const [startDate, setStartDate] = useState(null); + const [endDate, setEndDate] = useState(null); + const [isDatePickerVisible, setIsDatePickerVisible] = useState(false); + const dateButtonRef = useRef(null); const handleMainCategoryCheckbox = (kind) => { const futureStateOfMain = !mainCategoryStates[kind]; @@ -73,6 +76,27 @@ const SideNavigation = ({ categoryObject }) => { setMainCategoryStates(initialMainCategoryStates); setSubCategoryStates(initialSubCategoryStates); setSubCategoryVisibility(initialSubCategoryVisibility); + setStartDate(null); + setEndDate(null); + setIsDatePickerVisible(false); + }; + + const handleDateChange = (dates) => { + const [start, end] = dates; + setStartDate(start); + setEndDate(end); + setIsDatePickerVisible(false); + }; + + const getPosition = () => { + if (dateButtonRef.current) { + const rect = dateButtonRef.current.getBoundingClientRect(); + return { + top: rect.bottom + window.scrollY, + left: rect.left + window.scrollX, + }; + } + return {}; }; return ( @@ -102,12 +126,34 @@ const SideNavigation = ({ categoryObject }) => { 모집 기간 - - + + setIsDatePickerVisible(!isDatePickerVisible)} + > + {isDatePickerVisible && ( + setIsDatePickerVisible(false)} + position={getPosition()} + /> + )} + {/* 직종 분류 섹션 */} 직종 분류 {categoryObject.map((category) => ( diff --git a/src/components/SideNavigation/styles.js b/src/components/SideNavigation/styles.js index ce99474..b861035 100644 --- a/src/components/SideNavigation/styles.js +++ b/src/components/SideNavigation/styles.js @@ -87,6 +87,7 @@ export const WriteButton = styled.div` color: white; } `; + export const SearchInputContainer = styled.div` display: flex; align-items: center; @@ -98,8 +99,6 @@ export const SearchInput = styled.input` padding: 8px; border: 1px solid #ccc; border-radius: 4px; - background-color: #f3f3f3; - font-size: 14px; `; export const SearchButton = styled.button`