10 Commits

Author SHA1 Message Date
7b4b4f37fc fixes tasks 2024-08-14 17:12:11 +03:00
33af4ebbd6 fixes tasks 2024-08-14 17:12:03 +03:00
5608e4e4f2 Merge pull request 'developer_resume' (#42) from developer_resume into main
Reviewed-on: #42
2024-08-09 21:10:16 +03:00
214d309ffb partner categories fixes 2024-08-09 21:09:02 +03:00
a156557d57 partner categories fixes 2024-08-09 21:08:56 +03:00
1254557a08 Merge branch 'main' of https://git.itguild.info/apuc/guild_front 2024-08-09 15:45:30 +03:00
c22f26f6fe fix timer(Tracker/ModalTicket) fix fileUpload
(Tracker/ModalTicket) fix tgToken(PartnerSettings)
2024-08-09 15:43:51 +03:00
9cb59b61d6 Merge pull request 'developer_resume' (#41) from developer_resume into main
Reviewed-on: #41
2024-08-07 18:07:22 +03:00
4464324ae2 developer resume 2024-08-07 18:06:10 +03:00
4cd3118649 developer resume 2024-08-07 18:06:03 +03:00
13 changed files with 274 additions and 330 deletions

View File

@ -0,0 +1,3 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.4339 2.66676H7.24725L7.03392 2.0001C6.89562 1.60892 6.63908 1.27043 6.29985 1.03154C5.96062 0.792642 5.55549 0.665163 5.14059 0.666763H2.10059C1.57015 0.666763 1.06145 0.877477 0.686373 1.25255C0.3113 1.62762 0.100586 2.13633 0.100586 2.66676V11.3334C0.100586 11.8639 0.3113 12.3726 0.686373 12.7476C1.06145 13.1227 1.57015 13.3334 2.10059 13.3334H11.4339C11.9644 13.3334 12.4731 13.1227 12.8481 12.7476C13.2232 12.3726 13.4339 11.8639 13.4339 11.3334V4.66676C13.4339 4.13633 13.2232 3.62762 12.8481 3.25255C12.4731 2.87748 11.9644 2.66676 11.4339 2.66676ZM12.1006 11.3334C12.1006 11.5102 12.0303 11.6798 11.9053 11.8048C11.7803 11.9299 11.6107 12.0001 11.4339 12.0001H2.10059C1.92378 12.0001 1.75421 11.9299 1.62918 11.8048C1.50416 11.6798 1.43392 11.5102 1.43392 11.3334V2.66676C1.43392 2.48995 1.50416 2.32038 1.62918 2.19536C1.75421 2.07033 1.92378 2.0001 2.10059 2.0001H5.14059C5.28035 1.99974 5.41669 2.04331 5.53034 2.12466C5.64399 2.20601 5.7292 2.32102 5.77392 2.45343L6.13392 3.54676C6.17864 3.67918 6.26385 3.79419 6.3775 3.87553C6.49115 3.95688 6.62749 4.00046 6.76725 4.0001H11.4339C11.6107 4.0001 11.7803 4.07033 11.9053 4.19536C12.0303 4.32038 12.1006 4.48995 12.1006 4.66676V11.3334Z" fill="#52B709"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -39,13 +39,13 @@ export const AuthHeader = () => {
<div className="auth-nav">
<ul>
<li>
<NavLink to={"/stack"}>аутстафинг</NavLink>
<NavLink to={"/stack"}>Аутстафинг</NavLink>
</li>
<li>
<NavLink to={"/tracker-intro"}>трекер</NavLink>
<NavLink to={"/tracker-intro"}>Трекер</NavLink>
</li>
<li>
<NavLink to={"/auth-candidate"}>работа в IT</NavLink>
<NavLink to={"/auth-candidate"}>Работа в IT</NavLink>
</li>
</ul>
</div>

View File

@ -490,18 +490,27 @@ export const ModalTiсket = ({
}, [taskTags]);
async function handleUpload(event) {
const formData = new FormData();
formData.append("uploadFile", event.target.files[0]);
const res = await fetch("https://itguild.info/api/file/upload", {
method: "POST",
body: formData,
headers: { ...getToken() }
});
try {
const formData = new FormData();
formData.append("uploadFile", event.target.files[0]);
const data = await res.json();
const res = await fetch("https://itguild.info/api/file/upload", {
method: "POST",
body: formData,
headers: { ...getToken() }
});
// setUploadedFile(data);
attachFile(data[0].id);
const data = await res.json();
// setUploadedFile(data);
attachFile(data[0].id);
} catch {
showNotification({
show: true,
text: "Неверный формат файла",
type: "error"
});
}
}
// function deleteLoadedFile() {
@ -543,7 +552,7 @@ export const ModalTiсket = ({
function run() {
updateTimerSec++;
if (updateTimerSec > 60) {
if (updateTimerSec > 59) {
updateTimerMinute++;
updateTimerSec = 0;
}
@ -561,7 +570,7 @@ export const ModalTiсket = ({
function correctTimerTime(time) {
if (time < 10) return `0${time}`;
if (time > 10) return time;
if (time >= 10) return time;
}
useEffect(() => {
@ -800,7 +809,7 @@ export const ModalTiсket = ({
name="file"
id="input__file"
type="file"
accept="image/*,.png,.jpg,.svg,.jpeg"
accept="image/*,.png,.jpg,.svg,.jpeg,.doc,.docx,.xls,.xlsx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
className="input__file"
onChange={handleUpload}
/>

View File

@ -381,7 +381,7 @@ export const TicketFullScreen = () => {
function run() {
updateTimerSec++;
if (updateTimerSec > 60) {
if (updateTimerSec > 59) {
updateTimerMinute++;
updateTimerSec = 0;
}
@ -399,7 +399,7 @@ export const TicketFullScreen = () => {
function correctTimerTime(time) {
if (time < 10) return `0${time}`;
if (time > 10) return time;
if (time >= 10) return time;
}
function deleteTaskExecutor() {
@ -479,17 +479,27 @@ export const TicketFullScreen = () => {
}
async function handleUpload(event) {
const formData = new FormData();
formData.append("uploadFile", event.target.files[0]);
const res = await fetch("https://itguild.info/api/file/upload", {
method: "POST",
body: formData,
headers: { ...getToken() }
});
try {
const formData = new FormData();
formData.append("uploadFile", event.target.files[0]);
const data = await res.json();
const res = await fetch("https://itguild.info/api/file/upload", {
method: "POST",
body: formData,
headers: { ...getToken() }
});
setUploadedFile(data);
const data = await res.json();
// setUploadedFile(data);
attachFile(data[0].id);
} catch {
showNotification({
show: true,
text: "Неверный формат файла",
type: "error"
});
}
}
function attachFile() {
@ -774,7 +784,7 @@ export const TicketFullScreen = () => {
name="file"
id="input__file"
type="file"
accept="image/*,.png,.jpg,.svg,.jpeg"
accept="image/*,.png,.jpg,.svg,.jpeg,.doc,.docx,.xls,.xlsx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
className="input__file"
onChange={handleUpload}
/>

View File

@ -844,7 +844,7 @@ export const TrackerModal = ({
)}
{modalType === "create-project" && (
<div>
<div className="title-project">
<div className="title-project" style={{ minWidth: "350px" }}>
<h4>{titleProject}</h4>
<div className="input-container">
<input

View File

@ -88,12 +88,12 @@ export const Landing = () => {
регистрация
</div>
<BurgerButton active={menuActive} setActive={setMenuActive} />
<div className="head__tracker">
<Link className="head__tracker" to="/tracker-intro">
<div>
<img src={tracker} alt="tracker" />
</div>
<span>трекер</span>
</div>
</Link>
<SVG className="head__auth" src={authIcon} />
</div>
<div className="landing__info">

View File

@ -92,13 +92,13 @@ export const PartnerEmployeeReport = () => {
<>
<div className="employee-report__info">
<div className="employee-report__name">
<h2>{userInfo.fio}</h2>
<p>{userInfo.position}</p>
<h2>{userInfo?.userCard.fio}</h2>
<p>{userInfo?.userCard.position.name}</p>
</div>
<div className="employee-report__skills">
{userInfo?.stack &&
userInfo.stack.map((skill, index) => {
return <span key={index}>{skill}</span>;
{userInfo?.userCard?.skillValues &&
userInfo?.userCard?.skillValues.map((skill) => {
return <span key={skill.id}>{skill.skill.name}</span>;
})}
</div>
</div>

View File

@ -34,13 +34,13 @@ export const PartnerSettings = () => {
const [loader, setLoader] = useState(false);
const [tgLoader, setTgLoader] = useState(false);
useEffect(() => {
apiRequest("/user-tg-bot/get-token", {
method: "GET"
}).then((data) => {
setTgToken(data.token);
});
}, []);
// useEffect(() => {
// apiRequest("/user-tg-bot/get-token", {
// method: "GET"
// }).then((data) => {
// setTgToken(data.token);
// });
// }, []);
const setSettings = () => {
if (inputsValue.name.length < 2) {
@ -92,18 +92,43 @@ export const PartnerSettings = () => {
});
};
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(tgToken);
showNotification({
show: true,
text: "Телеграм токен успешно скопирован",
type: "success"
const handleGenerate = async () => {
if (tgToken == undefined) {
setTgLoader(true);
apiRequest("/user-tg-bot/get-token", {
method: "GET"
}).then((data) => {
setTgToken(data.token);
showNotification({
show: true,
text: "Телеграм токен успешно сгенерирован",
type: "success"
});
setTgLoader(false);
});
} catch (err) {
}
};
const handleCopy = async () => {
if (tgToken !== undefined) {
try {
await navigator.clipboard.writeText(tgToken);
showNotification({
show: true,
text: "Телеграм токен успешно скопирован",
type: "success"
});
} catch (err) {
showNotification({
show: true,
text: "Ошибка копирования",
type: "error"
});
}
} else {
showNotification({
show: true,
text: "Ошибка копирования",
text: "Необходимо сгенерировать код",
type: "error"
});
}
@ -226,12 +251,18 @@ export const PartnerSettings = () => {
<Loader style={"green"} width={"40px"} height={"40px"} />
) : (
<BaseButton
onClick={handleCopy}
onClick={handleGenerate}
styles={"settings__buttons-save"}
>
Скопировать
Сгенерировать
</BaseButton>
)}
<BaseButton
onClick={handleCopy}
styles={"settings__buttons-save"}
>
Скопировать
</BaseButton>
</div>
<div className="settings__agreement-tg">
<a href="#" target="_blank" rel="noopener noreferrer">

View File

@ -94,8 +94,7 @@
width: 100%;
display: flex;
flex-direction: row;
justify-content: flex-start;
gap: 20px;
justify-content: space-around;
margin: 30px 0 20px;
&-cancel,
@ -130,21 +129,11 @@
}
}
@media (max-width: 800px) {
&__input {
width: 95%;
}
@media (max-width: 440px) {
&__buttons {
margin: 15px 0 14px 0;
width: 100%;
flex-direction: column-reverse;
flex-direction: column;
gap: 10px;
align-items: center;
gap: 0px;
&-save {
margin-bottom: 15px;
}
}
}
}

View File

@ -6,7 +6,6 @@ import { useTheme } from "@table-library/react-table-library/theme";
import React, { useEffect, useState } from "react";
import { Link, Navigate } from "react-router-dom";
import { LEVELS, SKILLS } from "@utils/constants";
import { urlForLocal } from "@utils/helper";
import { apiRequest } from "@api/request";
@ -18,26 +17,12 @@ import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadc
import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
import rightArrow from "assets/icons/arrows/arrowRight.svg";
import folder from "assets/icons/folder.svg";
import report from "assets/icons/report.svg";
// import PartnerPersonCard from "@components/PartnerPersonCard/PartnerPersonCard";
// import { useDispatch } from "react-redux";
// import { setPartnerEmployees } from "@redux/outstaffingSlice";
// import rightArrow from "assets/icons/arrows/arrowRight.svg";
// import avatarImg from "assets/images/avatarMok.png";
// import AdminImg from "assets/images/partnerProfile/PersonalAdmin.svg";
// import ArchitectureImg from "assets/images/partnerProfile/PersonalArchitecture.svg";
// import CopyImg from "assets/images/partnerProfile/PersonalCopy.svg";
// import DesignImg from "assets/images/partnerProfile/PersonalDesign.svg";
// import FrontendImg from "assets/images/partnerProfile/PersonalFrontend.svg";
// import ManageImg from "assets/images/partnerProfile/PersonalMng.svg";
// import SmmImg from "assets/images/partnerProfile/PersonalSMM.svg";
// import TestImg from "assets/images/partnerProfile/PersonalTesters.svg";
// import BackEndImg from "assets/images/partnerProfile/personalBackEnd.svg";
import "./partnerСategories.scss";
export const PartnerCategories = () => {
// const dispatch = useDispatch();
if (localStorage.getItem("role_status") !== "18") {
return <Navigate to="/profile" replace />;
}
@ -46,7 +31,7 @@ export const PartnerCategories = () => {
const theme = useTheme(getTheme());
const [nodes, setNodes] = useState([]);
const [initialNodes, setInitialNodes] = useState([]);
const [activeTab, setActiveTab] = useState("Все");
const [activeTab, setActiveTab] = useState(0);
const [search, setSearch] = useState("");
@ -65,32 +50,39 @@ export const PartnerCategories = () => {
{
label: "",
renderCell: (item) => (
<img
className="table__avatar"
src={urlForLocal(item?.employee.avatar)}
alt="avatar"
/>
<Link to={`/profile/summary/${item.user_id}`}>
<img
className="table__avatar"
src={urlForLocal(item?.employee.avatar)}
alt="avatar"
/>
</Link>
)
},
{
label: "Данные",
renderCell: (item) => (
<div className="table__info">
<Link className="table__info" to={`/profile/summary/${item.user_id}`}>
<p>{item?.employee.fio}</p>
<span>
{LEVELS[item?.resume.userCard.level]} /{" "}
{SKILLS[item?.resume.userCard.position_id]}
{item?.employee.level_title} / {item?.employee.position.name}
</span>
</div>
</Link>
)
// sort: { sortKey: "NAME" }
},
{
label: "Участвует в проекте",
renderCell: (item) => (
<div className="table__project">
{item.resume.userCard.at_project ? (
<div>item.resume.userCard.at_project</div>
{item?.employee.projects.length ? (
item.employee.projects.map((project) => {
return (
<div className="table__project__item" key={project.id}>
<img src={folder} alt="folder" />{" "}
<p>{project.project.name}</p>
</div>
);
})
) : (
<span>Нет проектов</span>
)}
@ -143,23 +135,9 @@ export const PartnerCategories = () => {
useEffect(() => {
setLoader(true);
apiRequest("/project/my-employee").then((el) => {
const fetchResumes = async () => {
const promises = el.managerEmployees.map(async (manager) => {
const resume = await apiRequest(`/resume?userId=${manager.user_id}`);
return { ...manager, resume }; // Возвращаем объект с добавленным ключом resume
});
try {
const updatedManagers = await Promise.all(promises);
setInitialNodes(updatedManagers);
setNodes(updatedManagers);
setLoader(false);
} catch (error) {
console.error("Ошибка при получении резюме:", error);
}
};
fetchResumes();
setNodes(el.managerEmployees);
setInitialNodes(el.managerEmployees);
setLoader(false);
});
}, []);
@ -178,108 +156,6 @@ export const PartnerCategories = () => {
console.log(action, state);
}
// const [personalInfoItems] = useState([
// {
// title: "Backend разработчики",
// link: "/profile/categories/employees",
// description:
// "Java PHP Python C# React Vue.js NodeJs Golang Ruby JavaScript",
// available: true,
// img: BackEndImg
// },
// {
// title: "Frontend разработчики",
// link: "/profile/categories/employees",
// description:
// "Java PHP Python C# React Vue.js NodeJs Golang Ruby JavaScript",
// available: true,
// img: FrontendImg
// },
// {
// title: "Архитектура проектов",
// link: "/profile/categories/employees",
// description: "Потоки данных ER ERP CRM CQRS UML BPMN",
// available: true,
// img: ArchitectureImg
// },
// {
// title: "Дизайн проектов",
// link: "/profile/categories/employees",
// description:
// "Java PHP Python C# React Vue.js NodeJs Golang Ruby JavaScript",
// available: true,
// img: DesignImg
// },
// {
// title: "Тестирование проектов",
// link: "/profile/add-request",
// description: "SQL Postman TestRail Kibana Ручное тестирование",
// available: false,
// img: TestImg
// },
// {
// title: "Администрирование проектов",
// link: "/profile/add-request",
// description: "DevOps ELK Kubernetes Docker Bash Apache Oracle Git",
// available: false,
// img: AdminImg
// },
// {
// title: "Управление проектом",
// link: "/profile/add-request",
// description: "Scrum Kanban Agile Miro CustDev",
// available: false,
// img: ManageImg
// },
// {
// title: "Копирайтинг проектов",
// link: "/profile/add-request",
// description: "Теги Заголовок H1 Дескриптор Абзац Сценарий",
// available: false,
// img: CopyImg
// },
// {
// title: "Реклама и SMM",
// link: "/profile/add-request",
// description:
// "Java PHP Python C# React Vue.js NodeJs Golang Ruby JavaScript",
// available: false,
// img: SmmImg
// }
// ]);
// const [mokPersons] = useState([
// {
// personAvatar: avatarImg,
// name: "Макаренко Дмитрий",
// qualification: "PHP Backend - разработчик",
// level: "Middle",
// project: "Админка НВД Консалтинг",
// tasks_in_progress: 5,
// month_hours: 140,
// id: 1
// },
// {
// personAvatar: avatarImg,
// name: "Макаренко Дмитрий",
// qualification: "PHP Backend - разработчик",
// level: "Middle",
// project: "Админка НВД Консалтинг",
// tasks_in_progress: 5,
// month_hours: 140,
// id: 2
// },
// {
// personAvatar: avatarImg,
// name: "Макаренко Дмитрий",
// qualification: "PHP Backend - разработчик",
// level: "Middle",
// project: "Админка НВД Консалтинг",
// tasks_in_progress: 5,
// month_hours: 140,
// id: 3
// }
// ]);
return (
<div className="partner-categories">
<ProfileHeader />
@ -311,11 +187,11 @@ export const PartnerCategories = () => {
<div className="table__tabs">
<div
onClick={() => {
setActiveTab("Все");
setActiveTab(0);
setNodes(initialNodes);
}}
className={
activeTab === "Все"
activeTab === 0
? "table__tab table__tab--active"
: "table__tab"
}
@ -329,8 +205,7 @@ export const PartnerCategories = () => {
setActiveTab(tab.name);
setNodes(
initialNodes.filter(
(item) =>
item.resume.userCard.position_id === tab.value
(item) => item.employee.position.id === tab.value
)
);
}}
@ -353,54 +228,61 @@ export const PartnerCategories = () => {
sort={sort}
pagination={pagination}
/>
<div className="table__pagination">
<button
className={
pagination.state.page === 0 ? "switch disable" : "switch"
}
type="button"
disabled={pagination.state.page === 0}
onClick={() =>
pagination.fns.onSetPage(pagination.state.page - 1)
}
>
{"<"}
</button>
<span className="table__pages">
{pagination.state.getPages(data.nodes).map((_, index) => (
{Boolean(nodes.length) &&
pagination.state.getPages(data.nodes).length > 1 && (
<div className="table__pagination">
<button
key={index}
type="button"
className={
pagination.state.page === index
? "page page--active "
: "page"
pagination.state.page === 0
? "switch disable"
: "switch"
}
type="button"
disabled={pagination.state.page === 0}
onClick={() =>
pagination.fns.onSetPage(pagination.state.page - 1)
}
onClick={() => pagination.fns.onSetPage(index)}
>
{index + 1}
{"<"}
</button>
))}
</span>
<button
className={
pagination.state.page + 1 ===
pagination.state.getPages(data.nodes).length
? "switch disable"
: "switch"
}
type="button"
disabled={
pagination.state.page + 1 ===
pagination.state.getPages(data.nodes).length
}
onClick={() =>
pagination.fns.onSetPage(pagination.state.page + 1)
}
>
{">"}
</button>
</div>
<span className="table__pages">
{pagination.state
.getPages(data.nodes)
.map((_, index) => (
<button
key={index}
type="button"
className={
pagination.state.page === index
? "page page--active "
: "page"
}
onClick={() => pagination.fns.onSetPage(index)}
>
{index + 1}
</button>
))}
</span>
<button
className={
pagination.state.page + 1 ===
pagination.state.getPages(data.nodes).length
? "switch disable"
: "switch"
}
type="button"
disabled={
pagination.state.page + 1 ===
pagination.state.getPages(data.nodes).length
}
onClick={() =>
pagination.fns.onSetPage(pagination.state.page + 1)
}
>
{">"}
</button>
</div>
)}
</>
) : (
<div className="partner-categories__empty">
@ -411,39 +293,6 @@ export const PartnerCategories = () => {
</Link>
</div>
)}
{/*{personalInfoItems.map((item, index) => {*/}
{/* return (*/}
{/* <Link*/}
{/* to={item.link}*/}
{/* key={index}*/}
{/* className={*/}
{/* item.available*/}
{/* ? "partner-categories__item item"*/}
{/* : "partner-categories__item item item__disable"*/}
{/* }*/}
{/* onClick={() => {*/}
{/* dispatch(setPartnerEmployees(mokPersons));*/}
{/* }}*/}
{/* >*/}
{/* <div className="item__title">*/}
{/* <img src={item.img} alt={item.title} />*/}
{/* <h4>{item.title}</h4>*/}
{/* </div>*/}
{/* <div className="item__info">*/}
{/* <p>{item.description}</p>*/}
{/* <div className="more">*/}
{/* <img src={rightArrow} alt="arrow" />*/}
{/* </div>*/}
{/* </div>*/}
{/* {!item.available && (*/}
{/* <div className="item__disable-hover">*/}
{/* <p>У вас нет персонала из категории</p>*/}
{/* <button>Подобрать</button>*/}
{/* </div>*/}
{/* )}*/}
{/* </Link>*/}
{/* );*/}
{/*})}*/}
</div>
)}
</div>

View File

@ -255,6 +255,26 @@
font-size: 14px;
font-weight: 500;
line-height: 17.5px;
display: flex;
flex-wrap: wrap;
gap: 11px;
&__item {
border-radius: 5px;
padding: 8px;
color: rgba(46, 58, 89, 1);
font-size: 14px;
border: 1px solid rgba(237, 237, 237, 1);
display: flex;
gap: 8px;
p {
max-width: 100px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
&__action {

View File

@ -2,7 +2,7 @@ import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
import { CKEditor } from "@ckeditor/ckeditor5-react";
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { Navigate } from "react-router-dom";
import { useParams } from "react-router-dom";
import { getProfileInfo } from "@redux/outstaffingSlice";
@ -27,19 +27,18 @@ import avatarMok from "assets/images/avatarMok.webp";
import "./summary.scss";
export const Summary = () => {
if (localStorage.getItem("role_status") === "18") {
return <Navigate to="/profile" replace />;
}
const profileInfo = useSelector(getProfileInfo);
const [openGit, setOpenGit] = useState(false);
const [gitInfo, setGitInfo] = useState([]);
const [editSummaryOpen, setEditSummaryOpen] = useState(false);
const [editSkills, setEditSkills] = useState(false);
const [userInfo, setUserInfo] = useState({});
const [summary, setSummary] = useState("");
const [selectedSkills, setSelectedSkills] = useState([]);
const [selectSkillsOpen, setSelectSkillsOpen] = useState(false);
const [skillsList, seSkillsList] = useState([]);
const { showNotification } = useNotification();
const { id: userId } = useParams();
useEffect(() => {
apiRequest(
@ -48,8 +47,10 @@ export const Summary = () => {
}, []);
useEffect(() => {
setSummary(profileInfo.vc_text);
setSelectedSkills(profileInfo.skillValues);
if (!userId) {
setSummary(profileInfo.vc_text);
setSelectedSkills(profileInfo.skillValues);
}
}, [profileInfo]);
useEffect(() => {
@ -58,6 +59,22 @@ export const Summary = () => {
});
}, []);
useEffect(() => {
if (userId) {
apiRequest(`/resume?userId=${userId}`).then((res) => {
setUserInfo({
photo: res.userCard.photo,
fio: res.userCard.fio,
specification: res.userCard.specification,
level: res.userCard.level_title,
position: res.userCard.position.name
});
setSummary(res.userCard.vc_text);
setSelectedSkills(res.userCard.skillValues);
});
}
}, [userId]);
const addSkill = (skill) => {
const isSkillFound = selectedSkills.some(
(item) => item.skill_id == skill.id
@ -133,7 +150,9 @@ export const Summary = () => {
<div className="summary__person">
<img
src={
profileInfo?.photo
userId
? urlForLocal(userInfo.photo)
: profileInfo?.photo
? urlForLocal(profileInfo.photo)
: avatarMok
}
@ -141,12 +160,18 @@ export const Summary = () => {
alt="avatar"
/>
<p className="summary__name">
{profileInfo?.fio || profileInfo?.username}{" "}
{profileInfo.specification}
{userId
? userInfo.fio
: profileInfo?.fio || profileInfo?.username}{" "}
{userId ? userInfo.specification : profileInfo.specification}
</p>
<hr />
<div className="summary__direction">Front End</div>
<div className="summary__level">Middle+</div>
<div className="summary__direction">
{userId ? userInfo.position : profileInfo?.position?.name}
</div>
<div className="summary__level">
{userId ? userInfo.level : profileInfo?.level_title}
</div>
</div>
{!openGit && (
<button className="summary__git" onClick={() => setOpenGit(true)}>
@ -159,17 +184,19 @@ export const Summary = () => {
<div className="summary__skills skills__section">
<div className="summary__sections__head">
<h3>Основной стек</h3>
<button
className={editSkills ? "edit" : ""}
onClick={() => {
if (editSkills) {
setSkills();
}
setEditSkills(!editSkills);
}}
>
{editSkills ? "Сохранить" : "Редактировать"}
</button>
{!userId && (
<button
className={editSkills ? "edit" : ""}
onClick={() => {
if (editSkills) {
setSkills();
}
setEditSkills(!editSkills);
}}
>
{editSkills ? "Сохранить" : "Редактировать"}
</button>
)}
</div>
<div className="skills__section__items">
{editSkills ? (
@ -239,17 +266,19 @@ export const Summary = () => {
<div className="experience__block">
<div className="summary__sections__head">
<h3>Опыт работы</h3>
<button
className={editSummaryOpen ? "edit" : ""}
onClick={() => {
if (editSummaryOpen) {
editSummary();
}
setEditSummaryOpen(!editSummaryOpen);
}}
>
{editSummaryOpen ? "Сохранить" : "Редактировать"}
</button>
{!userId && (
<button
className={editSummaryOpen ? "edit" : ""}
onClick={() => {
if (editSummaryOpen) {
editSummary();
}
setEditSummaryOpen(!editSummaryOpen);
}}
>
{editSummaryOpen ? "Сохранить" : "Редактировать"}
</button>
)}
</div>
{editSummaryOpen ? (
<CKEditor

View File

@ -20,6 +20,7 @@ import { Profile } from "@pages/Profile/Profile";
import { ProjectTracker } from "@pages/ProjectTracker/ProjectTracker";
import { Stack } from "@pages/Stack/Stack";
import Statistics from "@pages/Statistics/Statistics";
import { Summary } from "@pages/Summary/Summary";
import { Tracker } from "@pages/Tracker/Tracker";
import { TrackerIntro } from "@pages/TrackerIntro/TrackerIntro";
import { ViewReport } from "@pages/ViewReport/ViewReport";
@ -27,6 +28,7 @@ import { WelcomePage } from "@pages/WelcomePage/WelcomePage";
import { Calendar } from "@components/Calendar/Calendar";
import { Candidate } from "@components/Candidate/Candidate";
import TicketFullScreen from "@components/Modal/Tracker/TicketFullScreen/TicketFullScreen";
export const PartnerPage = () => {
return (
@ -45,6 +47,7 @@ export const PartnerPage = () => {
<Route exact path="/candidate/:id/form" element={<FormPage />} />
<Route path="/:userId/calendar" element={<Calendar />} />
<Route exact path="/tracker/task/:id" element={<TicketFullScreen />} />
<Route
exact
path="/tracker/project/:id/task/:taskId"
@ -64,6 +67,7 @@ export const PartnerPage = () => {
<Route exact path="requests-edit" element={<PartnerAddRequest />} />
<Route exact path="requests-bid" element={<PartnerBid />} />
<Route exact path="employees" element={<PartnerCategories />} />
<Route exact path="summary/:id" element={<Summary />} />
<Route
exact
path="employees/report/:uuid"