partnerRequests
This commit is contained in:
		| @@ -1,9 +1,11 @@ | |||||||
| import React, { useState } from 'react'; | import React, {useEffect, useState } from 'react'; | ||||||
|  |  | ||||||
| import {ProfileHeader} from "../../components/ProfileHeader/ProfileHeader"; | import {ProfileHeader} from "../../components/ProfileHeader/ProfileHeader"; | ||||||
| import {ProfileBreadcrumbs} from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs" | import {ProfileBreadcrumbs} from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs" | ||||||
| import {Footer} from "../../components/Footer/Footer"; | import {Footer} from "../../components/Footer/Footer"; | ||||||
| import {Navigate} from "react-router-dom"; | import {Link, Navigate, useNavigate} from "react-router-dom"; | ||||||
|  |  | ||||||
|  | import {apiRequest} from "../../api/request"; | ||||||
|  |  | ||||||
| import arrowDown from "../../images/selectArrow.png" | import arrowDown from "../../images/selectArrow.png" | ||||||
| import processImg from "../../images/partnerAddRequestFirstImg.png" | import processImg from "../../images/partnerAddRequestFirstImg.png" | ||||||
| @@ -19,11 +21,62 @@ export const PartnerAddRequest = () => { | |||||||
|         return <Navigate to="/profile" replace/> |         return <Navigate to="/profile" replace/> | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const [skills, setSkills] = useState(['REST API', 'Async/await']) |     const navigate= useNavigate(); | ||||||
|     const [selectedSkills, setSelectedSkills] = useState([]) |  | ||||||
|     const [filteredSkills, setFilteredSkills] = useState(skills) |  | ||||||
|  |  | ||||||
|  |     const [skills, setSkills] = useState([]) | ||||||
|  |     const [filteredSkills, setFilteredSkills] = useState([]) | ||||||
|  |     const [specializationList, setSpecializationList] = useState([]) | ||||||
|  |     const [levelList, setLevelList] = useState([]) | ||||||
|  |     const [countList] = useState([1, 2, 3, 4, 5]) | ||||||
|     const [openSkillsSelect, setOpenSkillsSelect] = useState(false) |     const [openSkillsSelect, setOpenSkillsSelect] = useState(false) | ||||||
|  |     const [openSpecializationList, setOpenSpecializationListOpen] = useState(false) | ||||||
|  |     const [openLevelList, setOpenLevelList] = useState(false) | ||||||
|  |     const [openCountList, setOpenCountList] = useState(false) | ||||||
|  |     const [selectedSkills, setSelectedSkills] = useState([]) | ||||||
|  |     const [selectedSpecialization, setSelectedSpecialization] = useState('Выберите специализацию') | ||||||
|  |     const [selectedLevel, setSelectedLevel] = useState('Выберите уровень') | ||||||
|  |     const [selectedCount, setSelectedCount] = useState('Выберите кол-во сотрудников') | ||||||
|  |     const [inputs, setInputs] = useState({title: '', description: ''}) | ||||||
|  |  | ||||||
|  |     useEffect(() => { | ||||||
|  |         apiRequest(`/profile/positions-list`).then((el) => setSpecializationList(el)) | ||||||
|  |         apiRequest(`/profile/level-list`).then((el) => setLevelList(el)) | ||||||
|  |         apiRequest(`/skills/get-skills-list`).then((el) => { | ||||||
|  |             setSkills(el) | ||||||
|  |             setFilteredSkills(el) | ||||||
|  |         }) | ||||||
|  |     }, []) | ||||||
|  |  | ||||||
|  |     const disableBtn = () => { | ||||||
|  |         if (!inputs.title || | ||||||
|  |             typeof selectedSpecialization === "string" || | ||||||
|  |             typeof selectedLevel === "string" || | ||||||
|  |             typeof selectedCount === "string" || | ||||||
|  |             !inputs.description || | ||||||
|  |             !selectedSkills.length) { | ||||||
|  |             return false | ||||||
|  |         } | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const handler = () => { | ||||||
|  |         apiRequest('/request/create-request', { | ||||||
|  |             method: 'POST', | ||||||
|  |             data: { | ||||||
|  |                 user_id: localStorage.getItem('id'), | ||||||
|  |                 title: inputs.title, | ||||||
|  |                 position_id: selectedSpecialization.id, | ||||||
|  |                 knowledge_level_id: selectedLevel.id, | ||||||
|  |                 specialist_count: selectedCount, | ||||||
|  |                 status: 1, | ||||||
|  |                 descr: inputs.description, | ||||||
|  |                 skill_ids: selectedSkills.map((skill) => {return skill.id}) | ||||||
|  |             } | ||||||
|  |         }).then((res) => { | ||||||
|  |             navigate('/profile/requests'); | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|         <div className='partnerAddRequest'> |         <div className='partnerAddRequest'> | ||||||
| @@ -43,31 +96,42 @@ export const PartnerAddRequest = () => { | |||||||
|                             <div className='form__block__section'> |                             <div className='form__block__section'> | ||||||
|                                 <h3>Название вакансии</h3> |                                 <h3>Название вакансии</h3> | ||||||
|                                 <div className='form__block__section__input'> |                                 <div className='form__block__section__input'> | ||||||
|                                     <input type='text' placeholder='Вакансия'/> |                                     <input onChange={e => setInputs((prevValue) => ({...prevValue, title: e.target.value}) )} type='text' placeholder='Вакансия'/> | ||||||
|                                 </div> |                                 </div> | ||||||
|                             </div> |                             </div> | ||||||
|                             <div className='form__block__section'> |                             <div className='form__block__section'> | ||||||
|                                 <h3>Выберите специализацию</h3> |                                 <h3>Выберите специализацию</h3> | ||||||
|                                 <div className='form__block__section__selects'> |                                 <div className='form__block__section__selects' onClick={() => {setOpenSpecializationListOpen(!openSpecializationList)}}> | ||||||
|                                     <div className='form__block__section__select'> |                                     <div className='form__block__section__select'> | ||||||
|                                         <span>Разработка</span> |                                         <span>{typeof selectedSpecialization === "string" ? selectedSpecialization : selectedSpecialization.name}</span> | ||||||
|                                         <img src={arrowDown} /> |                                         <img className={openSpecializationList ? 'rotate' : ''} src={arrowDown} /> | ||||||
|                                     </div> |  | ||||||
|                                     <div className='form__block__section__select'> |  | ||||||
|                                         <span>Backend Developer</span> |  | ||||||
|                                         <img src={arrowDown} /> |  | ||||||
|                                     </div> |                                     </div> | ||||||
|                                 </div> |                                 </div> | ||||||
|  |                                 {openSpecializationList && Boolean(specializationList.length) && | ||||||
|  |                                     <div className='form__block__dropDown'> | ||||||
|  |                                         {specializationList.map((specialization, index) => { | ||||||
|  |                                             return <p | ||||||
|  |                                                 key={specialization.id} | ||||||
|  |                                                 onClick={() => { | ||||||
|  |                                                     setOpenSpecializationListOpen(false) | ||||||
|  |                                                     setSelectedSpecialization(specialization) | ||||||
|  |                                                 }} | ||||||
|  |                                             > | ||||||
|  |                                                             {specialization.name}</p> | ||||||
|  |                                         })} | ||||||
|  |                                     </div> | ||||||
|  |                                 } | ||||||
|                             </div> |                             </div> | ||||||
|                             <div className='form__block__section'> |                             <div className='form__block__section'> | ||||||
|                                 <h3>Навыки</h3> |                                 <h3>Навыки</h3> | ||||||
|                                 <div className='form__block__skills' onClick={() => {setOpenSkillsSelect(true)}}> |                                 <div className='form__block__skills' onClick={() => {setOpenSkillsSelect(true)}}> | ||||||
|                                     {Boolean(selectedSkills.length) && |                                     {Boolean(selectedSkills.length) && | ||||||
|                                         selectedSkills.map((skill, index) => { |                                         selectedSkills.map((skill, index) => { | ||||||
|                                             return<div className='skill' key={index}> |                                             return<div className='skill' key={`selected-${skill.id}`}> | ||||||
|                                                 <span >{skill}</span> |                                                 <span >{skill.name}</span> | ||||||
|                                                 <img src={deleteIcon} alt='delete' |                                                 <img src={deleteIcon} alt='delete' | ||||||
|                                                      onClick={() => { |                                                      onClick={() => { | ||||||
|  |                                                          setSkills(prevArray => [...prevArray, skill]) | ||||||
|                                                          setFilteredSkills(prevArray => [...prevArray, skill]) |                                                          setFilteredSkills(prevArray => [...prevArray, skill]) | ||||||
|                                                          setSelectedSkills(selectedSkills.filter((skill, indexSkill) => { |                                                          setSelectedSkills(selectedSkills.filter((skill, indexSkill) => { | ||||||
|                                                              return indexSkill !== index |                                                              return indexSkill !== index | ||||||
| @@ -76,29 +140,30 @@ export const PartnerAddRequest = () => { | |||||||
|                                             </div> |                                             </div> | ||||||
|                                         }) |                                         }) | ||||||
|                                     } |                                     } | ||||||
|                                     {!selectedSkills.length && |                                     <input type='text' placeholder='Выберите навыки' | ||||||
|                                         <input type='text' placeholder='Выберите навыки' |                                            onChange={(e) => { | ||||||
|                                                onChange={(e) => { |                                                setFilteredSkills(skills.filter((skill) => { | ||||||
|                                                    setFilteredSkills(skills.filter((skill) => { |                                                    return skill.name.toLowerCase().includes(e.target.value.toLowerCase()) | ||||||
|                                                        return skill.toLowerCase().includes(e.target.value.toLowerCase()) |                                                })) | ||||||
|                                                    })) |                                            }} /> | ||||||
|                                                }} /> |  | ||||||
|                                     } |  | ||||||
|                                 </div> |                                 </div> | ||||||
|                                 {openSkillsSelect && Boolean(filteredSkills.length) && |                                 {openSkillsSelect && Boolean(filteredSkills.length) && | ||||||
|                                     <div className='form__block__dropDown'> |                                     <div className='form__block__dropDown'> | ||||||
|                                         {filteredSkills.map((skill, index) => { |                                         {filteredSkills.map((skill, index) => { | ||||||
|                                             return <span |                                             return <span | ||||||
|                                                 key={skill} |                                                 key={skill.id} | ||||||
|                                                 onClick={() => { |                                                 onClick={() => { | ||||||
|                                                     setSelectedSkills(prevArray => [...prevArray, skill]) |                                                     setSelectedSkills(prevArray => [...prevArray, skill]) | ||||||
|                                                     setFilteredSkills(filteredSkills.filter((skill, skillIndex) => { |                                                     setFilteredSkills(filteredSkills.filter((skill, skillIndex) => { | ||||||
|                                                         return skillIndex !== index |                                                         return skillIndex !== index | ||||||
|                                                     })) |                                                     })) | ||||||
|  |                                                     setSkills(skills.filter((initSkill) => { | ||||||
|  |                                                         return initSkill.id !==skill.id | ||||||
|  |                                                     })) | ||||||
|                                                     setOpenSkillsSelect(false) |                                                     setOpenSkillsSelect(false) | ||||||
|                                                 }} |                                                 }} | ||||||
|                                             > |                                             > | ||||||
|                                                         {skill}</span> |                                                         {skill.name}</span> | ||||||
|                                         })} |                                         })} | ||||||
|                                     </div> |                                     </div> | ||||||
|                                 } |                                 } | ||||||
| @@ -108,25 +173,53 @@ export const PartnerAddRequest = () => { | |||||||
|                             <h3 className='form__block__title'>Квалификация</h3> |                             <h3 className='form__block__title'>Квалификация</h3> | ||||||
|                             <div className='form__block__section'> |                             <div className='form__block__section'> | ||||||
|                                 <h3>Выберите уровень знаний </h3> |                                 <h3>Выберите уровень знаний </h3> | ||||||
|                                 <div className='form__block__section__select'> |                                 <div className='form__block__section__select' onClick={() => setOpenLevelList(!openLevelList)}> | ||||||
|                                     <span>Разработка</span> |                                     <span>{typeof selectedLevel === "string" ? selectedLevel : selectedLevel.name}</span> | ||||||
|                                     <img src={arrowDown} /> |                                     <img className={openLevelList ? 'rotate' : ''} src={arrowDown} /> | ||||||
|                                 </div> |                                 </div> | ||||||
|  |                                 {openLevelList && Boolean(Object.values(levelList).length) && | ||||||
|  |                                     <div className='form__block__dropDown'> | ||||||
|  |                                         {Object.values(levelList).map((level, index) => { | ||||||
|  |                                             return <p | ||||||
|  |                                                 key={level} | ||||||
|  |                                                 onClick={() => { | ||||||
|  |                                                     setOpenLevelList(false) | ||||||
|  |                                                     setSelectedLevel({name: level, id: index + 1}) | ||||||
|  |                                                 }} | ||||||
|  |                                             > | ||||||
|  |                                                 {level}</p> | ||||||
|  |                                         })} | ||||||
|  |                                     </div> | ||||||
|  |                                 } | ||||||
|                             </div> |                             </div> | ||||||
|                             <div className='form__block__section'> |                             <div className='form__block__section'> | ||||||
|                                 <h3>Введите необходимое описание</h3> |                                 <h3>Введите необходимое описание</h3> | ||||||
|                                 <textarea/> |                                 <textarea onChange={e => setInputs((prevValue) => ({...prevValue, description: e.target.value}) )}/> | ||||||
|                             </div> |                             </div> | ||||||
|                             <div className='form__block__section'> |                             <div className='form__block__section'> | ||||||
|                                 <h3>Необходимое количество человек на позицию</h3> |                                 <h3>Необходимое количество человек на позицию</h3> | ||||||
|                                 <div className='form__block__section__select'> |                                 <div className='form__block__section__select' onClick={() => setOpenCountList(true)}> | ||||||
|                                     <span>2</span> |                                     <span>{selectedCount}</span> | ||||||
|                                     <img src={arrowDown} /> |                                     <img className={openCountList ? 'rotate' : ''} src={arrowDown} /> | ||||||
|                                 </div> |                                 </div> | ||||||
|  |                                 {openCountList && | ||||||
|  |                                 <div className='form__block__dropDown'> | ||||||
|  |                                     {countList.map((count) => { | ||||||
|  |                                         return <p | ||||||
|  |                                             key={count} | ||||||
|  |                                             onClick={() => { | ||||||
|  |                                                 setOpenCountList(false) | ||||||
|  |                                                 setSelectedCount(count) | ||||||
|  |                                             }} | ||||||
|  |                                         > | ||||||
|  |                                             {count}</p> | ||||||
|  |                                     })} | ||||||
|  |                                 </div> | ||||||
|  |                                 } | ||||||
|                             </div> |                             </div> | ||||||
|                             <div className='form__block__buttons'> |                             <div className='form__block__buttons'> | ||||||
|                                 <button className='form__block__cancel'>Отмена</button> |                                 <Link to='/profile/requests' className='form__block__cancel'>Отмена</Link> | ||||||
|                                 <button className='form__block__save'>Сохранить</button> |                                 <button onClick={() => handler()} className={disableBtn() ? 'form__block__save' : 'form__block__save disable'}>Сохранить</button> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                     </div> |                     </div> | ||||||
|   | |||||||
| @@ -101,7 +101,6 @@ | |||||||
|  |  | ||||||
|       &__selects { |       &__selects { | ||||||
|         display: flex; |         display: flex; | ||||||
|         column-gap: 32px; |  | ||||||
|         justify-content: space-between; |         justify-content: space-between; | ||||||
|  |  | ||||||
|         @media (max-width: 1020px) { |         @media (max-width: 1020px) { | ||||||
| @@ -122,7 +121,6 @@ | |||||||
|         display: flex; |         display: flex; | ||||||
|         align-items: center; |         align-items: center; | ||||||
|         justify-content: space-between; |         justify-content: space-between; | ||||||
|         max-width: 202px; |  | ||||||
|         width: 100%; |         width: 100%; | ||||||
|  |  | ||||||
|         span { |         span { | ||||||
| @@ -131,6 +129,14 @@ | |||||||
|           font-size: 15px; |           font-size: 15px; | ||||||
|           line-height: 18px; |           line-height: 18px; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         img { | ||||||
|  |           transition: all 0.3s ease; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         .rotate { | ||||||
|  |           transform: rotate(180deg); | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       textarea { |       textarea { | ||||||
| @@ -165,6 +171,12 @@ | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     &__cancel { |     &__cancel { | ||||||
|  |       max-width: 150px; | ||||||
|  |       width: 100%; | ||||||
|  |       height: 40px; | ||||||
|  |       display: flex; | ||||||
|  |       align-items: center; | ||||||
|  |       justify-content: center; | ||||||
|       border: 0.5px solid #8DC63F; |       border: 0.5px solid #8DC63F; | ||||||
|       border-radius: 44px; |       border-radius: 44px; | ||||||
|       color: #6F6F6F; |       color: #6F6F6F; | ||||||
| @@ -173,6 +185,10 @@ | |||||||
|       line-height: 32px; |       line-height: 32px; | ||||||
|       background: none; |       background: none; | ||||||
|       margin-right: 23px; |       margin-right: 23px; | ||||||
|  |  | ||||||
|  |       &:hover { | ||||||
|  |         text-decoration: none; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     &__save { |     &__save { | ||||||
| @@ -185,6 +201,11 @@ | |||||||
|       border: none; |       border: none; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     .disable { | ||||||
|  |       pointer-events: none; | ||||||
|  |       opacity: 0.5; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     &__skills { |     &__skills { | ||||||
|       display: flex; |       display: flex; | ||||||
|       gap: 5px; |       gap: 5px; | ||||||
| @@ -203,8 +224,6 @@ | |||||||
|         line-height: 14px; |         line-height: 14px; | ||||||
|         color: #263238; |         color: #263238; | ||||||
|         padding: 6px 6px 5px; |         padding: 6px 6px 5px; | ||||||
|         max-width: 100px; |  | ||||||
|         width: 100%; |  | ||||||
|         display: flex; |         display: flex; | ||||||
|         justify-content: space-evenly; |         justify-content: space-evenly; | ||||||
|         align-items: center; |         align-items: center; | ||||||
| @@ -217,7 +236,6 @@ | |||||||
|       input { |       input { | ||||||
|         border: none; |         border: none; | ||||||
|         outline: none; |         outline: none; | ||||||
|         width: 100%; |  | ||||||
|         background: none; |         background: none; | ||||||
|         font-weight: 400; |         font-weight: 400; | ||||||
|         font-size: 15px; |         font-size: 15px; | ||||||
| @@ -228,14 +246,57 @@ | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     &__dropDown { |     &__dropDown { | ||||||
|  |       width: 100%; | ||||||
|       position: absolute; |       position: absolute; | ||||||
|       display: flex; |       display: flex; | ||||||
|       flex-direction: column; |       background: #e6e6e7; | ||||||
|       background: #EFF2F7; |  | ||||||
|       border-radius: 8px; |       border-radius: 8px; | ||||||
|       padding: 5px 20px; |       padding: 5px 0; | ||||||
|       row-gap: 10px; |  | ||||||
|       z-index: 100; |       z-index: 100; | ||||||
|  |       flex-wrap: wrap; | ||||||
|  |       justify-content: center; | ||||||
|  |       gap: 8px; | ||||||
|  |       margin-top: 3px; | ||||||
|  |       align-items: center; | ||||||
|  |       max-height: 250px; | ||||||
|  |       overflow-y: auto; | ||||||
|  |  | ||||||
|  |       p { | ||||||
|  |         font-weight: 400; | ||||||
|  |         font-size: 18px; | ||||||
|  |         line-height: 14px; | ||||||
|  |         cursor: pointer; | ||||||
|  |         width: 100%; | ||||||
|  |         text-align: center; | ||||||
|  |         padding: 5px 0; | ||||||
|  |         border-radius: 50px; | ||||||
|  |  | ||||||
|  |         &:hover { | ||||||
|  |           background: #e8e8fc; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       &::-webkit-scrollbar { | ||||||
|  |         width: 4px; | ||||||
|  |         background: 0 0; | ||||||
|  |         box-shadow: 0 0 14px rgba(0, 0, 0, 0.04); | ||||||
|  |         border-radius: 20px; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       &::-webkit-scrollbar { | ||||||
|  |         width: 4px; | ||||||
|  |         border-radius: 20px; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       &::-webkit-scrollbar-thumb { | ||||||
|  |         background: #cbd9f9; | ||||||
|  |         border-radius: 20px; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       &::-webkit-scrollbar-track { | ||||||
|  |         background: #c5c0c6; | ||||||
|  |         border-radius: 20px; | ||||||
|  |       } | ||||||
|  |  | ||||||
|       span { |       span { | ||||||
|         cursor: pointer; |         cursor: pointer; | ||||||
|   | |||||||
| @@ -1,9 +1,15 @@ | |||||||
| import React, {useState} from 'react'; | import React, {useEffect, useState} from 'react'; | ||||||
| import {Link, Navigate} from "react-router-dom"; | import {Link, Navigate} from "react-router-dom"; | ||||||
|  | import {useSelector, useDispatch} from 'react-redux' | ||||||
|  | import {getPartnerRequestId, getPartnerRequests, setPartnerRequestId} from '../../redux/outstaffingSlice' | ||||||
|  |  | ||||||
| import {ProfileHeader} from "../../components/ProfileHeader/ProfileHeader"; | import {ProfileHeader} from "../../components/ProfileHeader/ProfileHeader"; | ||||||
| import {ProfileBreadcrumbs} from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs" | import {ProfileBreadcrumbs} from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs" | ||||||
| import {Footer} from "../../components/Footer/Footer"; | import {Footer} from "../../components/Footer/Footer"; | ||||||
|  | import {Loader} from "../../components/Loader/Loader" | ||||||
|  |  | ||||||
|  | import {apiRequest} from "../../api/request"; | ||||||
|  | import {getCorrectDate} from "../../components/Calendar/calendarHelper"; | ||||||
|  |  | ||||||
| import arrowSwitchDate from "../../images/arrowViewReport.png"; | import arrowSwitchDate from "../../images/arrowViewReport.png"; | ||||||
| import backEndImg from "../../images/QualificationInfo.png"; | import backEndImg from "../../images/QualificationInfo.png"; | ||||||
| @@ -17,20 +23,39 @@ export const PartnerBid = () => { | |||||||
|     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 requestId = useSelector(getPartnerRequestId); | ||||||
|  |     const partnerRequests = useSelector(getPartnerRequests); | ||||||
|  |  | ||||||
|  |     if (!requestId) { | ||||||
|  |         return <Navigate to="/profile/requests" replace/> | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     useEffect(() => { | ||||||
|  |         setLoader(true) | ||||||
|  |         apiRequest(`/request/get-request?request_id=${requestId}`).then((el) => { | ||||||
|  |             setRequestInfo(el) | ||||||
|  |             setLoader(false) | ||||||
|  |         }) | ||||||
|  |     }, [requestId]); | ||||||
|  |  | ||||||
|  |     const [requestInfo, setRequestInfo] = useState({}) | ||||||
|  |     const [loader, setLoader] = useState(false) | ||||||
|  |  | ||||||
|     const [mokPersons] = useState([ |     const [mokPersons] = useState([ | ||||||
|         { |         { | ||||||
|             name: 'Дмитрий, PHP Back end - разработчик, Middle', |             name: 'Дмитрий, PHP Back end - разработчик, Middle', | ||||||
|             link: '', |             link: '/candidate/110', | ||||||
|             img: personImg |             img: personImg | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             name: 'Дмитрий, PHP Back end - разработчик, Middle', |             name: 'Дмитрий, PHP Back end - разработчик, Middle', | ||||||
|             link: '', |             link: '/candidate/111', | ||||||
|             img: personImg |             img: personImg | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             name: 'Дмитрий, PHP Back end - разработчик, Middle', |             name: 'Дмитрий, PHP Back end - разработчик, Middle', | ||||||
|             link: '', |             link: '/candidate/112', | ||||||
|             img: personImg |             img: personImg | ||||||
|         } |         } | ||||||
|     ]) |     ]) | ||||||
| @@ -45,84 +70,101 @@ export const PartnerBid = () => { | |||||||
|                 ]} |                 ]} | ||||||
|                 /> |                 /> | ||||||
|                 <h2 className='partnerBid__title'>Страница заявки </h2> |                 <h2 className='partnerBid__title'>Страница заявки </h2> | ||||||
|                 <div className='partnerBid__qualification'> |                 {loader && <Loader />} | ||||||
|                     <h3>PHP разработчик</h3> |                 {!loader && | ||||||
|                     <div className='partnerBid__qualification__buttons'> |                     <> | ||||||
|                         <button>Редактировать</button> |                         <div className='partnerBid__qualification'> | ||||||
|                         <img src={deleteBtn} alt='delete' /> |                             <h3>{requestInfo.title}</h3> | ||||||
|                     </div> |                             <div className='partnerBid__qualification__buttons'> | ||||||
|                 </div> |                                 <button>Редактировать</button> | ||||||
|                 <div className='partnerBid__switcher'> |                                 <img src={deleteBtn} alt='delete'/> | ||||||
|                     <div className='partnerBid__switcher__prev switchDate'> |                             </div> | ||||||
|                         <img src={arrowSwitchDate} alt='arrow'/> |                         </div> | ||||||
|                     </div> |                         <div className='partnerBid__switcher'> | ||||||
|                     <p>Дата заявки : 19 декабря 2022 года </p> |                             <div className={partnerRequests[partnerRequests.findIndex(el => el.id === requestId) - 1]?.id ? 'partnerBid__switcher__prev switchDate' : 'partnerBid__switcher__prev switchDate disable'} | ||||||
|                     <div className='partnerBid__switcher__next switchDate'> |                                 onClick={() => { | ||||||
|                         <img src={arrowSwitchDate} alt='arrow'/> |                                     dispatch(setPartnerRequestId(partnerRequests[partnerRequests.findIndex(el => el.id === requestId) - 1].id)) | ||||||
|                     </div> |                                 }} | ||||||
|                 </div> |                             > | ||||||
|                 <div className='table__wrapper'> |                                 <img src={arrowSwitchDate} alt='arrow'/> | ||||||
|                     <table> |                             </div> | ||||||
|                         <thead> |                             <p>Дата заявки : {getCorrectDate(requestInfo.created_at)} </p> | ||||||
|                             <tr> |                             <div className={partnerRequests[partnerRequests.findIndex(el => el.id === requestId) + 1]?.id ? 'partnerBid__switcher__next switchDate' : 'partnerBid__switcher__next switchDate disable'} | ||||||
|                                 <th><p>Требования к стеку разработчика</p></th> |                                 onClick={() => { | ||||||
|                                 <th><p>Квалификация</p></th> |                                     dispatch(setPartnerRequestId(partnerRequests[partnerRequests.findIndex(el => el.id === requestId) + 1].id)) | ||||||
|                             </tr> |                                 }} | ||||||
|                         </thead> |                             > | ||||||
|                         <tbody> |                                 <img src={arrowSwitchDate} alt='arrow'/> | ||||||
|                             <tr> |                             </div> | ||||||
|                                 <td> |                         </div> | ||||||
|                                     <p> |                     </> | ||||||
|                                         PHP приветствуется аккуратность в коде. MySQL - умение писать запросы к MySQL, |                 } | ||||||
|                                         понимание как происходит запрос. Средний уровень: AJAX, JSON, общее понимание; |                 {Boolean(Object.keys(requestInfo).length) && !loader && | ||||||
|                                         CSS/CSS3, HTML, Bootstrap; |                     <div className='table__wrapper'> | ||||||
|                                     </p> |                         <table> | ||||||
|                                 </td> |                             <thead> | ||||||
|                                 <td> |                                 <tr> | ||||||
|                                     <div className='qualification__info'> |                                     <th><p>Требования к стеку разработчика</p></th> | ||||||
|                                         <div className='img__wrapper'> |                                     <th><p>Квалификация</p></th> | ||||||
|                                             <img src={backEndImg} alt='backEndImg' /> |                                 </tr> | ||||||
|  |                             </thead> | ||||||
|  |                             <tbody> | ||||||
|  |                                 <tr> | ||||||
|  |                                     <td> | ||||||
|  |                                         <p> | ||||||
|  |                                             {requestInfo.position.name}.   | ||||||
|  |                                             {requestInfo.skills.map((skill, index) => { | ||||||
|  |                                                 return <span key={skill.id}>{skill.name} | ||||||
|  |                                                 {requestInfo.skills.length > index + 1 ? ',' : '.'} | ||||||
|  |                                                   | ||||||
|  |                                                 </span> | ||||||
|  |                                             })} | ||||||
|  |                                         </p> | ||||||
|  |                                     </td> | ||||||
|  |                                     <td> | ||||||
|  |                                         <div className='qualification__info'> | ||||||
|  |                                             <div className='img__wrapper'> | ||||||
|  |                                                 <img src={backEndImg} alt='backEndImg' /> | ||||||
|  |                                             </div> | ||||||
|  |                                             <p>{requestInfo.position.name}</p> | ||||||
|                                         </div> |                                         </div> | ||||||
|                                         <p>Backend разработчик</p> |                                     </td> | ||||||
|                                     </div> |                                 </tr> | ||||||
|                                 </td> |                                 <tr> | ||||||
|                             </tr> |                                     <td> | ||||||
|                             <tr> |                                         <p> | ||||||
|                                 <td> |                                             {requestInfo.descr} | ||||||
|                                     <p> |                                         </p> | ||||||
|                                         Знание современных фреймворков Laravel, Yii 2, FuelPHP, Симфони; |                                     </td> | ||||||
|                                         Знания по разработке REST API; |                                     <td> | ||||||
|                                         Знание PHP,HTML,CSS,MySQL,Pyhton,JavaScript. |                                         <div className='qualification__info'> | ||||||
|                                     </p> |                                             <div className='img__wrapper'> | ||||||
|                                 </td> |                                                 <img src={middle} alt='middleImg' /> | ||||||
|                                 <td> |                                             </div> | ||||||
|                                     <div className='qualification__info'> |                                             <p className='middle'>{requestInfo.level}</p> | ||||||
|                                         <div className='img__wrapper'> |  | ||||||
|                                             <img src={middle} alt='middleImg' /> |  | ||||||
|                                         </div> |                                         </div> | ||||||
|                                         <p className='middle'>Средний<br/>(Middle)</p> |                                     </td> | ||||||
|                                     </div> |                                 </tr> | ||||||
|                                 </td> |                             </tbody> | ||||||
|                             </tr> |                         </table> | ||||||
|                         </tbody> |                     </div> | ||||||
|                     </table> |                 } | ||||||
|                 </div> |  | ||||||
|                 <div className='partnerBid__suitable'> |                 <div className='partnerBid__suitable'> | ||||||
|                     <div className='partnerBid__suitable__title'> |                     <div className='partnerBid__suitable__title'> | ||||||
|                         <p>Подходящие сотрудники по запросу</p> |                         <p>Подходящие сотрудники по запросу</p> | ||||||
|                     </div> |                     </div> | ||||||
|                     <div className='partnerBid__suitable__persons'> |                     <div className='partnerBid__suitable__persons'> | ||||||
|                         {mokPersons.map((person, index) => { |                         {mokPersons.map((person, index) => { | ||||||
|                             return <Link to='/candidate/110' key={index} className='partnerBid__suitable__person'> |                             return <div key={index} className='partnerBid__suitable__person'> | ||||||
|                                         <img src={person.img} alt='avatar' /> |                                         <img src={person.img} alt='avatar' /> | ||||||
|                                         <p>{person.name}</p> |                                         <p>{person.name}</p> | ||||||
|                                         <Link className='partnerBid__suitable__person__more' to='/candidate/110'> |                                         <Link className='partnerBid__suitable__person__more' to={person.link}> | ||||||
|                                             Подробнее |                                             Подробнее | ||||||
|                                         </Link> |                                         </Link> | ||||||
|                                         <div className='partnerBid__suitable__person__info'> |                                         <div className='partnerBid__suitable__person__info'> | ||||||
|  |  | ||||||
|                                         </div> |                                         </div> | ||||||
|                                     </Link> |                                     </div> | ||||||
|                         }) |                         }) | ||||||
|                         } |                         } | ||||||
|                     </div> |                     </div> | ||||||
|   | |||||||
| @@ -84,6 +84,11 @@ | |||||||
|       cursor: pointer; |       cursor: pointer; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     .disable { | ||||||
|  |       pointer-events: none; | ||||||
|  |       opacity: 0.5; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     &__prev { |     &__prev { | ||||||
|       transform: rotate(180deg); |       transform: rotate(180deg); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,11 +1,16 @@ | |||||||
| import React, {useState} from 'react'; | import React, {useEffect, useState} from 'react'; | ||||||
| import {Link, Navigate} from "react-router-dom"; | import {Link, Navigate} from "react-router-dom"; | ||||||
|  | import {useDispatch} from 'react-redux' | ||||||
|  | import {setPartnerRequestId, setPartnerRequests} from '../../redux/outstaffingSlice' | ||||||
|  |  | ||||||
| import {ProfileHeader} from "../../components/ProfileHeader/ProfileHeader"; | import {ProfileHeader} from "../../components/ProfileHeader/ProfileHeader"; | ||||||
| import {ProfileBreadcrumbs} from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs" | import {ProfileBreadcrumbs} from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs" | ||||||
| import {SliderWorkers} from "../../components/SliderWorkers/SliderWorkers" | import {SliderWorkers} from "../../components/SliderWorkers/SliderWorkers" | ||||||
|  | import {Loader} from "../../components/Loader/Loader" | ||||||
| import {Footer} from "../../components/Footer/Footer"; | import {Footer} from "../../components/Footer/Footer"; | ||||||
|  |  | ||||||
|  | import {apiRequest} from "../../api/request"; | ||||||
|  |  | ||||||
| import cursorImg from "../../images/cursorImg.png" | import cursorImg from "../../images/cursorImg.png" | ||||||
|  |  | ||||||
| import './partnerRequests.scss' | import './partnerRequests.scss' | ||||||
| @@ -14,24 +19,17 @@ export const PartnerRequests = () => { | |||||||
|     if(localStorage.getItem('role_status') !== '18') { |     if(localStorage.getItem('role_status') !== '18') { | ||||||
|         return <Navigate to="/profile" replace/> |         return <Navigate to="/profile" replace/> | ||||||
|     } |     } | ||||||
|     const [items] = useState([ |  | ||||||
|         { |     const dispatch = useDispatch(); | ||||||
|             name: 'PHP разработчик ', |     const [requests, setRequests] = useState([]) | ||||||
|             count: 4 |     const [loader, setLoader] = useState(true) | ||||||
|         }, |  | ||||||
|         { |     useEffect(() => { | ||||||
|             name: 'PHP разработчик ', |         apiRequest(`/request/get-request-list?user_id=${localStorage.getItem('id')}&search_depth=3`).then((el) => { | ||||||
|             count: 4 |             setRequests(el) | ||||||
|         }, |             setLoader(false) | ||||||
|         { |         }) | ||||||
|             name: 'PHP разработчик ', |     }, []) | ||||||
|             count: 4 |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             name: 'PHP разработчик ', |  | ||||||
|             count: 4 |  | ||||||
|         } |  | ||||||
|     ]) |  | ||||||
|     return ( |     return ( | ||||||
|         <div className='partnerRequests'> |         <div className='partnerRequests'> | ||||||
|             <ProfileHeader /> |             <ProfileHeader /> | ||||||
| @@ -42,59 +40,68 @@ export const PartnerRequests = () => { | |||||||
|                 ]} |                 ]} | ||||||
|                 /> |                 /> | ||||||
|                 <h2 className='partnerRequests__title'>Запросы</h2> |                 <h2 className='partnerRequests__title'>Запросы</h2> | ||||||
|                 {Boolean(items.length) ? |                 {loader && | ||||||
|                     <div className='partnerRequests__section'> |                     <Loader /> | ||||||
|                         <div className='partnerRequests__section__items'> |                 } | ||||||
|                             { |                 {Boolean(requests.length) && !loader && | ||||||
|                                 items.map((item, index) => { |                         <div className='partnerRequests__section'> | ||||||
|                                     return <Link key={index} to={'/profile/bid'} className='partnerRequests__section__item'> |                             <div className='partnerRequests__section__items'> | ||||||
|                                                 <p className='partnerRequests__section__item__name'> |                                 { | ||||||
|                                                     {item.name} |                                     requests.map((item, index) => { | ||||||
|                                                 </p> |                                         return <Link key={index} to={'/profile/bid'} className='partnerRequests__section__item' | ||||||
|                                                 <p className='partnerRequests__section__item__count'> |                                                      onClick={() => { | ||||||
|                                                     Подходящие кандидаты<span>{item.count}</span> |                                                          dispatch(setPartnerRequestId(item.id)) | ||||||
|                                                 </p> |                                                          dispatch(setPartnerRequests(requests)) | ||||||
|                                             </Link> |                                                      }}> | ||||||
|                                 }) |                                             <p className='partnerRequests__section__item__name'> | ||||||
|                             } |                                                 {item.position.name} | ||||||
|                         </div> |                                             </p> | ||||||
|                         <div className='partnerRequests__section__info'> |                                             <p className='partnerRequests__section__item__count'> | ||||||
|                             <h3>Инструкция: подачи заявки</h3> |                                                 Подходящие кандидаты | ||||||
|                             <p> |                                                 <span>{item.result_count}</span> | ||||||
|                                 Оператор компании заводит заявку и указывает необходимые параметры — |                                             </p> | ||||||
|                                 количество сотрудников, стек, уровень специалиста |                                         </Link> | ||||||
|                             </p> |                                     }) | ||||||
|                             <Link to={'/profile/add-request'}> |                                 } | ||||||
|                                 <span>+</span> |  | ||||||
|                                 Создать запрос |  | ||||||
|                             </Link> |  | ||||||
|                         </div> |  | ||||||
|                     </div> |  | ||||||
|                     : |  | ||||||
|                     <div className="partnerRequests__noItems"> |  | ||||||
|                         <div className="partnerRequests__noItems__create"> |  | ||||||
|                             <div className="partnerRequests__noItems__create__link"> |  | ||||||
|                                 <img src={cursorImg} alt="cursor" /> |  | ||||||
|                                 <p>У вас еще нет запросов на сотрудников</p> |  | ||||||
|                                 <Link to={'/profile/add-request'}> |  | ||||||
|                                     <span>+</span> |  | ||||||
|                                     Создать запрос |  | ||||||
|                                 </Link> |  | ||||||
|                             </div> |                             </div> | ||||||
|                             <div className="partnerRequests__noItems__create__instruction"> |                             <div className='partnerRequests__section__info'> | ||||||
|                                 <h3>Инструкция: подачи заявки</h3> |                                 <h3>Инструкция: подачи заявки</h3> | ||||||
|                                 <p> |                                 <p> | ||||||
|                                     Оператор компании заводит заявку и указывает необходимые параметры — |                                     Оператор компании заводит заявку и указывает необходимые параметры — | ||||||
|                                     количество сотрудников, стек, уровень специалиста |                                     количество сотрудников, стек, уровень специалиста | ||||||
|                                 </p> |                                 </p> | ||||||
|  |                                 <Link to={'/profile/add-request'}> | ||||||
|  |                                     <span>+</span> | ||||||
|  |                                     Создать запрос | ||||||
|  |                                 </Link> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div className="partnerRequests__noItems__freeEmployees"> |                     } | ||||||
|                             <SliderWorkers title={"Свободные разработчики"} titleInfo={"в нашей базе"} /> |                     {!Boolean(requests.length) && !loader && | ||||||
|                             <p>Перейти в полный <Link to={'/profile/catalog'}>КАТАЛОГ</Link> сотрудников</p> |                         <div className="partnerRequests__noItems"> | ||||||
|  |                             <div className="partnerRequests__noItems__create"> | ||||||
|  |                                 <div className="partnerRequests__noItems__create__link"> | ||||||
|  |                                     <img src={cursorImg} alt="cursor" /> | ||||||
|  |                                     <p>У вас еще нет запросов на сотрудников</p> | ||||||
|  |                                     <Link to={'/profile/add-request'}> | ||||||
|  |                                         <span>+</span> | ||||||
|  |                                         Создать запрос | ||||||
|  |                                     </Link> | ||||||
|  |                                 </div> | ||||||
|  |                                 <div className="partnerRequests__noItems__create__instruction"> | ||||||
|  |                                     <h3>Инструкция: подачи заявки</h3> | ||||||
|  |                                     <p> | ||||||
|  |                                         Оператор компании заводит заявку и указывает необходимые параметры — | ||||||
|  |                                         количество сотрудников, стек, уровень специалиста | ||||||
|  |                                     </p> | ||||||
|  |                                 </div> | ||||||
|  |                             </div> | ||||||
|  |                             <div className="partnerRequests__noItems__freeEmployees"> | ||||||
|  |                                 <SliderWorkers title={"Свободные разработчики"} titleInfo={"в нашей базе"} /> | ||||||
|  |                                 <p>Перейти в полный <Link to={'/profile/catalog'}>КАТАЛОГ</Link> сотрудников</p> | ||||||
|  |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                     </div> |                     } | ||||||
|                 } |  | ||||||
|             </div> |             </div> | ||||||
|             <Footer/> |             <Footer/> | ||||||
|         </div> |         </div> | ||||||
|   | |||||||
| @@ -9,11 +9,12 @@ import {ProfileHeader} from "../../components/ProfileHeader/ProfileHeader"; | |||||||
| import {ProfileBreadcrumbs} from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs" | import {ProfileBreadcrumbs} from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs" | ||||||
| import {Footer} from "../../components/Footer/Footer"; | import {Footer} from "../../components/Footer/Footer"; | ||||||
|  |  | ||||||
| import arrow from "../../images/right-arrow.png"; |  | ||||||
| import arrowSwitchDate from "../../images/arrowViewReport.png"; |  | ||||||
| import {apiRequest} from "../../api/request"; | import {apiRequest} from "../../api/request"; | ||||||
| import {getCorrectDate, getCreatedDate, hourOfNum} from '../../components/Calendar/calendarHelper' | 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 './viewReport.scss' | ||||||
|  |  | ||||||
| export const ViewReport = () => { | export const ViewReport = () => { | ||||||
|   | |||||||
| @@ -10,7 +10,9 @@ const initialState = { | |||||||
|   positionId: null, |   positionId: null, | ||||||
|   profileInfo: {}, |   profileInfo: {}, | ||||||
|   reportsDates: '', |   reportsDates: '', | ||||||
|   partnerEmployees: [] |   partnerEmployees: [], | ||||||
|  |   partnerRequestId: null, | ||||||
|  |   partnerRequests: [] | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const outstaffingSlice = createSlice({ | export const outstaffingSlice = createSlice({ | ||||||
| @@ -49,11 +51,17 @@ export const outstaffingSlice = createSlice({ | |||||||
|     }, |     }, | ||||||
|     setPartnerEmployees: (state, action) => { |     setPartnerEmployees: (state, action) => { | ||||||
|       state.partnerEmployees = action.payload |       state.partnerEmployees = action.payload | ||||||
|  |     }, | ||||||
|  |     setPartnerRequestId: (state, action) => { | ||||||
|  |       state.partnerRequestId = action.payload | ||||||
|  |     }, | ||||||
|  |     setPartnerRequests: (state, action) => { | ||||||
|  |       state.partnerRequests = action.payload | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
| }); | }); | ||||||
|  |  | ||||||
| export const { tags, profiles, selectedItems, auth, currentCandidate, filteredCandidates, setPositionId, setUserInfo, setProfileInfo, setReportsDates, setPartnerEmployees } = outstaffingSlice.actions; | export const { tags, profiles, selectedItems, auth, currentCandidate, filteredCandidates, setPositionId, setUserInfo, setProfileInfo, setReportsDates, setPartnerEmployees, setPartnerRequestId, setPartnerRequests } = outstaffingSlice.actions; | ||||||
|  |  | ||||||
| export const selectProfiles = (state) => state.outstaffing.profiles; | export const selectProfiles = (state) => state.outstaffing.profiles; | ||||||
| export const selectTags = (state) => state.outstaffing.tags; | export const selectTags = (state) => state.outstaffing.tags; | ||||||
| @@ -66,5 +74,7 @@ export const getProfileInfo = (state) => state.outstaffing.profileInfo; | |||||||
| export const selectUserInfo = (state) => state.outstaffing.userInfo; | export const selectUserInfo = (state) => state.outstaffing.userInfo; | ||||||
| export const getReportsDates = (state) => state.outstaffing.reportsDates; | export const getReportsDates = (state) => state.outstaffing.reportsDates; | ||||||
| export const getPartnerEmployees = (state) => state.outstaffing.partnerEmployees; | export const getPartnerEmployees = (state) => state.outstaffing.partnerEmployees; | ||||||
|  | export const getPartnerRequestId = (state) => state.outstaffing.partnerRequestId; | ||||||
|  | export const getPartnerRequests = (state) => state.outstaffing.partnerRequests; | ||||||
|  |  | ||||||
| export default outstaffingSlice.reducer; | export default outstaffingSlice.reducer; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user