diff --git a/package-lock.json b/package-lock.json index a017b22b..f21402f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,6 @@ "requires": true, "packages": { "": { - "name": "outstaffing-react", "version": "0.1.0", "dependencies": { "@reduxjs/toolkit": "^1.6.0", @@ -36,6 +35,7 @@ "react": "^18.2.0", "react-app-polyfill": "^2.0.0", "react-bootstrap": "^1.6.0", + "react-datepicker": "^4.10.0", "react-dev-utils": "^12.0.1", "react-dom": "^18.2.0", "react-inlinesvg": "3.0.1", @@ -61,7 +61,7 @@ "babel-loader": "^9.1.2", "copy-webpack-plugin": "^10.2.0", "cross-env": "^7.0.3", - "css-loader": "^6.7.3", + "css-loader": "6.7.3", "dotenv-webpack": "^7.0.3", "html-webpack-plugin": "5.5.0", "mini-css-extract-plugin": "^2.7.2", @@ -8738,6 +8738,18 @@ "node": ">=10" } }, + "node_modules/date-fns": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -20193,6 +20205,23 @@ "react-dom": ">=16.8.0" } }, + "node_modules/react-datepicker": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.10.0.tgz", + "integrity": "sha512-6IfBCZyWj54ZZGLmEZJ9c4Yph0s9MVfEGDC2evOvf9AmVz+RRcfP2Czqad88Ff9wREbcbqa4dk7IFYeXF1d3Ag==", + "dependencies": { + "@popperjs/core": "^2.9.2", + "classnames": "^2.2.6", + "date-fns": "^2.24.0", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.12.2", + "react-popper": "^2.3.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", @@ -20339,6 +20368,11 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "node_modules/react-fast-compare": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", + "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" + }, "node_modules/react-from-dom": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-from-dom/-/react-from-dom-0.6.2.tgz", @@ -20381,6 +20415,19 @@ "react-dom": "*" } }, + "node_modules/react-onclickoutside": { + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.12.2.tgz", + "integrity": "sha512-NMXGa223OnsrGVp5dJHkuKxQ4czdLmXSp5jSV9OqiCky9LOpPATn3vLldc+q5fK3gKbEHvr7J1u0yhBh/xYkpA==", + "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-outside-click-handler": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/react-outside-click-handler/-/react-outside-click-handler-1.3.0.tgz", @@ -20460,6 +20507,20 @@ "react-dom": "^16.12.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0" } }, + "node_modules/react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "dependencies": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + }, + "peerDependencies": { + "@popperjs/core": "^2.0.0", + "react": "^16.8.0 || ^17 || ^18", + "react-dom": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/react-redux": { "version": "7.2.9", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", @@ -32044,6 +32105,11 @@ "whatwg-url": "^8.0.0" } }, + "date-fns": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -40452,6 +40518,19 @@ "warning": "^4.0.3" } }, + "react-datepicker": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.10.0.tgz", + "integrity": "sha512-6IfBCZyWj54ZZGLmEZJ9c4Yph0s9MVfEGDC2evOvf9AmVz+RRcfP2Czqad88Ff9wREbcbqa4dk7IFYeXF1d3Ag==", + "requires": { + "@popperjs/core": "^2.9.2", + "classnames": "^2.2.6", + "date-fns": "^2.24.0", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.12.2", + "react-popper": "^2.3.0" + } + }, "react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -40561,6 +40640,11 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "react-fast-compare": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", + "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" + }, "react-from-dom": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-from-dom/-/react-from-dom-0.6.2.tgz", @@ -40594,6 +40678,12 @@ "prop-types": "^15.7.2" } }, + "react-onclickoutside": { + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.12.2.tgz", + "integrity": "sha512-NMXGa223OnsrGVp5dJHkuKxQ4czdLmXSp5jSV9OqiCky9LOpPATn3vLldc+q5fK3gKbEHvr7J1u0yhBh/xYkpA==", + "requires": {} + }, "react-outside-click-handler": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/react-outside-click-handler/-/react-outside-click-handler-1.3.0.tgz", @@ -40657,6 +40747,15 @@ "prop-types": "^15.7.2" } }, + "react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "requires": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + } + }, "react-redux": { "version": "7.2.9", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", diff --git a/package.json b/package.json index 3de129a5..c47905f4 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "react": "^18.2.0", "react-app-polyfill": "^2.0.0", "react-bootstrap": "^1.6.0", + "react-datepicker": "^4.10.0", "react-dev-utils": "^12.0.1", "react-dom": "^18.2.0", "react-inlinesvg": "3.0.1", diff --git a/src/components/ReportForm/ReportForm.js b/src/components/ReportForm/ReportForm.js index 7c8bbda1..11da8999 100644 --- a/src/components/ReportForm/ReportForm.js +++ b/src/components/ReportForm/ReportForm.js @@ -1,6 +1,9 @@ -import React, {useState} from 'react' +import React, {useState, useEffect} from 'react' import {useSelector} from 'react-redux' import {Link, useNavigate} from 'react-router-dom' +import DatePicker, { registerLocale } from "react-datepicker" +import ru from "date-fns/locale/ru" +registerLocale("ru", ru); import {Loader} from '../Loader/Loader' import {currentMonthAndDay} from '../Calendar/calendarHelper' @@ -18,26 +21,32 @@ import addIcon from '../../images/addIcon.png' import arrow from "../../images/right-arrow.png"; import './reportForm.scss' - - -const getCreatedDate = (day) => { - if (day) { - return `${new Date(day).getFullYear()}-${new Date(day).getMonth() + 1}-${new Date(day).getDate()}` - } else { - const date = new Date(); - const dd = String(date.getDate()).padStart(2, '0'); - const mm = String(date.getMonth() + 1).padStart(2, '0'); - const yyyy = date.getFullYear(); - return `${yyyy}-${mm}-${dd}` - } -}; +import "react-datepicker/dist/react-datepicker.css"; const ReportForm = () => { const navigate= useNavigate(); const reportDate = useSelector(getReportDate); + const getCreatedDate = (day) => { + if (day) { + return `${new Date(day).getFullYear()}-${new Date(day).getMonth() + 1}-${new Date(day).getDate()}` + } else { + const date = new Date(); + const dd = String(date.getDate()).padStart(2, '0'); + const mm = String(date.getMonth() + 1).padStart(2, '0'); + const yyyy = date.getFullYear(); + return `${yyyy}-${mm}-${dd}` + } + }; + + useEffect(() => { + initListeners() + }, []) + const [isFetching, setIsFetching] = useState(false); const [reportSuccess, setReportSuccess] = useState(''); + const [startDate, setStartDate] = useState(reportDate ? new Date (reportDate._d) : new Date()); + const [datePickerOpen, setDatePickerOpen] = useState(false); const [inputs, setInputs] = useState([{task: '', hours_spent: '', minutes_spent: 0}]); const [troublesInputValue, setTroublesInputValue] = useState(''); @@ -47,6 +56,18 @@ const ReportForm = () => { setInputs((prev) => [...prev, {task: '', hours_spent: '', minutes_spent: 0}]) }; + const initListeners = () => { + document.addEventListener('click', closeByClickingOut) + } + + const closeByClickingOut = (event) => { + const path = event.path || (event.composedPath && event.composedPath()) + + if (event && !path.find((div) => div.classList && (div.classList.contains('report-form__block-img') || div.classList.contains('react-datepicker-popper')))) { + setDatePickerOpen(false) + } + } + const totalHours = inputs.reduce((a, b) => a + b.hours_spent, 0); const deleteInput = (indexRemove) => { @@ -67,7 +88,7 @@ const ReportForm = () => { tasks: inputs, difficulties: troublesInputValue, tomorrow: scheduledInputValue, - created_at: getCreatedDate(reportDate), + created_at: getCreatedDate(startDate), status: 1, }, }).then((res) => { @@ -103,15 +124,24 @@ const ReportForm = () => {