Merge pull request #77 from apuc/add-blog

Add blog page
This commit is contained in:
NikoM1k 2023-05-02 20:36:45 +03:00 committed by GitHub
commit bdd386cbbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 614 additions and 20 deletions

View File

@ -15,6 +15,7 @@ import ReportForm from "./components/ReportForm/ReportForm";
import FreeDevelopers from "./components/UI/FreeDevelopers/FreeDevelopers";
import { TicketFullScreen } from "./components/UI/TicketFullScreen/TicketFullScreen";
import { ProfileCalendar } from "./components/ProfileCalendar/ProfileCalendar";
import Article from "./pages/Article/Article";
import FormPage from "./pages/FormPage/FormPage.js";
import SingleReportPage from "./pages/SingleReportPage/SingleReportPage";
import { QuizPage } from "./pages/quiz/QuizPage";
@ -35,6 +36,7 @@ import { AuthForCandidate } from "./pages/AuthForCandidate/AuthForCandidate";
import { RegistrationForCandidate } from "./pages/RegistrationForCandidate/RegistrationForCandidate";
import { ProfileCandidate } from "./pages/ProfileCandidate/ProfileCandidate";
import { PassingTests } from "./pages/quiz/PassingTests";
import Blog from "./pages/Blog/Blog";
import { ProjectTracker } from "./pages/ProjectTracker/ProjectTracker";
import "./assets/global.scss";
@ -51,10 +53,14 @@ const App = () => {
<Route exact path="/worker/:id" element={<FreeDevelopers />} />
<Route
exact
path="/tracker/:id"
path="/tracker/task/:id"
element={<TicketFullScreen />}
></Route>
<Route exact path="/tracker/project/:id" element={<ProjectTracker/>}/>
<Route
exact
path="/tracker/project/:id"
element={<ProjectTracker />}
/>
<Route exact path="/auth-candidate" element={<AuthForCandidate />} />
<Route
exact
@ -62,6 +68,9 @@ const App = () => {
element={<RegistrationForCandidate />}
/>
<Route exact path="/blog" element={<Blog />}></Route>
<Route exact path="/blog/article/:id" element={<Article />}></Route>
<Route exact path="/candidate/:id" element={<Candidate />} />
<Route exact path="/candidate/:id/form" element={<FormPage />} />
<Route path="/:userId/calendar" element={<Calendar />} />

View File

@ -4,6 +4,7 @@ import arrow from "../../images/sideBarArrow.svg";
import LogoITguild from "../../images/LogoITguild.svg";
import "./sidebar.scss";
import { Link } from "react-router-dom";
export const SideBar = () => {
const [active, setActive] = useState(false);
@ -46,10 +47,10 @@ export const SideBar = () => {
</div>
<ul className="auth-body__navigation">
<li>
<a href="#">Вход для партнеров</a>
<Link to={"/auth"}>Вход для партнеров</Link>
</li>
<li>
<a href="#">Кабинет разработчика</a>
<Link to={"/auth"}>Кабинет разработчика</Link>
</li>
<li>
<a href="#">Школа</a>
@ -61,7 +62,7 @@ export const SideBar = () => {
<a href="#">Контакты</a>
</li>
<li>
<a href="#">Блог</a>
<Link to={"/blog"}>Блог</Link>
</li>
<li>
<a href="#">FAQ</a>

View File

@ -20,11 +20,13 @@
}
.auth-title {
position: relative;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
height: 80%;
z-index: 9999;
.text {
display: flex;
@ -108,8 +110,10 @@
.auth-body {
padding: 40px;
display: none;
z-index: -1;
visibility: hidden;
transition: 0.2s ease-in-out;
opacity: 0;
z-index: 99;
position: absolute;
top: 0;
left: 0;
@ -173,6 +177,9 @@
}
.auth-body.active {
visibility: visible;
transition: 0.1s ease-in-out;
opacity: 1;
display: flex;
width: 424px;
left: 140px;
@ -184,6 +191,6 @@
@media (max-width: 1375px) {
left: 0;
width: 100%;
height: 535px;
height: 605px;
}
}

View File

@ -0,0 +1,22 @@
import React from "react";
import cardCalendar from "../../../images/cardCalendar.svg";
import { Link } from "react-router-dom";
import "./cardArticle.scss";
export const CardArticle = ({ images, title, data, id }) => {
return (
<div className="card-article">
<Link to={`/blog/article/${id}`}>
<img src={images} />
<h5>{title}</h5>
<div className="card-article__data">
<img src={cardCalendar} />
<p>{data}</p>
</div>
</Link>
</div>
);
};
export default CardArticle;

View File

@ -0,0 +1,36 @@
.card-article {
background: #ffffff;
border-radius: 12px;
width: 344px;
margin-bottom: 24px;
transition: 0.4s;
a {
color: #000000;
}
&:hover {
cursor: pointer;
transform: scale(1.05);
transition: 0.4s;
a {
color: #000000;
}
}
h5 {
font-style: normal;
font-weight: 500;
font-size: 17px;
line-height: 20px;
padding: 12px 16px 8px 16px;
}
&__data {
display: flex;
padding: 0 0 14px 16px;
img {
margin-right: 9px;
}
}
}

View File

@ -175,7 +175,6 @@
.auth-body.active {
left: 0;
width: 100%;
height: 535px;
}
.auth-body {

View File

@ -22,7 +22,13 @@ import fullScreen from "../../../images/inFullScreen.svg";
import "./ModalTicket.scss";
export const ModalTiсket = ({ active, setActive, task, projectId, projectName }) => {
export const ModalTiсket = ({
active,
setActive,
task,
projectId,
projectName,
}) => {
const dispatch = useDispatch();
const [tiket] = useState({
name: "Разработка трекера",
@ -44,16 +50,16 @@ export const ModalTiсket = ({ active, setActive, task, projectId, projectName }
const [addSubtask, setAddSubtask] = useState(false);
function deleteTask() {
apiRequest('/task/update-task', {
method: 'PUT',
apiRequest("/task/update-task", {
method: "PUT",
data: {
task_id: task.id,
status: 0
}
status: 0,
},
}).then((res) => {
setActive(false)
dispatch(setProjectBoardFetch(projectId))
})
setActive(false);
dispatch(setProjectBoardFetch(projectId));
});
}
return (

10
src/images/blogArrow.svg Normal file
View File

@ -0,0 +1,10 @@
<svg width="27" height="27" viewBox="0 0 27 27" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle opacity="0.3" cx="13.5" cy="13.5" r="13.5" transform="matrix(-1 0 0 1 27 0)" fill="#807777"/>
<rect x="18.5625" y="16.3125" width="10.0195" height="5.625" transform="rotate(180 18.5625 16.3125)" fill="url(#pattern0)"/>
<defs>
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
<use xlink:href="#image0_1082_1300" transform="matrix(0.0244088 0 0 0.0434783 -0.000381388 0)"/>
</pattern>
<image id="image0_1082_1300" width="41" height="23" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACkAAAAXCAMAAAChzpYZAAAAAXNSR0IB2cksfwAAAEJQTFRFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjuH28gAAABZ0Uk5TAEK0Cvb/vgaIlxC7oNwcwg/J2f1bS4SvOREAAABWSURBVHicY2CAA0YmZgaiACMLKxs7kQpZOUYV4lPIyUUYgBUSBRiYiFTIysDMBiS5eQgDBrBSXj5ifESSUn6ilQoIDi2lQkTlDqBSYRGiFAKViuKVBgCepwfqGDtvmgAAAABJRU5ErkJggg=="/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 KiB

13
src/images/yandexZen.svg Normal file
View File

@ -0,0 +1,13 @@
<svg width="39" height="39" viewBox="0 0 39 39" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1082_1494)">
<path d="M0 19.021V17.1032C0.3039 16.8841 0.206332 16.5274 0.267112 16.2395C2.02653 7.82463 7.07288 2.56716 15.3933 0.428659C15.91 0.294303 16.5002 0.404667 16.9432 0C17.6358 0 18.3284 0 19.021 0C19.0513 0.0383874 19.1073 0.0783743 19.1057 0.116762C19.0386 3.38449 19.0354 6.66021 18.354 9.87836C17.3959 14.3953 14.736 17.2599 10.1599 18.274C7.99578 18.7538 5.80449 18.9602 3.59882 19.0114C2.40081 19.0402 1.19961 19.2113 0 19.021Z" fill="#040505"/>
<path d="M0 20.2989C3.3541 20.2797 6.6986 20.3724 9.99992 21.0666C14.6448 22.0423 17.3847 24.8989 18.3524 29.4942C19.0034 32.5812 19.0338 35.7242 19.0977 38.8624C19.0977 38.9071 19.0481 38.9535 19.021 38.9999H16.9432C16.7721 38.6816 16.433 38.7632 16.1755 38.7184C8.40044 37.3812 2.16569 31.4424 0.454251 23.7649C0.326293 23.1939 0.415863 22.5541 0 22.0567V20.2989Z" fill="#040505"/>
<path d="M38.9999 19.021C37.7284 19.1729 36.4552 19.0434 35.1868 18.9938C33.0355 18.9106 30.8874 18.7187 28.7921 18.1828C24.2416 17.0184 21.764 13.973 20.9419 9.4545C20.3741 6.32752 20.2637 3.16856 20.2989 0H21.7368C21.772 0.180741 21.9192 0.147152 22.0439 0.164746C30.0685 1.26678 36.3912 6.91773 38.4289 14.7664C38.6305 15.5437 38.6033 16.3754 38.9999 17.1016V19.0194V19.021Z" fill="#040505"/>
<path d="M20.2992 39.0001C20.2912 35.7788 20.3984 32.5686 21.0622 29.3985C22.081 24.5329 25.1296 21.8154 29.9425 20.942C32.9383 20.3982 35.9645 20.2687 39.0003 20.2991V22.0569C38.6852 22.2296 38.7652 22.5671 38.7204 22.8246C37.3384 30.6685 31.4316 36.8456 23.6933 38.5555C23.0423 38.6994 22.3418 38.645 21.7372 38.9985H20.2992V39.0001Z" fill="#040505"/>
</g>
<defs>
<clipPath id="clip0_1082_1494">
<rect width="39" height="39" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,138 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import AuthHeader from "../../components/AuthHeader/AuthHeader";
import SideBar from "../../components/SideBar/SideBar";
import { Footer } from "../../components/Footer/Footer";
import { ProfileBreadcrumbs } from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs";
import CardArticle from "../../components/UI/CardArticle/CardArticle";
import mockImgArticle from "../../images/mockImgArticle.png";
import rightArrow from "../../images/right-arrow.png";
import yandexZen from "../../images/yandexZen.svg";
import cardCalendar from "../../images/cardCalendar.svg";
import cardImg1 from "../../images/cardArticleItem.png";
import cardImg2 from "../../images/cardArticleItem2.png";
import cardImg3 from "../../images/cardArticleItem3.png";
import "./article.scss";
export const Article = ({}) => {
const [article] = useState([
{
image: cardImg1,
title: "Аутстаффинг джунов: почему это выгодно",
data: "1 марта, 2023",
},
{
image: cardImg2,
title: "Аутстаффинг джунов: почему это выгодно",
data: "1 марта, 2023",
},
{
image: cardImg3,
title: "Аутстаффинг джунов: почему это выгодно",
data: "1 марта, 2023",
},
]);
return (
<div className="article-blog">
<AuthHeader />
<SideBar />
<div className="container">
<div className="article-blog__breadCrumbs">
<ProfileBreadcrumbs
links={[
{ name: "Главная", link: "/auth" },
{ name: "Блог", link: "/blog" },
{
name: "Аутстаффинг джунов: почему это выгодно",
link: "/blog",
},
]}
/>
</div>
<div className="article-blog__title">
<h1>Аутстаффинг джунов: почему это выгодно</h1>
</div>
<div className="article-blog__return">
<Link to={"/blog"} className="article-blog__return-link">
<div className="article-blog__return-arrow">
<img src={rightArrow} />
</div>
<span>вернуться к списку статей</span>
</Link>
</div>
<div className="article-blog__body">
<div className="article-blog__body-text">
<p>
Нет, мы работаем только с юридическими лицами и индивидуальными
предпринимателями и тщательно проверяем своих партнеров.
Партнерами являются агентства, которые специализируются на
оказании услуг в формате аутстафф-модели и обладают глубокой
экспертизой в разработке и внедрении ИТ-проектов.
</p>
</div>
<img src={mockImgArticle} className="article-blog__body-img" />
<div className="article-blog__body-text">
<p>
С одной стороны, зарплаты в сфере разработки растут, с другой
стороны, появляется огромное количество новичков, которые хотят
легко и просто войти в ИТ-сферу на волне востребованности и
больших зарплат. Разумеется, это приводит к осторожному отношению
работодателя к выпускникам различных курсов. Нет такого курса,
который даст на 100% готового джуна, слишком многое завязано на
личной инициативе, обучаемости и желании.
</p>
<br />
<p>
В итоге получается, что взгляды работодателя и потенциального
сотрудника расходятся: работодатель не хочет открывать ящик
пандоры, на который нужно тратить время, а работник, только
прошедший курсы, испытывает эффект завышенных ожиданий и имеет
зачастую неадекватные запросы.
</p>
</div>
<div className="article-blog__body-footer">
<div className="yandex">
<img src={yandexZen} />
<div className="yandex__text">
<p>Читать на Дзен</p>
<span>dzen.ru</span>
</div>
</div>
<div className="publication-date">
<img src={cardCalendar} />
<p>1 марта, 2023</p>
</div>
</div>
<div className="more-articles">
<h1>Читайте также</h1>
<div className="more-articles__arrow">
<img src={rightArrow} />
</div>
</div>
<div className="blog__body">
{article.map((item, index) => {
return (
<CardArticle
images={item.image}
title={item.title}
data={item.data}
key={index}
id={index}
/>
);
})}
</div>
</div>
</div>
<Footer />
</div>
);
};
export default Article;

View File

@ -0,0 +1,166 @@
.article-blog {
background: #f1f1f1;
&__breadCrumbs {
margin-top: 30px;
@media (max-width: 1375px) {
margin-top: 0;
padding-top: 110px;
}
@media (max-width: 600px) {
display: none;
}
}
&__title {
margin: 42px 0 44px 0;
h1 {
font-weight: 500;
font-size: 38px;
line-height: 32px;
}
@media (max-width: 600px) {
padding-top: 80px;
}
}
&__return {
display: flex;
align-items: center;
&-link {
display: flex;
align-items: center;
}
span {
font-weight: 400;
font-size: 12px;
line-height: 20px;
color: #6f6f6f;
margin-left: 19px;
}
&-arrow {
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
border-radius: 44px;
background: #8dc63f78;
img {
width: 45%;
}
}
}
&__body {
display: flex;
flex-direction: column;
&-text {
margin-top: 30px;
padding: 33px;
background: #ffffff;
text-align: justify;
border-radius: 12px;
p {
font-style: normal;
font-weight: 400;
font-size: 20px;
line-height: 24px;
}
}
&-img {
margin-top: 16px;
}
&-footer {
margin: 30px 0 78px 25px;
display: flex;
.yandex {
display: flex;
align-items: center;
img {
margin: 0;
width: 39px;
height: 39px;
}
&__text {
margin-left: 18px;
p {
font-weight: 500;
font-size: 16px;
line-height: 32px;
}
}
}
.publication-date {
margin-left: 76px;
display: flex;
align-items: center;
p {
font-weight: 400;
font-size: 14px;
line-height: 20px;
}
img {
margin: 0 16px 0 0;
}
}
@media (max-width: 600px) {
margin: 20px 0 20px 0;
flex-direction: column;
.publication-date {
margin: 0;
}
.yandex {
margin: 0 0 10px 0;
}
}
}
.more-articles {
display: flex;
align-items: center;
margin-bottom: 49px;
h1 {
font-weight: 500;
font-size: 33px;
line-height: 32px;
}
&__arrow {
margin: 0 0 0 21px;
display: flex;
justify-content: center;
align-items: center;
width: 27px;
height: 27px;
background: #80777770;
border-radius: 44px;
img {
width: 50%;
transform: rotate(180deg);
}
}
}
}
}

106
src/pages/Blog/Blog.jsx Normal file
View File

@ -0,0 +1,106 @@
import React, { useState } from "react";
import AuthHeader from "../../components/AuthHeader/AuthHeader";
import SideBar from "../../components/SideBar/SideBar";
import { ProfileBreadcrumbs } from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs";
import { Footer } from "../../components/Footer/Footer";
import CardArticle from "../../components/UI/CardArticle/CardArticle";
// import arrowRight from "../../images/arrowRight.png";
import blogArrow from "../../images/blogArrow.svg";
import cardImg1 from "../../images/cardArticleItem.png";
import cardImg2 from "../../images/cardArticleItem2.png";
import cardImg3 from "../../images/cardArticleItem3.png";
import cardImg4 from "../../images/cardArticleItem4.png";
import cardImg5 from "../../images/cardArticleItem5.png";
import cardImg6 from "../../images/cardArticleItem6.png";
import "./blog.scss";
export const Blog = ({}) => {
const [article] = useState([
{
image: cardImg1,
title: "Аутстаффинг джунов: почему это выгодно",
data: "1 марта, 2023",
},
{
image: cardImg2,
title: "Аутстаффинг джунов: почему это выгодно",
data: "1 марта, 2023",
},
{
image: cardImg3,
title: "Аутстаффинг джунов: почему это выгодно",
data: "1 марта, 2023",
},
{
image: cardImg4,
title: "Аутстаффинг джунов: почему это выгодно",
data: "1 марта, 2023",
},
{
image: cardImg5,
title: "Аутстаффинг джунов: почему это выгодно",
data: "1 марта, 2023",
},
{
image: cardImg6,
title: "Аутстаффинг джунов: почему это выгодно",
data: "1 марта, 2023",
},
]);
return (
<div className="blog">
<AuthHeader />
<SideBar />
<div className="container">
<div className="blog__breadCrumbs">
<ProfileBreadcrumbs
links={[
{ name: "Главная", link: "/auth" },
{ name: "Блог", link: "/blog" },
]}
/>
</div>
<div className="blog__title">
<div>
<h1>Блог</h1>
<img src={blogArrow} className="blog__title-arrow" />
</div>
<h3>
Из первых уст рассказываем о себе пользователям, делимся полезными и
важными материалами, стремимся получать обратную связь
</h3>
</div>
<div className="blog__body">
{article.map((item, index) => {
return (
<CardArticle
images={item.image}
title={item.title}
data={item.data}
key={index}
id={index}
/>
);
})}
</div>
<div className="blog__load-more">
<button>Загрузить еще</button>
</div>
</div>
<Footer />
</div>
);
};
export default Blog;

77
src/pages/Blog/blog.scss Normal file
View File

@ -0,0 +1,77 @@
.blog {
background: #f1f1f1;
&__breadCrumbs {
margin-top: 30px;
@media (max-width: 1375px) {
margin-top: 0;
padding-top: 100px;
}
@media (max-width: 600px) {
display: none;
}
}
&__title {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 40px;
h1 {
font-weight: 500;
font-size: 48px;
line-height: 32px;
}
h3 {
font-weight: 400;
font-size: 18px;
line-height: 28px;
text-align: justify;
}
div {
display: flex;
}
&-arrow {
margin: 0 27px 0 20px;
}
@media (max-width: 600px) {
padding-top: 110px;
flex-direction: column;
div {
margin: 0 0 15px 0;
}
}
}
&__body {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
&__load-more {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 35px;
button {
background: #52b709;
border-radius: 44px;
width: 202px;
height: 50px;
color: white;
font-size: 16px;
line-height: 32px;
border: none;
}
}
}