Merge pull request #54 from apuc/partner-personal-area

Partner personal area
This commit is contained in:
NikoM1k 2023-03-01 22:40:47 +02:00 committed by GitHub
commit bc2288e994
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 198 additions and 66 deletions

View File

@ -11,6 +11,49 @@
&__header { &__header {
display: flex; display: flex;
justify-content: space-between;
@media (max-width: 560px) {
flex-direction: column;
row-gap: 15px;
}
&-info {
display: flex;
@media (max-width: 685px) {
font-size: 7px;
}
@media (max-width: 560px) {
font-size: 10px;
}
@media (max-width: 560px) {
justify-content: center;
}
.calendar__hours {
margin: 0 10px;
line-height: 0;
font-weight: 500;
display: flex;
align-items: center;
}
}
&-switcher {
display: flex;
@media (max-width: 590px) {
font-size: 8px;
}
@media (max-width: 560px) {
justify-content: center;
font-size: 12px;
}
}
h3 { h3 {
@ -20,6 +63,7 @@
letter-spacing: normal; letter-spacing: normal;
line-height: 30px; line-height: 30px;
text-align: left; text-align: left;
margin-bottom: 0;
@media (max-width: 500px) { @media (max-width: 500px) {
font-size: 1.7em; font-size: 1.7em;
@ -58,6 +102,10 @@
font-size: 1.2em; font-size: 1.2em;
} }
} }
@media (max-width: 560px) {
margin-left: 0 !important;
}
} }
} }
@ -183,6 +231,12 @@
} }
} }
@media (max-width: 560px) {
.calendar-component {
padding-top: 10px;
}
}
//@media (max-width: 768px) { //@media (max-width: 768px) {
// .calendar-component__form > button { // .calendar-component__form > button {
// width: 70px; // width: 70px;

View File

@ -60,3 +60,9 @@ export function getCorrectDate(day) {
export function currentMonthAndDayReportPage() { export function currentMonthAndDayReportPage() {
return moment().format('D MMMM'); return moment().format('D MMMM');
} }
export function hourOfNum(number) {
const hours = [' час', ' часа', ' часов'];
const cases = [2, 0, 1, 1, 1, 2];
return hours[(number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5]];
}

View File

@ -80,9 +80,11 @@ export const ProfileCalendar = () => {
</Link> </Link>
</div> </div>
{loader ? {loader ?
<div className='loader__wrapper'>
<Loader height={80} width={80} /> <Loader height={80} width={80} />
</div>
: :
<div className='row'> <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>

View File

@ -3,7 +3,7 @@ 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, currentMonth, currentMonthAndDay, getReports} from '../Calendar/calendarHelper' import {calendarHelper, currentMonthAndDay, getReports, hourOfNum} from '../Calendar/calendarHelper'
import {setReportDate, setRequestDate} from '../../redux/reportSlice'; import {setReportDate, setRequestDate} from '../../redux/reportSlice';
import {useDispatch} from "react-redux"; import {useDispatch} from "react-redux";
import {Link} from "react-router-dom"; import {Link} from "react-router-dom";
@ -67,7 +67,13 @@ export const ProfileCalendarComponent = React.memo(({value, setValueHandler, rep
return ( return (
<div className='calendar-component'> <div className='calendar-component'>
<div className='calendar-component__header'> <div className='calendar-component__header'>
<h3>Мои отчеты</h3> <div className='calendar-component__header-info'>
<h3>Мои отчеты:</h3>
<p className='calendar__hours'>
{month} - <span> {totalHours} {hourOfNum(totalHours)} </span>
</p>
</div>
<div className='calendar-component__header-switcher'>
<div className='calendar-component__header-box' onClick={() => { <div className='calendar-component__header-box' onClick={() => {
setValueHandler(prevMonth()) setValueHandler(prevMonth())
dispatch(setRequestDate(getReports(prevMonth()))) dispatch(setRequestDate(getReports(prevMonth())))
@ -91,6 +97,7 @@ export const ProfileCalendarComponent = React.memo(({value, setValueHandler, rep
<img src={arrow} alt='' /> <img src={arrow} alt='' />
</div> </div>
</div> </div>
</div>
<div className='calendar-component__rectangle'> <div className='calendar-component__rectangle'>
<img src={rectangle} alt='' /> <img src={rectangle} alt='' />
@ -128,9 +135,6 @@ export const ProfileCalendarComponent = React.memo(({value, setValueHandler, rep
)} )}
</div> </div>
</div> </div>
<p className='calendar__hours'>
{month} : <span> {totalHours} часов </span>
</p>
</div> </div>
) )
}) })

View File

@ -21,8 +21,27 @@
} }
} }
.loader__wrapper {
min-height: 719px;
display: flex;
justify-content: center;
align-items: center;
@media (max-width: 1000px) {
min-height: 645px;
}
}
.calendar__wrapper {
min-height: 719px;
@media (max-width: 1000px) {
min-height: auto;
}
}
.loader { .loader {
margin: 20px 0 50px;
&:hover { &:hover {
path { path {
fill: #ffffff; fill: #ffffff;

View File

@ -46,18 +46,26 @@ export const ProfileHeader = () => {
}, },
], ],
partner: [ partner: [
{
path: '/employees',
name: 'Сотрудники'
},
{
path: '',
name: 'Отчетность'
},
{ {
path: '/requests', path: '/requests',
name: 'Запросы' name: 'Запросы'
}, },
{
path: '/employees',
name: 'Персонал'
},
{
path: '/tracker',
name: 'Трекер'
},
{
path: '/payouts',
name: 'Договора'
},
{
path: '/settings',
name: 'Настройки'
},
] ]
}) })
@ -86,14 +94,14 @@ export const ProfileHeader = () => {
<header className='profileHeader'> <header className='profileHeader'>
<div className='profileHeader__head'> <div className='profileHeader__head'>
<div className='profileHeader__container'> <div className='profileHeader__container'>
<h2 className='profileHeader__title'>itguild. <NavLink to={'/profile'} className='profileHeader__title'>itguild.
<span> <span>
{user === 'developer' ? {user === 'developer' ?
'для разработчиков' : 'для разработчиков' :
'для партнеров' 'для партнеров'
} }
</span> </span>
</h2> </NavLink>
<button onClick={handler} className='profileHeader__logout'> <button onClick={handler} className='profileHeader__logout'>
{isLoggingOut ? <Loader/> : 'Выйти'} {isLoggingOut ? <Loader/> : 'Выйти'}
</button> </button>

View File

@ -23,10 +23,16 @@
font-size: 20px; font-size: 20px;
line-height: 32px; line-height: 32px;
margin-bottom: 0; margin-bottom: 0;
color: black;
span { span {
color: #52B709; color: #52B709;
} }
&:hover {
color: black;
text-decoration: none;
}
} }
&__logout { &__logout {

View File

@ -2,7 +2,7 @@ import React, {useState, useEffect} from 'react'
import {useSelector} from 'react-redux' import {useSelector} from 'react-redux'
import {Link, Navigate, useNavigate} from 'react-router-dom' import {Link, Navigate, useNavigate} from 'react-router-dom'
import DatePicker, { registerLocale } from "react-datepicker" import DatePicker, { registerLocale } from "react-datepicker"
import {getCorrectDate, getCreatedDate} from '../Calendar/calendarHelper' import {getCorrectDate, getCreatedDate, hourOfNum} from '../Calendar/calendarHelper'
import ru from "date-fns/locale/ru" import ru from "date-fns/locale/ru"
registerLocale("ru", ru); registerLocale("ru", ru);
@ -67,11 +67,13 @@ const ReportForm = () => {
}; };
const handler = () => { const handler = () => {
if(!inputs[0].task || !inputs[0].hours_spent) { for (let input of inputs) {
if(!input.task || !input.hours_spent) {
setReportSuccess('Заполните задачи'); setReportSuccess('Заполните задачи');
setTimeout(() => setReportSuccess(''), 1000) setTimeout(() => setReportSuccess(''), 2000)
return return
} }
}
apiRequest('/reports/create', { apiRequest('/reports/create', {
method: 'POST', method: 'POST',
data: { data: {
@ -158,7 +160,8 @@ const ReportForm = () => {
{index + 1}. {index + 1}.
</div> </div>
<div className='report-form__task-input report-form__task-input--description'> <div className='report-form__task-input report-form__task-input--description'>
<input name='text' type='text' onChange={e => setInputs(inputs.map((input, inputIndex) => { <input value={inputs[index].task} className={!input.task && reportSuccess === 'Заполните задачи' ? 'checkTask' : ''} name='text' type='text'
onChange={e => setInputs(inputs.map((input, inputIndex) => {
return index === inputIndex return index === inputIndex
? { ? {
...input, ...input,
@ -168,7 +171,7 @@ const ReportForm = () => {
}))}/> }))}/>
</div> </div>
<div className='report-form__task-input report-form__task-input--hours'> <div className='report-form__task-input report-form__task-input--hours'>
<input name='number' type='number' min='1' <input value={inputs[index].hours_spent} className={!input.hours_spent && reportSuccess === 'Заполните задачи' ? 'checkTask' : ''} name='number' type='number' min='1'
onChange={e => setInputs(inputs.map((input, inputIndex) => { onChange={e => setInputs(inputs.map((input, inputIndex) => {
return index === inputIndex return index === inputIndex
? { ? {
@ -217,7 +220,7 @@ const ReportForm = () => {
{isFetching ? <Loader/> : 'Отправить'} {isFetching ? <Loader/> : 'Отправить'}
</button> </button>
<p className='report-form__footer-text'> <p className='report-form__footer-text'>
Всего за день : <span>{totalHours} часов</span> Всего за день : <span>{totalHours} {hourOfNum(totalHours)}</span>
</p> </p>
{reportSuccess && {reportSuccess &&
<p className={`report-form__footer-done ${reportSuccess === 'Заполните задачи' ? 'errorText' : ''}`}>{reportSuccess}</p> <p className={`report-form__footer-done ${reportSuccess === 'Заполните задачи' ? 'errorText' : ''}`}>{reportSuccess}</p>

View File

@ -151,27 +151,29 @@
p { p {
font-family: 'GT Eesti Pro Display'; font-family: 'GT Eesti Pro Display';
font-size: 1.3em; font-size: 1.5em;
font-weight: 100;
font-style: normal; font-style: normal;
letter-spacing: normal; letter-spacing: normal;
line-height: normal; line-height: normal;
text-align: left; text-align: left;
margin-bottom: 26px; margin-bottom: 26px;
white-space: nowrap; white-space: nowrap;
@media (max-width: 450px) {
font-size: 13px;
}
} }
} }
&-title { &-title {
//&--description { //&--description {
// margin-left: 20px;
//} //}
&--hours { &--hours {
margin-left: 330px; margin-left: 310px;
@media (max-width: 810px) { @media (max-width: 810px) {
margin-left: 125px; margin-left: 100px;
} }
@media (max-width: 610px) { @media (max-width: 610px) {
@ -202,6 +204,11 @@
margin-left: 20px; margin-left: 20px;
&--description { &--description {
.checkTask {
border-color: #fc0000;
}
input { input {
width: 460px; width: 460px;
height: 42px; height: 42px;
@ -225,6 +232,18 @@
} }
&--hours { &--hours {
@media (max-width: 610px) {
margin-left: 45px;
}
@media (max-width: 450px) {
margin-left: 22px;
}
.checkTask {
border-color: #fc0000;
}
input { input {
width: 141px; width: 141px;
height: 42px; height: 42px;
@ -257,8 +276,7 @@
span { span {
font-family: 'GT Eesti Pro Display'; font-family: 'GT Eesti Pro Display';
font-size: 1.3em; font-size: 1.5em;
font-weight: 100;
font-style: normal; font-style: normal;
letter-spacing: normal; letter-spacing: normal;
line-height: normal; line-height: normal;

View File

@ -60,7 +60,7 @@ export const Summary = () => {
<div className='skills__section__items'> <div className='skills__section__items'>
<div className='skills__section__items__wrapper'> <div className='skills__section__items__wrapper'>
{profileInfo.skillValues && profileInfo.skillValues.map((skill) => {profileInfo.skillValues && profileInfo.skillValues.map((skill) =>
<span key={skill.id} className='skill_item'>{skill.skill.name}</span> <span key={skill.id} className='skill_item'>{skill.skill.name},</span>
)} )}
</div> </div>
</div> </div>
@ -86,7 +86,7 @@ export const Summary = () => {
</div> </div>
<div className='summary__sectionGitItems'> <div className='summary__sectionGitItems'>
{Boolean(gitInfo.length) && gitInfo.map((itemGit) => { {Boolean(gitInfo.length) && gitInfo.map((itemGit) => {
return <div key={itemGit.id} className='summary__sectionGitItem gitItem'> return <a href={itemGit.link} target="_blank" rel="noreferrer" key={itemGit.id} className='summary__sectionGitItem gitItem'>
<div className='gitItem__info'> <div className='gitItem__info'>
<div className='gitItem__info__about'> <div className='gitItem__info__about'>
<img src={gitImgItem} alt='gitImg'/> <img src={gitImgItem} alt='gitImg'/>
@ -103,7 +103,7 @@ export const Summary = () => {
<a className='gitItem__link' href={itemGit.link} target="_blank" rel="noreferrer"> <a className='gitItem__link' href={itemGit.link} target="_blank" rel="noreferrer">
<img src={rightArrow} alt='arrowRight'/> <img src={rightArrow} alt='arrowRight'/>
</a> </a>
</div> </a>
}) })
} }
</div> </div>

View File

@ -51,7 +51,7 @@
margin-top: 30px; margin-top: 30px;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0 130px 0 45px; padding: 0 25px 0 45px;
justify-content: space-between; justify-content: space-between;
@media (max-width: 930px) { @media (max-width: 930px) {
@ -150,16 +150,16 @@
} }
&__git { &__git {
background: #52B709; border-radius: 31px;
border-radius: 44px;
width: 177px; width: 177px;
height: 50px; height: 62px;
font-weight: 500; font-weight: 500;
font-size: 16px; font-size: 1.9em;
line-height: 32px; line-height: 32px;
color: white; color: white;
border: none; border: none;
transition: all 0.3s ease; transition: all 0.3s ease;
background-image: linear-gradient(to top, #6aaf5c 0%, #52b709 100%), linear-gradient(36deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.16) 47%, rgba(255, 255, 255, 0.17) 50%, rgba(255, 255, 255, 0) 100%);
&:hover { &:hover {
box-shadow: 6px 5px 20px rgb(87 98 80 / 21%); box-shadow: 6px 5px 20px rgb(87 98 80 / 21%);
@ -168,6 +168,7 @@
@media (max-width: 690px) { @media (max-width: 690px) {
width: 120px; width: 120px;
height: 50px;
} }
} }
@ -307,10 +308,12 @@
border-radius: 12px; border-radius: 12px;
padding: 35px 30px 30px 45px; padding: 35px 30px 30px 45px;
transition: all 0.3s ease; transition: all 0.3s ease;
color: #000000;
&:hover { &:hover {
box-shadow: 6px 5px 20px rgb(87 98 80 / 21%); box-shadow: 6px 5px 20px rgb(87 98 80 / 21%);
transform: scale(1.02); transform: scale(1.02);
text-decoration: none;
} }
@media (max-width: 825px) { @media (max-width: 825px) {

View File

@ -12,7 +12,7 @@ import {Footer} from "../../components/Footer/Footer";
import arrow from "../../images/right-arrow.png"; import arrow from "../../images/right-arrow.png";
import arrowSwitchDate from "../../images/arrowViewReport.png"; import arrowSwitchDate from "../../images/arrowViewReport.png";
import {apiRequest} from "../../api/request"; import {apiRequest} from "../../api/request";
import {getCorrectDate, getCreatedDate} from '../../components/Calendar/calendarHelper' import {getCorrectDate, getCreatedDate, hourOfNum} from '../../components/Calendar/calendarHelper'
import './viewReport.scss' import './viewReport.scss'
@ -90,7 +90,7 @@ export const ViewReport = () => {
</Link> </Link>
<div className='viewReport__bar'> <div className='viewReport__bar'>
<h3 className='viewReport__bar__date'>{getCorrectDate(reportDay)}</h3> <h3 className='viewReport__bar__date'>{getCorrectDate(reportDay)}</h3>
<p className='viewReport__bar__hours'>Вами потрачено на работу : <span>{totalHours} часов</span></p> <p className='viewReport__bar__hours'>Вами потрачено на работу : <span>{totalHours} {hourOfNum(totalHours)}</span></p>
{/*<div className='viewReport__bar__progressBar'>*/} {/*<div className='viewReport__bar__progressBar'>*/}
{/* <span></span>*/} {/* <span></span>*/}
{/*</div>*/} {/*</div>*/}
@ -128,7 +128,7 @@ export const ViewReport = () => {
<td> <td>
<div className='viewReport__done__hours__item'> <div className='viewReport__done__hours__item'>
<span>{task.hours}</span> <span>{task.hours}</span>
<p className='hours'>часов на задачу</p> <p className='hours'>{hourOfNum(task.hours)} на задачу</p>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -64,6 +64,11 @@
height: 72px; height: 72px;
justify-content: space-between; justify-content: space-between;
@media (max-width: 540px) {
padding: 10px 15px;
height: 60px;
}
@media (max-width: 500px) { @media (max-width: 500px) {
column-gap: 0; column-gap: 0;
justify-content: space-between; justify-content: space-between;
@ -75,18 +80,22 @@
line-height: 32px; line-height: 32px;
color: #000000; color: #000000;
@media (max-width: 500px) { @media (max-width: 660px) {
font-size: 16px; font-size: 16px;
} }
@media (max-width: 490px) {
font-size: 12px;
}
} }
&__hours { &__hours {
font-weight: 400; font-weight: 400;
font-size: 12px; font-size: 15px;
line-height: 32px; line-height: 32px;
color: #000000; color: #000000;
@media (max-width: 500px) { @media (max-width: 660px) {
font-size: 11px; font-size: 11px;
} }