Merge pull request #88 from apuc/fix-report-page
Fixed report page and calendar component
This commit is contained in:
commit
9932720fd8
@ -88,8 +88,9 @@ const App = () => {
|
|||||||
<Route index element={<Profile />} />
|
<Route index element={<Profile />} />
|
||||||
<Route exact path="catalog" element={<Home />} />
|
<Route exact path="catalog" element={<Home />} />
|
||||||
<Route exact path="calendar" element={<ProfileCalendar />} />
|
<Route exact path="calendar" element={<ProfileCalendar />} />
|
||||||
|
<Route exact path="calendar/view/" element={<ProfileCalendar />} />
|
||||||
<Route exact path="summary" element={<Summary />} />
|
<Route exact path="summary" element={<Summary />} />
|
||||||
<Route exact path="view" element={<ViewReport />} />
|
<Route exact path="view/:id" element={<ViewReport />} />
|
||||||
<Route exact path="tracker" element={<Tracker />} />
|
<Route exact path="tracker" element={<Tracker />} />
|
||||||
<Route exact path="payouts" element={<Payouts />} />
|
<Route exact path="payouts" element={<Payouts />} />
|
||||||
<Route exact path="settings" element={<PartnerSettings />} />
|
<Route exact path="settings" element={<PartnerSettings />} />
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
padding-right: 54px;
|
padding-right: 54px;
|
||||||
padding-top: 48px;
|
padding-top: 48px;
|
||||||
padding-bottom: 40px;
|
padding-bottom: 40px;
|
||||||
font-family: 'LabGrotesque', sans-serif;
|
font-family: "LabGrotesque", sans-serif;
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -56,7 +56,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
|
|
||||||
font-size: 2.5em;
|
font-size: 2.5em;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@ -133,6 +132,8 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
margin-bottom: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__form {
|
&__form {
|
||||||
@ -142,8 +143,8 @@
|
|||||||
|
|
||||||
button {
|
button {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
//width: 125px;
|
width: 125px;
|
||||||
//height: 42px;
|
height: 42px;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
box-shadow: 0 0 59px rgba(44, 44, 44, 0.05);
|
box-shadow: 0 0 59px rgba(44, 44, 44, 0.05);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
@ -158,18 +159,21 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: flex;
|
color: black;
|
||||||
align-items: center;
|
}
|
||||||
justify-content: center;
|
|
||||||
width: 115px;
|
|
||||||
height: 42px;
|
|
||||||
text-decoration: none;
|
|
||||||
color: #000000;
|
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
margin: 0 10px 0 0;
|
margin: 0 10px 0 0;
|
||||||
|
|
||||||
|
@media (max-width: 968px) {
|
||||||
|
margin-right: 2px;
|
||||||
|
|
||||||
|
@media (max-width: 610px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1200px) {
|
@media (max-width: 1200px) {
|
||||||
@ -182,15 +186,7 @@
|
|||||||
height: 40px;
|
height: 40px;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
|
|
||||||
img {
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 610px) {
|
@media (max-width: 610px) {
|
||||||
img {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,23 @@
|
|||||||
import moment from 'moment';
|
import moment from "moment";
|
||||||
import 'moment/locale/ru';
|
import "moment/locale/ru";
|
||||||
|
|
||||||
export function calendarHelper(value) {
|
export function calendarHelper(value) {
|
||||||
const startDay = value.clone().startOf('month').startOf('week').startOf('day');
|
const startDay = value
|
||||||
const endDay = value.clone().endOf('month').endOf('week');
|
.clone()
|
||||||
|
.startOf("month")
|
||||||
|
.startOf("week")
|
||||||
|
.startOf("day");
|
||||||
|
const endDay = value.clone().endOf("month").endOf("week");
|
||||||
|
|
||||||
const day = startDay.clone().subtract(1, 'day');
|
const day = startDay.clone().subtract(1, "day");
|
||||||
|
|
||||||
const calendar = [];
|
const calendar = [];
|
||||||
|
|
||||||
while (day.isBefore(endDay, 'day')) {
|
while (day.isBefore(endDay, "day")) {
|
||||||
calendar.push(
|
calendar.push(
|
||||||
Array(1)
|
Array(1)
|
||||||
.fill(0)
|
.fill(0)
|
||||||
.map(() => day.add(1, 'day').clone())
|
.map(() => day.add(1, "day").clone())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,48 +25,84 @@ export function calendarHelper(value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getReports(value) {
|
export function getReports(value) {
|
||||||
const startDay = value.clone().startOf('month').startOf('week').startOf('day');
|
const startDay = value
|
||||||
const reportsStart = `${new Date(startDay).getFullYear()}-${new Date(startDay).getMonth() + 1}-${new Date(startDay).getDate()}`
|
.clone()
|
||||||
const endDay = value.clone().endOf('month').endOf('week');
|
.startOf("month")
|
||||||
const reportsEnd = `${new Date(endDay).getFullYear()}-${new Date(endDay).getMonth() + 1}-${new Date(endDay).getDate()}`
|
.startOf("week")
|
||||||
const getReports = `fromDate=${reportsStart}&toDate=${reportsEnd}`
|
.startOf("day");
|
||||||
|
const reportsStart = `${new Date(startDay).getFullYear()}-${
|
||||||
|
new Date(startDay).getMonth() + 1
|
||||||
|
}-${new Date(startDay).getDate()}`;
|
||||||
|
const endDay = value.clone().endOf("month").endOf("week");
|
||||||
|
const reportsEnd = `${new Date(endDay).getFullYear()}-${
|
||||||
|
new Date(endDay).getMonth() + 1
|
||||||
|
}-${new Date(endDay).getDate()}`;
|
||||||
|
const getReports = `fromDate=${reportsStart}&toDate=${reportsEnd}`;
|
||||||
|
|
||||||
return getReports;
|
return getReports;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCreatedDate(day) {
|
export function getCreatedDate(day) {
|
||||||
if (day) {
|
if (day) {
|
||||||
return `${new Date(day).getFullYear()}-${new Date(day).getMonth() + 1}-${new Date(day).getDate()}`
|
return `${new Date(day).getFullYear()}-${correctDay(
|
||||||
|
new Date(day).getMonth() + 1
|
||||||
|
)}-${correctDay(new Date(day).getDate())}`;
|
||||||
} else {
|
} else {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
const dd = String(date.getDate()).padStart(2, '0');
|
const dd = String(date.getDate()).padStart(2, "0");
|
||||||
const mm = String(date.getMonth() + 1).padStart(2, '0');
|
const mm = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
const yyyy = date.getFullYear();
|
const yyyy = date.getFullYear();
|
||||||
return `${yyyy}-${mm}-${dd}`
|
return `${yyyy}-${mm}-${dd}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function correctDay(day) {
|
||||||
|
if (day < 10) {
|
||||||
|
return `0${day}`;
|
||||||
|
}
|
||||||
|
return day;
|
||||||
|
}
|
||||||
|
|
||||||
export function currentMonth() {
|
export function currentMonth() {
|
||||||
const currentMonth = moment().format('MMMM');
|
const currentMonth = moment().format("MMMM");
|
||||||
|
|
||||||
return currentMonth.charAt(0).toUpperCase() + currentMonth.slice(1);
|
return currentMonth.charAt(0).toUpperCase() + currentMonth.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function currentMonthAndDay(day) {
|
export function currentMonthAndDay(day) {
|
||||||
return day.format('D MMMM');
|
return day.format("D MMMM");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCorrectDate(day) {
|
export function getCorrectDate(day) {
|
||||||
const months = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря']
|
const months = [
|
||||||
return `${new Date(day).getDate()} ${months[new Date(day).getMonth()]} ${new Date(day).getFullYear()} года`
|
"января",
|
||||||
};
|
"февраля",
|
||||||
|
"марта",
|
||||||
|
"апреля",
|
||||||
|
"мая",
|
||||||
|
"июня",
|
||||||
|
"июля",
|
||||||
|
"августа",
|
||||||
|
"сентября",
|
||||||
|
"октября",
|
||||||
|
"ноября",
|
||||||
|
"декабря",
|
||||||
|
];
|
||||||
|
return `${new Date(day).getDate()} ${
|
||||||
|
months[new Date(day).getMonth()]
|
||||||
|
} ${new Date(day).getFullYear()} года`;
|
||||||
|
}
|
||||||
|
|
||||||
export function currentMonthAndDayReportPage() {
|
export function currentMonthAndDayReportPage() {
|
||||||
return moment().format('D MMMM');
|
return moment().format("D MMMM");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hourOfNum(number) {
|
export function hourOfNum(number) {
|
||||||
const hours = [' час', ' часа', ' часов'];
|
const hours = [" час", " часа", " часов"];
|
||||||
const cases = [2, 0, 1, 1, 1, 2];
|
const cases = [2, 0, 1, 1, 1, 2];
|
||||||
return hours[(number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5]];
|
return hours[
|
||||||
|
number % 100 > 4 && number % 100 < 20
|
||||||
|
? 2
|
||||||
|
: cases[number % 10 < 5 ? number % 10 : 5]
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -1,99 +1,127 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from "react";
|
||||||
import {useDispatch, useSelector} from 'react-redux'
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
import {getReports} from '../Calendar/calendarHelper'
|
import { getReports } from "../Calendar/calendarHelper";
|
||||||
import {Link, Navigate} from 'react-router-dom'
|
import { Link, Navigate } from "react-router-dom";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
|
||||||
import {ProfileCalendarComponent} from "./ProfileCalendarComponent";
|
import { ProfileCalendarComponent } from "./ProfileCalendarComponent";
|
||||||
import {Loader} from "../Loader/Loader";
|
import { Loader } from "../Loader/Loader";
|
||||||
import {ProfileHeader} from "../ProfileHeader/ProfileHeader";
|
import { ProfileHeader } from "../ProfileHeader/ProfileHeader";
|
||||||
import {ProfileBreadcrumbs} from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs"
|
import { ProfileBreadcrumbs } from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs";
|
||||||
import { Footer } from '../Footer/Footer'
|
import { Footer } from "../Footer/Footer";
|
||||||
|
import { Navigation } from "../Navigation/Navigation";
|
||||||
|
import { ViewReport } from "../../pages/ViewReport/ViewReport";
|
||||||
|
|
||||||
import {urlForLocal} from "../../helper";
|
import { urlForLocal } from "../../helper";
|
||||||
|
|
||||||
import {apiRequest} from "../../api/request";
|
import { apiRequest } from "../../api/request";
|
||||||
import { getProfileInfo } from '../../redux/outstaffingSlice'
|
import { getProfileInfo } from "../../redux/outstaffingSlice";
|
||||||
import {getRequestDates, setReportDate, setRequestDate} from "../../redux/reportSlice";
|
import {
|
||||||
|
getRequestDates,
|
||||||
import 'moment/locale/ru'
|
setReportDate,
|
||||||
import './profileCalendar.scss'
|
setRequestDate,
|
||||||
import { Navigation } from '../Navigation/Navigation';
|
} from "../../redux/reportSlice";
|
||||||
|
|
||||||
|
import "moment/locale/ru";
|
||||||
|
import "./profileCalendar.scss";
|
||||||
|
|
||||||
export const ProfileCalendar = () => {
|
export const ProfileCalendar = () => {
|
||||||
if(localStorage.getItem('role_status') === '18') {
|
if (localStorage.getItem("role_status") === "18") {
|
||||||
return <Navigate to="/profile" replace/>
|
return <Navigate to="/profile" replace />;
|
||||||
}
|
}
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const profileInfo = useSelector(getProfileInfo)
|
const profileInfo = useSelector(getProfileInfo);
|
||||||
const requestDates = useSelector(getRequestDates)
|
const requestDates = useSelector(getRequestDates);
|
||||||
const [value, setValue] = useState(moment())
|
const [value, setValue] = useState(moment());
|
||||||
const [reports, setReports] = useState([]);
|
const [reports, setReports] = useState([]);
|
||||||
const [totalHours, setTotalHours] = useState(0);
|
const [totalHours, setTotalHours] = useState(0);
|
||||||
const [loader, setLoader] = useState(true)
|
const [loader, setLoader] = useState(true);
|
||||||
|
|
||||||
function setValueHandler (value) {
|
function setValueHandler(value) {
|
||||||
setValue(value)
|
setValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(setRequestDate(getReports(moment())))
|
dispatch(setRequestDate(getReports(moment())));
|
||||||
},[]);
|
}, []);
|
||||||
|
|
||||||
useEffect( () => {
|
useEffect(() => {
|
||||||
setLoader(true)
|
setLoader(true);
|
||||||
if (!requestDates) {
|
if (!requestDates) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
apiRequest(`/reports/reports-by-date?${requestDates}&user_card_id=${localStorage.getItem('cardId')}`)
|
apiRequest(
|
||||||
.then((reports) => {
|
`/reports/reports-by-date?${requestDates}&user_card_id=${localStorage.getItem(
|
||||||
|
"cardId"
|
||||||
|
)}`
|
||||||
|
).then((reports) => {
|
||||||
let spendTime = 0;
|
let spendTime = 0;
|
||||||
for (const report of reports) {
|
for (const report of reports) {
|
||||||
report.task.map((task) => {
|
report.task.map((task) => {
|
||||||
if(task.hours_spent) {
|
if (task.hours_spent) {
|
||||||
spendTime += Number(task.hours_spent)
|
spendTime += Number(task.hours_spent);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
setTotalHours(spendTime);
|
setTotalHours(spendTime);
|
||||||
setReports(reports)
|
setReports(reports);
|
||||||
setLoader(false)
|
setLoader(false);
|
||||||
})
|
});
|
||||||
}, [requestDates]);
|
}, [requestDates]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='profile__calendar'>
|
<div className="profile__calendar">
|
||||||
<ProfileHeader/>
|
<ProfileHeader />
|
||||||
<Navigation />
|
<Navigation />
|
||||||
<div className='container'>
|
<div className="container">
|
||||||
<ProfileBreadcrumbs links={[{name: 'Главная', link: '/profile'},{name: 'Ваша отчетность', link: '/profile/calendar'}]} />
|
<ProfileBreadcrumbs
|
||||||
<h2 className='summary__title'>Ваши отчеты</h2>
|
links={[
|
||||||
<div className='summary__info'>
|
{ name: "Главная", link: "/profile" },
|
||||||
<div className='summary__person'>
|
{ name: "Ваша отчетность", link: "/profile/calendar" },
|
||||||
<img src={urlForLocal(profileInfo.photo)} className='summary__avatar' alt='avatar'/>
|
]}
|
||||||
<p className='summary__name'>{profileInfo.fio}, {profileInfo.specification} разработчик</p>
|
/>
|
||||||
|
<h2 className="summary__title">Ваши отчеты</h2>
|
||||||
|
<div className="summary__info">
|
||||||
|
<div className="summary__person">
|
||||||
|
<img
|
||||||
|
src={urlForLocal(profileInfo.photo)}
|
||||||
|
className="summary__avatar"
|
||||||
|
alt="avatar"
|
||||||
|
/>
|
||||||
|
<p className="summary__name">
|
||||||
|
{profileInfo.fio}, {profileInfo.specification} разработчик
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Link to='/report'>
|
<Link to="/report">
|
||||||
<button className="calendar__btn" onClick={() => {
|
<button
|
||||||
dispatch(setReportDate(''))
|
className="calendar__btn"
|
||||||
}}>Заполнить отчет за день</button>
|
onClick={() => {
|
||||||
|
dispatch(setReportDate(""));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Заполнить отчет за день
|
||||||
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
{loader ?
|
{loader ? (
|
||||||
<div className='loader__wrapper'>
|
<div className="loader__wrapper">
|
||||||
<Loader height={80} width={80} />
|
<Loader height={80} width={80} />
|
||||||
</div>
|
</div>
|
||||||
:
|
) : (
|
||||||
<div className='row calendar__wrapper'>
|
<div className="row calendar__wrapper">
|
||||||
<div className='col-12 col-xl-12'>
|
<div className="col-12 col-xl-12">
|
||||||
<ProfileCalendarComponent setValueHandler={setValueHandler} value={value} reports={reports} totalHours={totalHours} />
|
<ProfileCalendarComponent
|
||||||
|
setValueHandler={setValueHandler}
|
||||||
|
value={value}
|
||||||
|
reports={reports}
|
||||||
|
totalHours={totalHours}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,109 +1,135 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from "react";
|
||||||
import arrow from '../../images/arrowCalendar.png'
|
import arrow from "../../images/arrowCalendar.png";
|
||||||
import rectangle from '../../images/rectangle__calendar.png'
|
import rectangle from "../../images/rectangle__calendar.png";
|
||||||
import calendarIcon from '../../images/calendar_icon.png'
|
import calendarIcon from "../../images/calendar_icon.png";
|
||||||
import moment from 'moment'
|
import moment from "moment";
|
||||||
import {calendarHelper, currentMonthAndDay, getReports, hourOfNum} from '../Calendar/calendarHelper'
|
import {
|
||||||
import {setReportDate, setRequestDate} from '../../redux/reportSlice';
|
calendarHelper,
|
||||||
import {useDispatch} from "react-redux";
|
currentMonthAndDay,
|
||||||
import {Link} from "react-router-dom";
|
getReports,
|
||||||
|
hourOfNum,
|
||||||
|
} from "../Calendar/calendarHelper";
|
||||||
|
import {
|
||||||
|
setReportDate,
|
||||||
|
setRequestDate,
|
||||||
|
setSendRequest,
|
||||||
|
} from "../../redux/reportSlice";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import ShortReport from "../ShortReport/ShortReport";
|
||||||
|
|
||||||
import 'moment/locale/ru'
|
import "moment/locale/ru";
|
||||||
import './../Calendar/calendarComponent.scss'
|
import "./../Calendar/calendarComponent.scss";
|
||||||
|
|
||||||
export const ProfileCalendarComponent = React.memo(({value, setValueHandler, reports, totalHours}) => {
|
export const ProfileCalendarComponent = React.memo(
|
||||||
|
({ value, setValueHandler, reports, totalHours }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [currentDay] = useState(moment())
|
|
||||||
const [calendar, setCalendar] = useState([])
|
const [currentDay] = useState(moment());
|
||||||
const [month, setMonth] = useState('');
|
const [calendar, setCalendar] = useState([]);
|
||||||
|
const [month, setMonth] = useState("");
|
||||||
|
const [shortReport, setShortReport] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCalendar(calendarHelper(value))
|
setCalendar(calendarHelper(value));
|
||||||
}, [value])
|
}, [value]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMonth(value.format('MMMM'))
|
setMonth(value.format("MMMM"));
|
||||||
}, [month]);
|
}, [month]);
|
||||||
|
|
||||||
function isToday(day) {
|
function isToday(day) {
|
||||||
return day.isSame(new Date(), 'day')
|
return day.isSame(new Date(), "day");
|
||||||
}
|
}
|
||||||
|
|
||||||
function correctDay(day) {
|
function correctDay(day) {
|
||||||
if (day < 10) {
|
if (day < 10) {
|
||||||
return `0${day}`
|
return `0${day}`;
|
||||||
} return day
|
}
|
||||||
|
return day;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dayStyles(day) {
|
function dayStyles(day) {
|
||||||
if (currentDay < day) return `block`
|
if (currentDay < day) return `block`;
|
||||||
for (const date of reports) {
|
for (const date of reports) {
|
||||||
if (`${new Date(day).getFullYear()}-${correctDay(new Date(day).getMonth() + 1)}-${correctDay(new Date(day).getDate())}` === date.created_at) {
|
if (
|
||||||
return `before`
|
`${new Date(day).getFullYear()}-${correctDay(
|
||||||
|
new Date(day).getMonth() + 1
|
||||||
|
)}-${correctDay(new Date(day).getDate())}` === date.created_at
|
||||||
|
) {
|
||||||
|
return `before`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (day.day() === 6 || day.day() === 0) return `selected`
|
if (day.day() === 6 || day.day() === 0) return `selected`;
|
||||||
if (isToday(day)) return `today`
|
if (isToday(day)) return `today`;
|
||||||
return 'pass'
|
return "pass";
|
||||||
}
|
}
|
||||||
|
|
||||||
function correctRoute(day) {
|
function correctRoute(day) {
|
||||||
for (const date of reports) {
|
for (const date of reports) {
|
||||||
if (`${new Date(day).getFullYear()}-${correctDay(new Date(day).getMonth() + 1)}-${correctDay(new Date(day).getDate())}` === date.created_at) {
|
if (
|
||||||
return `../view`
|
`${new Date(day).getFullYear()}-${correctDay(
|
||||||
|
new Date(day).getMonth() + 1
|
||||||
|
)}-${correctDay(new Date(day).getDate())}` === date.created_at
|
||||||
|
) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return '../../report'
|
return "../../report";
|
||||||
}
|
}
|
||||||
|
|
||||||
function prevMonth() {
|
function prevMonth() {
|
||||||
return value.clone().subtract(1, 'month')
|
return value.clone().subtract(1, "month");
|
||||||
}
|
}
|
||||||
|
|
||||||
function nextMonth() {
|
function nextMonth() {
|
||||||
return value.clone().add(1, 'month');
|
return value.clone().add(1, "month");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='calendar-component'>
|
<div className="calendar-component">
|
||||||
<div className='calendar-component__header'>
|
<div className="calendar-component__header">
|
||||||
<div className='calendar-component__header-info'>
|
<div className="calendar-component__header-info">
|
||||||
<h3>Мои отчеты:</h3>
|
<h3>Мои отчеты:</h3>
|
||||||
<p className='calendar__hours'>
|
<p className="calendar__hours">
|
||||||
{month} <span>{totalHours} {hourOfNum(totalHours)} </span>
|
{month}
|
||||||
|
<span>
|
||||||
|
{totalHours} {hourOfNum(totalHours)}{" "}
|
||||||
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='calendar-component__header-switcher'>
|
<div className="calendar-component__header-switcher">
|
||||||
<div className='calendar-component__header-box' onClick={() => {
|
<div
|
||||||
setValueHandler(prevMonth())
|
className="calendar-component__header-box"
|
||||||
dispatch(setRequestDate(getReports(prevMonth())))
|
onClick={() => {
|
||||||
}}>
|
setValueHandler(prevMonth());
|
||||||
<img src={arrow} alt='' />
|
dispatch(setRequestDate(getReports(prevMonth())));
|
||||||
<span>
|
}}
|
||||||
{prevMonth().format('MMMM')}
|
>
|
||||||
</span>
|
<img src={arrow} alt="" />
|
||||||
|
<span>{prevMonth().format("MMMM")}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className='calendar-component__header-box'>
|
<div className="calendar-component__header-box">
|
||||||
<span>{value.format('YYYY')}</span>
|
<span>{value.format("YYYY")}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className='calendar-component__header-box' onClick={() => {
|
<div
|
||||||
setValueHandler(nextMonth())
|
className="calendar-component__header-box"
|
||||||
dispatch(setRequestDate(getReports(nextMonth())))
|
onClick={() => {
|
||||||
|
setValueHandler(nextMonth());
|
||||||
}}>
|
dispatch(setRequestDate(getReports(nextMonth())));
|
||||||
<span>
|
}}
|
||||||
{nextMonth().format('MMMM')}
|
>
|
||||||
</span>
|
<span>{nextMonth().format("MMMM")}</span>
|
||||||
<img src={arrow} alt='' />
|
<img src={arrow} alt="" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='calendar-component__rectangle'>
|
<div className="calendar-component__rectangle">
|
||||||
<img src={rectangle} alt='' />
|
<img src={rectangle} alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='calendar-component__body'>
|
<div className="calendar-component__body">
|
||||||
<div>
|
<div>
|
||||||
<p>Пн</p>
|
<p>Пн</p>
|
||||||
<p>Вт</p>
|
<p>Вт</p>
|
||||||
@ -114,20 +140,26 @@ export const ProfileCalendarComponent = React.memo(({value, setValueHandler, rep
|
|||||||
<p>Вс</p>
|
<p>Вс</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='calendar-component__form'>
|
<div className="calendar-component__form">
|
||||||
{calendar.map((week) =>
|
{calendar.map((week) =>
|
||||||
week.map((day) => (
|
week.map((day) => (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
dispatch(setReportDate(day))
|
dispatch(setReportDate(day));
|
||||||
|
setShortReport(true);
|
||||||
|
dispatch(setSendRequest(true));
|
||||||
}}
|
}}
|
||||||
key={day}
|
key={day}
|
||||||
className={dayStyles(day)}
|
className={dayStyles(day)}
|
||||||
name={day.format('dddd')}
|
name={day.format("dddd")}
|
||||||
id='btn'
|
id="btn"
|
||||||
>
|
>
|
||||||
<Link to={correctRoute(day)}>
|
<Link to={correctRoute(day)}>
|
||||||
<img className={'calendar__icon'} src={calendarIcon} alt='' />
|
<img
|
||||||
|
className={"calendar__icon"}
|
||||||
|
src={calendarIcon}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
{currentMonthAndDay(day)}
|
{currentMonthAndDay(day)}
|
||||||
</Link>
|
</Link>
|
||||||
</button>
|
</button>
|
||||||
@ -135,7 +167,9 @@ export const ProfileCalendarComponent = React.memo(({value, setValueHandler, rep
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
{shortReport && <ShortReport />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.profile__calendar {
|
.profile__calendar {
|
||||||
background: #F1F1F1;
|
background: #f1f1f1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
font-family: "LabGrotesque", sans-serif;
|
font-family: "LabGrotesque", sans-serif;
|
||||||
@ -32,7 +32,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.calendar__wrapper {
|
.calendar__wrapper {
|
||||||
min-height: 719px;
|
min-height: 719px;
|
||||||
|
|
||||||
|
176
src/components/ShortReport/ShortReport.jsx
Normal file
176
src/components/ShortReport/ShortReport.jsx
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
import { apiRequest } from "../../api/request";
|
||||||
|
import {
|
||||||
|
getCorrectDate,
|
||||||
|
getCreatedDate,
|
||||||
|
hourOfNum,
|
||||||
|
} from "../../components/Calendar/calendarHelper";
|
||||||
|
import {
|
||||||
|
getReportDate,
|
||||||
|
getSendRequest,
|
||||||
|
setSendRequest,
|
||||||
|
} from "../../redux/reportSlice";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { Loader } from "../Loader/Loader";
|
||||||
|
|
||||||
|
import "./shortReport.scss";
|
||||||
|
|
||||||
|
export const ShortReport = ({}) => {
|
||||||
|
const reportDate = useSelector(getReportDate);
|
||||||
|
|
||||||
|
const sendReport = useSelector(getSendRequest);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const [taskText, setTaskText] = useState([]);
|
||||||
|
const [difficulties, setDifficulties] = useState([]);
|
||||||
|
const [tomorrowTask, setTomorrowTask] = useState([]);
|
||||||
|
const [totalHours, setTotalHours] = useState(0);
|
||||||
|
const [loader, setLoader] = useState(false);
|
||||||
|
const [dateCreate, setDateCreate] = useState("");
|
||||||
|
|
||||||
|
function getReportFromDate(day) {
|
||||||
|
setLoader(true);
|
||||||
|
setTaskText([]);
|
||||||
|
setDifficulties([]);
|
||||||
|
setTomorrowTask([]);
|
||||||
|
setTotalHours(0);
|
||||||
|
apiRequest(
|
||||||
|
`reports/find-by-date?user_card_id=${localStorage.getItem(
|
||||||
|
"cardId"
|
||||||
|
)}&date=${day}`
|
||||||
|
).then((res) => {
|
||||||
|
let spendTime = 0;
|
||||||
|
for (const item of res) {
|
||||||
|
setDateCreate(item.created_at);
|
||||||
|
if (item.difficulties) {
|
||||||
|
setDifficulties((prevArray) => [...prevArray, item.difficulties]);
|
||||||
|
}
|
||||||
|
if (item.tomorrow) {
|
||||||
|
setTomorrowTask((prevArray) => [...prevArray, item.tomorrow]);
|
||||||
|
}
|
||||||
|
item.task.map((task) => {
|
||||||
|
const taskInfo = {
|
||||||
|
hours: task.hours_spent,
|
||||||
|
task: task.task,
|
||||||
|
id: task.id,
|
||||||
|
};
|
||||||
|
if (task.hours_spent) {
|
||||||
|
spendTime += Number(task.hours_spent);
|
||||||
|
}
|
||||||
|
setTaskText((prevArray) => [...prevArray, taskInfo]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setTotalHours(spendTime);
|
||||||
|
setLoader(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sendReport) {
|
||||||
|
dispatch(setSendRequest(false));
|
||||||
|
getReportFromDate(getCreatedDate(reportDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="viewReport__info short-report">
|
||||||
|
<div className="viewReport__title-box">
|
||||||
|
<h2 className="viewReport__title">
|
||||||
|
Ваши отчеты - <span>просмотр отчета за день</span>
|
||||||
|
</h2>
|
||||||
|
<Link to={`../view/${dateCreate}`}>
|
||||||
|
Посмотреть подробнее об отчете
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="viewReport__bar">
|
||||||
|
<h3 className="viewReport__bar__date">
|
||||||
|
{getCorrectDate(reportDate)}
|
||||||
|
</h3>
|
||||||
|
<p className="viewReport__bar__hours">
|
||||||
|
Вами потрачено на работу :{" "}
|
||||||
|
<span>
|
||||||
|
{totalHours} {hourOfNum(totalHours)}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{loader && <Loader style="green" />}
|
||||||
|
{Boolean(taskText.length) && (
|
||||||
|
<div className="viewReport__content">
|
||||||
|
<div className="table__container">
|
||||||
|
<table className="viewReport__done">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<p>Какие задачи были выполнены?</p>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<p>Время</p>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{taskText.length &&
|
||||||
|
taskText.map((task, index) => {
|
||||||
|
return (
|
||||||
|
<tr key={task.id}>
|
||||||
|
<td>
|
||||||
|
<p>
|
||||||
|
{index + 1}. {task.task}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div className="viewReport__done__hours__item">
|
||||||
|
<span>{task.hours}</span>
|
||||||
|
<p className="hours">
|
||||||
|
{hourOfNum(task.hours)} на задачу
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>
|
||||||
|
<span>
|
||||||
|
Всего: {totalHours} {hourOfNum(totalHours)}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{Boolean(difficulties.length) && (
|
||||||
|
<div className="viewReport__item">
|
||||||
|
<h3>Какие сложности возникли?</h3>
|
||||||
|
{difficulties.map((item, index) => {
|
||||||
|
return <p key={index}>{item}</p>;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{Boolean(tomorrowTask.length) && (
|
||||||
|
<div className="viewReport__item">
|
||||||
|
<h3>Что планируется сделать завтра?</h3>
|
||||||
|
{tomorrowTask.map((item, index) => {
|
||||||
|
return <p key={index}>{item}</p>;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!Boolean(taskText.length) && !loader && (
|
||||||
|
<div className="viewReport__noTask">
|
||||||
|
<p>
|
||||||
|
В этот день вы <span>не заполняли</span> отчет
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ShortReport;
|
15
src/components/ShortReport/shortReport.scss
Normal file
15
src/components/ShortReport/shortReport.scss
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
.short-report {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewReport {
|
||||||
|
&__title-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,175 +0,0 @@
|
|||||||
import React, {useEffect, useState} from 'react'
|
|
||||||
import {Link, Navigate} from "react-router-dom";
|
|
||||||
|
|
||||||
import {useSelector} from "react-redux";
|
|
||||||
import {getReportDate} from "../../redux/reportSlice";
|
|
||||||
|
|
||||||
import {Loader} from "../../components/Loader/Loader"
|
|
||||||
import {ProfileHeader} from "../../components/ProfileHeader/ProfileHeader";
|
|
||||||
import {ProfileBreadcrumbs} from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs"
|
|
||||||
import {Footer} from "../../components/Footer/Footer";
|
|
||||||
|
|
||||||
import {apiRequest} from "../../api/request";
|
|
||||||
import {getCorrectDate, getCreatedDate, hourOfNum} from '../../components/Calendar/calendarHelper'
|
|
||||||
|
|
||||||
import arrow from "../../images/right-arrow.png";
|
|
||||||
import arrowSwitchDate from "../../images/arrowViewReport.png";
|
|
||||||
|
|
||||||
import './viewReport.scss'
|
|
||||||
import { Navigation } from '../../components/Navigation/Navigation';
|
|
||||||
|
|
||||||
export const ViewReport = () => {
|
|
||||||
if(localStorage.getItem('role_status') === '18') {
|
|
||||||
return <Navigate to="/profile" replace/>
|
|
||||||
}
|
|
||||||
const reportDate = useSelector(getReportDate);
|
|
||||||
|
|
||||||
const [taskText, setTaskText] = useState([]);
|
|
||||||
const [difficulties, setDifficulties] = useState([]);
|
|
||||||
const [tomorrowTask, setTomorrowTask] = useState([]);
|
|
||||||
const [totalHours, setTotalHours] = useState(0);
|
|
||||||
const [reportDay] = useState(new Date (getCreatedDate(reportDate)));
|
|
||||||
const [currentDay] = useState(new Date ());
|
|
||||||
const [loader, setLoader] = useState(false);
|
|
||||||
|
|
||||||
function getReportFromDate(day) {
|
|
||||||
setLoader(true);
|
|
||||||
setTaskText([]);
|
|
||||||
setDifficulties([]);
|
|
||||||
setTomorrowTask([]);
|
|
||||||
apiRequest(`reports/find-by-date?user_card_id=${localStorage.getItem('cardId')}&date=${day}`)
|
|
||||||
.then(res => {
|
|
||||||
let spendTime = 0;
|
|
||||||
for (const item of res) {
|
|
||||||
if(item.difficulties) {
|
|
||||||
setDifficulties(prevArray => [...prevArray, item.difficulties])
|
|
||||||
}
|
|
||||||
if(item.tomorrow) {
|
|
||||||
setTomorrowTask(prevArray => [...prevArray, item.tomorrow])
|
|
||||||
}
|
|
||||||
item.task.map((task) => {
|
|
||||||
const taskInfo = {
|
|
||||||
hours: task.hours_spent,
|
|
||||||
task: task.task,
|
|
||||||
id: task.id
|
|
||||||
};
|
|
||||||
if(task.hours_spent) {
|
|
||||||
spendTime += Number(task.hours_spent)
|
|
||||||
}
|
|
||||||
setTaskText(prevArray => [...prevArray, taskInfo])
|
|
||||||
})
|
|
||||||
}
|
|
||||||
setTotalHours(spendTime);
|
|
||||||
setLoader(false)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function nextDay() {
|
|
||||||
reportDay.setDate(reportDay.getDate() + 1);
|
|
||||||
getReportFromDate(getCreatedDate(reportDay))
|
|
||||||
}
|
|
||||||
|
|
||||||
function previousDay() {
|
|
||||||
reportDay.setDate(reportDay.getDate() - 1);
|
|
||||||
getReportFromDate(getCreatedDate(reportDay))
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getReportFromDate(getCreatedDate(reportDate))
|
|
||||||
}, []);
|
|
||||||
return (
|
|
||||||
<div className='viewReport'>
|
|
||||||
<ProfileHeader/>
|
|
||||||
<Navigation />
|
|
||||||
<div className='container'>
|
|
||||||
<div className='viewReport__info'>
|
|
||||||
<ProfileBreadcrumbs links={[{name: 'Главная', link: '/profile'},
|
|
||||||
{name: 'Ваша отчетность', link: '/profile/calendar'},
|
|
||||||
{name: 'Просмотр отчета за день', link: '/profile/view'}]}
|
|
||||||
/>
|
|
||||||
<h2 className='viewReport__title'>Ваши отчеты - <span>просмотр отчета за день</span></h2>
|
|
||||||
<Link className='viewReport__back' to={`/profile/calendar`}>
|
|
||||||
<img src={arrow} alt='arrow'/><p>Вернуться</p>
|
|
||||||
</Link>
|
|
||||||
<div className='viewReport__bar'>
|
|
||||||
<h3 className='viewReport__bar__date'>{getCorrectDate(reportDay)}</h3>
|
|
||||||
<p className='viewReport__bar__hours'>Вами потрачено на работу : <span>{totalHours} {hourOfNum(totalHours)}</span></p>
|
|
||||||
{/*<div className='viewReport__bar__progressBar'>*/}
|
|
||||||
{/* <span></span>*/}
|
|
||||||
{/*</div>*/}
|
|
||||||
{/*<p className='viewReport__bar__total'>122 часа из 160</p>*/}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='viewReport__switchDate'>
|
|
||||||
<div className='viewReport__switchDate__prev switchDate' onClick={() => previousDay()}>
|
|
||||||
<img src={arrowSwitchDate} alt='arrow'/>
|
|
||||||
</div>
|
|
||||||
<p>{getCorrectDate(reportDay)}</p>
|
|
||||||
<div className={`viewReport__switchDate__next switchDate ${getCreatedDate(currentDay) === getCreatedDate(reportDay) ? 'disable' : ''}`} onClick={() => nextDay()}>
|
|
||||||
<img src={arrowSwitchDate} alt='arrow'/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{loader &&
|
|
||||||
<Loader width={75} height={75}/>
|
|
||||||
}
|
|
||||||
{Boolean(taskText.length) &&
|
|
||||||
<div className='viewReport__content'>
|
|
||||||
<div className='table__container'>
|
|
||||||
<table className='viewReport__done'>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th><p>Какие задачи были выполнены?</p></th>
|
|
||||||
<th><p>Время</p></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{taskText.length && taskText.map((task, index) => {
|
|
||||||
return <tr key={task.id}>
|
|
||||||
<td>
|
|
||||||
<p>{index + 1}. {task.task}</p>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div className='viewReport__done__hours__item'>
|
|
||||||
<span>{task.hours}</span>
|
|
||||||
<p className='hours'>{hourOfNum(task.hours)} на задачу</p>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
})}
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td><span>Всего: {totalHours} {hourOfNum(totalHours)}</span></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{Boolean(difficulties.length) &&
|
|
||||||
<div className='viewReport__item'>
|
|
||||||
<h3>Какие сложности возникли?</h3>
|
|
||||||
{difficulties.map((item, index) => {
|
|
||||||
return <p key={index}>{item}</p>
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{Boolean(tomorrowTask.length) &&
|
|
||||||
<div className='viewReport__item'>
|
|
||||||
<h3>Что планируется сделать завтра?</h3>
|
|
||||||
{tomorrowTask.map((item, index) => {
|
|
||||||
return <p key={index}>{item}</p>
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{!Boolean(taskText.length) && !loader &&
|
|
||||||
<div className='viewReport__noTask'>
|
|
||||||
<p>В этот день вы <span>не заполняли</span> отчет</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<Footer />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
};
|
|
225
src/pages/ViewReport/ViewReport.jsx
Normal file
225
src/pages/ViewReport/ViewReport.jsx
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Link, Navigate, useParams } from "react-router-dom";
|
||||||
|
|
||||||
|
import { Loader } from "../../components/Loader/Loader";
|
||||||
|
import { ProfileHeader } from "../../components/ProfileHeader/ProfileHeader";
|
||||||
|
import { ProfileBreadcrumbs } from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs";
|
||||||
|
import { Footer } from "../../components/Footer/Footer";
|
||||||
|
import { Navigation } from "../../components/Navigation/Navigation";
|
||||||
|
|
||||||
|
import { apiRequest } from "../../api/request";
|
||||||
|
import {
|
||||||
|
getCorrectDate,
|
||||||
|
getCreatedDate,
|
||||||
|
hourOfNum,
|
||||||
|
} from "../../components/Calendar/calendarHelper";
|
||||||
|
|
||||||
|
import arrow from "../../images/right-arrow.png";
|
||||||
|
import arrowSwitchDate from "../../images/arrowViewReport.png";
|
||||||
|
|
||||||
|
import "./viewReport.scss";
|
||||||
|
|
||||||
|
export const ViewReport = () => {
|
||||||
|
if (localStorage.getItem("role_status") === "18") {
|
||||||
|
return <Navigate to="/profile" replace />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dateReport = useParams();
|
||||||
|
const [previousReportDay] = useState(new Date(dateReport.id));
|
||||||
|
const [nextReportDay] = useState(new Date(dateReport.id));
|
||||||
|
|
||||||
|
const [taskText, setTaskText] = useState([]);
|
||||||
|
const [difficulties, setDifficulties] = useState([]);
|
||||||
|
const [tomorrowTask, setTomorrowTask] = useState([]);
|
||||||
|
const [totalHours, setTotalHours] = useState(0);
|
||||||
|
const [currentDay] = useState(new Date());
|
||||||
|
const [loader, setLoader] = useState(false);
|
||||||
|
|
||||||
|
function getReportFromDate(day) {
|
||||||
|
setLoader(true);
|
||||||
|
setTaskText([]);
|
||||||
|
setDifficulties([]);
|
||||||
|
setTomorrowTask([]);
|
||||||
|
apiRequest(
|
||||||
|
`reports/find-by-date?user_card_id=${localStorage.getItem(
|
||||||
|
"cardId"
|
||||||
|
)}&date=${day}`
|
||||||
|
).then((res) => {
|
||||||
|
let spendTime = 0;
|
||||||
|
for (const item of res) {
|
||||||
|
if (item.difficulties) {
|
||||||
|
setDifficulties((prevArray) => [...prevArray, item.difficulties]);
|
||||||
|
}
|
||||||
|
if (item.tomorrow) {
|
||||||
|
setTomorrowTask((prevArray) => [...prevArray, item.tomorrow]);
|
||||||
|
}
|
||||||
|
item.task.map((task) => {
|
||||||
|
const taskInfo = {
|
||||||
|
hours: task.hours_spent,
|
||||||
|
task: task.task,
|
||||||
|
id: task.id,
|
||||||
|
};
|
||||||
|
if (task.hours_spent) {
|
||||||
|
spendTime += Number(task.hours_spent);
|
||||||
|
}
|
||||||
|
setTaskText((prevArray) => [...prevArray, taskInfo]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setTotalHours(spendTime);
|
||||||
|
setLoader(false);
|
||||||
|
});
|
||||||
|
previousReportDay.setDate(previousReportDay.getDate() - 1);
|
||||||
|
nextReportDay.setDate(nextReportDay.getDate() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextDay() {
|
||||||
|
getReportFromDate(getCreatedDate(nextReportDay));
|
||||||
|
previousReportDay.setDate(previousReportDay.getDate() + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function previousDay() {
|
||||||
|
getReportFromDate(getCreatedDate(previousReportDay));
|
||||||
|
nextReportDay.setDate(nextReportDay.getDate() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getReportFromDate(dateReport.id);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="viewReport">
|
||||||
|
<ProfileHeader />
|
||||||
|
<Navigation />
|
||||||
|
<div className="container">
|
||||||
|
<div className="viewReport__info">
|
||||||
|
<ProfileBreadcrumbs
|
||||||
|
links={[
|
||||||
|
{ name: "Главная", link: "/profile" },
|
||||||
|
{ name: "Ваша отчетность", link: "/profile/calendar" },
|
||||||
|
{ name: "Просмотр отчета за день", link: "/profile/view" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<h2 className="viewReport__title">
|
||||||
|
Ваши отчеты - <span>просмотр отчета за день</span>
|
||||||
|
</h2>
|
||||||
|
<Link className="viewReport__back" to={`/profile/calendar`}>
|
||||||
|
<img src={arrow} alt="arrow" />
|
||||||
|
<p>Вернуться</p>
|
||||||
|
</Link>
|
||||||
|
<div className="viewReport__bar">
|
||||||
|
<h3 className="viewReport__bar__date">
|
||||||
|
{getCorrectDate(dateReport.id)}
|
||||||
|
</h3>
|
||||||
|
<p className="viewReport__bar__hours">
|
||||||
|
Вами потрачено на работу :{" "}
|
||||||
|
<span>
|
||||||
|
{totalHours} {hourOfNum(totalHours)}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="viewReport__switchDate">
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
previousDay();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Link to={`../view/${getCreatedDate(previousReportDay)}`}>
|
||||||
|
<div className="viewReport__switchDate__prev switchDate">
|
||||||
|
<img src={arrowSwitchDate} alt="arrow" />
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>{getCorrectDate(dateReport.id)}</p>
|
||||||
|
|
||||||
|
<div
|
||||||
|
onClick={() => nextDay()}
|
||||||
|
className={`${
|
||||||
|
getCreatedDate(currentDay) === dateReport.id ? "disable" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<Link to={`../view/${getCreatedDate(nextReportDay)}`}>
|
||||||
|
<div className={`viewReport__switchDate__next switchDate`}>
|
||||||
|
<img src={arrowSwitchDate} alt="arrow" />
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{loader && <Loader width={75} height={75} />}
|
||||||
|
{Boolean(taskText.length) && (
|
||||||
|
<div className="viewReport__content">
|
||||||
|
<div className="table__container">
|
||||||
|
<table className="viewReport__done">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<p>Какие задачи были выполнены?</p>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<p>Время</p>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{taskText.length &&
|
||||||
|
taskText.map((task, index) => {
|
||||||
|
return (
|
||||||
|
<tr key={task.id}>
|
||||||
|
<td>
|
||||||
|
<p>
|
||||||
|
{index + 1}. {task.task}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div className="viewReport__done__hours__item">
|
||||||
|
<span>{task.hours}</span>
|
||||||
|
<p className="hours">
|
||||||
|
{hourOfNum(task.hours)} на задачу
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>
|
||||||
|
<span>
|
||||||
|
Всего: {totalHours} {hourOfNum(totalHours)}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{Boolean(difficulties.length) && (
|
||||||
|
<div className="viewReport__item">
|
||||||
|
<h3>Какие сложности возникли?</h3>
|
||||||
|
{difficulties.map((item, index) => {
|
||||||
|
return <p key={index}>{item}</p>;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{Boolean(tomorrowTask.length) && (
|
||||||
|
<div className="viewReport__item">
|
||||||
|
<h3>Что планируется сделать завтра?</h3>
|
||||||
|
{tomorrowTask.map((item, index) => {
|
||||||
|
return <p key={index}>{item}</p>;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!Boolean(taskText.length) && !loader && (
|
||||||
|
<div className="viewReport__noTask">
|
||||||
|
<p>
|
||||||
|
В этот день вы <span>не заполняли</span> отчет
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -1,13 +1,14 @@
|
|||||||
import { createSlice } from '@reduxjs/toolkit';
|
import { createSlice } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
dateSelected: '',
|
dateSelected: "",
|
||||||
reportDate: '',
|
reportDate: "",
|
||||||
requestDates: ''
|
requestDates: "",
|
||||||
|
sendRequest: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const reportSlice = createSlice({
|
export const reportSlice = createSlice({
|
||||||
name: 'report',
|
name: "report",
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
dateSelected: (state, action) => {
|
dateSelected: (state, action) => {
|
||||||
@ -17,17 +18,23 @@ export const reportSlice = createSlice({
|
|||||||
state.reportDate = action.payload;
|
state.reportDate = action.payload;
|
||||||
},
|
},
|
||||||
setRequestDate: (state, action) => {
|
setRequestDate: (state, action) => {
|
||||||
state.requestDates = action.payload
|
state.requestDates = action.payload;
|
||||||
}
|
},
|
||||||
|
setSendRequest: (state, action) => {
|
||||||
|
state.sendRequest = action.payload;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { dateSelected, setReportDate, setRequestDate} = reportSlice.actions;
|
export const { dateSelected, setReportDate, setRequestDate, setSendRequest } =
|
||||||
|
reportSlice.actions;
|
||||||
|
|
||||||
export const selectDate = (state) => state.report.dateSelected;
|
export const selectDate = (state) => state.report.dateSelected;
|
||||||
|
|
||||||
export const getReportDate = (state) => state.report.reportDate;
|
export const getReportDate = (state) => state.report.reportDate;
|
||||||
|
|
||||||
export const getRequestDates = (state) => state.report.requestDates
|
export const getRequestDates = (state) => state.report.requestDates;
|
||||||
|
|
||||||
|
export const getSendRequest = (state) => state.report.sendRequest;
|
||||||
|
|
||||||
export default reportSlice.reducer;
|
export default reportSlice.reducer;
|
||||||
|
Loading…
Reference in New Issue
Block a user