diff --git a/BackEnd/forum/pagination.py b/BackEnd/forum/pagination.py index 13181cc3c..a6158a910 100644 --- a/BackEnd/forum/pagination.py +++ b/BackEnd/forum/pagination.py @@ -3,9 +3,15 @@ class ForumPagination(PageNumberPagination): - page_size = 6 + page_size = 16 page_size_query_param = "page_size" - max_page_size = 18 + max_page_size = 64 + + def get_page_number(self, request, paginator): + page_number = super().get_page_number(request, paginator) + if int(page_number) > paginator.num_pages: + page_number = paginator.num_pages or 1 + return page_number def get_paginated_response(self, data): return Response( diff --git a/BackEnd/profiles/tests/test_new_members.py b/BackEnd/profiles/tests/test_new_members.py index eb130e7e4..723e42bdd 100644 --- a/BackEnd/profiles/tests/test_new_members.py +++ b/BackEnd/profiles/tests/test_new_members.py @@ -137,22 +137,6 @@ def setUp(self) -> None: self.company_dnipro.created_at = utc_datetime(2023, 12, 2) self.company_dnipro.save() - self.company_kharkiv = ProfileStartupFactory( - name="Kharkiv", - person=self.kharkiv_user, - completeness=1, - ) - self.company_kharkiv.created_at = utc_datetime(2023, 12, 3) - self.company_kharkiv.save() - - self.company_chernigiv = ProfileStartupFactory( - name="Chernigiv", - person=self.chernigiv_user, - completeness=1, - ) - self.company_chernigiv.created_at = utc_datetime(2023, 12, 4) - self.company_chernigiv.save() - self.company_kirovohrad = ProfileCompanyFactory( name="Kirovohrad", person=self.kirovohrad_user, @@ -163,17 +147,17 @@ def setUp(self) -> None: def test_get_less_companies(self): response = self.client.get( - path="/api/profiles/?ordering=-completeness,-created_at" + path="/api/profiles/?ordering=-completeness,-created_at&page_size=4" ) names_from_response = [ prof["name"] for prof in response.data["results"] ] self.assertEqual( - ["Kirovohrad", "Dnipro", "Kyiv", "Chernigiv", "Kharkiv"], + ["Kirovohrad", "Dnipro", "Kyiv"], names_from_response, ) self.assertEqual(200, response.status_code) - self.assertEqual(5, response.data["total_items"]) + self.assertEqual(3, response.data["total_items"]) self.assertEqual(1, response.data["current"]) self.assertEqual(1, response.data["total_pages"]) self.assertEqual(None, response.data["next"]) @@ -187,7 +171,7 @@ def test_get_enough_companies(self): self.company_synelnicovo.created_at = utc_datetime(2023, 12, 7) self.company_synelnicovo.save() response = self.client.get( - path="/api/profiles/?ordering=-completeness,-created_at" + path="/api/profiles/?ordering=-completeness,-created_at&page_size=4" ) self.assertEqual(200, response.status_code) names_from_response = [ @@ -200,12 +184,10 @@ def test_get_enough_companies(self): "Kirovohrad", "Dnipro", "Kyiv", - "Chernigiv", - "Kharkiv", ], names_from_response, ) - self.assertEqual(6, response.data["total_items"]) + self.assertEqual(4, response.data["total_items"]) self.assertEqual(1, response.data["current"]) self.assertEqual(1, response.data["total_pages"]) self.assertEqual(None, response.data["next"]) @@ -228,20 +210,20 @@ def test_get_more_companies(self): self.company_odesa.save() response = self.client.get( - path="/api/profiles/?ordering=-completeness,-created_at" + path="/api/profiles/?ordering=-completeness,-created_at&page_size=4" ) names_from_response = [ prof["name"] for prof in response.data["results"] ] self.assertEqual( - ["Odesa", "Mykolaiv", "Kirovohrad", "Dnipro", "Kyiv", "Chernigiv"], + ["Odesa", "Mykolaiv", "Kirovohrad", "Dnipro"], names_from_response, ) self.assertEqual(200, response.status_code) - self.assertEqual(7, response.data["total_items"]) + self.assertEqual(5, response.data["total_items"]) self.assertEqual(1, response.data["current"]) self.assertEqual(2, response.data["total_pages"]) self.assertEqual( - "http://testserver/api/profiles/?ordering=-completeness%2C-created_at&page=2", + "http://testserver/api/profiles/?ordering=-completeness%2C-created_at&page=2&page_size=4", response.data["next"], ) diff --git a/BackEnd/profiles/tests/test_ordering.py b/BackEnd/profiles/tests/test_ordering.py index 6bc36057a..0b410f0fe 100644 --- a/BackEnd/profiles/tests/test_ordering.py +++ b/BackEnd/profiles/tests/test_ordering.py @@ -156,8 +156,8 @@ def test_get_list_of_profiles_completeness_order_asc(self): self.assertEqual(status.HTTP_200_OK, response.status_code) self.assertEqual( [ - "Winery", "Bakery", + "Winery", "Delivery company", "Catering service", "Retail company", diff --git a/FrontEnd/package-lock.json b/FrontEnd/package-lock.json index bb9aad578..6d4200ac0 100644 --- a/FrontEnd/package-lock.json +++ b/FrontEnd/package-lock.json @@ -17641,7 +17641,6 @@ "version": "0.20.0", "resolved": "https://registry.npmjs.org/react-highlight-words/-/react-highlight-words-0.20.0.tgz", "integrity": "sha512-asCxy+jCehDVhusNmCBoxDf2mm1AJ//D+EzDx1m5K7EqsMBIHdZ5G4LdwbSEXqZq1Ros0G0UySWmAtntSph7XA==", - "license": "MIT", "dependencies": { "highlight-words-core": "^1.2.0", "memoize-one": "^4.0.0", diff --git a/FrontEnd/public/favicon-16x16.png b/FrontEnd/public/favicon-16x16.png index 9839240bb..14c58dcad 100644 Binary files a/FrontEnd/public/favicon-16x16.png and b/FrontEnd/public/favicon-16x16.png differ diff --git a/FrontEnd/public/favicon-32x32.png b/FrontEnd/public/favicon-32x32.png index 71ddb1293..c71d92a98 100644 Binary files a/FrontEnd/public/favicon-32x32.png and b/FrontEnd/public/favicon-32x32.png differ diff --git a/FrontEnd/public/favicon.ico b/FrontEnd/public/favicon.ico index 63eabdcfd..bd10115ab 100644 Binary files a/FrontEnd/public/favicon.ico and b/FrontEnd/public/favicon.ico differ diff --git a/FrontEnd/public/forum-logo.ico b/FrontEnd/public/forum-logo.ico deleted file mode 100644 index 62bea69b4..000000000 Binary files a/FrontEnd/public/forum-logo.ico and /dev/null differ diff --git a/FrontEnd/public/img/cookies.png b/FrontEnd/public/img/cookies.png new file mode 100644 index 000000000..530b9351b Binary files /dev/null and b/FrontEnd/public/img/cookies.png differ diff --git a/FrontEnd/public/img/main-baner.png b/FrontEnd/public/img/main-baner.png new file mode 100644 index 000000000..08b8ffbb0 Binary files /dev/null and b/FrontEnd/public/img/main-baner.png differ diff --git a/FrontEnd/public/svg/arrow-down.svg b/FrontEnd/public/svg/arrow-down.svg new file mode 100644 index 000000000..96d156440 --- /dev/null +++ b/FrontEnd/public/svg/arrow-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/FrontEnd/public/svg/arrow-up.svg b/FrontEnd/public/svg/arrow-up.svg new file mode 100644 index 000000000..224c57140 --- /dev/null +++ b/FrontEnd/public/svg/arrow-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/FrontEnd/public/svg/empty-decore-31x29.svg b/FrontEnd/public/svg/empty-decore-31x29.svg new file mode 100644 index 000000000..40424cdff --- /dev/null +++ b/FrontEnd/public/svg/empty-decore-31x29.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FrontEnd/public/svg/empty-decore-50x46.svg b/FrontEnd/public/svg/empty-decore-50x46.svg new file mode 100644 index 000000000..3eb189b20 --- /dev/null +++ b/FrontEnd/public/svg/empty-decore-50x46.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FrontEnd/src/App.css b/FrontEnd/src/App.css index e5d392976..4066ac164 100644 --- a/FrontEnd/src/App.css +++ b/FrontEnd/src/App.css @@ -7,4 +7,4 @@ body { width: 100vw; -} \ No newline at end of file +} diff --git a/FrontEnd/src/components/CompanyCard/CompanyCard.jsx b/FrontEnd/src/components/CompanyCard/CompanyCard.jsx index 00f1e77c7..7870c6d03 100644 --- a/FrontEnd/src/components/CompanyCard/CompanyCard.jsx +++ b/FrontEnd/src/components/CompanyCard/CompanyCard.jsx @@ -1,4 +1,5 @@ import { Link } from 'react-router-dom'; +import { mutate } from 'swr'; import styles from './CompanyCard.module.css'; import { useAuth } from '../../hooks'; import PropTypes from 'prop-types'; @@ -45,6 +46,11 @@ export default function CompanyCard({ changeCompanies(profile.id, false); try { await axios.delete(`${process.env.REACT_APP_BASE_API_URL}/api/saved-list/${profile.id}`); + await mutate( + (key) => typeof key === 'string' && key.includes('/api/profiles/?is_saved=True'), + undefined, + {revalidate: true} + ); } catch (error) { console.error(error); } diff --git a/FrontEnd/src/components/CompanyCard/CompanyCard.module.css b/FrontEnd/src/components/CompanyCard/CompanyCard.module.css index 81a5137c9..0cb137dfd 100644 --- a/FrontEnd/src/components/CompanyCard/CompanyCard.module.css +++ b/FrontEnd/src/components/CompanyCard/CompanyCard.module.css @@ -2,11 +2,11 @@ width: 345px; height: 365px; display: block; - align-items: center; border-radius: 11px; position: relative; margin: auto; background: var(--company-card-color); + box-shadow: 0px 0px 2px 0px #41404533; } .company-card:hover { @@ -80,7 +80,8 @@ text-align: left; padding-left: 16px; padding-top: 6px; - max-width: 300px; + max-width: 262px; + height: 35px; } .company-card__name-text { @@ -152,7 +153,7 @@ height: 50px; background: var(--company-card-color); border-radius: 9999px; - border: 2px solid #232424; + border: 1px solid var(--grey-border-color); } .company-card__logo-image { @@ -169,7 +170,8 @@ bottom: 13px; } -@media only screen and (min-width: 1200px) { +@media only screen and (min-width: 1512px) { + .company-card, .company-card__image-frame, .company-card__image, @@ -180,7 +182,8 @@ .company-card__star { left: 256px; } + .company-card__category-text { - max-width: 250px; + max-width: 220px; } -} \ No newline at end of file +} diff --git a/FrontEnd/src/components/CookieAcception/CookieMod.jsx b/FrontEnd/src/components/CookieAcception/CookieMod.jsx index adeb74350..8821e613a 100644 --- a/FrontEnd/src/components/CookieAcception/CookieMod.jsx +++ b/FrontEnd/src/components/CookieAcception/CookieMod.jsx @@ -1,81 +1,164 @@ -import { Link } from 'react-router-dom'; +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; import { useCookies } from 'react-cookie'; +import { Link } from 'react-router-dom'; import styles from './CookieMod.module.css'; -import { useState } from 'react'; const CookieMod = ({ active, setActive }) => { - const [cookies, setCookie] = useCookies(); + const [cookies, setCookie] = useCookies(['necessary', 'statistics', 'preferences', 'marketing']); const [detailsVisible, setDetailsVisible] = useState(false); const accessCookie = () => { const d = new Date(); - const cookieLifeTime = 30 * 24 * 60 * 60 * 1000; - d.setTime(d.getTime() + cookieLifeTime); - setCookie('first', true, { expires: d, sameSite: 'lax' }); - setActive(false); - }; - - const denyCookie = () => { - const d = new Date(); - const cookieLifeTime = 30 * 24 * 60 * 60 * 1000; - d.setTime(d.getTime() + cookieLifeTime); - setCookie('first', false, { expires: d, sameSite: 'lax' }); + d.setTime(d.getTime() + 30 * 24 * 60 * 60 * 1000); + setCookie('necessary', true, { expires: d, sameSite: 'lax' }); + setCookie('statistics', true, { expires: d, sameSite: 'lax' }); + setCookie('preferences', true, { expires: d, sameSite: 'lax' }); + setCookie('marketing', true, { expires: d, sameSite: 'lax' }); setActive(false); }; - const toggleDetails = (event) => { - event.preventDefault(); + const toggleDetails = () => { setDetailsVisible(!detailsVisible); }; - return cookies.first ? null : ( -
-
e.stopPropagation()}> -

- Наш веб-сайт використовує файли cookie, щоб покращити ваш досвід. Ви - можете відмовитися, якщо хочете. Дізнатися більше{' '} - { - - про кукі-файли + return active ? ( +

+ {!detailsVisible ? ( +
+
+ cookies +

Cookies

+
+

+ Наш веб-сайт використовує файли cookie, щоб покращити ваш досвід. +

+

+ Дізнатися більше + + про файли cookies. - } - -

- {detailsVisible && ( -
-

Використання файлів "cookies"

-

- 1. Файли "cookies" є невеликими текстовими файлами, які можуть бути розміщені на пристрої - користувача під час відвідування Сайту. Вони дозволяють збирати та зберігати певну інформацію про - відвідувачів, таку як налаштування мови, історія перегляду, дані автентифікації та інші деталі. - Використання файлів "cookies" на Сайті сприяє поліпшенню зручності та персоналізації досвіду - користувачів, дозволяючи зберігати інформацію про їхній вибір та взаємодію з різними елементами Сайту. -

-

- 2. Користувач має можливість керувати використанням файлів "cookies" у налаштуваннях свого - веб-браузера. Відключення файлів "cookies" може бути здійснено користувачем у будь-який - момент. Проте важливо зауважити, що відключення "cookies" може призвести до обмеження - функціональності Сайту, а також до втрати певних персоналізованих налаштувань та зручностей, які вони - забезпечують. -

+

+
+ + +
+
+ ) : ( +
+
+
+ cookies +

+ Використання файлів "Cookies" +

+
+
+

+ Файли "cookies" є невеликими текстовими файлами, які можуть бути розміщені на + пристрої користувача під час відвідування Сайту. Вони дозволяють збирати та зберігати певну + інформацію про відвідувачів, таку як налаштування мови, історія перегляду, дані + автентифікації та інші деталі. Використання файлів "cookies" на Сайті сприяє + поліпшенню зручності та персоналізації досвіду користувачів, дозволяючи зберігати інформацію + про їхній вибір та взаємодію з різними елементами Сайту. +

+

+ Your permission applies to the following domains: +

+
    +
  • cookieinfo.net
  • +
  • intranet.cookieinfo.net
  • +
+
+
    +
  • +
    +

    Necessary

    + +
    +

    + Necessary cookies help make a website usable by enabling basic functions like page + navigation and access to secure areas of the website. The website cannot function properly + without these cookies. +

    +
  • +
  • +
    +

    Statistic

    + +
    +

    + Statistic cookies help website owners understand how visitors interact with websites by + collecting and reporting information anonymously. +

    +
  • +
  • +
    +

    Preferences

    + +
    +

    + Preference cookies enable a website to remember information that changes the way the + website behaves or looks, like your preferred language or the region that you are in. +

    +
  • +
  • +
    +

    Marketing

    + +
    +

    + Marketing cookies are used to track visitors across websites. The intention is to display + ads that are relevant and engaging for the individual user and thereby more valuable for + publishers and third-party advertisers. +

    +
  • +
+
+ + +
- )} - cookies - - -
+
+ )}
- ); + ) : null; +}; + +CookieMod.propTypes = { + active: PropTypes.bool.isRequired, + setActive: PropTypes.func.isRequired, }; export default CookieMod; diff --git a/FrontEnd/src/components/CookieAcception/CookieMod.module.css b/FrontEnd/src/components/CookieAcception/CookieMod.module.css index a9821cef6..f92b73a39 100644 --- a/FrontEnd/src/components/CookieAcception/CookieMod.module.css +++ b/FrontEnd/src/components/CookieAcception/CookieMod.module.css @@ -1,68 +1,311 @@ -.modal-window { - height: 100vh; - width: var(--main-block-size); - background-color: rgba(0, 0, 0, 0.4); +.cookie-banner { + position: fixed; + bottom: 20px; + right: 20px; + width: 600px; + background: var(--cookie-light-color); + box-shadow: 0 4px 12px var(--cookie-shadow-color); + padding: 20px; + display: flex; + flex-direction: column; + z-index: 1000; +} + +.cookie-content { + text-align: left; + padding: 5px 5px; +} + +.cookie-logo { + width: 42.96px; + height: 40px; + gap: 0px; + opacity: 1; + margin-right: 8px; +} + +.cookie-header { + display: flex; + align-items: center; + margin-bottom: 16px; +} + +.cookie-title { + font-family: 'Geologica', sans-serif; + font-size: 30px; + font-weight: 600; + line-height: 30px; + text-align: left; + color: var(--cookie-dark-color); + padding: 10px 5px; + border-radius: 4px; +} + +.cookie-text { + font-family: 'Geologica', sans-serif; + font-size: 14px; + font-weight: 600; + line-height: 20px; + text-align: left; + color: var(--cookie-dark-color); +} + +.cookie-link { + font-size: 14px; + line-height: 1.5; + margin-left: 4px; + color: var(--cookie-black-color); + text-decoration: underline; + cursor: pointer; +} + +.cookie-buttons { + display: flex; + justify-content: flex-start; + gap: 11px; + margin-top: 20px; +} + +.allow-all-btn { + background: var(--cookie-black-color); + color: var(--cookie-light-color); + width: 144px; + height: 40px; + padding: 10px 16px; + border-radius: 4px 0px 0px 0px; + border: none; + font-size: 14px; + font-weight: bold; + cursor: pointer; + transition: all 0.3s ease; +} + +.allow-all-btn:hover { + background: transparent; + color: var(--cookie-black-color); + border: 1px solid var(--cookie-black-color); +} + +.settings-btn { + background: var(--cookie-light-color); + color: var(--cookie-black-color); + width: 144px; + height: 40px; + padding: 10px 16px; + border-radius: 0px; + border: 1px solid var(--cookie-black-color); + font-size: 14px; + font-weight: bold; + cursor: pointer; + transition: all 0.3s ease; +} + +.settings-btn:hover { + background: var(--cookie-black-color); + color: var(--cookie-light-color); +} + +.cookie-modal { position: fixed; top: 0; left: 0; + width: 100vw; + height: 100vh; + background: var(--cookie-overlay-color); display: flex; - align-items: center; justify-content: center; - visibility: hidden; + align-items: center; + z-index: 1001; + padding-bottom: 20px; } -.modal-window.active { - visibility: visible; +.modal-content { + background: var(--cookie-light-color); + width: 600px; + max-width: 90%; + height: auto; + max-height: 85vh; + padding: 30px; + display: flex; + flex-direction: column; + gap: 16px; + overflow-y: auto; + border: 1px solid var(--cookie-border-color); + box-shadow: 0 4px 10px var(--cookie-shadow-color); } -.modal-content { - padding: 20px; - border-radius: 12px; - background-color: white; - width: 400px; +.modal-header { + display: flex; + align-items: center; + gap: 15px; } -.green-btn { - color: #ffffff; - background: #20aa87; - border-color: #1f9a7c; - border-style: solid; - font-size: 15px; - border-radius: 4px; - margin: 14px; - margin-right: 50px; - padding: 4px; - margin-left: 64px; - cursor: pointer; +.modal-header img { + width: 40px; + height: 40px; } -.red-btn { - color: #ffffff; - background: #fa7979; - border-color: #fa7979; - border-style: solid; - font-size: 15px; - border-radius: 4px; - margin: 10px; +.modal-title { + font-family: 'Geologica', sans-serif; + font-size: 20px; + font-weight: 600; + color: var(--cookie-dark-color); + text-align: left; +} + +.modal-text-container { + font-family: 'Geologica', sans-serif; + font-size: 14px; + line-height: 20px; + padding: 0px 0px 0px 73px; + color: var(--cookie-dark-color); +} + +.modal-text-domains { + padding: 20px 0px 0px 0px; +} + +.modal-domains { + list-style-type: disc; margin-left: 20px; - padding: 4px; + font-size: 14px; + color: var(--cookie-dark-color); + margin-bottom: 20px; +} + +.modal-item { + display: flex; + flex-direction: column; + align-items: stretch; + padding: 15px; + border: 1px solid var(--cookie-border-color); + background: var(--cookie-light-color); + margin-bottom: 0px; + border-radius: 5px; +} + +.item-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 10px; + width: 100%; +} + +.item-title { + font-size: 16px; + font-weight: bold; + color: var(--cookie-dark-color); + margin: 0; +} + +.cookie-modal input[type="checkbox"] { + appearance: auto; + width: 20px; + height: 20px; + border: 1px solid var(--cookie-black-color); cursor: pointer; + accent-color: var(--cookie-black-color); } -.cookie-image { - margin-left: 150px; - margin-right: 50px; - width: 100px; - height: 70px; +.cookie-modal input[type="checkbox"]::before { + content: none; } -.cookie-text { - text-align: justify; - color: #187860; +.item-description { + font-family: 'Geologica', sans-serif; + font-size: 14px; + font-weight: 400; + color: var(--cookie-dark-color); + line-height: 20px; + padding: 0px 90px 0px 0px; } -.cookie-details { - text-align: justify; - color: #187860; - padding-top: 8px; +.modal-buttons { + display: flex; + justify-content: flex-start; + gap: 15px; + margin-top: 20px; +} + +.cancel-btn { + background: var(--cookie-light-color); + color: var(--cookie-dark-color); + padding: 10px 20px; + font-size: 14px; + cursor: pointer; + transition: all 0.3s ease; +} + +.cancel-btn:hover { + background: var(--cookie-black-color); + color: var(--cookie-light-color); +} + +.save-btn { + background: var(--cookie-dark-color); + color: var(--cookie-light-color); + border: none; + padding: 10px 20px; + font-size: 14px; + cursor: pointer; + transition: all 0.3s ease; +} + +.save-btn:hover { + background: transparent; + color: var(--cookie-black-color); +} + +@media (max-width: 768px) { + .cookie-banner { + bottom: 15px; + right: 10px; + padding: 15px 15px; + width: 90%; + max-width: 640px; + } +} + +@media (max-width: 375px) { + .cookie-banner { + width: 100%; + max-width: 375px; + bottom: 0; + right: 0; + } + + .cookie-content { + padding: 5px 40px; + text-align: center; + } + + .modal-content { + width: 90%; + max-height: 95vh; + padding: 20px; + } + + .cookie-modal .cookie-logo { + margin: 0 auto 15px; + order: -1; + } + + .modal-title { + margin: 0; + text-align: center; + font-size: 18px; + margin-bottom: 20px; + } + + .modal-header { + display: flex; + flex-direction: column; + align-items: center; + } + + .modal-text-container { + text-align: left; + padding: 0 10px; + } } diff --git a/FrontEnd/src/components/CookieAcception/tests/CookieModal.test.js b/FrontEnd/src/components/CookieAcception/tests/CookieModal.test.js index 150404a7a..4128134f9 100644 --- a/FrontEnd/src/components/CookieAcception/tests/CookieModal.test.js +++ b/FrontEnd/src/components/CookieAcception/tests/CookieModal.test.js @@ -6,44 +6,54 @@ import CookieMod from '../CookieMod'; afterEach(cleanup); describe('CookieMod component unit tests', () => { - test('renders agree button', () => { + test('renders "Allow All" button', () => { render( ); - const buttonElement = screen.getByText(/Погоджуюсь/i); + const buttonElement = screen.getByText(/Дозволити всі/i); expect(buttonElement).toBeInTheDocument(); }); - test('renders deny button', () => { + test('renders "Settings" button', () => { render( ); - const buttonElement = screen.getByText(/Відмовляюсь/i); + const buttonElement = screen.getByText(/Налаштувати/i); expect(buttonElement).toBeInTheDocument(); }); - test('renders cookiepolicy link', async () => { + test('renders link to cookie policy', async () => { render( ); - const linkElement = screen.getByText(/про кукі-файли/i); + const linkElement = screen.getByText(/про файли cookie/i); expect(linkElement).toBeInTheDocument(); }); - test('renders hidden cookie modal window', () => { + test('does not render cookie modal when inactive', () => { render( ); - const cookieElement = screen.queryByTestId('cookiemodal', { hidden: true }); + const cookieElement = screen.queryByTestId('cookiemodal'); + expect(cookieElement).not.toBeInTheDocument(); + }); + + test('renders cookie modal when active', () => { + render( + + + + ); + const cookieElement = screen.getByTestId('cookiemodal'); expect(cookieElement).toBeInTheDocument(); }); }); diff --git a/FrontEnd/src/components/Footer/FooterComponents/ScrollToTopButton.module.css b/FrontEnd/src/components/Footer/FooterComponents/ScrollToTopButton.module.css index f3e163c8a..20b2313e5 100644 --- a/FrontEnd/src/components/Footer/FooterComponents/ScrollToTopButton.module.css +++ b/FrontEnd/src/components/Footer/FooterComponents/ScrollToTopButton.module.css @@ -1,13 +1,14 @@ .scroll-to-top-button { position: fixed; bottom: 30px; - left: 90%; + left: 80%; width: 40px; height: 40px; background-color: var(--footer-scroll-button); color: white; border: none; border-radius: 50%; + border: 1px solid gray; font-size: 20px; display: flex; justify-content: center; @@ -24,3 +25,9 @@ .scroll-to-top-button:hover { background-color: var(--footer-scroll-button); } + +@media only screen and (min-width: 1512px) { + .scroll-to-top-button { + left: 95%; + } +} \ No newline at end of file diff --git a/FrontEnd/src/components/Header/Menu/HeaderMenu.jsx b/FrontEnd/src/components/Header/Menu/HeaderMenu.jsx deleted file mode 100644 index a8c11173a..000000000 --- a/FrontEnd/src/components/Header/Menu/HeaderMenu.jsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Link } from 'react-router-dom'; -import css from './HeaderMenu.module.css'; - -const SERVICES_LINKS = [ - { - title: 'Виробники', - link: '/profiles/producers' - }, - { - title: 'Імпортери', - link: '/profiles/importers' - }, - { - title: 'Роздрібні мережі', - link: '/profiles/retailers' - }, - { - title: 'HORECA', - link: '/profiles/horeca' - }, - { - title: 'Інші послуги', - link: '/profiles/other-services' - } -]; - -function HeaderMenu() { - return ( -
-
-
- {SERVICES_LINKS.map((element) => ( -
- {element.title} -
- ))} -
-
-
- ); -} - -export default HeaderMenu; diff --git a/FrontEnd/src/components/Header/Menu/HeaderMenu.module.css b/FrontEnd/src/components/Header/Menu/HeaderMenu.module.css deleted file mode 100644 index 840528e04..000000000 --- a/FrontEnd/src/components/Header/Menu/HeaderMenu.module.css +++ /dev/null @@ -1,40 +0,0 @@ -.menu { - width: var(--main-block-size); - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} - -.menu-section{ - display: flex; - padding: 8px 104px; - align-items: center; - gap: 983px; -} - -.menu-section-content { - display: flex; - align-items: flex-start; - gap: 16px; -} - -.menu-element { - display: flex; - padding: 6px 12px; - align-items: flex-start; - gap: 10px; -} - -.menu-element__text { - color: var(--main-black-90, #292E32); - font-feature-settings: 'calt' off; - text-decoration: none; - - font-family: var(--font-main); - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 20px; - letter-spacing: -0.14px; -} diff --git a/FrontEnd/src/components/Header/Navbar/BurgerMenu.jsx b/FrontEnd/src/components/Header/Navbar/BurgerMenu.jsx index 01c6938ac..57efaa299 100644 --- a/FrontEnd/src/components/Header/Navbar/BurgerMenu.jsx +++ b/FrontEnd/src/components/Header/Navbar/BurgerMenu.jsx @@ -1,26 +1,24 @@ -import React, { useState } from 'react'; +import React from 'react'; import Hamburger from 'hamburger-react'; import Menu from './Menu'; import SearchBox from './SearchBox'; +import { useBurgerMenu } from '../../../context/BurgerMenuContext'; import css from './BurgerMenu.module.css'; const BurgerMenu = () => { - const [isOpen, setOpen] = useState(false); + const { isOpen, toggleMenu } = useBurgerMenu(); return (
- - {isOpen && ( -
- - -
- )} + +
+ {isOpen && ( + <> + + + + )} +
); }; diff --git a/FrontEnd/src/components/Header/Navbar/BurgerMenu.module.css b/FrontEnd/src/components/Header/Navbar/BurgerMenu.module.css index 1dd3bf522..1af406e9d 100644 --- a/FrontEnd/src/components/Header/Navbar/BurgerMenu.module.css +++ b/FrontEnd/src/components/Header/Navbar/BurgerMenu.module.css @@ -1,17 +1,23 @@ -.burgerMenuContainer { - position: relative; - top: -4px; +.menu { + position: absolute; + top: 61px; + left: -100vw; + width: 100vw; + background-color: white; + overflow: hidden; + max-height: 0; + display: flex; + flex-direction: column; + gap: 20px; + transition: max-height 0.3s ease, left 0.3s ease, padding 0.3s ease; } -.menu { - position: absolute; - top: 61px; - left: calc(-100vw + 80px); - width: calc(100vw - 40px); - background-color: white; - padding: 30px 20px; - display: flex; - flex-direction: column; - gap: 20px; - z-index: 1000; +.menu.open { + left: 0; + max-height: 180px; + padding: 20px; } + + + + diff --git a/FrontEnd/src/components/Header/Navbar/Menu.jsx b/FrontEnd/src/components/Header/Navbar/Menu.jsx index e7f69b14f..2e3a1c505 100644 --- a/FrontEnd/src/components/Header/Navbar/Menu.jsx +++ b/FrontEnd/src/components/Header/Navbar/Menu.jsx @@ -9,7 +9,7 @@ const MENU_LINKS = [ }, { title: 'Підприємства та сектори', - link: '/profiles/companies', // SHOULD BE CHANGED FOR COMPANY LIST (Підприємства та сектори) + link: '/profiles', }, ]; diff --git a/FrontEnd/src/components/Header/Navbar/Navbar.module.css b/FrontEnd/src/components/Header/Navbar/Navbar.module.css index 1a1b1b1f3..ca5d02389 100644 --- a/FrontEnd/src/components/Header/Navbar/Navbar.module.css +++ b/FrontEnd/src/components/Header/Navbar/Navbar.module.css @@ -6,9 +6,9 @@ .navbar-content { display: flex; - max-width: calc(1512px - 60px); + max-width: calc(1512px - 208px); width: 100%; - padding: 16px 30px; + padding: 16px 23px; align-items: center; justify-content: space-between; height: var(--navbar-content-height); @@ -17,12 +17,13 @@ .navbar-logo__text { display: flex; + align-items: center; + flex-shrink: 0; } .navbar-main-logo { display: flex; align-items: center; - justify-content: space-between; gap: 10px; color: var(--header-bunner-text-color); width: 208px; @@ -34,14 +35,16 @@ .navbar-utility-bar { display: flex; gap: 24px; - height: 40px; + align-items: center; } + + .burger-menu-wrapper { display: none; } -.menu-search-wrapper{ +.menu-search-wrapper { display: flex; gap: 24px; } @@ -53,12 +56,31 @@ .burger-menu-wrapper { display: block; + margin-left: auto; } } @media (max-width: 630px) { - .navbar-main-logo{ - width: 30px; + .navbar-content { + padding: 8px 16px; + justify-content: space-between; + } + + .navbar-main-logo { + order: 2; + margin: 0 auto; + width: auto; + font-size: 20px; + } + + .burger-menu-wrapper { + order: 1; + margin: 0; + } + + .navbar-utility-bar { + order: 3; + gap: 12px; } .navbar-main-logo span { @@ -66,3 +88,26 @@ } } +@media (max-width: 380px) { + .navbar-content { + padding: 8px 12px; + } + + .navbar-utility-bar { + gap: 8px; + justify-content: flex-end; + } + + .navbar-utility-bar button { + padding: 6px 12px; + font-size: 12px; + } + + .navbar-main-logo { + margin: 0 auto; + } + + .burger-menu-wrapper { + margin-right: 0; + } +} diff --git a/FrontEnd/src/components/Header/Navbar/Profile.jsx b/FrontEnd/src/components/Header/Navbar/Profile.jsx index a2fd3369a..f8e717c78 100644 --- a/FrontEnd/src/components/Header/Navbar/Profile.jsx +++ b/FrontEnd/src/components/Header/Navbar/Profile.jsx @@ -27,17 +27,17 @@ function Profile() { return (
-
+
Avatar
- + Мій профіль - {!isStaff && Мої збережені} + {!isStaff && Мої збережені}
diff --git a/FrontEnd/src/components/Header/Navbar/SearchBox.jsx b/FrontEnd/src/components/Header/Navbar/SearchBox.jsx index f27e41262..6dee898e3 100644 --- a/FrontEnd/src/components/Header/Navbar/SearchBox.jsx +++ b/FrontEnd/src/components/Header/Navbar/SearchBox.jsx @@ -14,6 +14,11 @@ function SearchBox() { setSearchTerm(''); } }; + + const handleClear = () => { + setSearchTerm(''); + }; + return (
@@ -30,6 +35,14 @@ function SearchBox() { } }} /> + {searchTerm && ( + + )}
+
diff --git a/FrontEnd/src/pages/ErrorPages/ErrorPage404.module.css b/FrontEnd/src/pages/ErrorPages/ErrorPage404.module.css index 22aac1b6d..cdfea2aae 100644 --- a/FrontEnd/src/pages/ErrorPages/ErrorPage404.module.css +++ b/FrontEnd/src/pages/ErrorPages/ErrorPage404.module.css @@ -1,61 +1,160 @@ .ErrorPage404__page { - min-height: var(--min-height-block-main); + background: var(--join-us-main-color, #B4D27A); + width: 100vw; + min-height: 62.4vh; display: flex; + flex-direction: column; + align-items: center; justify-content: center; - background: var(--primary-green-80, #1f9a7c); - + box-sizing: border-box; } .ErrorPage404__container { display: flex; + flex-direction: column; align-items: center; - gap: 80px; + justify-content: center; + text-align: center; + gap: 20px; font-family: var(--font-main); - color: var(--primary-green-20, #effff6); - font-feature-settings: "calt" off; - font-style: normal; + max-width: 343px; } .ErrorPage404__text404 { - display: flex; - height: 178px; - flex-direction: column; - justify-content: center; - font-size: 200px; + font-size: 84px; font-weight: 600; - line-height: 20px; - letter-spacing: -2px; + line-height: 1.2; + letter-spacing: -0.84px; + color: var(--main-grey-90, #25292c); + margin: 0; } .ErrorPage404__block { display: flex; flex-direction: column; - align-items: flex-start; - gap: 36px; + align-items: center; + gap: 24px; } .ErrorPage404__explanation { display: flex; flex-direction: column; - align-items: flex-start; - gap: 24px; + align-items: center; + gap: 16px; } .ErrorPage404__main-text { - font-size: 48px; + font-size: 32px; font-weight: 700; - line-height: 120%; - letter-spacing: 0.48px; + color: var(--main-grey-90, #25292c); + margin: 0; + line-height: 1.2; } .ErrorPage404__details { - width: 548px; - font-size: 16px; + font-size: 14px; + color: var(--main-grey-90, #25292c); + margin: 0; font-weight: 400; - line-height: 20px; - letter-spacing: -0.16px; + line-height: 1.5; +} + +.ErrorPage404__button { + display: flex; + justify-content: center; + align-items: center; + background-color: #000000; + color: #FFFFFF; + border-radius: 4px; + cursor: pointer; + text-align: center; + width: 100%; + height: 40px; + max-width: 206px; + font-weight: 500; } .ErrorPage404__button-text { - font-family: var(--font-main); + color: #FFFFFF; + text-decoration: none; + font-size: 14px; +} + +@media only screen and (min-width: 768px) { + .ErrorPage404__page { + height: 598px; + } + + .ErrorPage404__container { + max-width: 558px; + gap: 20px;; + } + + .ErrorPage404__text404 { + font-size: 200px; + } + + .ErrorPage404__main-text { + font-size: 48px; + } + + .ErrorPage404__details { + font-size: 16px; + } + + .ErrorPage404__button { + max-width: 231px; + padding: 10px 24px; + } } + +@media only screen and (min-width: 1200px) { + .ErrorPage404__page { + height: 418px; + } + + .ErrorPage404__container { + flex-direction: row; + justify-content: space-between; + align-items: center; + max-width: 1512px; + gap: 50px; + text-align: start; + } + + .ErrorPage404__text404 { + font-size: 200px; + line-height: 1; + margin-right: 80px; + } + + .ErrorPage404__block { + display: flex; + flex-direction: column; + align-items: flex-start; + height: 178px; + max-width: 500px; + } + + .ErrorPage404__explanation { + display: flex; + flex-direction: column; + align-items: flex-start; + } + + .ErrorPage404__main-text { + font-size: 48px; + line-height: 1.2; + } + + .ErrorPage404__details { + display: flex; + flex-direction: column; + align-items: flex-start; + font-size: 16px; + } + + .ErrorPage404__button { + max-width: 231px; + } +} \ No newline at end of file diff --git a/FrontEnd/src/pages/LandingPage/Banner/Banner.css b/FrontEnd/src/pages/LandingPage/Banner/Banner.css deleted file mode 100644 index 5a2d3cf78..000000000 --- a/FrontEnd/src/pages/LandingPage/Banner/Banner.css +++ /dev/null @@ -1,374 +0,0 @@ -.main-banner-group { - width: var(--main-block-size); - height: 500px; - flex-shrink: 0; - position: relative; -} - -.main-banner-group__main-rectangle { - width: var(--main-block-size); - height: 500px; - flex-shrink: 0; - background: var(--banner-main-dark-color); - left: 0; - top: 0; - position: absolute; - -} - -.main-banner-group__white-rectangle { - width: 786px; - height: 500px; - flex-shrink: 0; - background: #FFF; - left: 0; - top: 0; - position: absolute; -} - -.main-banner-group__frame-rectangle9 { - width: 199px; - height: 258px; - transform: rotate(-9.235deg); - flex-shrink: 0; - border-radius: 8px; - border: 1px solid #FFF; - left: 845.59px; - top: 65.64px; - position: absolute; -} - -.main-banner-group__frame-rectangle10 { - width: 199px; - height: 258px; - transform: rotate(-2.266deg); - flex-shrink: 0; - border-radius: 8px; - border: 1px solid #FFF; - opacity: 0.30000001192092896; - left: 857.98px; - top: 67.04px; - position: absolute; -} - -.main-banner-group__frame-rectangle11 { - width: 220px; - height: 179px; - transform: rotate(-2.266deg); - flex-shrink: 0; - border-radius: 8px; - border: 1px solid #FFF; - opacity: 0.800000011920929; - left: 1072px; - top: 78.87px; - position: absolute; -} - -.main-banner-group__frame-rectangle12 { - width: 210px; - height: 171px; - transform: rotate(-2.266deg); - flex-shrink: 0; - border-radius: 8px; - border: 1px solid #FFF; - opacity: 0.800000011920929; - left: 1087.91px; - top: 310.49px; - position: absolute; -} - -.main-banner-group__frame-rectangle13 { - width: 209.828px; - height: 170.787px; - transform: rotate(-2.266deg); - flex-shrink: 0; - border-radius: 8px; - border: 1px solid #FFF; - opacity: 0.10000000149011612; - left: 1094px; - top: 293.30px; - position: absolute; -} - -.main-banner-group__frame-description { - display: inline-flex; - flex-direction: column; - align-items: flex-start; - gap: 40px; - width: 584px; - height: 264px; - left: 103px; - top: 112px; - position: absolute; -} - -.main-banner-group__banner-text { - width: 584px; - color: var(-banner-main-font-color); - font-family: var(--font-main); - font-size: 40px; - font-style: normal; - font-weight: 700; - line-height: 120%; - /* 48px */ - letter-spacing: 0.4px; - position: absolute; -} - -.main-banner-group__frame-login { - display: flex; - align-items: flex-start; - gap: 12px; - position: absolute; -} - -.main-banner-group__login-button { - display: flex; - padding: 5px 15px; - justify-content: center; - align-items: center; - gap: 10px; - border-radius: 4px; - border: 1px solid var(--banner-main-dark-color); - background: var(--banner-main-dark-color); - box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.04); - top: 245px; - position: relative; -} - -.main-banner-group__login-button-text { - color: #FFF; - text-align: center; - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; - /* 125% */ - letter-spacing: -0.16px; - text-decoration: none; -} - -.main-banner-group__register-button { - display: flex; - padding: 5px 15px; - justify-content: center; - align-items: center; - gap: 10px; - border-radius: 4px; - border: 1px solid var(--banner-main-dark-color); - background: #FFF; - box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.02); - top: 245px; - position: relative; -} - -.main-banner-group__register-button-text { - color: var(--banner-main-dark-color); - text-align: center; - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; - /* 125% */ - letter-spacing: -0.16px; - text-decoration: none; -} - -.main-banner-group__banner-image1 { - width: 199px; - height: 258px; - flex-shrink: 0; - border-radius: 8px; - background: lightgray 50% / cover no-repeat; - left: 849px; - top: 79px; - position: absolute; - object-fit: cover; -} - -.main-banner-group__banner-image2 { - width: 220px; - height: 148px; - flex-shrink: 0; - border-radius: 8px; - background: lightgray 50% / cover no-repeat; - left: 1064px; - top: 293px; - position: absolute; - object-fit: cover; -} - -.main-banner-group__banner-image3 { - width: 212px; - height: 182px; - flex-shrink: 0; - border-radius: 8px; - background: lightgray 50% / cover no-repeat; - left: 1064px; - top: 79px; - position: absolute; - object-fit: cover; -} - -.main-banner-wine { - width: 123px; - height: 36px; - display: inline-flex; - padding: 6px 16px; - align-items: center; - border-radius: 8px; - background: #FFF; - box-shadow: 0 0 2px 0 rgba(65, 64, 69, 0.20); - left: 840px; - top: 328px; - position: absolute; -} - -.main-banner-group__frame { - display: flex; - justify-content: center; - align-items: center; - gap: 8px; -} - -.main-banner-wine__winemaking { - display: flex; - padding: 9px 10.5px; - align-items: flex-start; - gap: 10px; - border-radius: 16px; - background: #BE4F28; -} - -.winemaking { - width: 15px; - height: 18px; - fill: #FFF; -} - -.main-banner-group__content { - display: flex; - flex-direction: column; - align-items: flex-start; -} - -.main-banner-group__banner-item-text { - color: #292E32; - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 10px; - font-style: normal; - font-weight: 600; - line-height: 16px; - /* 160% */ - text-transform: uppercase; -} - -.main-banner-group__banner-item-counter { - color: #BE4F28; - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 10px; - font-style: normal; - font-weight: 400; - line-height: 16px; - /* 160% */ - text-transform: uppercase; -} - -.main-banner-cheese { - display: flex; - width: 180px; - padding: 6px 16px 6px 20px; - align-items: center; - border-radius: 8px; - background: #FFF; - box-shadow: 0 0 2px 0 rgba(65, 64, 69, 0.20); - height: 16px; - left: 1055px; - top: 427px; - position: absolute; -} - -.banner-cheese { - display: flex; - align-items: flex-start; - gap: 8px; -} - -.main-banner-cheese__cheese { - display: inline-flex; - padding: 8px; - align-items: flex-start; - gap: 10px; - border-radius: 16px; - background: #F0AB4E; - width: 20px; - height: 20px; - left: 1240px; - top: 301px; - position: absolute; -} - -.cheese { - width: 20px; - height: 20px; - position: relative; -} - -.main-banner-delivery { - display: inline-flex; - padding: 6px 16px; - align-items: center; - border-radius: 8px; - background: #FFF; - box-shadow: 0 0 2px 0 rgba(65, 64, 69, 0.20); - width: 101px; - height: 36px; - left: 1125px; - top: 237px; - position: absolute; -} - -.main-banner-delivery__delivery { - display: flex; - padding: 8px; - align-items: flex-start; - gap: 10px; - border-radius: 16px; - background: #FFDEC6; -} - -.delivery { - width: 20px; - height: 20px; - position: relative; -} - -.main-banner-group__white-dots { - width: 179px; - height: 150px; - display: inline-flex; - flex-direction: column; - align-items: flex-start; - gap: 24px; - right: 10px; - top: 75px; - position: absolute; -} - -.main-banner-group__green-dots { - width: 179px; - height: 150px; - display: inline-flex; - flex-direction: column; - align-items: flex-start; - gap: 24px; - right: -25px; - bottom: 3px; - position: absolute; -} \ No newline at end of file diff --git a/FrontEnd/src/pages/LandingPage/Banner/Banner.jsx b/FrontEnd/src/pages/LandingPage/Banner/Banner.jsx index 5594a4f69..e0961acd3 100644 --- a/FrontEnd/src/pages/LandingPage/Banner/Banner.jsx +++ b/FrontEnd/src/pages/LandingPage/Banner/Banner.jsx @@ -1,126 +1,31 @@ -import './Banner.css'; +import styles from './Banner.module.css'; import { Link } from 'react-router-dom'; -import { PropTypes } from 'prop-types'; -const MainBanner = (props) => { +const MainBanner = () => { return ( -
-
-
- dots_7x6.png -
-
-
-
-
-
-
-

- CRAFTMERGE - обʼєднуємо
- крафтових виробників та
- інноваторів -

- {!props.isAuthorized ? ( -
-
- - Увійти - -
-
- - Зареєстуватися - -
-
- ) : null} -
- dots_7x6W.png - Banner img - Banner img - Banner img -
-
-
-
- Winemaking -
-
-
-
- Виноробство -
-
146+
+
+
+
+

CRAFTMERGE

+

Обʼєднуємо крафтових виробників та інноваторів

+
+ + Детальніше про нас +
-
-
-
-
Сироварня
-
56+
-
-
-
-
- Cheese + Banner img
-
-
-
-
- Delivery -
-
-
-
Доставка
-
14+
-
-
-
); }; export default MainBanner; - -MainBanner.propTypes = { - isAuthorized: PropTypes.bool.isRequired, -}; diff --git a/FrontEnd/src/pages/LandingPage/Banner/Banner.module.css b/FrontEnd/src/pages/LandingPage/Banner/Banner.module.css new file mode 100644 index 000000000..f28729247 --- /dev/null +++ b/FrontEnd/src/pages/LandingPage/Banner/Banner.module.css @@ -0,0 +1,132 @@ +.main-baner__container { + display: flex; + justify-content: center; + background-color: #B4D27A; + width: 100vw; +} + +.main-container{ + display:flex; + justify-content: center; + flex-direction:row; + padding: 32px 104px 32px 104px; +} + +.main-baner-text{ + display: flex; + flex-direction: column; + justify-content: center; + align-items:flex-start; + font-family: Geologica; + font-weight: 900; + line-height: 57.6px; + letter-spacing: 0.01em; +} + +.main-baner-text__logo{ + margin-bottom: 10px; + font-size: 48px; +} + +.main-banner-link__container{ + display: flex; + max-width: 194px; + max-height: 46px; + justify-content:center; + align-items: center; + border-radius: 4px; + border: 1px solid black; + padding: 13px 16px 13px 16px; + margin-top: 30px; + background: #000000; + box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.04); +} + +.main-baner-text__explanation{ + font-size: 40px; + max-width: 557px; +} + +.main-banner-link{ + font-family: Geologica; + font-size: 15px; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.01em; + color: #FFFFFF; +} + +.main-banner__img{ + max-width: 100vw; + height: auto; +} + +@media (min-width: 768px) and (max-width: 1511px) { + .main-container{ + flex-direction:column-reverse; + + } + .main-baner-text{ + display: flex; + flex-direction: column; + align-items: center; + padding-top: 5vh; + + } + .main-baner-text__explanation{ + display: flex; + align-items: center; + justify-content: center; + max-width: 714px; + text-align: center; + font-size: 30px; + } + .main-banner__img{ + max-width: 100%; + } +} + +@media (max-width: 767px) { + .main-baner__container{ + display:flex; + justify-content:space-around; + align-items: center; + padding: 0px; + + } + .main-container{ + display:flex; + justify-content: center; + flex-direction:column-reverse; + background-color: #B4D27A; + max-width: 375px; + padding: 16px 32px 16px 32px; + } + .main-baner-text__logo{ + font-size: 34px; + } + .main-baner-text{ + display: flex; + flex-direction: column; + align-items: center; + max-width: 343px; + padding-top: 5vh; + text-align: center; + margin: 0px; + } + .main-baner-text__explanation{ + display: flex; + align-items: center; + justify-content: center; + text-align: center; + max-width: 343px; + font-size: 20px; + font-family: Geologica; + font-weight: 700; + line-height: 28.8px; + letter-spacing: 0.01em; + } + .main-banner__img{ + max-width: 344px; + } +} diff --git a/FrontEnd/src/pages/LandingPage/Companies/Companies.jsx b/FrontEnd/src/pages/LandingPage/Companies/Companies.jsx index ffbc70cb5..f1bb1b94e 100644 --- a/FrontEnd/src/pages/LandingPage/Companies/Companies.jsx +++ b/FrontEnd/src/pages/LandingPage/Companies/Companies.jsx @@ -50,7 +50,7 @@ const MainCompanies = ({ isAuthorized }) => { Нові учасники
- +

{linkText} Arrow icon for all companies link @@ -59,7 +59,7 @@ const MainCompanies = ({ isAuthorized }) => {

- + {companyDataList.map((result, resultIndex) => ( -
- {!data.banner?.path && - - - - } -
-
- ); -} - -export default BannerImage; - -BannerImage.propTypes = { - data: PropTypes.shape({ - banner: PropTypes.shape({ - path: PropTypes.string, - }) - }), -}; diff --git a/FrontEnd/src/pages/ProfileDetail/BannerImage.module.css b/FrontEnd/src/pages/ProfileDetail/BannerImage.module.css deleted file mode 100644 index 784747652..000000000 --- a/FrontEnd/src/pages/ProfileDetail/BannerImage.module.css +++ /dev/null @@ -1,15 +0,0 @@ -.banner-image__block { - width: var(--main-block-size); - height: 200px; - flex-shrink: 0; -} - -.default-banner { - display: flex; - justify-content: center; - align-items: center; - width: var(--main-block-size); - height: 200px; - flex-shrink: 0; - background: var(--main-grey-20, #DEE1E8); -} diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Company.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Company.jsx deleted file mode 100644 index 987dcccfd..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Company.jsx +++ /dev/null @@ -1,71 +0,0 @@ -import { PropTypes } from 'prop-types'; -import { useEffect } from 'react'; -import classes from './Company.module.css'; -import ReadMore from './ReadMore'; -import { useContext } from 'react'; -import { ActiveLinksContext } from '../../../context/ActiveLinksContext'; - -function Company ({ data }) { - const { setActiveLinks } = useContext(ActiveLinksContext); - - // TODO: implement logic for getting data from db when it's added on server side - - const competitiveEdge = ''; - const slogan = ''; - const companyData = data.common_info || competitiveEdge || slogan; - - useEffect(() => { - if (companyData) { - setActiveLinks(prevData => [ - ...prevData, - 'about-company', - ]); - } - }, [setActiveLinks, companyData]); - - return ( - companyData ? ( -
-
-
-

Про компанію

-
-
-
-
- {data.common_info ? ( -
- - {data.common_info} - -
- ) : null} - {competitiveEdge ? ( -
-

Конкурентна перевага

-
- - {competitiveEdge} - -
-
- ) : null} - {slogan ? ( -
-

Візія, слоган

-

{slogan}

-
- ) : null} -
-
- ) : null - ); -} - -export default Company; - -Company.propTypes = { - data: PropTypes.shape({ - common_info: PropTypes.string, - }), - }; diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Company.module.css b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Company.module.css deleted file mode 100644 index 022817303..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Company.module.css +++ /dev/null @@ -1,103 +0,0 @@ -.about-company { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; - border-radius: 8px; -} - -.about-company__title { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; -} - -.about-company__title--block { - display: flex; - padding: 8px 12px; - align-items: flex-start; - gap: 10px; - align-self: stretch; - border-radius: 4px; -} - -.about-company__title--text { - width: 742px; - color: var(--main-grey-90, #25292C); - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 700; - line-height: 20px; - text-transform: uppercase; -} - -.about-company__title--divider { - width: 795px; - height: 1px; - background: var(--main-grey-20, #DEE1E8); -} - -.about-company__content { - display: flex; - padding: 12px; - flex-direction: column; - align-items: flex-start; - gap: 24px; -} - -.about-company__content--common { - width: 776px; - color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; - letter-spacing: -0.14px; -} - -.about-company__content--advantage, -.about-company__content--slogan { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; -} - -.about-company__content--advantage--title { - color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; - letter-spacing: -0.16px; -} - -.about-company__content--advantage--description { - width: 776px; - color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; - letter-spacing: -0.14px; -} - -.about-company__content--slogan--title, -.about-company__content--slogan--text { - color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; - letter-spacing: -0.16px; -} diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/CompanyDescription.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/CompanyDescription.jsx deleted file mode 100644 index e5c3896ae..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/CompanyDescription.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import { PropTypes } from 'prop-types'; -import classes from './CompanyDescription.module.css'; -import Company from './Company'; -import Startup from './Startup'; -import ProductsServices from './ProductsServices'; -import Logistics from './Logistics'; -import Cooperation from './Cooperation'; - -function CompanyDescription ({ data }) { - return ( -
- - {data.is_startup && } - {data.is_registered && } - {data.is_registered && } - {data.is_registered && } -
- ); -} - -export default CompanyDescription; - -CompanyDescription.propTypes = { - data: PropTypes.shape({ - is_registered: PropTypes.bool.isRequired, - is_startup: PropTypes.bool.isRequired, - common_info: PropTypes.string, - startup_idea: PropTypes.string, - product_info: PropTypes.string, - service_info: PropTypes.string, - }), -}; diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/CompanyDescription.module.css b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/CompanyDescription.module.css deleted file mode 100644 index e06f6ead2..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/CompanyDescription.module.css +++ /dev/null @@ -1,7 +0,0 @@ -.company-description-block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 16px; - min-width: 800px; -} diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Cooperation.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Cooperation.jsx deleted file mode 100644 index 934cac30d..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Cooperation.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import { useEffect } from 'react'; -import { useContext } from 'react'; -import { ActiveLinksContext } from '../../../context/ActiveLinksContext'; -import classes from './Cooperation.module.css'; -import ReadMore from './ReadMore'; - -function Cooperation () { - const { setActiveLinks } = useContext(ActiveLinksContext); - const cooperationData = ''; - - useEffect(() => { - if (cooperationData) { - setActiveLinks(prevData => [ - ...prevData, - 'cooperation']); - } - }, [cooperationData, setActiveLinks]); - - // TODO: implement logic for getting data from db when it's added on server side - - return ( - cooperationData ? ( -
-
-
-
-

Формат співпраці

-
-
-
-
-
- - {cooperationData} - -
-
-
-
- ) : null - ); -} - -export default Cooperation; diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Cooperation.module.css b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Cooperation.module.css deleted file mode 100644 index da8f2f351..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Cooperation.module.css +++ /dev/null @@ -1,64 +0,0 @@ -.cooperation-wrapper { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 24px; - border-radius: 8px; -} - -.cooperation, -.cooperation__content--block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; -} - -.cooperation__title { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; -} - -.cooperation__title--block { - display: flex; - padding: 8px 12px; - align-items: flex-start; - gap: 10px; - align-self: stretch; - border-radius: 4px; -} - -.cooperation__title--text { - width: 742px; - color: var(--main-grey-90, #25292C); - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 700; - line-height: 20px; - text-transform: uppercase; -} - -.cooperation__title--divider { - height: 1px; - width: 795px; - background: var(--main-grey-20, #DEE1E8); -} - -.cooperation__content--description { - display: flex; - padding: 12px; - align-items: flex-start; - gap: 10px; - width: 776px; - color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; - letter-spacing: -0.14px; -} diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts.jsx deleted file mode 100644 index c799015b3..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts.jsx +++ /dev/null @@ -1,124 +0,0 @@ -import React from 'react'; -import { Link } from 'react-router-dom'; -import { PropTypes } from 'prop-types'; -import PhoneEmail from './PhoneEmail'; -import classes from './DataContacts.module.css'; - -function DataContacts ({ data, isAuthorized }) { - - const companyData = { - 'ЄДРПОУ': data.edrpou, - 'РНОКПП': data.rnokpp, - 'Рік заснування': data.founded, - 'Розмір компанії': '', - 'Аудит': '' - }; - - const companyContacts = { - 'Сайт': '', - 'PhoneEmail': , - 'Поштова адреса': data.address, - 'Соціальні мережі': [ - { - name: 'facebook', - url: '', - svgPath: , - }, - { - name: 'instagram', - url: '', - svgPath: , - }, - ], - 'Співпрацюємо з': '' - }; - - const hasSocialLinks = companyContacts['Соціальні мережі'].filter(socialLink => socialLink.url !== '').length > 0; - - const renderedDataSections = Object.entries(companyData).map(([key, value]) => { - const className = key === ('ЄДРПОУ' || 'РНОКПП') ? `${classes['data-block__field']} ${classes['edrpou']}` : classes['data-block__field']; - if (value) { - return ( -
-

{key}

-

- {value} -

-
- ); - } - return null; - }); - - const hasDataSections = renderedDataSections.some((section) => section !== null); - - const renderedContactSections = Object.entries(companyContacts).map(([key, value]) => { - if (value) { - if (key === 'Соціальні мережі') { - return ( - hasSocialLinks ? - (
-

{key}

- {value.map((contact, index) => { - if (contact.url) { - return ( - - {contact.svgPath} - - ); - } - return null; - })} -
) : null - ); - } else if (key === 'PhoneEmail') { - return ( - - {value } - ); - } else { - const className = key === 'Адрес(и)' ? classes['data-block__field--address'] : classes['data-block__field']; - const valueClassName = key === 'Сайт' ? classes['data-block__field--site'] : classes['data-block__field--value']; - return ( -
-

{key}

-

{value}

-
- ); - } - } - return null; - }); - - const hasContactSections = renderedContactSections.some((section) => section !== null); - - return ( -
-
- {hasDataSections ? ( -
- {renderedDataSections} -
- ) : null} - {hasContactSections ? ( -
- {renderedContactSections} -
- ) : null} -
-
- ); -} - -export default DataContacts; - -DataContacts.propTypes = { - isAuthorized: PropTypes.bool, - data: PropTypes.shape({ - id: PropTypes.number.isRequired, - person: PropTypes.number, - edrpou: PropTypes.string, - founded: PropTypes.number, - address: PropTypes.string, - }), -}; diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts/DataContacts.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts/DataContacts.jsx new file mode 100644 index 000000000..422c81585 --- /dev/null +++ b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts/DataContacts.jsx @@ -0,0 +1,137 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { PropTypes } from 'prop-types'; + +import PhoneEmail from './DataContactsPhoneEmail'; + +import classes from './DataContacts.module.css'; + + +function DataContacts ({ data, isAuthorized }) { + + const companyData = { + 'ЄДРПОУ': data.edrpou, + 'РНОКПП': data.rnokpp, + 'Рік заснування': data.founded, + 'Розмір компанії': '', + 'Аудит': '' + }; + + const companyContacts = { + 'Сайт': '', + 'PhoneEmail': < + PhoneEmail + isAuthorized={isAuthorized} + profileId={data.id} + personId={data.person} / + >, + 'Поштова адреса': data.address, + 'Соціальні мережі': [ + { + name: 'facebook', + url: '', + svgPath: , + }, + { + name: 'instagram', + url: '', + svgPath: , + }, + ], + 'Співпрацюємо з': '' + }; + + const hasSocialLinks = companyContacts['Соціальні мережі'].filter(socialLink => socialLink.url !== '').length > 0; + + const renderedDataSections = Object.entries(companyData).map(([key, value]) => { + const className = key === ('ЄДРПОУ' || 'РНОКПП') ? + `${classes['data-block__field']} ${classes['edrpou']}` : + classes['data-block__field']; + if (value) { + return ( +
+

{key}

+

{value}

+
+ ); + } + return null; + }); + + const hasDataSections = renderedDataSections.some((section) => section !== null); + + const renderedContactSections = Object.entries(companyContacts).map(([key, value]) => { + if (value) { + if (key === 'Соціальні мережі') { + return ( + hasSocialLinks ? + (
+

{key}

+ {value.map((contact, index) => { + if (contact.url) { + return ( + + {contact.svgPath} + + ); + } + return null; + })} +
) : null + ); + } else if (key === 'PhoneEmail') { + return ( + + {value} + ); + } else { + const className = key === 'Адрес(и)' ? + classes['data-block__field--address'] : + classes['data-block__field']; + const valueClassName = key === 'Сайт' ? + classes['data-block__field--site'] : + classes['data-block__field--value']; + return ( +
+

{key}

+

{value}

+
+ ); + } + } + return null; + }); + + const hasContactSections = renderedContactSections.some((section) => section !== null); + + return ( +
+
+ {hasDataSections ? ( +
+ {renderedDataSections} +
+ ) : null} + {hasContactSections ? ( +
+ {renderedContactSections} +
+ ) : null} +
+
+ ); +} + +export default DataContacts; + +DataContacts.propTypes = { + isAuthorized: PropTypes.bool, + data: PropTypes.shape({ + id: PropTypes.number.isRequired, + person: PropTypes.number, + edrpou: PropTypes.string, + rnokpp: PropTypes.string, + founded: PropTypes.number, + address: PropTypes.string, + }), +}; diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts.module.css b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts/DataContacts.module.css similarity index 52% rename from FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts.module.css rename to FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts/DataContacts.module.css index fb352a84f..0d0a2ee79 100644 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts.module.css +++ b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts/DataContacts.module.css @@ -1,27 +1,30 @@ -.data-wrapper { +.data-block { display: flex; flex-direction: column; align-items: flex-start; - gap: 16px; + padding-top: 16px; + padding-bottom: 16px; } -.data { +.data-content { display: flex; padding: 16px; + width: 312px; flex-direction: column; align-items: flex-start; - gap: 36px; - border-radius: 2px; - border: 1px solid var(--main-grey-05, #F8F8F8); - background: var(--main-grey-05, #F8F8F8); + gap: 32px; + border-radius: 6px; + border: 1px solid none; + background: var(--profile-detail-data-contacts-backround); } -.data-block { +.data-block_render-contact, +.data-content_render-data { display: flex; + width: 345px; flex-direction: column; align-items: flex-start; gap: 6px; - min-width: 338px; } .data-block__field { @@ -33,7 +36,7 @@ .data-block__field--title { width: 130px; - color: var(--main-black-90, #292E32); + color: var(--profile-detail-data-contacts-color-text); font-feature-settings: 'calt' off; font-family: var(--font-main); font-size: 14px; @@ -47,9 +50,8 @@ font-weight: 600; } -.data-block__field--value { - width: 200px; - color: var(--main-black-90, #292E32); +.data-block__field--value, +.data-block__field--site { font-feature-settings: 'calt' off; font-family: var(--font-main); font-size: 14px; @@ -59,16 +61,14 @@ letter-spacing: -0.14px; } +.data-block__field--value { + width: 170px; + color: var(--profile-detail-data-contacts-color-text); +} + .data-block__field--site { - width: 200px; - color: var(--system-blue-100, #4A73E2); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 14px; - font-style: normal; - font-weight: 600; - line-height: 22px; - letter-spacing: -0.14px; + width: 170px; + color: #4A73E2; } .data-block__field--address, @@ -77,3 +77,29 @@ align-items: flex-start; gap: 8px; } + +@media only screen and (min-width: 768px) { + .data-block__field--value { + min-width: 506px; + } + + .data-content { + width: 600px; + min-width: 688px; + } +} + +@media only screen and (min-width: 1200px) { + .data-block__field--value { + min-width: 200px; + } + + .data-content { + width: 411px; + min-width: 411px; + } + + .data-block { + padding-left: 40px; + } +} diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/PhoneEmail.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts/DataContactsPhoneEmail.jsx similarity index 74% rename from FrontEnd/src/pages/ProfileDetail/DetailedInfo/PhoneEmail.jsx rename to FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts/DataContactsPhoneEmail.jsx index aace7b194..cc1d94fa7 100644 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/PhoneEmail.jsx +++ b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts/DataContactsPhoneEmail.jsx @@ -1,12 +1,15 @@ import axios from 'axios'; import { useState } from 'react'; +import { toast } from 'react-toastify'; import useSWR from 'swr'; -import { useAuth } from '../../../hooks'; + import { PropTypes } from 'prop-types'; -import classes from './PhoneEmail.module.css'; import { CheckOutlined, CopyOutlined } from '@ant-design/icons'; -import { toast } from 'react-toastify'; import { Tooltip } from 'antd'; +import { useAuth } from '../../../../hooks'; + +import classes from './DataContactsPhoneEmail.module.css'; + const LENGTH_EMAIL = 14; @@ -18,7 +21,8 @@ function PhoneEmail({ isAuthorized, profileId, personId }) { const copyContent = (key) => { try { - navigator.clipboard.writeText(profileData[key]); + const contentToCopy = key === 'phone' ? `+${profileData.phone}` : profileData.email; + navigator.clipboard.writeText(contentToCopy); if (key === 'phone') { setIsPhoneCopied(true); setTimeout(() => setIsPhoneCopied(false), 4000); @@ -33,9 +37,9 @@ function PhoneEmail({ isAuthorized, profileId, personId }) { const renderIcons = (state) => { return state ? ( - + ) : ( - + ); }; @@ -73,28 +77,28 @@ function PhoneEmail({ isAuthorized, profileId, personId }) { {isContactsShown || (user && user.id === personId) ? (

- {profileData.phone} - { - profileData.phone ? copyContent('phone')}> - {renderIcons(isPhoneCopied)} - - : null - } + {(profileData.phone) ? ('+' + profileData.phone) : ''} + { + profileData.phone ? copyContent('phone')}> + {renderIcons(isPhoneCopied)} + + : null + }

- {profileData.email.length > LENGTH_EMAIL ? ( + {profileData.email.length > LENGTH_EMAIL ? ( {`${profileData.email.slice(0, LENGTH_EMAIL)}...`} ) : ( {profileData.email} )} - { - profileData.email ? copyContent('email')}> - {renderIcons(isEmailCopied)} - - : null - } + { + profileData.email ? copyContent('email')}> + {renderIcons(isEmailCopied)} + + : null + }

) : ( @@ -117,4 +121,5 @@ export default PhoneEmail; PhoneEmail.propTypes = { profileId: PropTypes.number.isRequired, personId: PropTypes.number, + isAuthorized: PropTypes.bool, }; diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/PhoneEmail.module.css b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts/DataContactsPhoneEmail.module.css similarity index 61% rename from FrontEnd/src/pages/ProfileDetail/DetailedInfo/PhoneEmail.module.css rename to FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts/DataContactsPhoneEmail.module.css index a8945f89e..f21fcc946 100644 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/PhoneEmail.module.css +++ b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DataContacts/DataContactsPhoneEmail.module.css @@ -6,7 +6,7 @@ .data-block__field--title { width: 130px; - color: var(--main-black-90, #292E32); + color: var(--profile-detail-data-contacts-color-text); font-feature-settings: 'calt' off; font-family: var(--font-main); font-size: 14px; @@ -18,26 +18,19 @@ .data-block__field button { display: flex; - width: 200px; height: 32px; - max-width: 200px; padding: 5px 15px; justify-content: center; align-items: center; gap: 4px; border-radius: 4px; - border: 1px solid var(--primary-green-80, #1F9A7C); - background: var(--neutral-1, #FFF); + border: 1px solid var(--profile-detail-data-contacts-color-text); cursor: pointer; } +.data-block__field--show--contacts, .data-block__field--contacts { - display: flex; - flex-direction: column; - width: 200px; - height: auto; - align-items: flex-start; - color: var(--main-black-90, #292E32); + text-align: center; font-feature-settings: 'calt' off; font-family: var(--font-main); font-size: 14px; @@ -47,22 +40,35 @@ letter-spacing: -0.14px; } +.data-block__field--contacts { + display: flex; + flex-direction: column; + height: auto; + align-items: flex-start; + color: var(--profile-detail-data-contacts-color-text); +} + .data-block__field--show--contacts { flex: 1 0 0; - color: var(--primary-green-80, #1F9A7C); - text-align: center; - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; - letter-spacing: -0.16px; + color: var(--profile-detail-data-contacts-color-text); } -.contact-container{ +.contact-container { display: flex; + min-width: 164px; justify-content: space-between; - align-items: center; - min-width: 100%; + padding-bottom: 10px; +} + +@media only screen and (min-width: 768px) { + .contact-container { + min-width: 535px; + } +} + +@media only screen and (min-width: 1200px) { + .contact-container { + width: 240px; + min-width: 140px; + } } diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/Company.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/Company.jsx new file mode 100644 index 000000000..abcab204a --- /dev/null +++ b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/Company.jsx @@ -0,0 +1,44 @@ +import { PropTypes } from 'prop-types'; +import { useEffect, useContext } from 'react'; + +import ReadMore from '../../ProfileDetailComponents/ReadMore'; + +import { ActiveLinksContext } from '../../../../context/ActiveLinksContext'; + +import classes from './Company.module.css'; + +function Company({ data }) { + const { setActiveLinks } = useContext(ActiveLinksContext); + const companyData = data.common_info ; + + useEffect(() => { + if (companyData) { + setActiveLinks(prevData => [ + ...prevData, + 'about-company', + ]); + } + }, [setActiveLinks, companyData]); + + return ( + companyData ? ( +
+ {data.common_info ? ( +
+ + {data.common_info} + +
+ ) : null} +
+ ) : null + ); +} + +export default Company; + +Company.propTypes = { + data: PropTypes.shape({ + common_info: PropTypes.string, + }), +}; diff --git a/FrontEnd/src/pages/ProfileDetail/EmptyData.module.css b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/Company.module.css similarity index 51% rename from FrontEnd/src/pages/ProfileDetail/EmptyData.module.css rename to FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/Company.module.css index 5803123a1..56f3f3ace 100644 --- a/FrontEnd/src/pages/ProfileDetail/EmptyData.module.css +++ b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/Company.module.css @@ -1,20 +1,18 @@ -.empty-data-wrapper { +.about-company { + padding-top: 24px; display: flex; - padding: 12px; flex-direction: column; align-items: flex-start; gap: 24px; - flex: 1; } -.empty-data { - width: 776px; - color: var(--main-grey-40, #A3AAB0); +.about-company__content { + color: var(--profile-detail-info-color-text); font-feature-settings: 'calt' off; font-family: var(--font-main); - font-size: 14px; + font-size: 16px; font-style: normal; font-weight: 400; - line-height: 22px; - letter-spacing: -0.14px; + line-height: 24px; + letter-spacing: -0.16px; } diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/ProductsServices.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/ProductsServices.jsx new file mode 100644 index 000000000..670af673b --- /dev/null +++ b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/ProductsServices.jsx @@ -0,0 +1,60 @@ +import { useMemo, useEffect, useContext } from 'react'; +import { PropTypes } from 'prop-types'; +import { ActiveLinksContext } from '../../../../context/ActiveLinksContext'; + +import ReadMore from '../../ProfileDetailComponents/ReadMore'; + +import classes from './ProductsServices.module.css'; + + +function ProductsServices({ data }) { + const { setActiveLinks } = useContext(ActiveLinksContext); + const profile = useMemo(() => { + return { + products: data.product_info, + services: data.service_info + }; + }, [data]); + + useEffect(() => { + if (profile.products || profile.services) { + setActiveLinks(prevData => [ + ...prevData, + 'products-services']); + } + }, [setActiveLinks, profile.products, profile.services]); + + return ( + (profile.products || profile.services) ? ( +
+

Інформація про товари/послуги

+
+ {profile.products && +
+ + Товари: + {profile.products} + + +
} + {profile.services && +
+ + Послуги: + {profile.services} + +
} +
+
+ ) : null + ); +} + +export default ProductsServices; + +ProductsServices.propTypes = { + data: PropTypes.shape({ + product_info: PropTypes.string, + service_info: PropTypes.string, + }) +}; diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/ProductsServices.module.css b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/ProductsServices.module.css new file mode 100644 index 000000000..11425a32a --- /dev/null +++ b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/ProductsServices.module.css @@ -0,0 +1,55 @@ +.products-services { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 24px; +} + +.products-services__title--text { + color: var(--profile-detail-info-color-title); + font-family: var(--font-main); + font-size: 18px; + font-style: normal; + font-weight: 700; + line-height: 21.6px; + letter-spacing: -0.18px; +} + +.products-services__content--block { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 12px; +} + +.products-services__content--title { + color: var(--profile-detail-info-color-text); + font-feature-settings: 'calt' off; + font-family: var(--font-main); + font-size: 16px; + font-style: normal; + line-height: 24px; + letter-spacing: -0.16px; + font-weight: 700; +} + +.products-services__content--text { + color: var(--profile-detail-info-color-text); + font-feature-settings: 'calt' off; + font-family: var(--font-main); + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 24px; + letter-spacing: -0.16px; + flex: 1; +} + +@media only screen and (min-width: 768px) { + .products-services__title--text { + font-size: 34px; + font-weight: 700; + line-height: 40.8px; + letter-spacing: -0.34px; + } +} diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/Startup.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/Startup.jsx new file mode 100644 index 000000000..aa4a02693 --- /dev/null +++ b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/Startup.jsx @@ -0,0 +1,52 @@ +import { useMemo, useEffect, useContext } from 'react'; +import { PropTypes } from 'prop-types'; + +import { ActiveLinksContext } from '../../../../context/ActiveLinksContext'; + +import ReadMore from '../../ProfileDetailComponents/ReadMore'; +import classes from './Startup.module.css'; + + +function Startup({ data }) { + const { setActiveLinks } = useContext(ActiveLinksContext); + const profile = useMemo(() => { + return { + idea: data.startup_idea, + }; + }, [data]); + + + useEffect(() => { + if (profile.idea) { + setActiveLinks(prevData => [ + ...prevData, + 'startup']); + } + }, [profile.idea, setActiveLinks]); + + return ( + profile.idea ? ( +
+

Стартап

+
+ + Ідея стартапу: + {profile.idea} + +
+
+ ) : null + ); +} + +export default Startup; + +Startup.propTypes = { + data: PropTypes.shape({ + startup_idea: PropTypes.string, + }), +}; + +ReadMore.propTypes = { + children: PropTypes.node, +}; diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/Startup.module.css b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/Startup.module.css new file mode 100644 index 000000000..1780a1a71 --- /dev/null +++ b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoComponents/Startup.module.css @@ -0,0 +1,50 @@ +.startup-wrapper { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 24px; +} + +.startup__title--text { + color: var(--profile-detail-info-color-title); + font-family: var(--font-main); + font-size: 18px; + font-style: normal; + font-weight: 700; + line-height: 21.6px; + letter-spacing: -0.18px; +} + +.startup__content--block { + display: flex; + flex-direction: column; + align-items: flex-start; + color: var(--profile-detail-info-color-text); + font-feature-settings: 'calt' off; + font-family: var(--font-main); + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 24px; + letter-spacing: -0.16px; +} + +.startup__content--title { + color: var(--profile-detail-info-color-text); + font-feature-settings: 'calt' off; + font-family: var(--font-main); + font-size: 16px; + font-style: normal; + font-weight: 700; + line-height: 24px; + letter-spacing: -0.16px; +} + +@media only screen and (min-width: 768px) { + .startup__title--text { + font-size: 34px; + font-weight: 700; + line-height: 40.8px; + letter-spacing: -0.34px; + } +} diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoSection.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoSection.jsx index 03e18a384..c779a4f13 100644 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoSection.jsx +++ b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoSection.jsx @@ -1,29 +1,53 @@ import { PropTypes } from 'prop-types'; + +import DataContacts from './DataContacts/DataContacts'; +import Company from './DetailedInfoComponents/Company'; +import Startup from './DetailedInfoComponents/Startup'; +import ProductsServices from './DetailedInfoComponents/ProductsServices'; + import classes from './DetailedInfoSection.module.css'; -import CompanyDescription from './CompanyDescription'; -import DataContacts from './DataContacts'; -import EmptyData from '../EmptyData'; -function DetailedInfoSection ({ isAuthorized, data, containsNotRequiredData }) { - return ( -
- {containsNotRequiredData ? : } - -
- ); + +function DetailedInfoSection({ isAuthorized, data, containsNotRequiredData }) { + return ( +
+
+ {containsNotRequiredData + ?

Про Компанію

+ : '' + } + + {containsNotRequiredData ? +
+

Про Компанію

+ + {data.is_registered && } + {data.is_startup && } +
+ : +
+

+ Інформація не заповнена +

+
} +
+
+ ); } export default DetailedInfoSection; DetailedInfoSection.propTypes = { - isAuthorized: PropTypes.bool, - data: PropTypes.shape({ - id: PropTypes.number.isRequired, - common_info: PropTypes.string, - startup_idea: PropTypes.string, - product_info: PropTypes.string, - service_info: PropTypes.string, - address: PropTypes.string, - }), - containsNotRequiredData: PropTypes.bool.isRequired, - }; + isAuthorized: PropTypes.bool, + data: PropTypes.shape({ + id: PropTypes.number.isRequired, + common_info: PropTypes.string, + startup_idea: PropTypes.string, + product_info: PropTypes.string, + service_info: PropTypes.string, + address: PropTypes.string, + is_startup: PropTypes.bool, + is_registered: PropTypes.bool, + }), + containsNotRequiredData: PropTypes.bool.isRequired, +}; diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoSection.module.css b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoSection.module.css index bf89c99f8..cc44f87d1 100644 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoSection.module.css +++ b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/DetailedInfoSection.module.css @@ -1,5 +1,122 @@ +.detail-info-page_block { + display: flex; + width: var(--profile-detail-width); + align-items: center; + justify-content: center; +} + .detail-info-page { + display: flex; + flex-direction: column; + justify-content: center; + width: 344px; + padding: 24px 16px; +} + +.company-description-block { + width: 100%; +} + +.profile-detail__tags-mobile { display: flex; align-items: flex-start; - gap: 134px; + color: var(--profile-detail-info-color-title); + font-feature-settings: 'calt' off; + text-decoration: none; + font-family: var(--font-main); + font-size: 18px; + font-style: normal; + font-weight: 700; + line-height: 21.6px; + letter-spacing: -0.18px; + white-space: nowrap; +} + +.profile-detail__tags-desktop { + display: none; +} + +.empty-data-wrapper { + display: flex; + align-items: center; + justify-content: center; +} + +.empty-data { + color: #A3AAB0; + font-feature-settings: 'calt' off; + font-family: var(--font-main); + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 22px; + letter-spacing: -0.14px; +} + +@media only screen and (min-width: 768px) { + .detail-info-page { + display: flex; + flex-direction: column; + width: 768px; + padding: 24px; + } + + .company-description-block { + width: 720px; + } + + .profile-detail__tags-mobile { + font-size: 34px; + line-height: 40.8px; + letter-spacing: -0.34px; + } +} + +@media only screen and (min-width: 1200px) { + .detail-info-page_block { + justify-content: center; + } + + .detail-info-page { + display: flex; + flex-direction: row-reverse; + justify-content: space-between; + width: 1100px; + } + + .company-description-block { + width: 860px; + } + + .profile-detail__tags-mobile { + display: none; + } + + .profile-detail__tags-desktop { + display: flex; + align-items: flex-start; + color: var(--profile-detail-info-color-title); + font-feature-settings: 'calt' off; + text-decoration: none; + font-family: var(--font-main); + font-size: 34px; + font-style: normal; + font-weight: 700; + line-height: 40.8px; + letter-spacing: -0.34px; + white-space: nowrap; + } + .empty-data { + padding-left: 100px; + } +} + +@media only screen and (min-width: 1512px) { + .detail-info-page { + width: 1304px; + } + + .company-description-block { + width: 860px; + } } diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Logistics.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Logistics.jsx deleted file mode 100644 index bb3e015a7..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Logistics.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import { useEffect } from 'react'; -import { useContext } from 'react'; -import { ActiveLinksContext } from '../../../context/ActiveLinksContext'; -import classes from './Logistics.module.css'; -import ReadMore from './ReadMore'; - -function Logistics () { - const { setActiveLinks } = useContext(ActiveLinksContext); - const logisticsData = ''; - - useEffect(() => { - if (logisticsData) { - setActiveLinks(prevData => [ - ...prevData, - 'logistics']); - } - }, [logisticsData, setActiveLinks]); - - // TODO: implement logic for getting data from db when it's added on server side - - return ( - logisticsData ? ( -
-
-
-
-

Логістика товарів / послуг

-
-
-
-
-
- - {logisticsData} - -
-
-
-
- ) : null - ); -} - -export default Logistics; diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Logistics.module.css b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Logistics.module.css deleted file mode 100644 index febce9021..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Logistics.module.css +++ /dev/null @@ -1,64 +0,0 @@ -.logistics-wrapper { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 24px; - border-radius: 8px; -} - -.logistics, -.logistics__content--block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; -} - -.logistics__title { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; -} - -.logistics__title--block { - display: flex; - padding: 8px 12px; - align-items: flex-start; - gap: 10px; - align-self: stretch; - border-radius: 4px; -} - -.logistics__title--text { - width: 742px; - color: var(--main-grey-90, #25292C); - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 700; - line-height: 20px; - text-transform: uppercase; -} - -.logistics__title--divider { - height: 1px; - width: 795px; - background: var(--main-grey-20, #DEE1E8); -} - -.logistics__content--description { - display: flex; - padding: 12px; - align-items: flex-start; - gap: 10px; - width: 776px; - color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; - letter-spacing: -0.14px; -} diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/ProductsServices.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/ProductsServices.jsx deleted file mode 100644 index f48702edd..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/ProductsServices.jsx +++ /dev/null @@ -1,65 +0,0 @@ -import { useMemo, useEffect, useContext} from 'react'; -import { PropTypes } from 'prop-types'; -import { ActiveLinksContext } from '../../../context/ActiveLinksContext'; -import classes from './ProductsServices.module.css'; -import ReadMore from './ReadMore'; - -function ProductsServices ({ data }) { - const { setActiveLinks } = useContext(ActiveLinksContext); - const profile = useMemo(() => { - return { - products: data.product_info, - services: data.service_info - }; - }, [data]); - - useEffect(() => { - if (profile.products || profile.services) { - setActiveLinks(prevData => [ - ...prevData, - 'products-services']); - } - }, [setActiveLinks, profile.products, profile.services]); - - return ( - (profile.products || profile.services) ? ( -
-
-
-

Товари / послуги

-
-
-
-
- {profile.products && -
-

Товари

-
- - {profile.products} - -
-
} - {profile.services && -
-

Послуги

-
- - {profile.services} - -
-
} -
-
- ) : null - ); -} - -export default ProductsServices; - -ProductsServices.propTypes = { - data: PropTypes.shape({ - product_info: PropTypes.string, - service_info: PropTypes.string, - }) -}; diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/ProductsServices.module.css b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/ProductsServices.module.css deleted file mode 100644 index 348edee1f..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/ProductsServices.module.css +++ /dev/null @@ -1,78 +0,0 @@ -.products-services { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; - border-radius: 8px; -} - -.products-services__title { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; -} - -.products-services__title--block { - display: flex; - padding: 8px 12px; - align-items: flex-start; - gap: 10px; - align-self: stretch; - border-radius: 4px; -} - -.products-services__title--text { - width: 742px; - color: var(--main-grey-90, #25292C); - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 700; - line-height: 20px; - text-transform: uppercase; -} - -.products-services__title--divider { - height: 1px; - width: 795px; - background: var(--main-grey-20, #DEE1E8); -} - -.products-services__content { - display: flex; - padding: 12px; - flex-direction: column; - align-items: flex-start; - gap: 24px; -} - -.products-services__content--block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; -} - -.products-services__content--title { - color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; - letter-spacing: -0.16px; -} - -.products-services__content--description { - width: 776px; - color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; - letter-spacing: -0.14px; -} diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Startup.jsx b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Startup.jsx deleted file mode 100644 index 3a6f6f826..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Startup.jsx +++ /dev/null @@ -1,78 +0,0 @@ -import { useMemo } from 'react'; -import { PropTypes } from 'prop-types'; -import { useEffect } from 'react'; -import { useContext } from 'react'; -import { ActiveLinksContext } from '../../../context/ActiveLinksContext'; -import classes from './Startup.module.css'; -import ReadMore from './ReadMore'; - -function Startup ({ data }) { - const { setActiveLinks } = useContext(ActiveLinksContext); - const profile = useMemo(() => { - return { - startup_idea: data.startup_idea, - }; - }, [data]); - - // TODO: implement logic for getting data from db when it's added on server side - - const startupData = { - 'Ідея стартапу': profile.startup_idea, - 'Розмір інвестицій': '', - 'Ціль співпраці': '', - 'Кінцевий результат': '', - 'Конкурентна перевага ідеї': '', - 'Ризики': '', - 'Пошук партнерів': '', - }; - - const renderedSections = Object.entries(startupData).map(([key, value]) => { - if (value) { - return ( -
-

{key}

-
- {value} -
-
- ); - } - return null; - }); - - const hasSections = renderedSections.some((section) => section !== null); - - useEffect(() => { - if (hasSections) { - setActiveLinks(prevData => [ - ...prevData, - 'startup']); - } - }, [hasSections, setActiveLinks]); - - return ( - hasSections ? ( -
-
-
-
-

Стартап

-
-
-
-
- {renderedSections} -
-
-
- ) : null - ); -} - -export default Startup; - -Startup.propTypes = { - data: PropTypes.shape({ - startup_idea: PropTypes.string, - }), - }; diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Startup.module.css b/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Startup.module.css deleted file mode 100644 index cbd4bac14..000000000 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/Startup.module.css +++ /dev/null @@ -1,79 +0,0 @@ -.startup-wrapper { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 24px; - border-radius: 8px; -} - -.startup, -.startup__content--block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; -} - -.startup__title { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; -} - -.startup__title--block { - display: flex; - padding: 8px 12px; - align-items: flex-start; - gap: 10px; - align-self: stretch; - border-radius: 4px; -} - -.startup__title--text { - width: 742px; - color: var(--main-grey-90, #25292C); - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 700; - line-height: 20px; - text-transform: uppercase; -} - -.startup__title--divider { - width: 795px; - height: 1px; - background: var(--main-grey-20, #DEE1E8); -} - -.startup__content { - display: flex; - padding: 12px; - flex-direction: column; - align-items: flex-start; - gap: 12px; -} - -.startup__content--title { - color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; - letter-spacing: -0.16px; -} - -.startup__content--description { - width: 776px; - color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; - letter-spacing: -0.14px; -} diff --git a/FrontEnd/src/pages/ProfileDetail/EmptyData.jsx b/FrontEnd/src/pages/ProfileDetail/EmptyData.jsx deleted file mode 100644 index 20dc43e84..000000000 --- a/FrontEnd/src/pages/ProfileDetail/EmptyData.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import classes from './EmptyData.module.css'; - -function EmptyData () { - return ( -
-

- Інформація не заповнена -

-
- ); -} - -export default EmptyData; diff --git a/FrontEnd/src/pages/ProfileDetail/MainInfo/MainInfoSection.jsx b/FrontEnd/src/pages/ProfileDetail/MainInfo/MainInfoSection.jsx deleted file mode 100644 index efa266594..000000000 --- a/FrontEnd/src/pages/ProfileDetail/MainInfo/MainInfoSection.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import { PropTypes } from 'prop-types'; -import TitleInfo from './TitleInfo'; -import ProfileDetailNavBar from './ProfileDetailNavBar'; -import classes from './MainInfoSection.module.css'; - -function MainInfoSection({ isAuthorized, data, containsNotRequiredData }) { - return ( -
- - {containsNotRequiredData ? : null} -
- ); -} - -export default MainInfoSection; - -MainInfoSection.propTypes = { - isAuthorized: PropTypes.bool, - data: PropTypes.shape({ - id: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - address: PropTypes.string, - region_display: PropTypes.string, - categories: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.number, - name: PropTypes.string, - }) - ), - activities: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.number, - name: PropTypes.string, - }) - ), - common_info: PropTypes.string, - is_saved: PropTypes.bool.isRequired, - is_registered: PropTypes.bool.isRequired, - is_startup: PropTypes.bool.isRequired, - }).isRequired, - containsNotRequiredData: PropTypes.bool.isRequired, - }; diff --git a/FrontEnd/src/pages/ProfileDetail/MainInfo/MainInfoSection.module.css b/FrontEnd/src/pages/ProfileDetail/MainInfo/MainInfoSection.module.css deleted file mode 100644 index 2e4524823..000000000 --- a/FrontEnd/src/pages/ProfileDetail/MainInfo/MainInfoSection.module.css +++ /dev/null @@ -1,5 +0,0 @@ -.basic-info-content { - display: flex; - flex-direction: column; - align-items: flex-start; -} diff --git a/FrontEnd/src/pages/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx b/FrontEnd/src/pages/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx deleted file mode 100644 index 808eca9b8..000000000 --- a/FrontEnd/src/pages/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx +++ /dev/null @@ -1,101 +0,0 @@ -import { HashLink } from 'react-router-hash-link'; -import { useLocation, useNavigate } from 'react-router-dom'; -import { useState, useEffect } from 'react'; -import { PropTypes } from 'prop-types'; -import { useContext } from 'react'; -import { ActiveLinksContext } from '../../../context/ActiveLinksContext'; -import classes from './ProfileDetailNavBar.module.css'; - -const MENU_LINKS = { - registeredAndStartup: { - 'about-company': 'Про компанію', - 'startup': 'Стартап', - 'products-services': 'Товари / послуги', - 'logistics': 'Логістика товарів / послуг', - 'cooperation': 'Формат співпраці', - }, - registered: { - 'about-company': 'Про компанію', - 'products-services': 'Товари / послуги', - 'logistics': 'Логістика товарів / послуг', - 'cooperation': 'Формат співпраці', - }, - startup: { - 'about-company': 'Про компанію', - 'startup': 'Стартап', - } -}; - -function ProfileDetailNavBar({ data }) { - const { hash } = useLocation (); - const navigate = useNavigate (); - const { activeLinks } = useContext(ActiveLinksContext); - const [activeLink, setActiveLink] = useState(''); - - const companyType = () => { - if (data.is_registered && data.is_startup) { - return MENU_LINKS.registeredAndStartup; - } else if (data.is_registered) { - return MENU_LINKS.registered; - } else if (data.is_startup) { - return MENU_LINKS.startup; - } - }; - - useEffect(() => { - if (hash) { - setActiveLink(hash.substring(1)); - } else { - setActiveLink( - data.is_registered && activeLinks.includes('about-company') ? 'about-company' : - data.is_startup && activeLinks.includes('startup') ? 'startup' : '' - ); - } - }, [hash, data.is_registered, data.is_startup, activeLinks]); - - useEffect(() => { - navigate(hash.pathname, {replace: true}); - }, [navigate, hash.pathname]); - - return ( -
-
- {Object.entries(companyType()).map( - ([link, label]) => - activeLinks.includes(link) && ( -
-
- - {label} - -
-
-
- ) - )} -
-
-
- ); -} - -export default ProfileDetailNavBar; - -ProfileDetailNavBar.propTypes = { - data: PropTypes.shape({ - is_registered: PropTypes.bool.isRequired, - is_startup: PropTypes.bool.isRequired, - }).isRequired, -}; diff --git a/FrontEnd/src/pages/ProfileDetail/MainInfo/ProfileDetailNavBar.module.css b/FrontEnd/src/pages/ProfileDetail/MainInfo/ProfileDetailNavBar.module.css deleted file mode 100644 index e568f729b..000000000 --- a/FrontEnd/src/pages/ProfileDetail/MainInfo/ProfileDetailNavBar.module.css +++ /dev/null @@ -1,63 +0,0 @@ -.navbar-menu { - display: flex; - align-items: flex-start; -} - -.navbar-menu__block { - display: flex; - flex-direction: column; - align-items: flex-start; -} - -.navbar-menu__item { - display: flex; - padding: 8px 12px; - align-items: flex-start; - gap: 10px; -} - -.navbar-menu__item a { - text-decoration: none; - color: inherit; -} - -.navbar-menu__item a.inactive-link { - color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 400; - line-height: 20px; - letter-spacing: -0.16px; -} - -.navbar-menu__item a.active-link { - text-decoration: none; - color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; - letter-spacing: -0.16px; -} - -.devider { - width: 795px; - height: 1px; - background: var(--main-grey-20, #DEE1E8); -} - -.inactive-devider { - height: 1px; - align-self: stretch; - background: var(--main-grey-20, #DEE1E8); -} - -.active-devider { - height: 1px; - align-self: stretch; - background: var(--primary-green-80, #1F9A7C); -} diff --git a/FrontEnd/src/pages/ProfileDetail/MainInfo/TitleInfo.jsx b/FrontEnd/src/pages/ProfileDetail/MainInfo/TitleInfo.jsx deleted file mode 100644 index 0355a21eb..000000000 --- a/FrontEnd/src/pages/ProfileDetail/MainInfo/TitleInfo.jsx +++ /dev/null @@ -1,155 +0,0 @@ -import axios from 'axios'; -import { useState, useMemo } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { PropTypes } from 'prop-types'; -import classNames from 'classnames'; -import { useAuth } from '../../../hooks'; -import DefaultLogo from './DefaultLogo'; -import classes from './TitleInfo.module.css'; -import CategoryBadges from '../../../components/MiniComponents/CategoryBadges'; -import StarForLike from '../../../components/MiniComponents/StarForLike'; - -function TitleInfo({ isAuthorized, data }) { - const { user } = useAuth(); - const navigate = useNavigate(); - const [isSaved, setIsSaved] = useState(data.is_saved); - const profile = useMemo(() => { - return { - id: data.id, - personId: data.person, - name: data.name, - activities: - data.activities && data.activities.length - ? data.activities.map((activity) => activity.name).join(', ') - : null, - regions: data.regions_ukr_display ? data.regions_ukr_display : '', - categories: data.categories ? data.categories : null, - isSaved: data.is_saved, - logo: data.logo, - }; - }, [data]); - - const ownProfile = user && user.id === profile.personId; - - const handleSave = async () => { - setIsSaved(true); - try { - await axios.post(`${process.env.REACT_APP_BASE_API_URL}/api/saved-list/`,{ company_pk: profile.id }); - } catch (error) { - console.error(error); - } - }; - - const handleDeleteSaved = async () => { - setIsSaved(false); - try { - await axios.delete(`${process.env.REACT_APP_BASE_API_URL}/api/saved-list/${profile.id}`); - } catch (error) { - console.error(error); - } - }; - - const navigateToEditProfile = () => { - navigate('/profile/user-info'); - }; - - return ( -
-
- {!profile.logo?.path ? ( - - ) : ( - Company logo - )} -
-
-

- {profile.activities} -

-
-

- {profile.name} -

-
- -
-
-

- {profile.regions} -

-
- {isAuthorized ? ( - <> - {!ownProfile && ( - - )} - {ownProfile && ( - - - Редагувати профіль - - - )} - - ) : null} -
- ); -} - -export default TitleInfo; - -TitleInfo.propTypes = { - isAuthorized: PropTypes.bool, - data: PropTypes.shape({ - id: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - person: PropTypes.number, - address: PropTypes.string, - regions_ukr_display: PropTypes.string, - categories: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.number, - name: PropTypes.string, - }) - ), - activities: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.number, - name: PropTypes.string, - }) - ), - is_saved: PropTypes.bool.isRequired, - logo: PropTypes.shape({ - path: PropTypes.string, - uuid: PropTypes.string, - }), - }).isRequired, -}; diff --git a/FrontEnd/src/pages/ProfileDetail/MainInfo/TitleInfo.module.css b/FrontEnd/src/pages/ProfileDetail/MainInfo/TitleInfo.module.css deleted file mode 100644 index 6ace21f93..000000000 --- a/FrontEnd/src/pages/ProfileDetail/MainInfo/TitleInfo.module.css +++ /dev/null @@ -1,121 +0,0 @@ -.title-block { - display: flex; - width: 1280px; - padding: 16px 12px 8px 12px; - align-items: flex-start; - gap: 12px; -} - -.title-block__logo { - width: 40px; - height: 40px; - flex-shrink: 0; - display: flex; - justify-content: center; - align-items: center; - border-radius: 32px; - box-shadow: 0px 0px 2px 0px rgba(65, 64, 69, 0.2); -} - -.title-block__logo { - width: 40px; - height: 40px; - flex-shrink: 0; - border-radius: 26px; - object-fit: cover; -} - -.title-block__about { - display: flex; - flex-direction: column; - align-items: flex-start; - flex: 1 0 0; -} - -.title-block__activity { - color: var(--main-grey-90, #25292c); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; - letter-spacing: -0.14px; -} - -.title-block__company { - display: flex; - align-items: flex-start; - max-width: 72%; - gap: 16px; -} - -.title-block__company_name { - display: flex; - align-items: flex-start; - min-width: fit-content; - gap: 4px; - color: var(--main-grey-90, #25292c); - font-family: var(--font-main); - font-size: 20px; - font-style: normal; - font-weight: 700; - line-height: 120%; - text-transform: uppercase; -} - -.title-block__company_category { - display: flex; - flex-wrap: wrap; - align-items: flex-start; - gap: 8px; -} - -.title-block__company_region { - color: var(--main-black-90, #292e32); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 10px; - font-style: normal; - font-weight: 400; - line-height: 16px; - max-width: 72%; -} - -.title-block__button { - display: flex; - height: 32px; - padding: 5px 15px; - justify-content: center; - align-items: center; - gap: 4px; - border-radius: 4px; - border: 1px solid var(--primary-green-80, #1f9a7c); - background: var(--neutral-1, #fff); - cursor: pointer; -} - -.title-block__link { - height: 22px; -} - -.added_to_saved__button { - background: var(--primary-green-80, #1f9a7c); -} - -.title-block__button--text { - display: flex; - color: var(--primary-green-80, #1f9a7c); - text-align: center; - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; - letter-spacing: -0.16px; -} - -.added_to_saved__button--text { - color: var(--main-white, #fff); -} diff --git a/FrontEnd/src/pages/ProfileDetail/ProfileDetailBaner/BannerImage.jsx b/FrontEnd/src/pages/ProfileDetail/ProfileDetailBaner/BannerImage.jsx new file mode 100644 index 000000000..7cef78f95 --- /dev/null +++ b/FrontEnd/src/pages/ProfileDetail/ProfileDetailBaner/BannerImage.jsx @@ -0,0 +1,25 @@ +import { PropTypes } from 'prop-types'; +import classes from './BannerImage.module.css'; + +function BannerImage({ data }) { + const backgroundImage = data?.banner?.path + ? `url(${data.banner.path}) lightgray center / cover no-repeat` + : `url(${process.env.REACT_APP_PUBLIC_URL}/svg/empty-decore-50x46.svg) #e0e0e0 left top / 50px 46px repeat `; + + return ( +
+ ); +} + +BannerImage.propTypes = { + data: PropTypes.shape({ + banner: PropTypes.shape({ + path: PropTypes.string, + }), + }), +}; + +export default BannerImage; diff --git a/FrontEnd/src/pages/ProfileDetail/ProfileDetailBaner/BannerImage.module.css b/FrontEnd/src/pages/ProfileDetail/ProfileDetailBaner/BannerImage.module.css new file mode 100644 index 000000000..abf787621 --- /dev/null +++ b/FrontEnd/src/pages/ProfileDetail/ProfileDetailBaner/BannerImage.module.css @@ -0,0 +1,10 @@ +.banner-image__block { + width: var(--profile-detail-width); + height: 195px; +} + +@media only screen and (min-width: 768px) { + .banner-image__block { + height: 368px; + } +} diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/ReadMore.jsx b/FrontEnd/src/pages/ProfileDetail/ProfileDetailComponents/ReadMore.jsx similarity index 100% rename from FrontEnd/src/pages/ProfileDetail/DetailedInfo/ReadMore.jsx rename to FrontEnd/src/pages/ProfileDetail/ProfileDetailComponents/ReadMore.jsx diff --git a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/ReadMore.module.css b/FrontEnd/src/pages/ProfileDetail/ProfileDetailComponents/ReadMore.module.css similarity index 59% rename from FrontEnd/src/pages/ProfileDetail/DetailedInfo/ReadMore.module.css rename to FrontEnd/src/pages/ProfileDetail/ProfileDetailComponents/ReadMore.module.css index 214038b8d..cc8016990 100644 --- a/FrontEnd/src/pages/ProfileDetail/DetailedInfo/ReadMore.module.css +++ b/FrontEnd/src/pages/ProfileDetail/ProfileDetailComponents/ReadMore.module.css @@ -1,5 +1,5 @@ -.read-more-symbol { - color: var(--primary-green-80, #1F9A7C); +.read-more-symbo, +.read-more { font-feature-settings: 'calt' off; font-family: var(--font-main); font-size: 14px; @@ -7,17 +7,13 @@ font-weight: 400; line-height: 22px; letter-spacing: -0.14px; +} + +.read-more-symbol { + color: var(--primary-green-80, #1F9A7C); cursor: pointer; } .read-more { - font-family: var(--font-main); color: var(--main-grey-90, #25292C); - font-feature-settings: 'calt' off; - font-family: var(--font-main); - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; - letter-spacing: -0.14px; -} +} \ No newline at end of file diff --git a/FrontEnd/src/pages/ProfileDetail/ProfileDetailPage.jsx b/FrontEnd/src/pages/ProfileDetail/ProfileDetailPage.jsx index 4d1b6d3da..c61c62055 100644 --- a/FrontEnd/src/pages/ProfileDetail/ProfileDetailPage.jsx +++ b/FrontEnd/src/pages/ProfileDetail/ProfileDetailPage.jsx @@ -6,13 +6,18 @@ import { PropTypes } from 'prop-types'; import Loader from '../../components/Loader/Loader'; import ErrorPage404 from '../../pages/ErrorPages/ErrorPage404'; -import MainInfoSection from './MainInfo/MainInfoSection'; + +import BannerImage from './ProfileDetailBaner/BannerImage'; +import TitleInfo from './TitelInfo/TitleInfo'; import DetailedInfoSection from './DetailedInfo/DetailedInfoSection'; -import BannerImage from './BannerImage'; + import { ActiveLinksContext } from '../../context/ActiveLinksContext'; -import classes from './ProfileDetailPage.module.css'; + import PendingStatus from '../../components/MiniComponents/PendingModerationIcon/PendingStatus'; +import classes from './ProfileDetailPage.module.css'; + + function ProfileDetailPage({ isAuthorized }) { const [activeLinks, setActiveLinks] = useState([]); const { id } = useParams(); @@ -20,7 +25,7 @@ function ProfileDetailPage({ isAuthorized }) { async function fetcher(url) { return axios.get(url) - .then(res => res.data); + .then(res => res.data); } const { @@ -43,7 +48,11 @@ function ProfileDetailPage({ isAuthorized }) { return (error && error.status !== 401) ? ( ) : ( -
+
{isLoading ? ( ) : ( @@ -52,26 +61,23 @@ function ProfileDetailPage({ isAuthorized }) {
-
- -
- -
- +
+
+ + )}
); - } export default ProfileDetailPage; diff --git a/FrontEnd/src/pages/ProfileDetail/ProfileDetailPage.module.css b/FrontEnd/src/pages/ProfileDetail/ProfileDetailPage.module.css index a5a3bdbb7..bb68cb7a7 100644 --- a/FrontEnd/src/pages/ProfileDetail/ProfileDetailPage.module.css +++ b/FrontEnd/src/pages/ProfileDetail/ProfileDetailPage.module.css @@ -1,8 +1,7 @@ .profile-detail__main { display: flex; flex-direction: column; - min-height: var(--min-height-block-main); - align-content: center; + min-height: calc(100vh - 342px); } .profile-detail__loader-content { @@ -16,13 +15,6 @@ padding-left: 112px; } -.profile-detail__page { - display: inline-flex; - flex-direction: column; - align-items: center; - gap: 16px; -} - .profile-detail__logo-tooltip { display: flex; position: absolute; diff --git a/FrontEnd/src/pages/ProfileDetail/MainInfo/DefaultLogo.jsx b/FrontEnd/src/pages/ProfileDetail/TitelInfo/DefaultLogo.jsx similarity index 100% rename from FrontEnd/src/pages/ProfileDetail/MainInfo/DefaultLogo.jsx rename to FrontEnd/src/pages/ProfileDetail/TitelInfo/DefaultLogo.jsx diff --git a/FrontEnd/src/pages/ProfileDetail/MainInfo/DefaultLogo.module.css b/FrontEnd/src/pages/ProfileDetail/TitelInfo/DefaultLogo.module.css similarity index 77% rename from FrontEnd/src/pages/ProfileDetail/MainInfo/DefaultLogo.module.css rename to FrontEnd/src/pages/ProfileDetail/TitelInfo/DefaultLogo.module.css index ae44225c9..2df5918e8 100644 --- a/FrontEnd/src/pages/ProfileDetail/MainInfo/DefaultLogo.module.css +++ b/FrontEnd/src/pages/ProfileDetail/TitelInfo/DefaultLogo.module.css @@ -4,10 +4,6 @@ height: 100%; } -.default_ellipse { - position: absolute; -} - .default_logo { position: absolute; top: 3px; diff --git a/FrontEnd/src/pages/ProfileDetail/TitelInfo/TitleInfo.jsx b/FrontEnd/src/pages/ProfileDetail/TitelInfo/TitleInfo.jsx new file mode 100644 index 000000000..d418e3bba --- /dev/null +++ b/FrontEnd/src/pages/ProfileDetail/TitelInfo/TitleInfo.jsx @@ -0,0 +1,165 @@ +import axios from 'axios'; +import { useState, useMemo } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { PropTypes } from 'prop-types'; +import classNames from 'classnames'; + +import DefaultLogo from './DefaultLogo'; + +import CategoryBadges from '../../../components/MiniComponents/CategoryBadges'; +import StarForLike from '../../../components/MiniComponents/StarForLike'; +import { useAuth } from '../../../hooks'; + +import classes from './TitleInfo.module.css'; + + +function TitleInfo({ isAuthorized, data }) { + const { user } = useAuth(); + const navigate = useNavigate(); + const [isSaved, setIsSaved] = useState(data.is_saved); + const profile = useMemo(() => { + return { + id: data.id, + personId: data.person, + name: data.name, + activities: + data.activities && data.activities.length + ? data.activities.map((activity) => activity.name).join(', ') + : null, + regions: data.regions_ukr_display ? data.regions_ukr_display : '', + categories: data.categories ? data.categories : null, + isSaved: data.is_saved, + logo: data.logo, + }; + }, [data]); + + const ownProfile = user && user.id === profile.personId; + + const handleSave = async () => { + setIsSaved(true); + try { + await axios.post(`${process.env.REACT_APP_BASE_API_URL}/api/saved-list/`, { company_pk: profile.id }); + } catch (error) { + console.error(error); + } + }; + + const handleDeleteSaved = async () => { + setIsSaved(false); + try { + await axios.delete(`${process.env.REACT_APP_BASE_API_URL}/api/saved-list/${profile.id}`); + } catch (error) { + console.error(error); + } + }; + + const navigateToEditProfile = () => { + navigate('/profile/user-info'); + }; + + return ( +
+
+
+
+ {!profile.logo?.path ? ( + + ) : ( + Логотип компанії + )} +
+
+

+ {profile.activities} +

+
+

+ {profile.name} +

+

+ {profile.regions} +

+
+ +
+
+
+
+ {isAuthorized ? ( +
+ {!ownProfile && ( + + )} + {ownProfile && ( + + + Редагувати + + + )} +
+ ) : null} +
+
+ ); +} + +export default TitleInfo; + +TitleInfo.propTypes = { + isAuthorized: PropTypes.bool, + data: PropTypes.shape({ + id: PropTypes.number.isRequired, + name: PropTypes.string.isRequired, + person: PropTypes.number, + address: PropTypes.string, + regions_ukr_display: PropTypes.string, + categories: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.number, + name: PropTypes.string, + }) + ), + activities: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.number, + name: PropTypes.string, + }) + ), + is_saved: PropTypes.bool, + logo: PropTypes.shape({ + path: PropTypes.string, + uuid: PropTypes.string, + }), + }).isRequired, +}; diff --git a/FrontEnd/src/pages/ProfileDetail/TitelInfo/TitleInfo.module.css b/FrontEnd/src/pages/ProfileDetail/TitelInfo/TitleInfo.module.css new file mode 100644 index 000000000..a141383c3 --- /dev/null +++ b/FrontEnd/src/pages/ProfileDetail/TitelInfo/TitleInfo.module.css @@ -0,0 +1,193 @@ +.title-block { + display: flex; + background: var(--profile-detail-title-background); + width: var(--profile-detail-width); + justify-content: center; + align-items: center; +} + +.title-block__content { + display: flex; + align-items: flex-start; + flex-direction: column; +} + +.title-block__content-info { + display: flex; + flex-direction: column; + width: 345px; + padding: 24px 16px; +} + +.title-block__logo-block { + width: 64px; + height: 64px; + display: flex; + justify-content: center; + align-items: center; +} + +.title-block__logo-img { + width: 64px; + height: 64px; + display: flex; + justify-content: center; + align-items: center; + object-fit: scale-down; +} + +.title-block__about { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 4px; +} + +.title-block__activity { + color: var(--profile-detail-title-color-activity); + font-feature-settings: 'calt' off; + font-family: var(--font-main); + font-size: 14px; + font-style: normal; + font-weight: 700; + line-height: 16.8px; + letter-spacing: -0.14px; +} + +.title-block__company { + display: flex; + flex-direction: column; + justify-content: flex-start; + gap: 10px; +} + +.title-block__company_name { + color: var(--profile-detail-title-color-company-name); + font-family: var(--font-main); + font-size: 24px; + font-style: normal; + font-weight: 700; + line-height: 28.8px; + letter-spacing: -0.24px; +} + +.title-block__company_category { + display: flex; + align-items: flex-start; +} + +.title-block__company_region { + color: var(--profile-detail-title-color-company-region); + font-feature-settings: 'calt' off; + font-family: var(--font-main); + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 24px; + letter-spacing: -0.14px; +} + +.title-block__link { + height: 22px; +} + +.added_to_saved__button { + background: var(--profile-detail-title-color-company-button); +} + +.title-block__button-block { + display: flex; + justify-content: center; + padding: 0px 16px 24px 16px; +} + +.title-block__button { + display: flex; + height: 46px; + width: 345px; + justify-content: center; + align-items: center; + gap: 4px; + border-radius: 4px; + border: 1px solid var(--profile-detail-title-color-company-button); + cursor: pointer; + padding: 7px 16px; +} + +.title-block__button--text { + display: flex; + color: var(--profile-detail-title-color-company-button); + text-align: center; + font-feature-settings: 'calt' off; + font-family: var(--font-main); + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: 20px; + letter-spacing: -0.16px; + padding-right: 4px; +} + +.added_to_saved__button--text { + color: var(--profile-detail-title-color-company-button-saved); +} + +@media only screen and (min-width: 768px) { + .title-block__content { + width: 768px; + } + + .title-block { + justify-content: center; + } + + .title-block__content-info { + flex-direction: row; + width: 768px; + gap: 24px; + } + + .title-block__button-block { + padding-left: 104px; + } + + .title-block__button { + width: 253px; + } +} + +@media only screen and (min-width: 1200px) { + .title-block { + flex-direction: row; + justify-content: center; + } + + .title-block__content { + width: 1100px; + flex-direction: row; + justify-content: space-between; + } + + .title-block__content-info { + flex-direction: row; + width: 800px; + gap: 24px; + } + + .title-block__button { + width: 100%; + min-width: 124px; + } + + .title-block__button-block { + display: flex; + justify-content: center; + padding: 24px 16px; + } +} + +@media only screen and (min-width: 1512px) { + .title-block__content { + width: 1304px; + } +} diff --git a/FrontEnd/src/pages/ProfileList/ProfileCard.jsx b/FrontEnd/src/pages/ProfileList/ProfileCard.jsx deleted file mode 100644 index 3525e9ef4..000000000 --- a/FrontEnd/src/pages/ProfileList/ProfileCard.jsx +++ /dev/null @@ -1,153 +0,0 @@ -import { useState, useMemo } from 'react'; -import { Link } from 'react-router-dom'; - -import { Typography } from 'antd'; -import { PropTypes } from 'prop-types'; - -import { useAuth } from '../../hooks'; -import css from './ProfileCard.module.css'; -import axios from 'axios'; -import CategoryBadges from '../../components/MiniComponents/CategoryBadges'; -import StarForLike from '../../components/MiniComponents/StarForLike'; -import BellForUpdates from '../../components/MiniComponents/BellForUpdates'; - -const { Paragraph } = Typography; - -export default function ProfileCard({ isAuthorized, data, savedIsUpdated, onClearUpdate }) { - const { user } = useAuth(); - const [isSaved, setIsSaved] = useState(data.is_saved); - const profile = useMemo(() => { - return { - id: data.id, - personId: data.person, - name: data.name, - activities: !data.activities.length - ? null - : data.activities.map((activity) => activity.name).join(', '), - region: data.regions_ukr_display ? data.regions_ukr_display : '', - categories: data.categories, - isSaved: data.is_saved, - savedIsUpdated: savedIsUpdated, - commonInfo: data.common_info, - logo: data.logo, - }; - }, [data]); - - const ownProfile = user && user.id === profile.personId; - - const handleSave = async () => { - setIsSaved(true); - try { - await axios.post(`${process.env.REACT_APP_BASE_API_URL}/api/saved-list/`,{ company_pk: profile.id }); - } catch (error) { - console.error(error); - } - }; - - const handleDeleteSaved = async () => { - setIsSaved(false); - try { - await axios.delete(`${process.env.REACT_APP_BASE_API_URL}/api/saved-list/${profile.id}`); - } catch (error) { - console.error(error); - } - }; - - const handleProfileViewed = async () => { - if (savedIsUpdated) { - onClearUpdate(false); - try { - await axios.patch(`${process.env.REACT_APP_BASE_API_URL}/api/saved-list/${profile.id}/`, { - is_updated: false - }); - } catch (error) { - console.error(error); - onClearUpdate(true); - } - } - }; - - return ( -
- -
- Company logo -
-
-
-
-

- {profile.activities} -

-
-
{profile.name}
-
- {profile.region} -
-
-
- - {profile.commonInfo} - -
-
- -
-
- -
- -
- -
- ); -} - -ProfileCard.propTypes = { - isAuthorized: PropTypes.bool, - data: PropTypes.shape({ - id: PropTypes.number.isRequired, - person: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - address: PropTypes.string, - regions_ukr_display: PropTypes.string, - categories: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.number, - name: PropTypes.string, - }) - ), - activities: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.number, - name: PropTypes.string, - }) - ), - common_info: PropTypes.string, - is_saved: PropTypes.bool.isRequired, - logo: PropTypes.shape({ - path: PropTypes.string, - uuid: PropTypes.string, - }), - }).isRequired, - savedIsUpdated: PropTypes.bool, - onClearUpdate: PropTypes.func, -}; diff --git a/FrontEnd/src/pages/ProfileList/ProfileCard.module.css b/FrontEnd/src/pages/ProfileList/ProfileCard.module.css deleted file mode 100644 index 76de337c2..000000000 --- a/FrontEnd/src/pages/ProfileList/ProfileCard.module.css +++ /dev/null @@ -1,137 +0,0 @@ -.company-card { - display: flex; - width: 100%; - padding: 8px; - align-items: flex-start; - border-radius: 12px; - border: 1px solid var(--main-grey-10, #eeeff1); - background: var(--main-white, #fff); - box-shadow: 0px 4px 8px 0px rgba(65, 64, 69, 0.2); -} - -.company-card__link { - display: flex; - gap: 16px; -} - -.logo-box { - width: 64px; - height: 64px; - display: flex; - justify-content: center; - align-items: center; - border-radius: 32px; - box-shadow: 0px 0px 2px 0px rgba(65, 64, 69, 0.2); -} - -.logo { - width: 54px; - height: 54px; - border-radius: 26px; - object-fit: cover; -} - -.description__avatar { - display: flex; - flex-direction: column; - align-items: flex-end; - border-radius: 100px; - border: 3px solid var(--secondary-white, #e2e5eb); - background: var(--main-white, #fff); -} - -.content { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; - flex: 1 0 0; - border-radius: 0px 0px 12px 12px; -} - -.content-header { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 5px; - align-self: stretch; -} - -.content-header__activity { - display: flex; - align-items: center; - gap: 10px; -} - -.content-header__activity--text { - display: flex; - align-items: center; - color: var(--main-grey-20, #767f86); - font-feature-settings: "calt" off; - - font-family: var(--font-main); - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; - letter-spacing: -0.16px; -} - -.content-header__name { - display: flex; - align-items: flex-start; - gap: 4px; - align-self: stretch; - color: var(--main-grey-90, #25292c); - - font-family: var(--font-main); - font-size: 20px; - font-style: normal; - font-weight: 700; - line-height: 24px; - text-transform: uppercase; -} - -.content-header__address { - display: flex; - align-items: flex-start; - gap: 4px; - color: var(--main-grey-80, #292e32); - font-feature-settings: "calt" off; - - font-family: var(--font-main); - font-size: 10px; - font-style: normal; - font-weight: 400; - line-height: 16px; -} - -.content__common-info { - width: 1150px; - color: var(--main-grey-90, #25292c); - font-feature-settings: "calt" off; - - font-family: var(--font-main); - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; - letter-spacing: -0.14px; -} - -.content__categories { - display: flex; - flex-wrap: wrap; - align-items: flex-start; - align-self: stretch; - max-width: 100%; - gap: 8px; -} - -.bell-container { - display: flex; - justify-content: center; - align-items: center; - width: 30px; - height: 100%; -} \ No newline at end of file diff --git a/FrontEnd/src/pages/ProfileList/ProfileList.jsx b/FrontEnd/src/pages/ProfileList/ProfileList.jsx index 9d266073c..01f143730 100644 --- a/FrontEnd/src/pages/ProfileList/ProfileList.jsx +++ b/FrontEnd/src/pages/ProfileList/ProfileList.jsx @@ -1,42 +1,26 @@ import { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; import { List } from 'antd'; -import ProfileCard from './ProfileCard'; -import css from './ProfileList.module.css'; - -const PAGE_SIZE = 6; - -const getCompanyWord = (number) => { - if (number === 1 || (number > 20 && number % 10 === 1)) { - return 'компанія'; - } else if ((number >= 2 && number <= 4) || (number > 20 && number % 10 >= 2 && number % 10 <= 4)) { - return 'компанії'; - } else { - return 'компаній'; - } -}; - -const ListHeader = ({ number }) => ( -
-

{number}

-

{getCompanyWord(number)}

-
-); +import CompanyCard from '../../components/CompanyCard/CompanyCard'; export default function ProfileList({ isAuthorized, current, - data, + items, + profiles, paginationFunc, + pageSize, + changeCompanies, }) { const [savedIsUpdatedMap, setSavedIsUpdatedMap] = useState({}); useEffect(() => { - const initialMap = data.results.reduce((acc, item) => { + const initialMap = profiles.reduce((acc, item) => { acc[item.id] = item.saved_is_updated; return acc; }, {}); setSavedIsUpdatedMap(initialMap); - }, [data]); + }, [profiles]); const handleClearUpdate = (profileId, isUpdated) => { setSavedIsUpdatedMap((prev) => ({ @@ -47,30 +31,53 @@ export default function ProfileList({ return ( { paginationFunc(page); }, position: 'bottom', align: 'center', - pageSize: PAGE_SIZE, - total: data.total_items, + pageSize: pageSize, + total: items, hideOnSinglePage: true, current: current, }} - header={} - dataSource={data.results} + dataSource={profiles} split={false} + locale={{emptyText: 'Жодна компанія не відповідає обраному фільтру.'}} renderItem={(item) => ( - handleClearUpdate(item.id, isUpdated)} + changeCompanies={changeCompanies} /> )} /> ); } + +ProfileList.propTypes = { + isAuthorized: PropTypes.bool.isRequired, + current: PropTypes.number.isRequired, + profiles: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.number.isRequired, + saved_is_updated: PropTypes.bool, + }) + ).isRequired, + items: PropTypes.number, + paginationFunc: PropTypes.func.isRequired, + pageSize: PropTypes.number.isRequired, +}; diff --git a/FrontEnd/src/pages/ProfileList/ProfileList.module.css b/FrontEnd/src/pages/ProfileList/ProfileList.module.css index 381d9ea4c..12f3841cb 100644 --- a/FrontEnd/src/pages/ProfileList/ProfileList.module.css +++ b/FrontEnd/src/pages/ProfileList/ProfileList.module.css @@ -13,30 +13,6 @@ align-self: stretch; } -.results-header { - width: 413px; - height: 24px; - display: flex; - gap: 5px; - - font-family: var(--font-main); - font-size: 20px; - font-style: normal; - font-weight: 700; - line-height: 24px; - text-transform: uppercase; - text-align: left; -} - - -.results-header__number { - color: var(--primary-green-100, #0b6c61); -} - -.results-header__text { - color: var(--main-grey-20, #767f86); -} - .results-list { display: flex; flex-direction: column; diff --git a/FrontEnd/src/pages/ProfileList/ProfileListHeader.jsx b/FrontEnd/src/pages/ProfileList/ProfileListHeader.jsx new file mode 100644 index 000000000..9f0222110 --- /dev/null +++ b/FrontEnd/src/pages/ProfileList/ProfileListHeader.jsx @@ -0,0 +1,20 @@ +import css from './ProfileListHeader.module.css'; + +export default function ListHeader ({ number }) { + const getCompanyWord = (number) => { + if (number === 1 || (number > 20 && number % 10 === 1)) { + return 'підприємство'; + } else if ((number >= 2 && number <= 4) || (number > 20 && number % 10 >= 2 && number % 10 <= 4)) { + return 'підприємства'; + } else { + return 'підприємств'; + } + }; + + return ( +
+

{number} {getCompanyWord(number)}

+
+ ); + +} \ No newline at end of file diff --git a/FrontEnd/src/pages/ProfileList/ProfileListHeader.module.css b/FrontEnd/src/pages/ProfileList/ProfileListHeader.module.css new file mode 100644 index 000000000..3bfaaacf1 --- /dev/null +++ b/FrontEnd/src/pages/ProfileList/ProfileListHeader.module.css @@ -0,0 +1,17 @@ +.results-header { + display: flex; + flex-direction: row; + align-items: center; + +} + +.results-header__text { + font-family: var(--font-main); + font-size: 14px; + font-style: normal; + font-weight: 700; + line-height: 16.8px; + text-transform: uppercase; + white-space: nowrap; + color: #767676; +} diff --git a/FrontEnd/src/pages/ProfileList/ProfileListPage.jsx b/FrontEnd/src/pages/ProfileList/ProfileListPage.jsx index a7406d7b0..695d81b60 100644 --- a/FrontEnd/src/pages/ProfileList/ProfileListPage.jsx +++ b/FrontEnd/src/pages/ProfileList/ProfileListPage.jsx @@ -1,59 +1,93 @@ import { useEffect, useState } from 'react'; -import { useParams, useNavigate, useLocation } from 'react-router-dom'; +import { useSearchParams } from 'react-router-dom'; import axios from 'axios'; - -import { Radio } from 'antd'; import useSWR from 'swr'; +import useWindowWidth from '../../hooks/useWindowWidth'; import ErrorPage404 from '../ErrorPages/ErrorPage404'; import Loader from '../../components/Loader/Loader'; +import ProfileListHeader from './ProfileListHeader'; import ProfileList from './ProfileList'; import css from './ProfileListPage.module.css'; -export default function ProfileListPage({ isAuthorized }) { - const location = useLocation(); - const navigate = useNavigate(); - const { filter } = useParams(); - const queryParams = new URLSearchParams(location.search); - const pageNumber = Number(queryParams.get('page')) || 1; +const COMPANY_TYPE = [ + { title: 'Усі підприємства', key: 'all', value: '' }, + { title: 'Компанії', key: 'companies', value: 'companies' }, + { title: 'Стартапи', key: 'startups', value: 'startups' }, +]; + +const ACTIVITY_TYPE = [ + { title: 'Усі сектори', key: 'all', value: '' }, + { title: 'Виробники', key: 'producers', value: 'producers' }, + { title: 'Імпортери', key: 'importers', value: 'importers' }, + { title: 'Роздрібні мережі', key: 'retailers', value: 'retailers' }, + { title: 'HORECA', key: 'horeca', value: 'horeca' }, + { title: 'Інші послуги', key: 'other-services', value: 'other-services' }, +]; - const [filterSaved, setFilterSaved] = useState(false); +export default function ProfileListPage({ isAuthorized, isSaved }) { + const [searchParams, setSearchParams] = useSearchParams(); + const pageNumber = Number(searchParams.get('page')) || 1; + const companyType = searchParams.get('companyType') || ''; + const activity = searchParams.get('activity') || ''; + const [profiles, setProfiles] = useState([]); + const [filters, setFilters] = useState([]); const [currentPage, setCurrentPage] = useState(pageNumber); - const [profileFilter, setProfileFilter] = useState(''); + const [activeTab, setActiveTab] = useState(searchParams.get('companyType') || 'all'); + const [activeBtn, setActiveBtn] = useState(searchParams.get('activity') || 'all'); - useEffect(() => { - const FILTER_MAP = { - companies: 'is_registered=True', - startups: 'is_startup=True', - producers: 'activities__name=Виробник', - importers: 'activities__name=Імпортер', - retailers: 'activities__name=Роздрібна мережа', - horeca: 'activities__name=HORECA', - 'other-services': 'activities__name=Інші послуги' - }; - setProfileFilter(FILTER_MAP[filter]); - setFilterSaved(false); - setCurrentPage(pageNumber); - }, [filter, pageNumber]); + const windowWidth = useWindowWidth(); + const linkText = windowWidth >= 768 ? 'Усі підприємства' : 'Усі'; + const pageSize = windowWidth >= 768 ? 16 : 4; - const updateQueryParams = (newPage) => { - queryParams.set('page', newPage); - navigate(`?${queryParams.toString()}`); + const [url, setUrl] = useState( + `${process.env.REACT_APP_BASE_API_URL}/api/profiles/?ordering=name&page_size=${pageSize}&page=${currentPage}` + ); + + + const companyTypeMap = { + '': '', + companies: 'is_registered=True', + startups: 'is_startup=True', }; - const handlePageChange = (page) => { - setCurrentPage(page); - updateQueryParams(page); + const activityTypeMap = { + '': '', + producers: 'activities__name=Виробник', + importers: 'activities__name=Імпортер', + retailers: 'activities__name=Роздрібна мережа', + horeca: 'activities__name=HORECA', + 'other-services': 'activities__name=Інші послуги', }; - const urlForAll = `${process.env.REACT_APP_BASE_API_URL}/api/profiles/?${profileFilter}&ordering=name&page=${currentPage}`; + useEffect(() => { + const companyTypeFilter = companyTypeMap[companyType] || ''; + const activityTypeFilter = activityTypeMap[activity] || ''; + + setFilters([companyTypeFilter, activityTypeFilter].filter(Boolean)); + setCurrentPage(1); + }, [companyType, activity]); + + useEffect(() => { + const baseUrl = `${process.env.REACT_APP_BASE_API_URL}/api/profiles/`; + let queryString = !isSaved + ? `?ordering=name&page_size=${pageSize}&page=${currentPage}` + : `?is_saved=True&ordering=name&page_size=${pageSize}&page=${currentPage}`; + + if (filters.length === 2) { + queryString = !isSaved + ? `?${filters.join('&')}&ordering=name&page_size=${pageSize}&page=${currentPage}` + : `?is_saved=True&${filters.join('&')}&ordering=name&page_size=${pageSize}&page=${currentPage}`; + } else if (filters.length === 1) { + queryString = !isSaved + ? `?${filters[0]}&ordering=name&page_size=${pageSize}&page=${currentPage}` + : `?is_saved=True&${filters[0]}&ordering=name&page_size=${pageSize}&page=${currentPage}`; + } - const urlForSaved = `${ - process.env.REACT_APP_BASE_API_URL - }/api/profiles/?${profileFilter}${ - filterSaved ? '&is_saved=True' : '' - }&ordering=-saved_at&page=${currentPage}`; + setUrl(`${baseUrl}${queryString}`); + setCurrentPage(pageNumber); + }, [filters, pageNumber, pageSize, currentPage, isSaved]); async function fetcher(url) { return axios.get(url) @@ -64,13 +98,62 @@ export default function ProfileListPage({ isAuthorized }) { data: fetchedProfiles, error, isLoading, - } = useSWR(filterSaved && isAuthorized ? urlForSaved : urlForAll, fetcher); + } = useSWR(url, fetcher, {onSuccess: (data) => setProfiles(data.results)}); - const handleRadioSelect = () => { - if (!filterSaved) { + useEffect(() => { + if (fetchedProfiles?.total_items === 0) { setCurrentPage(1); + searchParams.delete('page'); + setSearchParams(searchParams); + } else { + const totalPages = Math.ceil(fetchedProfiles?.total_items / pageSize); + if (currentPage > totalPages) { + setCurrentPage(totalPages); + updateQueryParams(totalPages); + } } - setFilterSaved(!filterSaved); + }, [fetchedProfiles, pageSize, currentPage, isSaved]); + + const changeCompanies = (companyId, saved) => { + setProfiles((prevProfiles) => + prevProfiles.map((profile) => + profile.id === companyId ? { ...profile, is_saved: saved } : profile + ) + ); + }; + + const handleFilters = (companyType, activity) => { + if (companyType) { + searchParams.set('companyType', companyType); + } else { + searchParams.delete('companyType'); + } + + if (activity) { + searchParams.set('activity', activity); + } else { + searchParams.delete('activity'); + } + + setSearchParams(searchParams); + }; + + const updateQueryParams = (newPage) => { + searchParams.set('page', newPage); + setSearchParams(searchParams); + }; + + const handlePageChange = (page) => { + setCurrentPage(page); + updateQueryParams(page); + }; + + const handleActiveTab = (activeTab) => { + setActiveTab(activeTab); + }; + + const handleActiveBtn = (activeBtn) => { + setActiveBtn(activeBtn); }; return ( @@ -79,31 +162,65 @@ export default function ProfileListPage({ isAuthorized }) { ) : (
- {isAuthorized ? ( -
- - Усі - Збережені - +
+
+

+ {!isSaved ? 'Підприємства та сектори' : 'Мої збережені'} +

+
+ {COMPANY_TYPE.map((item) => ( +
+ (handleFilters(item.value, activity), handleActiveTab(item.key))} + > + {item.title === 'Усі підприємства' ? linkText : item.title} + + + +
+ ))} +
+
+
+
+
+
+ {ACTIVITY_TYPE.map((item) => ( + + ))} +
+
- ) : null} - {isLoading ? ( - - ) : ( - - )} + {isLoading ? ( + + ) : ( +
+ +
+ )} +
)}
diff --git a/FrontEnd/src/pages/ProfileList/ProfileListPage.module.css b/FrontEnd/src/pages/ProfileList/ProfileListPage.module.css index dae96ee5a..20f382443 100644 --- a/FrontEnd/src/pages/ProfileList/ProfileListPage.module.css +++ b/FrontEnd/src/pages/ProfileList/ProfileListPage.module.css @@ -1,20 +1,157 @@ .page { + display: flex; + flex-direction: column; min-height: 470px; - border-radius: 8px; - background: var(--wf-base-white, #fff); flex-grow: 1; } .page-content { + width: 100vw; + display: flex; + flex-direction: column; + +} + +.company-list__header--wrapper { + width: 100%; display: flex; flex-direction: column; - width: 1305px; - gap: 16px; - margin: 17px 100px; + background: var(--light-seashell-background); +} + +.company-list__header { + width: 375px; + box-sizing: border-box; + display: flex; + flex-direction: column; + align-self: center; + gap: 32px; + padding: 40px 16px 0px 30px; +} + +.company-list__title { + font-family: Geologica; + font-weight: 700; + line-height: 28.8px; + letter-spacing: 0.01em; + +} + +.company-list__tabs { + display: flex; + flex-direction: row; + gap: 24px; + height: 33px; +} + +.company-list__tabs--wrapper { + display: flex; + flex-direction: column; + gap: 12px; +} + +.company-list__tabs--element, +.company-list__tabs--element--active { + font-family: var(--font-main); + font-weight: 400; + line-height: 19.2px; + letter-spacing: 0.01em; + text-align: left; + cursor: pointer; +} + +.divider { + height: 2px; + width: 100%; + background: var(--link-text-color); +} + +.company-list__tabs--element--active { + font-weight: 700; } -.group { +.company-list__content { + box-sizing: border-box; + width: 375px; display: flex; - align-items: center; + align-self: center; flex-direction: column; + padding: 24px 16px 40px; + gap: 20px; +} + +.company-list__content--btns-wrapper { + display: flex; + flex-direction: column; + gap: 32px; +} + +.company-list__content--btns { + display: flex; + justify-content: flex-start; + flex-flow: row wrap; + gap: 8px; + width: 100%; +} + +.company-list__btns--element, +.company-list__btns--element--active { + border-radius: 4px; + padding: 8px; + border: 1px solid #231C09; + + font-family: var(--font-main); + font-size: 16px; + font-weight: 300; + line-height: 20px; + cursor: pointer; +} + +.company-list__btns--element--active { + color: var(--light-button-text-color); + background: #231C09; +} + +.company-list__content--items { + display: flex; + flex-direction: column; +} + +@media only screen and (min-width: 768px) { + + .company-list__header, + .company-list__content { + width: 768px; + } + + @media only screen and (min-width: 1512px) { + + .company-list__header, + .company-list__content { + width: 1512px; + } + + .company-list__content { + padding: 24px 104px 40px; + gap: 32px; + } + + .company-list__header { + padding: 40px 104px 0px; + } + + .company-list__content--btns { + display: flex; + justify-content: flex-start; + flex-flow: row nowrap; + gap: 8px; + width: 100%; + } + + .company-list__content--btns-wrapper { + flex-direction: row; + justify-content: space-between; + } + + } } diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/AdditionalInfo.jsx b/FrontEnd/src/pages/ProfilePage/FormComponents/AdditionalInfo.jsx index cc0f0fd14..593b45b7c 100644 --- a/FrontEnd/src/pages/ProfilePage/FormComponents/AdditionalInfo.jsx +++ b/FrontEnd/src/pages/ProfilePage/FormComponents/AdditionalInfo.jsx @@ -8,6 +8,7 @@ import defineChanges from '../../../utils/defineChanges'; import { useAuth, useProfile } from '../../../hooks'; import HalfFormField from './FormFields/HalfFormField'; import Loader from '../../../components/Loader/Loader'; +import ProfileFormButton from '../UI/ProfileFormButton/ProfileFormButton'; import css from './FormComponents.module.css'; const LABELS = { @@ -32,10 +33,6 @@ const AdditionalInfo = (props) => { setFormIsDirty(isDirty); }, [mainProfile, profile]); - useEffect(() => { - props.currentFormNameHandler(props.curForm); - }, []); - const onUpdateFoundationYearField = (e) => { const currentYear = new Date().getFullYear(); const year = Number(e.target.value); @@ -92,6 +89,8 @@ const AdditionalInfo = (props) => { return (
+

Додаткова інформація

+
{user && profile && mainProfile ? (
{ { />
+
+ ) : ( diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/BanerModeration.css b/FrontEnd/src/pages/ProfilePage/FormComponents/BanerModeration.css index 5f437e077..a360d26c1 100644 --- a/FrontEnd/src/pages/ProfilePage/FormComponents/BanerModeration.css +++ b/FrontEnd/src/pages/ProfilePage/FormComponents/BanerModeration.css @@ -2,7 +2,7 @@ display: flex; align-items: flex-start; color: black; - margin-bottom: 20px; + padding: 16px } .warning-icon { @@ -19,7 +19,7 @@ } .moderation-text { - font-family: 'Inter', sans-serif; + font-family: var(--font-main), sans-serif; font-weight: 400; font-size: 14px; line-height: 22px; diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/ChangePassword.jsx b/FrontEnd/src/pages/ProfilePage/FormComponents/ChangePassword.jsx index d466d07bf..94aaedf30 100644 --- a/FrontEnd/src/pages/ProfilePage/FormComponents/ChangePassword.jsx +++ b/FrontEnd/src/pages/ProfilePage/FormComponents/ChangePassword.jsx @@ -11,7 +11,6 @@ import css from './ChangePassword.module.css'; export default function ChangePassword(props) { const { setFormIsDirty } = useContext(DirtyFormContext); - const { currentFormNameHandler, curForm } = props; const { register, handleSubmit, @@ -28,9 +27,6 @@ export default function ChangePassword(props) { }, }); - useEffect(() => { - currentFormNameHandler(curForm); - }, [currentFormNameHandler, curForm]); useEffect(() => { setFormIsDirty(isDirty); @@ -63,6 +59,8 @@ export default function ChangePassword(props) { return (
+

Змінити пароль

+
{props.user ? (
+
+
+ +
) : ( @@ -121,6 +128,4 @@ ChangePassword.propTypes = { profile_id: PropTypes.number.isRequired, is_staff: PropTypes.bool.isRequired, }).isRequired, - currentFormNameHandler: PropTypes.func.isRequired, - curForm: PropTypes.string.isRequired, }; diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/ChangePassword.module.css b/FrontEnd/src/pages/ProfilePage/FormComponents/ChangePassword.module.css index 776533af1..a718e2476 100644 --- a/FrontEnd/src/pages/ProfilePage/FormComponents/ChangePassword.module.css +++ b/FrontEnd/src/pages/ProfilePage/FormComponents/ChangePassword.module.css @@ -1,5 +1,83 @@ .form__container { word-wrap: break-word; - width: 530px; - margin-left: 10px; + background-color: var(--main-white); + border-radius: 6px; + height: fit-content; + +} + +.form__container form { + display: flex; + flex-direction: column; + gap: 20px; + margin-top: 20px; +} + +.form__head { + display: none; +} + +.divider { + display: none; +} + +.bottom-divider { + width: 100%; + height: 1px; + background-color: var(--light-seashell-background); +} + +.submit-button__conteiner { + display: flex; + align-items: flex-start; + padding: 11px 17px; + background-color: var(--main-white); +} + +.submit-button { + border-radius: 4px; + background: var(--main-button-color); + color: var(--main-white); + padding: 10px 16px; + font-family: var(--font-main); + font-size: 16px; + font-weight: 600; + line-height: 20px; + cursor: pointer; +} + +@media only screen and (min-width: 768px) { + .form__container { + width: 474px; + } + + .form__head { + font-family: var(--font-main); + font-size: 16px; + font-weight: 600; + height: 52px; + display: flex; + flex-direction: row; + align-items: center; + padding-left: 24px; + } + + .divider { + width: 100%; + height: 1px; + background-color: var(--light-seashell-background); + display: inherit; + } + + .submit-button__conteiner { + padding: 11px 24px; +} + +} + +@media only screen and (min-width: 1200px) { + .form__container { + width: 636px; + margin-left: 180px; + } } \ No newline at end of file diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/ContactsInfo.jsx b/FrontEnd/src/pages/ProfilePage/FormComponents/ContactsInfo.jsx index 6d5f9fe88..f01887bc6 100644 --- a/FrontEnd/src/pages/ProfilePage/FormComponents/ContactsInfo.jsx +++ b/FrontEnd/src/pages/ProfilePage/FormComponents/ContactsInfo.jsx @@ -6,9 +6,9 @@ import { useAuth, useProfile } from '../../../hooks'; import checkFormIsDirty from '../../../utils/checkFormIsDirty'; import defineChanges from '../../../utils/defineChanges'; import { formatPhoneNumber } from '../../../utils/formatPhoneNumber'; -import FullField from './FormFields/FullField'; import HalfFormField from './FormFields/HalfFormField'; import Loader from '../../../components/Loader/Loader'; +import ProfileFormButton from '../UI/ProfileFormButton/ProfileFormButton'; import css from './FormComponents.module.css'; import { useMask } from '@react-input/mask'; @@ -26,7 +26,7 @@ const ContactsInfo = (props) => { const { setFormIsDirty } = useContext(DirtyFormContext); const fields = { - phone: { defaultValue: mainProfile?.phone ?? null, type: 'phone'}, + phone: { defaultValue: mainProfile?.phone ?? null, type: 'phone' }, address: { defaultValue: mainProfile?.address ?? null }, }; @@ -37,10 +37,6 @@ const ContactsInfo = (props) => { const inputRef = useMask({ mask: '+380XX XXX XX XX', replacement: { X: /\d/ } }); - useEffect(() => { - props.currentFormNameHandler(props.curForm); - }, []); - useEffect(() => { if (mainProfile?.phone) { setProfile((prevState) => ({ @@ -116,6 +112,8 @@ const ContactsInfo = (props) => { return (
+

Контакти

+
{user && profile && mainProfile ? (
{ value={phone ?? ''} error={phoneNumberError} /> +
-
+
+ ) : ( diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfileModal.jsx b/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfileModal.jsx index 6f3cf8658..21b71f27e 100644 --- a/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfileModal.jsx +++ b/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfileModal.jsx @@ -3,10 +3,13 @@ import css from './DeleteProfileModal.module.css'; import { useAuth } from '../../../../hooks'; import { useState } from 'react'; import preventEnterSubmit from '../../../../utils/preventEnterSubmit'; +import classNames from 'classnames'; +import EyeVisible from '../../../Authorization/EyeVisible'; +import EyeInvisible from '../../../Authorization/EyeInvisible'; const DeleteProfileModal = (props) => { const { logout, user } = useAuth(); - const [typePassword, setTypePassword] = useState('password'); + const [passwordIsVisible, setPasswordIsVisible] = useState(false); const [inputEmail, setInputEmail] = useState(''); const [inputPassword, setInputPassword] = useState(''); const [isCorrectEmail, setIsCorrectEmail] = useState(true); @@ -43,73 +46,67 @@ const DeleteProfileModal = (props) => { }; const passwordVisisbilityHandler = () => { - if (typePassword === 'password') { - setTypePassword('text'); - } else setTypePassword('password'); + setPasswordIsVisible(!passwordIsVisible); }; return (
- Ви впевнені, що хочете видалити профіль? - +

Ви впевнені, що хочете видалити профіль?

-
-
- Цей профіль буде видалено. Для того, щоб підтвердити видалення, - будь-ласка, введіть вашу почту та пароль -
+
+

Це призведе до остаточного видалення всіх ваших даних про компанію чи стартап й також включно з списком сподобаних профілів.

+

Для видалення вашого профілю введіть вашу електронну пошту та пароль.

+ Ця дія не може бути відміненою!
-
- -
-
- -
- {!isCorrectEmail && ( -
Некоректна пошта
- )} -
- +
+
+ +
+
+ +
+ {!isCorrectEmail && ( +
Некоректна пошта
+ )}
-
- - - +
+ +
+
+ - + + {!passwordIsVisible ? : } + +
+ -
-
+
); }; diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfileModal.module.css b/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfileModal.module.css index 8d59d822d..869f3ec36 100644 --- a/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfileModal.module.css +++ b/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfileModal.module.css @@ -6,18 +6,21 @@ font-weight: 400; line-height: 20px; letter-spacing: -0.01em; - margin: 24px 24px 8px 24px; + margin: 14px 24px 0px 24px; + display: flex; + flex-direction: column; + gap: 13px; } .buttons__section { display: flex; - justify-content: flex-end; + justify-content: flex-start; align-items: flex-start; gap: 12px; border-top: 1px #E2E5EB solid; padding-bottom: 10px; padding-top: 10px; - padding-right: 16px; + padding-left: 25px; } .button__cancel { @@ -82,7 +85,6 @@ justify-content: space-between; align-items: center; align-self: stretch; - background: var(--main-white, #FFF); box-shadow: 0px -1px 0px 0px #F0F0F0 inset; color: var(--character-title-85, rgba(0, 0, 0, 0.85)); font-feature-settings: 'calt' off; @@ -95,14 +97,16 @@ } .form__body { - margin: 8px 24px 24px 24px; + margin: 24px; + display: flex; + flex-direction: column; + gap: 20px; } .fields__label--text { display: flex; - padding-bottom: 8px; + padding-bottom: 6px; align-items: center; - gap: 4px; font-family: var(--font-main); font-size: 14px; font-weight: 400; @@ -123,29 +127,42 @@ .fields__field--input { display: flex; - height: 22px; + height: 30px; padding: 5px 12px; align-items: center; gap: 4px; flex: 1 0 0; border-radius: 2px; - border: 1px solid var(--neutral-5, #D9D9D9); + border: none; background: var(--main-white, #FFF); } -.fields__field--input:focus { +.fields__field:focus-within { border-radius: 2px; border: 1px solid #1f9a7c; background: #fff; outline: none; } -.password__eye { - width: 23px; - padding: 5px 3px 2px 3px; +.password-visible-field { + display: flex; + align-items: center; + align-self: stretch; + border-radius: 2px; + background: var(--main-white, #FFF); + border: 1px solid #B4D27A; +} + +.password-visibility-button { + width: 25px; cursor: pointer; } +.fields__field--input:focus-visible { + outline: none; +} + + .delete__cancelButton { cursor: pointer; } diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfilePage.jsx b/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfilePage.jsx index eef063fa3..ff0680cfd 100644 --- a/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfilePage.jsx +++ b/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfilePage.jsx @@ -1,27 +1,26 @@ import css from './DeleteProfilePage.module.css'; import DeleteProfileModal from './DeleteProfileModal'; import MyModal from '../../UI/MyModal/MyModal'; -import { useState, useEffect } from 'react'; +import { useState } from 'react'; -const DeleteProfilePage = (props) => { +const DeleteProfilePage = () => { const [modal, setModal] = useState(false); - useEffect(() => { - props.currentFormNameHandler(props.curForm); - }, []); - const cancelHandler = () => { setModal(false); }; return ( -
-
Видалити акаунт
- - - - +
+

Видалити профіль

+
+
+ + + + +
); }; diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfilePage.module.css b/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfilePage.module.css index 92ca3d4ba..786eb5a0e 100644 --- a/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfilePage.module.css +++ b/FrontEnd/src/pages/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfilePage.module.css @@ -1,33 +1,56 @@ .button__delete-main { - height: calc(var(--profile-min-height-block) + 42px); + padding: 10px; } .button__delete { - color: #F15831; - cursor: pointer; - width: 109px; - height: 32px; - padding: 5px 15px 5px 15px; - margin-top: 8px; - margin-bottom: 10px; border-radius: 4px; - gap: 10px; - background: linear-gradient(0deg, #FFFFFF, #FFFFFF), - linear-gradient(0deg, #F15831, #F15831); - border: 1px solid #F15831; + background: var(--main-button-color); + color: var(--main-white); + padding: 10px 15px; font-family: var(--font-main); font-size: 16px; font-weight: 600; line-height: 20px; - letter-spacing: -0.01em; - text-align: center; + cursor: pointer; } -.text__for__delete { - font-family: var(--font-main); - font-size: 14px; - font-weight: 400; - line-height: 20px; - letter-spacing: -0.01em; - text-align: left; +.button__delete-head { + display: none; } + +@media only screen and (min-width: 768px) { + .button__delete-container { + display: flex; + flex-direction: column; + background-color: var(--main-white); + width: 474px; + height: 112px; + border-radius: 6px; + } + .button__delete-head { + font-family: var(--font-main); + font-size: 16px; + font-weight: 600; + height: 52px; + display: flex; + flex-direction: row; + align-items: center; + padding-left: 24px; + } + + .divider { + width: 100%; + height: 1px; + background-color: var(--light-seashell-background); + } + .button__delete { + margin-left: 14px; + } +} + +@media only screen and (min-width: 1200px) { + .button__delete-container { + width: 636px; + margin-left: 180px; + } +} \ No newline at end of file diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/FormComponents.module.css b/FrontEnd/src/pages/ProfilePage/FormComponents/FormComponents.module.css index 154cfd909..1bcaa4f7e 100644 --- a/FrontEnd/src/pages/ProfilePage/FormComponents/FormComponents.module.css +++ b/FrontEnd/src/pages/ProfilePage/FormComponents/FormComponents.module.css @@ -10,8 +10,19 @@ .fields-groups { display: flex; + flex-direction: column; align-items: flex-start; gap: 16px; + padding-left: 9px; + padding-top: 7px; +} + +.form__head { + display: none; +} + +.divider { + display: none; } .fop-field { @@ -23,5 +34,50 @@ .form__container { word-wrap: break-word; - width: 530px; + background-color: var(--main-white); + border-radius: 6px; + height: fit-content; + +} + +.bottom-divider { + width: 100%; + height: 1px; + background-color: var(--light-seashell-background); +} + +@media only screen and (min-width: 768px) { + .form__container { + width: 474px; + } + + .fields-groups { + padding-left: 16px; + } + + .form__head { + font-family: var(--font-main); + font-size: 16px; + font-weight: 600; + height: 52px; + display: flex; + flex-direction: row; + align-items: center; + padding-left: 24px; + } + + .divider { + width: 100%; + height: 1px; + background-color: var(--light-seashell-background); + display: inherit; + } + +} + +@media only screen and (min-width: 1200px) { + .form__container { + width: 636px; + margin-left: 180px; + } } \ No newline at end of file diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/FormFields/CheckBoxField.jsx b/FrontEnd/src/pages/ProfilePage/FormComponents/FormFields/CheckBoxField.jsx index 19a3960cb..58026bb69 100644 --- a/FrontEnd/src/pages/ProfilePage/FormComponents/FormFields/CheckBoxField.jsx +++ b/FrontEnd/src/pages/ProfilePage/FormComponents/FormFields/CheckBoxField.jsx @@ -8,9 +8,10 @@ const CheckBoxField = (props) => {
{props.requiredField && ( - + * )}