From bb07dbe146aaeae636cef1f07113d8d8d4d49d83 Mon Sep 17 00:00:00 2001 From: Lvyshnevska Date: Wed, 25 Oct 2023 18:54:52 +0200 Subject: [PATCH 01/51] link added to profile card, styles upd --- .../components/profileList/ProfileCard.jsx | 51 ++++++++++--------- .../profileList/ProfileCard.module.css | 4 ++ 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/FrontEnd/src/components/profileList/ProfileCard.jsx b/FrontEnd/src/components/profileList/ProfileCard.jsx index 37a6f06cb..3a053ea03 100644 --- a/FrontEnd/src/components/profileList/ProfileCard.jsx +++ b/FrontEnd/src/components/profileList/ProfileCard.jsx @@ -1,4 +1,5 @@ import { useState, useMemo } from 'react'; +import { Link } from 'react-router-dom'; import { Badge, Typography } from 'antd'; import { StarOutlined, StarFilled } from '@ant-design/icons'; @@ -104,32 +105,34 @@ export default function ProfileCard({ isAuthorized, data }) { return (
-
- -
-
-
-
-

- {profile.activities} -

-
-
{profile.name}
-
{profile.region}
-
-
- - {profile.commonInfo} - + +
+
-
- +
+
+
+

+ {profile.activities} +

+
+
{profile.name}
+
{profile.region}
+
+
+ + {profile.commonInfo} + +
+
+ +
-
+ {isAuthorized ? (isSaved ? filledStar : outlinedStar) : null}
); diff --git a/FrontEnd/src/components/profileList/ProfileCard.module.css b/FrontEnd/src/components/profileList/ProfileCard.module.css index 596fd32b3..53bf54d6a 100644 --- a/FrontEnd/src/components/profileList/ProfileCard.module.css +++ b/FrontEnd/src/components/profileList/ProfileCard.module.css @@ -9,6 +9,10 @@ box-shadow: 0px 4px 8px 0px rgba(65, 64, 69, 0.2); } +.company-card__link { + display: flex; +} + .logo-box { width: 64px; height: 64px; From 67a609c87c9c5bdcd27b9719dc065e4ae31445ed Mon Sep 17 00:00:00 2001 From: Lvyshnevska Date: Wed, 25 Oct 2023 19:21:09 +0200 Subject: [PATCH 02/51] detail page component added, route added --- .../ProfileDetail/ProfileDetailPage.jsx | 64 +++++++++++++++++++ .../ProfileDetailPage.module.css | 8 +++ .../src/components/basicPage/BasicPage.jsx | 2 + 3 files changed, 74 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/ProfileDetailPage.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/ProfileDetailPage.module.css diff --git a/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.jsx b/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.jsx new file mode 100644 index 000000000..aa768bc17 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.jsx @@ -0,0 +1,64 @@ +import useSWR from 'swr'; +import { useParams } from 'react-router-dom'; +import { PropTypes } from 'prop-types'; + +import Loader from '../loader/Loader'; +import ErrorPage404 from '../errorPages/ErrorPage404'; +import MainInfo from './MainInfo/MainInfo'; +import DetailedInfo from './DetailedInfo/DetailedInfo'; +import BannerImage from './BannerImage'; +import classes from './ProfileDetailPage.module.css'; + +function ProfileDetailPage({ isAuthorized }) { + const { id } = useParams(); + const urlProfile = `${process.env.REACT_APP_BASE_API_URL}/api/profiles/${id}`; + + async function fetcher(url) { + const headers = { + 'Content-Type': 'application/json', + }; + if (isAuthorized) { + const authToken = localStorage.getItem('Token'); + headers.Authorization = `Token ${authToken}`; + } + return fetch(url, { + method: 'GET', + headers: headers, + }).then((res) => res.json()); + } + + const { + data: fetchedProfile, + error, + isLoading, + } = useSWR(urlProfile, fetcher); + + console.log('DATA', fetchedProfile); + + return error ? ( + + ) : ( + isLoading ? ( + + ) : ( <> + +
+ + +
+ + ) + ); + +} + +export default ProfileDetailPage; + +ProfileDetailPage.propTypes = { + isAuthorized: PropTypes.bool, +}; diff --git a/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.module.css b/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.module.css new file mode 100644 index 000000000..f31ac420a --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.module.css @@ -0,0 +1,8 @@ +.profile-page { + display: inline-flex; + flex-direction: column; + align-items: flex-start; + gap: 16px; + margin-left: 104px; + margin-right: 104px; +} \ No newline at end of file diff --git a/FrontEnd/src/components/basicPage/BasicPage.jsx b/FrontEnd/src/components/basicPage/BasicPage.jsx index 71f9d1a09..6383688c3 100644 --- a/FrontEnd/src/components/basicPage/BasicPage.jsx +++ b/FrontEnd/src/components/basicPage/BasicPage.jsx @@ -8,6 +8,7 @@ import Footer from '../HeaderFooter/footer/Footer'; import Header from '../HeaderFooter/header/Header'; import MainPage from '../landing-page/MainPage'; import PrivacyPolicy from '../PrivacyPolicyPage/privacy/PrivacyPolicyComponent'; +import ProfileDetailPage from '../ProfileDetail/ProfileDetailPage'; import ProfileListPage from '../profileList/ProfileListPage'; import ProfilePage from '../ProfilePage/ProfilePage'; import { SignUpPage } from '../SignUp/pages/SignUpPage'; @@ -56,6 +57,7 @@ function BasicPage() { } /> } /> + }/> }/> {auth.isAuth ? ( } /> From d29667aceb99204129100fdbe3cb6577de98c4f2 Mon Sep 17 00:00:00 2001 From: Lvyshnevska Date: Wed, 25 Oct 2023 19:22:02 +0200 Subject: [PATCH 03/51] banner image component added --- .../components/ProfileDetail/BannerImage.jsx | 32 +++++++++++++++++++ .../ProfileDetail/BannerImage.module.css | 15 +++++++++ 2 files changed, 47 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/BannerImage.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/BannerImage.module.css diff --git a/FrontEnd/src/components/ProfileDetail/BannerImage.jsx b/FrontEnd/src/components/ProfileDetail/BannerImage.jsx new file mode 100644 index 000000000..e15399ee5 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/BannerImage.jsx @@ -0,0 +1,32 @@ +import { useMemo } from 'react'; +import classes from './BannerImage.module.css'; + +function BannerImage ({ data }) { + const profile = useMemo(() => { + return { + banner: data.banner_image, + }; + }, [data]); + + return ( +
+
+ {profile.banner ? ( + Profile Banner + ) : ( + + + + )} +
+
+ ); +} + +export default BannerImage; diff --git a/FrontEnd/src/components/ProfileDetail/BannerImage.module.css b/FrontEnd/src/components/ProfileDetail/BannerImage.module.css new file mode 100644 index 000000000..4844edbda --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/BannerImage.module.css @@ -0,0 +1,15 @@ +.banner-image__block { + width: 1512px; + height: 200px; + flex-shrink: 0; +} + +.banner-image { + display: flex; + justify-content: center; + align-items: center; + width: 1512px; + height: 200px; + flex-shrink: 0; + background: var(--main-grey-20, #DEE1E8); +} \ No newline at end of file From 6f2012d07cdc77e30c28805c981626fd9333ea58 Mon Sep 17 00:00:00 2001 From: Lvyshnevska Date: Wed, 25 Oct 2023 19:23:35 +0200 Subject: [PATCH 04/51] main section components added --- .../ProfileDetail/MainInfo/MainInfo.jsx | 41 +++++ .../MainInfo/MainInfo.module.css | 5 + .../MainInfo/ProfileDetailNavBar.jsx | 48 ++++++ .../MainInfo/ProfileDetailNavBar.module.css | 57 +++++++ .../ProfileDetail/MainInfo/Title.jsx | 150 ++++++++++++++++++ .../ProfileDetail/MainInfo/Title.module.css | 110 +++++++++++++ 6 files changed, 411 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.module.css create mode 100644 FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.module.css create mode 100644 FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/MainInfo/Title.module.css diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.jsx new file mode 100644 index 000000000..20ae21a7a --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.jsx @@ -0,0 +1,41 @@ +import { PropTypes } from 'prop-types'; +import Title from './Title'; +import ProfileDetailNavBar from './ProfileDetailNavBar'; +import classes from './MainInfo.module.css'; + +function MainInfo ({ isAuthorized, data }) { + + return ( +
+ + <ProfileDetailNavBar /> + </div> + +); +} + +export default MainInfo; + +MainInfo.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, + }).isRequired, + }; \ No newline at end of file diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.module.css b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.module.css new file mode 100644 index 000000000..6416e59c4 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.module.css @@ -0,0 +1,5 @@ +.basic-info-content { + display: flex; + flex-direction: column; + align-items: flex-start; +} \ No newline at end of file diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx new file mode 100644 index 000000000..82eb3f877 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx @@ -0,0 +1,48 @@ +import { HashLink } from 'react-router-hash-link'; +import classes from './ProfileDetailNavBar.module.css'; + +function ProfileDetailNavBar() { + const menuItems = [ + 'Про компанію', + 'Стартап', + 'Товари / послуги', + 'Логістика товарів / послуг', + 'Формат співпраці', + ]; + const menuLinks = [ + 'about-company', + 'startup', + 'products-services', + 'logistics', + 'cooperation', + ]; + + const activeHash = window.location.hash.substring(1); + + const handleItemClick = (link) => { + window.location.hash = link; + }; + + return ( + <div className={classes['navbar-menu']}> + {menuItems.map((item, index) => ( + <div key={index} className={classes['navbar-menu__block']}> + <div + onClick={() => handleItemClick(menuLinks[index])} + className={classes['navbar-menu__item']}> + <HashLink + smooth + to={`#${menuLinks[index]}`} + className={menuLinks[index] === activeHash ? `${classes['active-link']}` : `${classes['inactive-link']}`} + > + {item} + </HashLink> + </div> + <div className={menuLinks[index] === activeHash ? `${classes['active-devider']}` : `${classes['inactive-devider']}`}/> + </div> + ))} + </div> + ); +} + +export default ProfileDetailNavBar; diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.module.css b/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.module.css new file mode 100644 index 000000000..70912336b --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.module.css @@ -0,0 +1,57 @@ +.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: Inter; + 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: Inter; + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: 20px; + letter-spacing: -0.16px; +} + +.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); +} \ No newline at end of file diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx new file mode 100644 index 000000000..d1b4070a8 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx @@ -0,0 +1,150 @@ +import { useState, useMemo } from 'react'; + +import { Badge } from 'antd'; +import { StarOutlined, StarFilled } from '@ant-design/icons'; +import { useSWRConfig } from 'swr'; +import { PropTypes } from 'prop-types'; +import useSWRMutation from 'swr/mutation'; + +import classes from './Title.module.css'; + +function Title({ isAuthorized, data }) { + console.log('DATA', data); + const { mutate } = useSWRConfig(); + const [isSaved, setIsSaved] = useState(data.is_saved); + const profile = useMemo(() => { + return { + id: data.id, + name: data.name, + activities: !data.activities.length + ? null + : data.activities.map((activity) => activity.name).join(', '), + region: data.region_display ? data.region_display : '', + categories: + data.categories.length > 4 + ? data.categories.slice(0, 4) + : data.categories, + isSaved: data.is_saved, + }; + }, [data]); + + async function sendRequest(url, { arg: data }) { + const authToken = localStorage.getItem('Token'); + return fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Token ${authToken}`, + }, + body: JSON.stringify(data), + }).then(); + } + + const { trigger } = useSWRMutation( + `${process.env.REACT_APP_BASE_API_URL}/api/saved-list/`, + sendRequest + ); + + const handleClick = async () => { + try { + await trigger( + { company_pk: profile.id }, + { optimisticData: () => setIsSaved(!isSaved) } + ); + } catch (error) { + console.error(error); + } + }; + + mutate((key) => typeof key === 'string' && key.startsWith('/api/profiles/'), { + revalidate: true, + }); + + const filledStar = ( + <StarFilled + style={{ color: '#FFD800', fontSize: '24px' }} + onClick={handleClick} + /> + ); + const outlinedStar = ( + <StarOutlined + style={{ color: '#FFD800', fontSize: '24px' }} + onClick={handleClick} + /> + ); + + const CategoryBadges = ({ categories }) => { + return ( + <> + {categories + ? categories.map((category) => ( + <Badge + key={category.id} + size="medium" + count={category.name.toUpperCase()} + style={{ + backgroundColor: '#1F9A7C', + fontWeight: 600, + fontFamily: 'Inter', + fontSize: 10, + }} + /> + )) + : ''} + </> + ); + }; + + return ( + <div className={classes['title-block']}> + <div className={classes['title-block__logo']}> + <img className={classes['logo']} + src={`${process.env.PUBLIC_URL}/companies-logos/1.png`} + alt="" + /> + </div> + <div className={classes['title-block__about']}> + <div className={classes['title-block__activity']}>{profile.activities}</div> + <div className={classes['title-block__company']}> + <div className={classes['title-block__company_name']}>{profile.name}</div> + <div className={classes['title-block__company_category']}> + <CategoryBadges categories={profile.categories} /> + </div> + </div> + <div className={classes['title-block__company_region']}>{profile.region}</div> + </div> + <button onClick={handleClick} + type="button" + className={`${classes['title-block__button']} ${isSaved && classes['added_to_saved__button']}`} + > + <span className={`${classes['title-block__button--text']} ${isSaved && classes['added_to_saved__button--text']}`}>{!isSaved ? 'Додати в збережені' : 'Додано в збережені'}</span> + {isAuthorized ? (isSaved ? filledStar : outlinedStar) : null} + </button> + </div> + ); +} + +export default Title; + +Title.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, + }) + ), + is_saved: PropTypes.bool.isRequired, + }).isRequired, +}; diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/Title.module.css b/FrontEnd/src/components/ProfileDetail/MainInfo/Title.module.css new file mode 100644 index 000000000..47588be6a --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/Title.module.css @@ -0,0 +1,110 @@ +.title-block { + display: flex; + width: 1304px; + 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.20); +} + +.logo { + width: 33.75px; + height: 33.75px; + flex-shrink: 0; + border-radius: 26px; +} + +.title-block__about { + display: flex; + width: 1010px; + flex-direction: column; + align-items: flex-start; + flex-shrink: 0; +} + +.title-block__activity { + color: var(--main-grey-90, #25292C); + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 22px; + letter-spacing: -0.14px; +} + +.title-block__company { + display: flex; + align-items: center; + gap: 16px; +} + +.title-block__company_name { + color: var(--main-grey-90, #25292C); + font-family: Inter; + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: 120%; + text-transform: uppercase; +} + +.title-block__company_category { + display: flex; + align-items: flex-start; + gap: 6px; +} + +.title-block__company_region { + color: var(--main-black-90, #292E32); + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 10px; + font-style: normal; + font-weight: 400; + line-height: 16px; +} + +.title-block__button { + display: flex; + height: 34px; + 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; +} + +.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: Inter; + 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); +} \ No newline at end of file From 1096948c6e61d6d33d3830e82e48754ed177caf1 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Wed, 25 Oct 2023 19:26:39 +0200 Subject: [PATCH 05/51] detailed info component added --- .../ProfileDetail/DetailedInfo/DetailedInfo.jsx | 14 ++++++++++++++ .../DetailedInfo/DetailedInfo.module.css | 5 +++++ 2 files changed, 19 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.module.css diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.jsx new file mode 100644 index 000000000..9c9e4e27e --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.jsx @@ -0,0 +1,14 @@ +import classes from './DetailedInfo.module.css'; +import CompanyDescription from './CompanyDescription'; +import DataContacts from './DataContacts'; + +function DetailedInfo ({ isAuthorized, data }) { + return ( + <div className={classes['detail-info-page']}> + <CompanyDescription isAuthorized={isAuthorized} data={data} /> + <DataContacts isAuthorized={isAuthorized} data={data} /> + </div> + ); +} + +export default DetailedInfo; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.module.css new file mode 100644 index 000000000..f81a80b15 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.module.css @@ -0,0 +1,5 @@ +.detail-info-page { + display: flex; + align-items: flex-start; + gap: 134px; +} \ No newline at end of file From d9b48785a8dae9b325cbf38b370c82f6ad1621bc Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Wed, 25 Oct 2023 19:27:37 +0200 Subject: [PATCH 06/51] company description component added --- .../DetailedInfo/CompanyDescription.jsx | 20 +++++++++++++++++++ .../CompanyDescription.module.css | 6 ++++++ 2 files changed, 26 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.module.css diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx new file mode 100644 index 000000000..461c3bce0 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx @@ -0,0 +1,20 @@ +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 ( + <div className={classes['company-description-block']}> + <Company data={data} /> + <Startup data={data} /> + <ProductsServices /> + <Logistics /> + <Cooperation /> + </div> + ); +} + +export default CompanyDescription; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.module.css new file mode 100644 index 000000000..f24aa4263 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.module.css @@ -0,0 +1,6 @@ +.company-description-block { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 16px; +} \ No newline at end of file From 3cff28ff1ea7349ee5cc71fc5d26d87e4ea69993 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Wed, 25 Oct 2023 19:28:28 +0200 Subject: [PATCH 07/51] read more component added --- .../ProfileDetail/DetailedInfo/ReadMore.jsx | 29 +++++++++++++++++++ .../DetailedInfo/ReadMore.module.css | 11 +++++++ 2 files changed, 40 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/ReadMore.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/ReadMore.module.css diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/ReadMore.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ReadMore.jsx new file mode 100644 index 000000000..5f5d56ddf --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ReadMore.jsx @@ -0,0 +1,29 @@ +import { useState } from 'react'; +import { PropTypes } from 'prop-types'; +import classes from './ReadMore.module.css'; + +const ReadMore = ({ children }) => { + const text = children; + const [readMore, setReadMore] = useState(false); + + const toggleReadMore = () => { + setReadMore(!readMore); + }; + const displayText = text && (readMore ? text : `${text.slice(0, 150)}...`); + + return ( + text ? ( + <p className={classes['read-more']}> + {displayText} + <span onClick={toggleReadMore} className={classes['read-or-hide']}> + {!readMore ? 'читати далі' : 'приховати'} + </span> + </p>) : null + ); +}; + +export default ReadMore; + +ReadMore.propTypes = { + children: PropTypes.string, +}; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/ReadMore.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ReadMore.module.css new file mode 100644 index 000000000..32bcec138 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ReadMore.module.css @@ -0,0 +1,11 @@ +.read-or-hide { + color: var(--primary-green-80, #1F9A7C); + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 22px; + letter-spacing: -0.14px; + cursor: pointer; +} \ No newline at end of file From 26d98333933f7c2f8027dcdf65df5399f9bf3bf4 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Wed, 25 Oct 2023 19:29:11 +0200 Subject: [PATCH 08/51] company component added --- .../ProfileDetail/DetailedInfo/Company.jsx | 41 +++++++ .../DetailedInfo/Company.module.css | 103 ++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.module.css diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx new file mode 100644 index 000000000..b2f78eda1 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx @@ -0,0 +1,41 @@ +import { useMemo } from 'react'; +import classes from './Company.module.css'; +import ReadMore from './ReadMore'; + +function Company ({ data }) { + const profile = useMemo(() => { + return { + common_info: data.common_info, + }; + }, [data]); + + return ( + <div id="about-company" className={classes['about-company']}> + <div className={classes['about-company__title']}> + <div className={classes['about-company__title--block']}> + <p className={classes['about-company__title--text']}>Про компанію</p> + </div> + <div className={classes['about-company__title--divider']}></div> + </div> + <div className={classes['about-company__content']}> + <p className={classes['about-company__content--common']}> + <ReadMore > + {profile.common_info} + </ReadMore> + </p> + <div className={classes['about-company__content--advantage']}> + <p className={classes['about-company__content--advantage--title']}>Конкурентна перевага</p> + <p className={classes['about-company__content--advantage--description']}> + <ReadMore> + </ReadMore> + </p> + </div><div className={classes['about-company__content--slogan']}> + <p className={classes['about-company__content--slogan--title']}>Візія, слоган</p> + <p className={classes['about-company__content--slogan--text']}></p> + </div> + </div> + </div> + ); +} + +export default Company; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.module.css new file mode 100644 index 000000000..e24b8ec7b --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.module.css @@ -0,0 +1,103 @@ +.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: Inter; + 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: Inter; + 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: Inter; + 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: Inter; + 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: Inter; + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: 20px; + letter-spacing: -0.16px; +} \ No newline at end of file From 6675864a731ed33478ac5ef1756a5d0e446e56d2 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Wed, 25 Oct 2023 19:29:54 +0200 Subject: [PATCH 09/51] startup component added --- .../ProfileDetail/DetailedInfo/Startup.jsx | 82 +++++++++++++++++++ .../DetailedInfo/Startup.module.css | 79 ++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.module.css diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.jsx new file mode 100644 index 000000000..87cdce07c --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.jsx @@ -0,0 +1,82 @@ +import { useMemo } from 'react'; +import { PropTypes } from 'prop-types'; +import classes from './Startup.module.css'; +import ReadMore from './ReadMore'; + +function Startup ({ data }) { + const profile = useMemo(() => { + return { + startup_idea: data.startup_idea, + }; + }, [data]); + + return ( + <div id="startup" className={classes['startup-wrapper']}> + <div className={classes['startup']}> + <div className={classes['startup__title']}> + <div className={classes['startup__title--block']}> + <p className={classes['startup__title--text']}>Стартап</p> + </div> + <div className={classes['startup__title--divider']}></div> + </div> + <div className={classes['startup__content']}> + <div className={classes['startup__content--block']}> + <p className={classes['startup__content--title']}>Ідея стартапу</p> + <p className={classes['startup__content--description']}> + <ReadMore> + {profile.startup_idea} + </ReadMore> + </p> + </div> + <div className={classes['startup__content--block']}> + <p className={classes['startup__content--title']}>Розмір інвестиції</p> + <p className={classes['startup__content--description']}></p> + </div> + <div className={classes['startup__content--block']}> + <p className={classes['startup__content--title']}>Ціль співпраці</p> + <p className={classes['startup__content--description']}> + <ReadMore> + </ReadMore> + </p> + </div> + <div className={classes['startup__content--block']}> + <p className={classes['startup__content--title']}>Кінцевий результат</p> + <p className={classes['startup__content--description']}> + <ReadMore> + </ReadMore> + </p> + </div> + <div className={classes['startup__content--block']}> + <p className={classes['startup__content--title']}>Конкурентна перевага ідеї</p> + <p className={classes['startup__content--description']}> + <ReadMore> + </ReadMore> + </p> + </div> + <div className={classes['startup__content--block']}> + <p className={classes['startup__content--title']}>Ризики</p> + <p className={classes['startup__content--description']}> + <ReadMore> + </ReadMore> + </p> + </div> + <div className={classes['startup__content--block']}> + <p className={classes['startup__content--title']}>Пошук партнерів</p> + <p className={classes['startup__content--description']}> + <ReadMore> + </ReadMore> + </p> + </div> + </div> + </div> + </div> + ); +} + +export default Startup; + +Startup.propTypes = { + data: PropTypes.shape({ + startup_idea: PropTypes.string, + }), + }; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.module.css new file mode 100644 index 000000000..3d34c0069 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.module.css @@ -0,0 +1,79 @@ +.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: Inter; + 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: Inter; + 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: Inter; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 22px; + letter-spacing: -0.14px; +} \ No newline at end of file From 09256e7f897808b46cbdb5744d80d29ec483e358 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Wed, 25 Oct 2023 19:30:34 +0200 Subject: [PATCH 10/51] logistics component added --- .../ProfileDetail/DetailedInfo/Logistics.jsx | 25 ++++++++ .../DetailedInfo/Logistics.module.css | 60 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.module.css diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.jsx new file mode 100644 index 000000000..44e83352d --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.jsx @@ -0,0 +1,25 @@ +import classes from './Logistics.module.css'; +import ReadMore from './ReadMore'; + +function Logistics () { + return ( + <div id="logistics" className={classes['logistics-wrapper']}> + <div className={classes['logistics']}> + <div className={classes['logistics__title']}> + <div className={classes['logistics__title--block']}> + <p className={classes['logistics__title--text']}>Логістика товарів / послуг</p> + </div> + <div className={classes['logistics__title--divider']}></div> + </div> + <div className={classes['logistics__content--block']}> + <p className={classes['logistics__content--description']}> + <ReadMore> + </ReadMore> + </p> + </div> + </div> + </div> + ); +} + +export default Logistics; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.module.css new file mode 100644 index 000000000..f499df33b --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.module.css @@ -0,0 +1,60 @@ +.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: Inter; + 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 { + width: 776px; + color: var(--main-grey-90, #25292C); + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 22px; + letter-spacing: -0.14px; +} \ No newline at end of file From a056eea075edee3bb3f49e2da292f10f1e8bc3c6 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Wed, 25 Oct 2023 19:31:15 +0200 Subject: [PATCH 11/51] products and services component added --- .../DetailedInfo/ProductsServices.jsx | 40 ++++++++++ .../DetailedInfo/ProductsServices.module.css | 78 +++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.module.css diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.jsx new file mode 100644 index 000000000..6608d039c --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.jsx @@ -0,0 +1,40 @@ +// import { useMemo } from 'react'; +// import { PropTypes } from 'prop-types'; +import classes from './ProductsServices.module.css'; +import ReadMore from './ReadMore'; + +function ProductsServices () { + // const profile = useMemo(() => { + // return { + // }; + // }, [data]); + + return ( + <div id="products-services" className={classes['products-services']}> + <div className={classes['products-services__title']}> + <div className={classes['products-services__title--block']}> + <p className={classes['products-services__title--text']}>Товари / послуги</p> + </div> + <div className={classes['products-services__title--divider']}></div> + </div> + <div className={classes['products-services__content']}> + <div className={classes['products-services__content--block']}> + <p className={classes['products-services__content--title']}>Товари</p> + <p className={classes['products-services__content--description']}> + <ReadMore> + </ReadMore> + </p> + </div> + <div className={classes['products-services__content--block']}> + <p className={classes['products-services__content--title']}>Послуги</p> + <p className={classes['products-services__content--description']}> + <ReadMore> + </ReadMore> + </p> + </div> + </div> + </div> + ); +} + +export default ProductsServices; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.module.css new file mode 100644 index 000000000..19c524980 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.module.css @@ -0,0 +1,78 @@ +.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: Inter; + 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: Inter; + 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: Inter; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 22px; + letter-spacing: -0.14px; +} \ No newline at end of file From 8cadfd18e1bde44ec3bdf047f1939e1a3d4e1517 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Wed, 25 Oct 2023 19:31:51 +0200 Subject: [PATCH 12/51] cooperation component added --- .../DetailedInfo/Cooperation.jsx | 32 ++++++++++ .../DetailedInfo/Cooperation.module.css | 60 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.module.css diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.jsx new file mode 100644 index 000000000..251aa004c --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.jsx @@ -0,0 +1,32 @@ +// import { useMemo } from 'react'; +// import { PropTypes } from 'prop-types'; +import classes from './Cooperation.module.css'; +import ReadMore from './ReadMore'; + +function Cooperation () { + // const profile = useMemo(() => { + // return { + // }; + // }, [data]); + + return ( + <div id="cooperation" className={classes['cooperation-wrapper']}> + <div className={classes['cooperation']}> + <div className={classes['cooperation__title']}> + <div className={classes['cooperation__title--block']}> + <p className={classes['cooperation__title--text']}>Формат співпраці</p> + </div> + <div className={classes['cooperation__title--divider']}></div> + </div> + <div className={classes['cooperation__content--block']}> + <p className={classes['cooperation__content--description']}> + <ReadMore> + </ReadMore> + </p> + </div> + </div> + </div> + ); +} + +export default Cooperation; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.module.css new file mode 100644 index 000000000..c76933c1b --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.module.css @@ -0,0 +1,60 @@ +.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: Inter; + 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 { + width: 776px; + color: var(--main-grey-90, #25292C); + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 22px; + letter-spacing: -0.14px; +} \ No newline at end of file From bf4fa50b4dd9521ec48c6d0a8e85381b1ce209cd Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Wed, 25 Oct 2023 19:32:35 +0200 Subject: [PATCH 13/51] data and contacts component added --- .../DetailedInfo/DataContacts.jsx | 70 ++++++++++++++ .../DetailedInfo/DataContacts.module.css | 91 +++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.module.css diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx new file mode 100644 index 000000000..d533f258e --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx @@ -0,0 +1,70 @@ +import { useMemo } from 'react'; +import PhoneEmail from './PhoneEmail'; +import classes from './DataContacts.module.css'; + +function DataContacts ({ data }) { + + const profile = useMemo(() => { + return { + id: data.id, + edrpou: data.edrpou, + founded: data.founded, + address: data.address, + }; + }, [data]); + + return ( + <div className={classes['data-wrapper']}> + <div className={classes['data']}> + <div className={classes['data-block']}> + <div className={classes['data-block__field']}> + <p className={`${classes['data-block__field--title']} ${classes['edrpou']}`} >ЄДРПОУ</p> + <p className={classes['data-block__field--value']}>{profile.edrpou}</p> + </div> + <div className={classes['data-block__field']}> + <p className={classes['data-block__field--title']}>Рік заснування</p> + <p className={classes['data-block__field--value']}>{profile.founded}</p> + </div> + <div className={classes['data-block__field']}> + <p className={classes['data-block__field--title']}>Розмір компанії</p> + <p className={classes['data-block__field--value']}></p> + </div> + <div className={classes['data-block__field']}> + <p className={classes['data-block__field--title']}>Аудит</p> + <p className={classes['data-block__field--value']}></p> + </div> + </div> + <div className={classes['data-block']}> + <div className={classes['data-block__field']}> + <p className={classes['data-block__field--title']}>Сайт</p> + <p className={classes['data-block__field--site']}></p> + </div> + <PhoneEmail profileId={data.id}/> + <div className={classes['data-block__field--address']}> + <p className={classes['data-block__field--title']}>Адрес(и)</p> + <p className={classes['data-block__field--address--value']}>{profile.address}</p> + </div> + <div className={classes['data-block__field--social-networks']}> + <p className={classes['data-block__field--title']}>Соціальні мережі</p> + <a href="#"> + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> + <path d="M14 13.5H16.5L17.5 9.5H14V7.5C14 6.47 14 5.5 16 5.5H17.5V2.14C17.174 2.097 15.943 2 14.643 2C11.928 2 10 3.657 10 6.7V9.5H7V13.5H10V22H14V13.5Z" fill="black"/> + </svg> + </a> + <a href="#"> + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> + <path d="M13.0286 2.00123C13.7583 1.99843 14.488 2.00576 15.2176 2.02323L15.4116 2.03023C15.6356 2.03823 15.8566 2.04823 16.1236 2.06023C17.1876 2.11023 17.9136 2.27823 18.5506 2.52523C19.2106 2.77923 19.7666 3.12323 20.3226 3.67923C20.831 4.17884 21.2244 4.78318 21.4756 5.45023C21.7226 6.08723 21.8906 6.81423 21.9406 7.87823C21.9526 8.14423 21.9626 8.36623 21.9706 8.59023L21.9766 8.78423C21.9943 9.51342 22.002 10.2428 21.9996 10.9722L22.0006 11.7182V13.0282C22.003 13.758 21.9954 14.4877 21.9776 15.2172L21.9716 15.4112C21.9636 15.6352 21.9536 15.8562 21.9416 16.1232C21.8916 17.1872 21.7216 17.9132 21.4756 18.5502C21.2252 19.218 20.8317 19.8228 20.3226 20.3222C19.8225 20.8306 19.2179 21.224 18.5506 21.4752C17.9136 21.7222 17.1876 21.8902 16.1236 21.9402C15.8566 21.9522 15.6356 21.9622 15.4116 21.9702L15.2176 21.9762C14.4881 21.994 13.7583 22.0017 13.0286 21.9992L12.2826 22.0002H10.9736C10.2438 22.0027 9.5141 21.995 8.78458 21.9772L8.59058 21.9712C8.35319 21.9626 8.11585 21.9526 7.87858 21.9412C6.81458 21.8912 6.08858 21.7212 5.45058 21.4752C4.78326 21.2246 4.17881 20.8311 3.67958 20.3222C3.17062 19.8225 2.7768 19.2178 2.52558 18.5502C2.27858 17.9132 2.11058 17.1872 2.06058 16.1232C2.04944 15.8859 2.03944 15.6486 2.03058 15.4112L2.02558 15.2172C2.00714 14.4877 1.99881 13.758 2.00058 13.0282V10.9722C1.99779 10.2428 2.00512 9.51343 2.02258 8.78423L2.02958 8.59023C2.03758 8.36623 2.04758 8.14423 2.05958 7.87823C2.10958 6.81323 2.27758 6.08823 2.52458 5.45023C2.77595 4.78285 3.17054 4.17868 3.68058 3.68023C4.17947 3.17098 4.78354 2.7768 5.45058 2.52523C6.08858 2.27823 6.81358 2.11023 7.87858 2.06023L8.59058 2.03023L8.78458 2.02523C9.51376 2.0068 10.2432 1.99847 10.9726 2.00023L13.0286 2.00123ZM12.0006 7.00123C11.3381 6.99186 10.6803 7.11425 10.0656 7.3613C9.45077 7.60834 8.89122 7.97511 8.41942 8.44029C7.94762 8.90546 7.57298 9.45977 7.31726 10.071C7.06155 10.6822 6.92987 11.3382 6.92987 12.0007C6.92987 12.6633 7.06155 13.3192 7.31726 13.9305C7.57298 14.5417 7.94762 15.096 8.41942 15.5612C8.89122 16.0264 9.45077 16.3931 10.0656 16.6402C10.6803 16.8872 11.3381 17.0096 12.0006 17.0002C13.3267 17.0002 14.5984 16.4734 15.5361 15.5358C16.4738 14.5981 17.0006 13.3263 17.0006 12.0002C17.0006 10.6741 16.4738 9.40238 15.5361 8.4647C14.5984 7.52701 13.3267 7.00123 12.0006 7.00123ZM12.0006 9.00123C12.3991 8.99389 12.7951 9.06603 13.1654 9.21344C13.5357 9.36085 13.8729 9.58057 14.1574 9.85978C14.4418 10.139 14.6678 10.4721 14.822 10.8396C14.9763 11.2071 15.0558 11.6016 15.0558 12.0002C15.0559 12.3988 14.9766 12.7934 14.8224 13.1609C14.6683 13.5285 14.4424 13.8617 14.1581 14.141C13.8737 14.4203 13.5366 14.6401 13.1663 14.7876C12.796 14.9352 12.4001 15.0074 12.0016 15.0002C11.2059 15.0002 10.4429 14.6842 9.88026 14.1216C9.31765 13.5589 9.00158 12.7959 9.00158 12.0002C9.00158 11.2046 9.31765 10.4415 9.88026 9.87891C10.4429 9.3163 11.2059 9.00023 12.0016 9.00023L12.0006 9.00123ZM17.2506 5.50123C16.928 5.51414 16.6229 5.65138 16.3992 5.8842C16.1755 6.11702 16.0506 6.42736 16.0506 6.75023C16.0506 7.0731 16.1755 7.38344 16.3992 7.61626C16.6229 7.84908 16.928 7.98632 17.2506 7.99923C17.5821 7.99923 17.9 7.86753 18.1345 7.63311C18.3689 7.39869 18.5006 7.08075 18.5006 6.74923C18.5006 6.41771 18.3689 6.09977 18.1345 5.86535C17.9 5.63093 17.5821 5.49923 17.2506 5.49923V5.50123Z" fill="black"/> + </svg> + </a> + </div> + <div className={classes['data-block__field']}> + <p className={classes['data-block__field--title']}>Співпрацюємо з</p> + <p className={classes['data-block__field--cooperate--value']}></p> + </div> + </div> + </div> + </div> + ); +} + +export default DataContacts; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.module.css new file mode 100644 index 000000000..80ef696ec --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.module.css @@ -0,0 +1,91 @@ +.data-wrapper { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 16px; +} + +.data { + display: flex; + padding: 16px; + 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); +} + +.data-block { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 6px; +} + +.data-block__field { + display: flex; + height: 32px; + align-items: center; + gap: 8px; +} + +.data-block__field--title { + width: 130px; + color: var(--main-black-90, #292E32); + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 22px; + letter-spacing: -0.14px; +} + +.edrpou { + font-weight: 600; +} + +.data-block__field--value { + width: 200px; + color: var(--main-black-90, #292E32); + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 22px; + letter-spacing: -0.14px; +} + +.data-block__field--site { + width: 200px; + color: var(--system-blue-100, #4A73E2); + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 22px; + letter-spacing: -0.14px; +} + +.data-block__field--address, +.data-block__field--social-networks { + display: flex; + align-items: flex-start; + gap: 8px; +} + +.data-block__field--address--value, +.data-block__field--cooperate--value { + width: 200px; + color: var(--main-black-90, #292E32); + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 22px; + letter-spacing: -0.14px; +} \ No newline at end of file From ae513033f794fea87cb502e33ebb90f5ffe08fcf Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Wed, 25 Oct 2023 19:33:31 +0200 Subject: [PATCH 14/51] phone, email component added --- .../ProfileDetail/DetailedInfo/PhoneEmail.jsx | 118 ++++++++++++++++++ .../DetailedInfo/PhoneEmail.module.css | 67 ++++++++++ 2 files changed, 185 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.module.css diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx new file mode 100644 index 000000000..b50082424 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx @@ -0,0 +1,118 @@ +import { useState, useEffect } from 'react'; +import useSWR from 'swr'; +import { PropTypes } from 'prop-types'; +import classes from './PhoneEmail.module.css'; + +function PhoneEmail ({ profileId }) { + const [isPhoneShown, setPhoneShown] = useState(false); + const [isEmailShown, setEmailShown] = useState(false); + const [user, setUser] = useState(null); + const [profile, setProfile] = useState(null); + + const authToken = localStorage.getItem('Token'); + const { data: userData, error: userError } = useSWR( + authToken ? `${process.env.REACT_APP_BASE_API_URL}/api/auth/users/me/` : null, + url => + fetch(url, { + method: 'GET', + headers: { + 'Authorization': `Token ${authToken}`, + }, + }).then(res => res.json()), + ); + + const { data: profileData, error: profileError } = useSWR( + authToken ? `${process.env.REACT_APP_BASE_API_URL}/api/profiles/${profileId}?with_contacts=True` : null, + url => + fetch(url, { + method: 'GET', + headers: { + 'Authorization': `Token ${authToken}`, + }, + }).then(res => res.json()), + ); + + useEffect(() => { + if (userData) { + setUser(userData); + } + if (userError) { + console.error(userError); + } + if (profileData) { + setProfile(profileData); + } + if (profileError) { + console.error(profileError); + } + }, [userData, profileData, userError, profileError]); + + async function sendRequest(url, data ) { + return fetch(url, { + method: 'POST', + headers: { + Authorization: `Token ${authToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }).then(); + } + + const handlePhoneClick = async () => { + setPhoneShown(true); + try { + await sendRequest( + `${process.env.REACT_APP_BASE_API_URL}/api/viewed-list/`, + { + user: user.id, + company: profileId, + } + ); + } catch (error) { + console.error(error); + } + }; + + const handleEmailClick = async () => { + setEmailShown(true); + try { + await sendRequest( + `${process.env.REACT_APP_BASE_API_URL}/api/viewed-list/`, + { + user: user.id, + company: profileId, + } + ); + } catch (error) { + console.error(error); + } + }; + + return ( + <> + <div className={classes['data-block__field']}> + <p className={classes['data-block__field--title']}>Телефон</p> + {isPhoneShown ? + ( + <p className={classes['data-block__field--phone']}>{profile.phone}</p> ) : ( + <button type="button" onClick={handlePhoneClick} className={classes['data-block__field--show--phone']}> + Показати телефон + </button> + )} + </div> + <div className={classes['data-block__field']}> + <p className={classes['data-block__field--title']}>Електронна пошта</p> + {isEmailShown ? ( + <p className={classes['data-block__field--email']}>{profile.email}</p> ) : ( + <button type="button" onClick={handleEmailClick} className={classes['data-block__field--show--email']}>Показати ел. пошту</button> + )} + </div> + </> + ); +} + +export default PhoneEmail; + +PhoneEmail.propTypes = { + profileId: PropTypes.number.isRequired + }; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.module.css new file mode 100644 index 000000000..57ca40b17 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.module.css @@ -0,0 +1,67 @@ +.data-block__field { + display: flex; + height: 32px; + align-items: center; + gap: 8px; +} + +.data-block__field--title { + width: 130px; + color: var(--main-black-90, #292E32); + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 22px; + letter-spacing: -0.14px; +} + +.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); + cursor: pointer; +} + +.data-block__field--phone, +.data-block__field--email { + display: flex; + height: 32px; + align-items: center; + gap: 8px; +} + +.data-block__field--show--phone, +.data-block__field--show--email { + flex: 1 0 0; + color: var(--primary-green-80, #1F9A7C); + text-align: center; + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: 20px; + letter-spacing: -0.16px; +} + +.data-block__field--shown--phone { + width: 200px; + color: var(--main-black-90, #292E32); + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 22px; + letter-spacing: -0.14px; +} \ No newline at end of file From 47cbb17a0100c5ff77eeb83f85fb967bfc562d30 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Wed, 25 Oct 2023 21:07:31 +0200 Subject: [PATCH 15/51] some updates added to buttons --- .../ProfileDetail/DetailedInfo/DataContacts.jsx | 5 ++--- .../components/ProfileDetail/DetailedInfo/PhoneEmail.jsx | 9 +++++---- FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx | 5 ++--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx index d533f258e..8c02e7027 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx @@ -2,8 +2,7 @@ import { useMemo } from 'react'; import PhoneEmail from './PhoneEmail'; import classes from './DataContacts.module.css'; -function DataContacts ({ data }) { - +function DataContacts ({ isAuthorized, data }) { const profile = useMemo(() => { return { id: data.id, @@ -39,7 +38,7 @@ function DataContacts ({ data }) { <p className={classes['data-block__field--title']}>Сайт</p> <p className={classes['data-block__field--site']}></p> </div> - <PhoneEmail profileId={data.id}/> + <PhoneEmail isAuthorized={isAuthorized} profileId={data.id}/> <div className={classes['data-block__field--address']}> <p className={classes['data-block__field--title']}>Адрес(и)</p> <p className={classes['data-block__field--address--value']}>{profile.address}</p> diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx index b50082424..2842ce55a 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx @@ -3,7 +3,7 @@ import useSWR from 'swr'; import { PropTypes } from 'prop-types'; import classes from './PhoneEmail.module.css'; -function PhoneEmail ({ profileId }) { +function PhoneEmail ({ isAuthorized, profileId }) { const [isPhoneShown, setPhoneShown] = useState(false); const [isEmailShown, setEmailShown] = useState(false); const [user, setUser] = useState(null); @@ -22,7 +22,7 @@ function PhoneEmail ({ profileId }) { ); const { data: profileData, error: profileError } = useSWR( - authToken ? `${process.env.REACT_APP_BASE_API_URL}/api/profiles/${profileId}?with_contacts=True` : null, + `${process.env.REACT_APP_BASE_API_URL}/api/profiles/${profileId}?with_contacts=True`, url => fetch(url, { method: 'GET', @@ -95,7 +95,7 @@ function PhoneEmail ({ profileId }) { {isPhoneShown ? ( <p className={classes['data-block__field--phone']}>{profile.phone}</p> ) : ( - <button type="button" onClick={handlePhoneClick} className={classes['data-block__field--show--phone']}> + <button type="button" onClick={handlePhoneClick} disabled={!isAuthorized} className={classes['data-block__field--show--phone']}> Показати телефон </button> )} @@ -104,7 +104,7 @@ function PhoneEmail ({ profileId }) { <p className={classes['data-block__field--title']}>Електронна пошта</p> {isEmailShown ? ( <p className={classes['data-block__field--email']}>{profile.email}</p> ) : ( - <button type="button" onClick={handleEmailClick} className={classes['data-block__field--show--email']}>Показати ел. пошту</button> + <button type="button" onClick={handleEmailClick} disabled={!isAuthorized} className={classes['data-block__field--show--email']}>Показати ел. пошту</button> )} </div> </> @@ -114,5 +114,6 @@ function PhoneEmail ({ profileId }) { export default PhoneEmail; PhoneEmail.propTypes = { + isAuthorized: PropTypes.bool.isRequired, profileId: PropTypes.number.isRequired }; diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx index d1b4070a8..f6287a765 100644 --- a/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx @@ -9,7 +9,6 @@ import useSWRMutation from 'swr/mutation'; import classes from './Title.module.css'; function Title({ isAuthorized, data }) { - console.log('DATA', data); const { mutate } = useSWRConfig(); const [isSaved, setIsSaved] = useState(data.is_saved); const profile = useMemo(() => { @@ -113,13 +112,13 @@ function Title({ isAuthorized, data }) { </div> <div className={classes['title-block__company_region']}>{profile.region}</div> </div> - <button onClick={handleClick} + {isAuthorized && (<button onClick={handleClick} type="button" className={`${classes['title-block__button']} ${isSaved && classes['added_to_saved__button']}`} > <span className={`${classes['title-block__button--text']} ${isSaved && classes['added_to_saved__button--text']}`}>{!isSaved ? 'Додати в збережені' : 'Додано в збережені'}</span> {isAuthorized ? (isSaved ? filledStar : outlinedStar) : null} - </button> + </button>)} </div> ); } From 7660b95a809d8a7834ff7b7c4b799378a90512c0 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 26 Oct 2023 11:32:55 +0200 Subject: [PATCH 16/51] show email, phone upd --- .../ProfileDetail/DetailedInfo/PhoneEmail.jsx | 48 ++++++------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx index 2842ce55a..3c86afa38 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react'; +import { useState } from 'react'; import useSWR from 'swr'; import { PropTypes } from 'prop-types'; import classes from './PhoneEmail.module.css'; @@ -6,11 +6,9 @@ import classes from './PhoneEmail.module.css'; function PhoneEmail ({ isAuthorized, profileId }) { const [isPhoneShown, setPhoneShown] = useState(false); const [isEmailShown, setEmailShown] = useState(false); - const [user, setUser] = useState(null); - const [profile, setProfile] = useState(null); - const authToken = localStorage.getItem('Token'); - const { data: userData, error: userError } = useSWR( + + const { data: userData } = useSWR( authToken ? `${process.env.REACT_APP_BASE_API_URL}/api/auth/users/me/` : null, url => fetch(url, { @@ -21,8 +19,8 @@ function PhoneEmail ({ isAuthorized, profileId }) { }).then(res => res.json()), ); - const { data: profileData, error: profileError } = useSWR( - `${process.env.REACT_APP_BASE_API_URL}/api/profiles/${profileId}?with_contacts=True`, + const { data: profileData} = useSWR( + authToken ? `${process.env.REACT_APP_BASE_API_URL}/api/profiles/${profileId}?with_contacts=True` : null, url => fetch(url, { method: 'GET', @@ -32,20 +30,8 @@ function PhoneEmail ({ isAuthorized, profileId }) { }).then(res => res.json()), ); - useEffect(() => { - if (userData) { - setUser(userData); - } - if (userError) { - console.error(userError); - } - if (profileData) { - setProfile(profileData); - } - if (profileError) { - console.error(profileError); - } - }, [userData, profileData, userError, profileError]); + const urlViewed = `${process.env.REACT_APP_BASE_API_URL}/api/viewed-list/`; + const viewedData = {user: userData.id, company: profileId,}; async function sendRequest(url, data ) { return fetch(url, { @@ -56,17 +42,14 @@ function PhoneEmail ({ isAuthorized, profileId }) { }, body: JSON.stringify(data), }).then(); - } + } const handlePhoneClick = async () => { setPhoneShown(true); try { await sendRequest( - `${process.env.REACT_APP_BASE_API_URL}/api/viewed-list/`, - { - user: user.id, - company: profileId, - } + urlViewed, + viewedData ); } catch (error) { console.error(error); @@ -77,11 +60,8 @@ function PhoneEmail ({ isAuthorized, profileId }) { setEmailShown(true); try { await sendRequest( - `${process.env.REACT_APP_BASE_API_URL}/api/viewed-list/`, - { - user: user.id, - company: profileId, - } + urlViewed, + viewedData ); } catch (error) { console.error(error); @@ -94,7 +74,7 @@ function PhoneEmail ({ isAuthorized, profileId }) { <p className={classes['data-block__field--title']}>Телефон</p> {isPhoneShown ? ( - <p className={classes['data-block__field--phone']}>{profile.phone}</p> ) : ( + <p className={classes['data-block__field--phone']}>{profileData.phone}</p> ) : ( <button type="button" onClick={handlePhoneClick} disabled={!isAuthorized} className={classes['data-block__field--show--phone']}> Показати телефон </button> @@ -103,7 +83,7 @@ function PhoneEmail ({ isAuthorized, profileId }) { <div className={classes['data-block__field']}> <p className={classes['data-block__field--title']}>Електронна пошта</p> {isEmailShown ? ( - <p className={classes['data-block__field--email']}>{profile.email}</p> ) : ( + <p className={classes['data-block__field--email']}>{profileData.email}</p> ) : ( <button type="button" onClick={handleEmailClick} disabled={!isAuthorized} className={classes['data-block__field--show--email']}>Показати ел. пошту</button> )} </div> From e2ce50491f3147f4adbf36089f68dbf658d0ed53 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 26 Oct 2023 17:37:16 +0200 Subject: [PATCH 17/51] default logo component added --- .../ProfileDetail/MainInfo/DefaultLogo.jsx | 22 +++++++++++++++++++ .../MainInfo/DefaultLogo.module.css | 15 +++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/MainInfo/DefaultLogo.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/MainInfo/DefaultLogo.module.css diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/DefaultLogo.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/DefaultLogo.jsx new file mode 100644 index 000000000..4d65a0544 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/DefaultLogo.jsx @@ -0,0 +1,22 @@ +import classes from './DefaultLogo.module.css'; + +function DefaultLogo () { + return ( + <div className={classes['default_logo_container']}> + <svg className={classes['default_ellipse']} xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40" fill="none"> + <circle cx="20" cy="20" r="20" fill="#DEE1E8"/> + </svg> + <svg className={classes['default_logo']} xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 34 34" fill="none"> + <mask id="mask0_2511_4933" x="0" y="0" width="34" height="34"> + <circle cx="17" cy="17" r="16.875" fill="white"/> + </mask> + <g mask="url(#mask0_2511_4933)"> + <path fillRule="evenodd" clipRule="evenodd" d="M4.5 17.3125V27H17H29.5V17.3125V7.625H17H4.5V17.3125ZM25.1917 10.2048L26.8301 10.3591V17.3503V24.3413L16.9393 24.2781L7.04854 24.2148L6.98422 17.2684L6.9199 10.322L7.59102 10.2208C8.70655 10.0524 23.4335 10.0391 25.1917 10.2048ZM10.9927 12.2459C10.2786 12.661 9.80898 13.8097 10.0718 14.499C10.7061 16.164 13.1939 15.8909 13.6163 14.1096C13.7417 13.5806 13.6272 13.3043 13.0386 12.717C12.275 11.9551 11.715 11.8262 10.9927 12.2459ZM18.5136 15.4355C18.0602 16.0015 17.4447 16.8189 17.1459 17.252C16.4922 18.1994 16.1735 18.2316 15.4155 17.4266L14.8388 16.8138L12.582 19.0565C11.3408 20.29 10.3252 21.3829 10.3252 21.4854C10.3252 21.5881 13.4498 21.6719 17.2687 21.6719C23.2388 21.6719 24.1932 21.6225 24.0769 21.3202C23.9002 20.8608 19.5706 14.4062 19.4391 14.4062C19.3837 14.4062 18.9672 14.8696 18.5136 15.4355Z" fill="#BFC6CF"/> + </g> + </svg> + </div> + ); + +} + +export default DefaultLogo; diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/DefaultLogo.module.css b/FrontEnd/src/components/ProfileDetail/MainInfo/DefaultLogo.module.css new file mode 100644 index 000000000..d01b9b9df --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/DefaultLogo.module.css @@ -0,0 +1,15 @@ +.default_logo_container { + position: relative; + width: 100%; + height: 100%; +} + +.default_ellipse { + position: absolute; +} + +.default_logo { + position: absolute; + top: 3px; + left: 3px; +} \ No newline at end of file From 1a017687ca767ced7bbcb98b9964e45676c3b95c Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 26 Oct 2023 17:39:53 +0200 Subject: [PATCH 18/51] components updated --- .../components/ProfileDetail/BannerImage.jsx | 2 +- .../ProfileDetail/DetailedInfo/Company.jsx | 60 +++++++----- .../DetailedInfo/CompanyDescription.jsx | 2 +- .../DetailedInfo/Cooperation.jsx | 38 ++++---- .../ProfileDetail/DetailedInfo/Logistics.jsx | 33 ++++--- .../ProfileDetail/DetailedInfo/PhoneEmail.jsx | 2 +- .../DetailedInfo/ProductsServices.jsx | 71 ++++++++------ .../ProfileDetail/DetailedInfo/ReadMore.jsx | 12 ++- .../ProfileDetail/DetailedInfo/Startup.jsx | 94 ++++++++----------- .../ProfileDetail/MainInfo/MainInfo.jsx | 2 +- .../ProfileDetail/MainInfo/Title.jsx | 23 +++-- 11 files changed, 184 insertions(+), 155 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/BannerImage.jsx b/FrontEnd/src/components/ProfileDetail/BannerImage.jsx index e15399ee5..e1c252479 100644 --- a/FrontEnd/src/components/ProfileDetail/BannerImage.jsx +++ b/FrontEnd/src/components/ProfileDetail/BannerImage.jsx @@ -12,7 +12,7 @@ function BannerImage ({ data }) { <div className={classes['banner-image__block']}> <div className={classes['banner-image']}> {profile.banner ? ( - <img src={profile.banner} alt="Profile Banner" /> + <img src={profile.banner} alt="Company Banner" /> ) : ( <svg xmlns="http://www.w3.org/2000/svg" diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx index b2f78eda1..32031fc18 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx @@ -9,32 +9,48 @@ function Company ({ data }) { }; }, [data]); + // TODO: implement logic for getting data from db when it's added on server side + + const competitiveEdge = ''; + const slogan = ''; + const companyData = profile.common_info || competitiveEdge || slogan; + return ( - <div id="about-company" className={classes['about-company']}> - <div className={classes['about-company__title']}> - <div className={classes['about-company__title--block']}> - <p className={classes['about-company__title--text']}>Про компанію</p> + companyData ? ( + <div id="about-company" className={classes['about-company']}> + <div className={classes['about-company__title']}> + <div className={classes['about-company__title--block']}> + <p className={classes['about-company__title--text']}>Про компанію</p> + </div> + <div className={classes['about-company__title--divider']}></div> </div> - <div className={classes['about-company__title--divider']}></div> - </div> - <div className={classes['about-company__content']}> - <p className={classes['about-company__content--common']}> - <ReadMore > - {profile.common_info} - </ReadMore> - </p> - <div className={classes['about-company__content--advantage']}> - <p className={classes['about-company__content--advantage--title']}>Конкурентна перевага</p> - <p className={classes['about-company__content--advantage--description']}> - <ReadMore> - </ReadMore> - </p> - </div><div className={classes['about-company__content--slogan']}> - <p className={classes['about-company__content--slogan--title']}>Візія, слоган</p> - <p className={classes['about-company__content--slogan--text']}></p> + <div className={classes['about-company__content']}> + {profile.common_info ? ( + <p className={classes['about-company__content--common']}> + <ReadMore > + {profile.common_info} + </ReadMore> + </p> + ) : null} + {competitiveEdge ? ( + <div className={classes['about-company__content--advantage']}> + <p className={classes['about-company__content--advantage--title']}>Конкурентна перевага</p> + <p className={classes['about-company__content--advantage--description']}> + <ReadMore> + {competitiveEdge} + </ReadMore> + </p> + </div> + ) : null} + {slogan ? ( + <div className={classes['about-company__content--slogan']}> + <p className={classes['about-company__content--slogan--title']}>Візія, слоган</p> + <p className={classes['about-company__content--slogan--text']}>{slogan}</p> + </div> + ) : null} </div> </div> - </div> + ) : null ); } diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx index 461c3bce0..7722324e1 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx @@ -10,7 +10,7 @@ function CompanyDescription ({ data }) { <div className={classes['company-description-block']}> <Company data={data} /> <Startup data={data} /> - <ProductsServices /> + <ProductsServices data={data} /> <Logistics /> <Cooperation /> </div> diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.jsx index 251aa004c..d58d4dde2 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.jsx @@ -1,31 +1,31 @@ -// import { useMemo } from 'react'; -// import { PropTypes } from 'prop-types'; import classes from './Cooperation.module.css'; import ReadMore from './ReadMore'; function Cooperation () { - // const profile = useMemo(() => { - // return { - // }; - // }, [data]); + const cooperationData = ''; + + // TODO: implement logic for getting data from db when it's added on server side return ( - <div id="cooperation" className={classes['cooperation-wrapper']}> - <div className={classes['cooperation']}> - <div className={classes['cooperation__title']}> - <div className={classes['cooperation__title--block']}> - <p className={classes['cooperation__title--text']}>Формат співпраці</p> + cooperationData ? ( + <div id="cooperation" className={classes['cooperation-wrapper']}> + <div className={classes['cooperation']}> + <div className={classes['cooperation__title']}> + <div className={classes['cooperation__title--block']}> + <p className={classes['cooperation__title--text']}>Формат співпраці</p> + </div> + <div className={classes['cooperation__title--divider']}></div> + </div> + <div className={classes['cooperation__content--block']}> + <p className={classes['cooperation__content--description']}> + <ReadMore> + {cooperationData} + </ReadMore> + </p> </div> - <div className={classes['cooperation__title--divider']}></div> - </div> - <div className={classes['cooperation__content--block']}> - <p className={classes['cooperation__content--description']}> - <ReadMore> - </ReadMore> - </p> </div> </div> - </div> + ) : null ); } diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.jsx index 44e83352d..ac5204926 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.jsx @@ -2,23 +2,30 @@ import classes from './Logistics.module.css'; import ReadMore from './ReadMore'; function Logistics () { + const logisticsData = ''; + + // TODO: implement logic for getting data from db when it's added on server side + return ( - <div id="logistics" className={classes['logistics-wrapper']}> - <div className={classes['logistics']}> - <div className={classes['logistics__title']}> - <div className={classes['logistics__title--block']}> - <p className={classes['logistics__title--text']}>Логістика товарів / послуг</p> + logisticsData ? ( + <div id="logistics" className={classes['logistics-wrapper']}> + <div className={classes['logistics']}> + <div className={classes['logistics__title']}> + <div className={classes['logistics__title--block']}> + <p className={classes['logistics__title--text']}>Логістика товарів / послуг</p> + </div> + <div className={classes['logistics__title--divider']}></div> + </div> + <div className={classes['logistics__content--block']}> + <p className={classes['logistics__content--description']}> + <ReadMore> + {logisticsData} + </ReadMore> + </p> </div> - <div className={classes['logistics__title--divider']}></div> - </div> - <div className={classes['logistics__content--block']}> - <p className={classes['logistics__content--description']}> - <ReadMore> - </ReadMore> - </p> </div> </div> - </div> + ) : null ); } diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx index 3c86afa38..18b48d9a4 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx @@ -31,7 +31,7 @@ function PhoneEmail ({ isAuthorized, profileId }) { ); const urlViewed = `${process.env.REACT_APP_BASE_API_URL}/api/viewed-list/`; - const viewedData = {user: userData.id, company: profileId,}; + const viewedData = userData && {user: userData.id, company: profileId,}; async function sendRequest(url, data ) { return fetch(url, { diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.jsx index 6608d039c..b7fb2d2e8 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.jsx @@ -1,40 +1,55 @@ -// import { useMemo } from 'react'; -// import { PropTypes } from 'prop-types'; +import { useMemo } from 'react'; +import { PropTypes } from 'prop-types'; import classes from './ProductsServices.module.css'; import ReadMore from './ReadMore'; -function ProductsServices () { - // const profile = useMemo(() => { - // return { - // }; - // }, [data]); +function ProductsServices ({ data }) { + const profile = useMemo(() => { + return { + products: data.product_info, + services: data.service_info + }; + }, [data]); return ( - <div id="products-services" className={classes['products-services']}> - <div className={classes['products-services__title']}> - <div className={classes['products-services__title--block']}> - <p className={classes['products-services__title--text']}>Товари / послуги</p> + (profile.products || profile.services) ? ( + <div id="products-services" className={classes['products-services']}> + <div className={classes['products-services__title']}> + <div className={classes['products-services__title--block']}> + <p className={classes['products-services__title--text']}>Товари / послуги</p> + </div> + <div className={classes['products-services__title--divider']}></div> </div> - <div className={classes['products-services__title--divider']}></div> - </div> - <div className={classes['products-services__content']}> - <div className={classes['products-services__content--block']}> - <p className={classes['products-services__content--title']}>Товари</p> - <p className={classes['products-services__content--description']}> - <ReadMore> - </ReadMore> - </p> - </div> - <div className={classes['products-services__content--block']}> - <p className={classes['products-services__content--title']}>Послуги</p> - <p className={classes['products-services__content--description']}> - <ReadMore> - </ReadMore> - </p> + <div className={classes['products-services__content']}> + {profile.products && + <div className={classes['products-services__content--block']}> + <p className={classes['products-services__content--title']}>Товари</p> + <p className={classes['products-services__content--description']}> + <ReadMore> + {profile.products} + </ReadMore> + </p> + </div>} + {profile.services && + <div className={classes['products-services__content--block']}> + <p className={classes['products-services__content--title']}>Послуги</p> + <p className={classes['products-services__content--description']}> + <ReadMore> + {profile.services} + </ReadMore> + </p> + </div>} </div> </div> - </div> + ) : null ); } export default ProductsServices; + +ProductsServices.PropTypes = { + data: PropTypes.shape({ + product_info: PropTypes.string, + service_info: PropTypes.string, + }) +}; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/ReadMore.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ReadMore.jsx index 5f5d56ddf..90577d1f7 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/ReadMore.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ReadMore.jsx @@ -9,15 +9,19 @@ const ReadMore = ({ children }) => { const toggleReadMore = () => { setReadMore(!readMore); }; - const displayText = text && (readMore ? text : `${text.slice(0, 150)}...`); + const maxTextLength = 150; + + const displayText = text && (readMore || text.length <= maxTextLength ? text : `${text.slice(0, maxTextLength)}...`); return ( text ? ( <p className={classes['read-more']}> {displayText} - <span onClick={toggleReadMore} className={classes['read-or-hide']}> - {!readMore ? 'читати далі' : 'приховати'} - </span> + {text.length > maxTextLength && ( + <span onClick={toggleReadMore} className={classes['read-or-hide']}> + {!readMore ? 'читати далі' : 'приховати'} + </span> + )} </p>) : null ); }; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.jsx index 87cdce07c..1fbda7413 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.jsx @@ -10,66 +10,50 @@ function Startup ({ data }) { }; }, [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 ( + <div key={key} className={classes['startup__content--block']}> + <p className={classes['startup__content--title']}>{key}</p> + <p className={classes['startup__content--description']}> + <ReadMore>{value}</ReadMore> + </p> + </div> + ); + } + return null; + }); + + const hasSections = renderedSections.some((section) => section !== null); + return ( - <div id="startup" className={classes['startup-wrapper']}> - <div className={classes['startup']}> - <div className={classes['startup__title']}> - <div className={classes['startup__title--block']}> - <p className={classes['startup__title--text']}>Стартап</p> - </div> - <div className={classes['startup__title--divider']}></div> - </div> - <div className={classes['startup__content']}> - <div className={classes['startup__content--block']}> - <p className={classes['startup__content--title']}>Ідея стартапу</p> - <p className={classes['startup__content--description']}> - <ReadMore> - {profile.startup_idea} - </ReadMore> - </p> - </div> - <div className={classes['startup__content--block']}> - <p className={classes['startup__content--title']}>Розмір інвестиції</p> - <p className={classes['startup__content--description']}></p> - </div> - <div className={classes['startup__content--block']}> - <p className={classes['startup__content--title']}>Ціль співпраці</p> - <p className={classes['startup__content--description']}> - <ReadMore> - </ReadMore> - </p> - </div> - <div className={classes['startup__content--block']}> - <p className={classes['startup__content--title']}>Кінцевий результат</p> - <p className={classes['startup__content--description']}> - <ReadMore> - </ReadMore> - </p> - </div> - <div className={classes['startup__content--block']}> - <p className={classes['startup__content--title']}>Конкурентна перевага ідеї</p> - <p className={classes['startup__content--description']}> - <ReadMore> - </ReadMore> - </p> - </div> - <div className={classes['startup__content--block']}> - <p className={classes['startup__content--title']}>Ризики</p> - <p className={classes['startup__content--description']}> - <ReadMore> - </ReadMore> - </p> + hasSections ? ( + <div id="startup" className={classes['startup-wrapper']}> + <div className={classes['startup']}> + <div className={classes['startup__title']}> + <div className={classes['startup__title--block']}> + <p className={classes['startup__title--text']}>Стартап</p> + </div> + <div className={classes['startup__title--divider']}></div> </div> - <div className={classes['startup__content--block']}> - <p className={classes['startup__content--title']}>Пошук партнерів</p> - <p className={classes['startup__content--description']}> - <ReadMore> - </ReadMore> - </p> + <div className={classes['startup__content']}> + {renderedSections} </div> </div> </div> - </div> + ) : null ); } diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.jsx index 20ae21a7a..d5097cead 100644 --- a/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.jsx +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.jsx @@ -38,4 +38,4 @@ MainInfo.propTypes = { common_info: PropTypes.string, is_saved: PropTypes.bool.isRequired, }).isRequired, - }; \ No newline at end of file + }; diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx index f6287a765..618db3880 100644 --- a/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx @@ -2,14 +2,13 @@ import { useState, useMemo } from 'react'; import { Badge } from 'antd'; import { StarOutlined, StarFilled } from '@ant-design/icons'; -import { useSWRConfig } from 'swr'; import { PropTypes } from 'prop-types'; import useSWRMutation from 'swr/mutation'; +import DefaultLogo from './DefaultLogo'; import classes from './Title.module.css'; function Title({ isAuthorized, data }) { - const { mutate } = useSWRConfig(); const [isSaved, setIsSaved] = useState(data.is_saved); const profile = useMemo(() => { return { @@ -55,10 +54,6 @@ function Title({ isAuthorized, data }) { } }; - mutate((key) => typeof key === 'string' && key.startsWith('/api/profiles/'), { - revalidate: true, - }); - const filledStar = ( <StarFilled style={{ color: '#FFD800', fontSize: '24px' }} @@ -94,13 +89,21 @@ function Title({ isAuthorized, data }) { ); }; + // TODO: add logo from db once it's implemented on the server side + + const logo = ''; + return ( <div className={classes['title-block']}> <div className={classes['title-block__logo']}> - <img className={classes['logo']} - src={`${process.env.PUBLIC_URL}/companies-logos/1.png`} - alt="" - /> + {!logo ? ( + <DefaultLogo /> + ) : ( + <img className={classes['logo']} + src="" + alt="Company logo" + /> + )} </div> <div className={classes['title-block__about']}> <div className={classes['title-block__activity']}>{profile.activities}</div> From 187d8bde8be8f130aab26945e4803e332f5184d4 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 26 Oct 2023 22:12:30 +0200 Subject: [PATCH 19/51] data and contacts components updated --- .../DetailedInfo/DataContacts.jsx | 143 ++++++++++++------ .../DetailedInfo/DataContacts.module.css | 13 -- .../ProfileDetail/DetailedInfo/PhoneEmail.jsx | 41 ++--- 3 files changed, 121 insertions(+), 76 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx index 8c02e7027..0188dbc8d 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx @@ -12,55 +12,110 @@ function DataContacts ({ isAuthorized, data }) { }; }, [data]); + // TODO: implement logic for getting data from db when it's added on server side + + const companyData = { + 'ЄДРПОУ': profile.edrpou, + 'Рік заснування': profile.founded, + 'Розмір компанії': '', + 'Аудит': '' + }; + + const companyContacts = { + 'Сайт': '', + 'PhoneEmail': <PhoneEmail isAuthorized={isAuthorized} profileId={data.id}/>, + 'Адрес(и)': profile.address, + 'Соціальні мережі': [ + { + name: 'facebook', + url: '', + svgPath: + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> + <path d="M14 13.5H16.5L17.5 9.5H14V7.5C14 6.47 14 5.5 16 5.5H17.5V2.14C17.174 2.097 15.943 2 14.643 2C11.928 2 10 3.657 10 6.7V9.5H7V13.5H10V22H14V13.5Z" fill="black"/> + </svg> + , + }, + { + name: 'instagram', + url: '', + svgPath: + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> + <path d="M13.0286 2.00123C13.7583 1.99843 14.488 2.00576 15.2176 2.02323L15.4116 2.03023C15.6356 2.03823 15.8566 2.04823 16.1236 2.06023C17.1876 2.11023 17.9136 2.27823 18.5506 2.52523C19.2106 2.77923 19.7666 3.12323 20.3226 3.67923C20.831 4.17884 21.2244 4.78318 21.4756 5.45023C21.7226 6.08723 21.8906 6.81423 21.9406 7.87823C21.9526 8.14423 21.9626 8.36623 21.9706 8.59023L21.9766 8.78423C21.9943 9.51342 22.002 10.2428 21.9996 10.9722L22.0006 11.7182V13.0282C22.003 13.758 21.9954 14.4877 21.9776 15.2172L21.9716 15.4112C21.9636 15.6352 21.9536 15.8562 21.9416 16.1232C21.8916 17.1872 21.7216 17.9132 21.4756 18.5502C21.2252 19.218 20.8317 19.8228 20.3226 20.3222C19.8225 20.8306 19.2179 21.224 18.5506 21.4752C17.9136 21.7222 17.1876 21.8902 16.1236 21.9402C15.8566 21.9522 15.6356 21.9622 15.4116 21.9702L15.2176 21.9762C14.4881 21.994 13.7583 22.0017 13.0286 21.9992L12.2826 22.0002H10.9736C10.2438 22.0027 9.5141 21.995 8.78458 21.9772L8.59058 21.9712C8.35319 21.9626 8.11585 21.9526 7.87858 21.9412C6.81458 21.8912 6.08858 21.7212 5.45058 21.4752C4.78326 21.2246 4.17881 20.8311 3.67958 20.3222C3.17062 19.8225 2.7768 19.2178 2.52558 18.5502C2.27858 17.9132 2.11058 17.1872 2.06058 16.1232C2.04944 15.8859 2.03944 15.6486 2.03058 15.4112L2.02558 15.2172C2.00714 14.4877 1.99881 13.758 2.00058 13.0282V10.9722C1.99779 10.2428 2.00512 9.51343 2.02258 8.78423L2.02958 8.59023C2.03758 8.36623 2.04758 8.14423 2.05958 7.87823C2.10958 6.81323 2.27758 6.08823 2.52458 5.45023C2.77595 4.78285 3.17054 4.17868 3.68058 3.68023C4.17947 3.17098 4.78354 2.7768 5.45058 2.52523C6.08858 2.27823 6.81358 2.11023 7.87858 2.06023L8.59058 2.03023L8.78458 2.02523C9.51376 2.0068 10.2432 1.99847 10.9726 2.00023L13.0286 2.00123ZM12.0006 7.00123C11.3381 6.99186 10.6803 7.11425 10.0656 7.3613C9.45077 7.60834 8.89122 7.97511 8.41942 8.44029C7.94762 8.90546 7.57298 9.45977 7.31726 10.071C7.06155 10.6822 6.92987 11.3382 6.92987 12.0007C6.92987 12.6633 7.06155 13.3192 7.31726 13.9305C7.57298 14.5417 7.94762 15.096 8.41942 15.5612C8.89122 16.0264 9.45077 16.3931 10.0656 16.6402C10.6803 16.8872 11.3381 17.0096 12.0006 17.0002C13.3267 17.0002 14.5984 16.4734 15.5361 15.5358C16.4738 14.5981 17.0006 13.3263 17.0006 12.0002C17.0006 10.6741 16.4738 9.40238 15.5361 8.4647C14.5984 7.52701 13.3267 7.00123 12.0006 7.00123ZM12.0006 9.00123C12.3991 8.99389 12.7951 9.06603 13.1654 9.21344C13.5357 9.36085 13.8729 9.58057 14.1574 9.85978C14.4418 10.139 14.6678 10.4721 14.822 10.8396C14.9763 11.2071 15.0558 11.6016 15.0558 12.0002C15.0559 12.3988 14.9766 12.7934 14.8224 13.1609C14.6683 13.5285 14.4424 13.8617 14.1581 14.141C13.8737 14.4203 13.5366 14.6401 13.1663 14.7876C12.796 14.9352 12.4001 15.0074 12.0016 15.0002C11.2059 15.0002 10.4429 14.6842 9.88026 14.1216C9.31765 13.5589 9.00158 12.7959 9.00158 12.0002C9.00158 11.2046 9.31765 10.4415 9.88026 9.87891C10.4429 9.3163 11.2059 9.00023 12.0016 9.00023L12.0006 9.00123ZM17.2506 5.50123C16.928 5.51414 16.6229 5.65138 16.3992 5.8842C16.1755 6.11702 16.0506 6.42736 16.0506 6.75023C16.0506 7.0731 16.1755 7.38344 16.3992 7.61626C16.6229 7.84908 16.928 7.98632 17.2506 7.99923C17.5821 7.99923 17.9 7.86753 18.1345 7.63311C18.3689 7.39869 18.5006 7.08075 18.5006 6.74923C18.5006 6.41771 18.3689 6.09977 18.1345 5.86535C17.9 5.63093 17.5821 5.49923 17.2506 5.49923V5.50123Z" fill="black"/> + </svg> + , + }, + ], + 'Співпрацюємо з': '' + }; + + const hasSocialLinks = companyContacts['Соціальні мережі'].some(socialLink => socialLink.url !== null); + + const renderedDataSections = Object.entries(companyData).map(([key, value]) => { + const className = key === 'ЄДРПОУ' ? `${classes['data-block__field']} ${classes['edrpou']}` : classes['data-block__field']; + if (value) { + return ( + <div key={key} className={className}> + <p className={classes['data-block__field--title']}>{key}</p> + <p className={classes['data-block__field--value']}> + {value} + </p> + </div> + ); + } + return null; + }); + + const hasDataSections = renderedDataSections.some((section) => section !== null); + + const renderedContactSections = Object.entries(companyContacts).map(([key, value]) => { + if (value) { + if (key === 'Соціальні мережі' && hasSocialLinks) { + return ( + <div key={key} className={classes['data-block__field--social-networks']}> + <p className={classes['data-block__field--title']}>{key}</p> + {companyContacts['Соціальні мережі'].map((socialLink, index) => { + if (socialLink.url) { + return ( + <a key={index} href={socialLink.url}> + {socialLink.svgPath} + </a> + ); + } + return null; + })} + </div> + ); + } 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 ( + <div key={key} className={className}> + <p className={classes['data-block__field--title']}>{key}</p> + <p className={valueClassName}>{value}</p> + </div> + ); + } + } + return null; + }); + + const hasContactSections = renderedContactSections.some((section) => section !== null); + return ( <div className={classes['data-wrapper']}> <div className={classes['data']}> - <div className={classes['data-block']}> - <div className={classes['data-block__field']}> - <p className={`${classes['data-block__field--title']} ${classes['edrpou']}`} >ЄДРПОУ</p> - <p className={classes['data-block__field--value']}>{profile.edrpou}</p> - </div> - <div className={classes['data-block__field']}> - <p className={classes['data-block__field--title']}>Рік заснування</p> - <p className={classes['data-block__field--value']}>{profile.founded}</p> - </div> - <div className={classes['data-block__field']}> - <p className={classes['data-block__field--title']}>Розмір компанії</p> - <p className={classes['data-block__field--value']}></p> - </div> - <div className={classes['data-block__field']}> - <p className={classes['data-block__field--title']}>Аудит</p> - <p className={classes['data-block__field--value']}></p> - </div> - </div> - <div className={classes['data-block']}> - <div className={classes['data-block__field']}> - <p className={classes['data-block__field--title']}>Сайт</p> - <p className={classes['data-block__field--site']}></p> - </div> - <PhoneEmail isAuthorized={isAuthorized} profileId={data.id}/> - <div className={classes['data-block__field--address']}> - <p className={classes['data-block__field--title']}>Адрес(и)</p> - <p className={classes['data-block__field--address--value']}>{profile.address}</p> - </div> - <div className={classes['data-block__field--social-networks']}> - <p className={classes['data-block__field--title']}>Соціальні мережі</p> - <a href="#"> - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> - <path d="M14 13.5H16.5L17.5 9.5H14V7.5C14 6.47 14 5.5 16 5.5H17.5V2.14C17.174 2.097 15.943 2 14.643 2C11.928 2 10 3.657 10 6.7V9.5H7V13.5H10V22H14V13.5Z" fill="black"/> - </svg> - </a> - <a href="#"> - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> - <path d="M13.0286 2.00123C13.7583 1.99843 14.488 2.00576 15.2176 2.02323L15.4116 2.03023C15.6356 2.03823 15.8566 2.04823 16.1236 2.06023C17.1876 2.11023 17.9136 2.27823 18.5506 2.52523C19.2106 2.77923 19.7666 3.12323 20.3226 3.67923C20.831 4.17884 21.2244 4.78318 21.4756 5.45023C21.7226 6.08723 21.8906 6.81423 21.9406 7.87823C21.9526 8.14423 21.9626 8.36623 21.9706 8.59023L21.9766 8.78423C21.9943 9.51342 22.002 10.2428 21.9996 10.9722L22.0006 11.7182V13.0282C22.003 13.758 21.9954 14.4877 21.9776 15.2172L21.9716 15.4112C21.9636 15.6352 21.9536 15.8562 21.9416 16.1232C21.8916 17.1872 21.7216 17.9132 21.4756 18.5502C21.2252 19.218 20.8317 19.8228 20.3226 20.3222C19.8225 20.8306 19.2179 21.224 18.5506 21.4752C17.9136 21.7222 17.1876 21.8902 16.1236 21.9402C15.8566 21.9522 15.6356 21.9622 15.4116 21.9702L15.2176 21.9762C14.4881 21.994 13.7583 22.0017 13.0286 21.9992L12.2826 22.0002H10.9736C10.2438 22.0027 9.5141 21.995 8.78458 21.9772L8.59058 21.9712C8.35319 21.9626 8.11585 21.9526 7.87858 21.9412C6.81458 21.8912 6.08858 21.7212 5.45058 21.4752C4.78326 21.2246 4.17881 20.8311 3.67958 20.3222C3.17062 19.8225 2.7768 19.2178 2.52558 18.5502C2.27858 17.9132 2.11058 17.1872 2.06058 16.1232C2.04944 15.8859 2.03944 15.6486 2.03058 15.4112L2.02558 15.2172C2.00714 14.4877 1.99881 13.758 2.00058 13.0282V10.9722C1.99779 10.2428 2.00512 9.51343 2.02258 8.78423L2.02958 8.59023C2.03758 8.36623 2.04758 8.14423 2.05958 7.87823C2.10958 6.81323 2.27758 6.08823 2.52458 5.45023C2.77595 4.78285 3.17054 4.17868 3.68058 3.68023C4.17947 3.17098 4.78354 2.7768 5.45058 2.52523C6.08858 2.27823 6.81358 2.11023 7.87858 2.06023L8.59058 2.03023L8.78458 2.02523C9.51376 2.0068 10.2432 1.99847 10.9726 2.00023L13.0286 2.00123ZM12.0006 7.00123C11.3381 6.99186 10.6803 7.11425 10.0656 7.3613C9.45077 7.60834 8.89122 7.97511 8.41942 8.44029C7.94762 8.90546 7.57298 9.45977 7.31726 10.071C7.06155 10.6822 6.92987 11.3382 6.92987 12.0007C6.92987 12.6633 7.06155 13.3192 7.31726 13.9305C7.57298 14.5417 7.94762 15.096 8.41942 15.5612C8.89122 16.0264 9.45077 16.3931 10.0656 16.6402C10.6803 16.8872 11.3381 17.0096 12.0006 17.0002C13.3267 17.0002 14.5984 16.4734 15.5361 15.5358C16.4738 14.5981 17.0006 13.3263 17.0006 12.0002C17.0006 10.6741 16.4738 9.40238 15.5361 8.4647C14.5984 7.52701 13.3267 7.00123 12.0006 7.00123ZM12.0006 9.00123C12.3991 8.99389 12.7951 9.06603 13.1654 9.21344C13.5357 9.36085 13.8729 9.58057 14.1574 9.85978C14.4418 10.139 14.6678 10.4721 14.822 10.8396C14.9763 11.2071 15.0558 11.6016 15.0558 12.0002C15.0559 12.3988 14.9766 12.7934 14.8224 13.1609C14.6683 13.5285 14.4424 13.8617 14.1581 14.141C13.8737 14.4203 13.5366 14.6401 13.1663 14.7876C12.796 14.9352 12.4001 15.0074 12.0016 15.0002C11.2059 15.0002 10.4429 14.6842 9.88026 14.1216C9.31765 13.5589 9.00158 12.7959 9.00158 12.0002C9.00158 11.2046 9.31765 10.4415 9.88026 9.87891C10.4429 9.3163 11.2059 9.00023 12.0016 9.00023L12.0006 9.00123ZM17.2506 5.50123C16.928 5.51414 16.6229 5.65138 16.3992 5.8842C16.1755 6.11702 16.0506 6.42736 16.0506 6.75023C16.0506 7.0731 16.1755 7.38344 16.3992 7.61626C16.6229 7.84908 16.928 7.98632 17.2506 7.99923C17.5821 7.99923 17.9 7.86753 18.1345 7.63311C18.3689 7.39869 18.5006 7.08075 18.5006 6.74923C18.5006 6.41771 18.3689 6.09977 18.1345 5.86535C17.9 5.63093 17.5821 5.49923 17.2506 5.49923V5.50123Z" fill="black"/> - </svg> - </a> + {hasDataSections ? ( + <div className={classes['data-block']}> + {renderedDataSections} </div> - <div className={classes['data-block__field']}> - <p className={classes['data-block__field--title']}>Співпрацюємо з</p> - <p className={classes['data-block__field--cooperate--value']}></p> + ) : null} + {hasContactSections ? ( + <div className={classes['data-block']}> + {renderedContactSections} </div> - </div> + ) : null} </div> </div> ); diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.module.css index 80ef696ec..40343dfd4 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.module.css +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.module.css @@ -75,17 +75,4 @@ display: flex; align-items: flex-start; gap: 8px; -} - -.data-block__field--address--value, -.data-block__field--cooperate--value { - width: 200px; - color: var(--main-black-90, #292E32); - font-feature-settings: 'calt' off; - font-family: Inter; - font-size: 14px; - font-style: normal; - font-weight: 600; - line-height: 22px; - letter-spacing: -0.14px; } \ No newline at end of file diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx index 18b48d9a4..a54c157d1 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx @@ -69,25 +69,28 @@ function PhoneEmail ({ isAuthorized, profileId }) { }; return ( - <> - <div className={classes['data-block__field']}> - <p className={classes['data-block__field--title']}>Телефон</p> - {isPhoneShown ? - ( - <p className={classes['data-block__field--phone']}>{profileData.phone}</p> ) : ( - <button type="button" onClick={handlePhoneClick} disabled={!isAuthorized} className={classes['data-block__field--show--phone']}> - Показати телефон - </button> - )} - </div> - <div className={classes['data-block__field']}> - <p className={classes['data-block__field--title']}>Електронна пошта</p> - {isEmailShown ? ( - <p className={classes['data-block__field--email']}>{profileData.email}</p> ) : ( - <button type="button" onClick={handleEmailClick} disabled={!isAuthorized} className={classes['data-block__field--show--email']}>Показати ел. пошту</button> - )} - </div> - </> + profileData ? ( + <> + <div className={classes['data-block__field']}> + <p className={classes['data-block__field--title']}>Телефон</p> + {isPhoneShown ? + ( + <p className={classes['data-block__field--phone']}>{profileData.phone}</p> ) : ( + <button type="button" onClick={handlePhoneClick} disabled={!isAuthorized} className={classes['data-block__field--show--phone']}> + Показати телефон + </button> + )} + </div> + <div className={classes['data-block__field']}> + <p className={classes['data-block__field--title']}>Електронна пошта</p> + {isEmailShown ? ( + <p className={classes['data-block__field--email']}>{profileData.email}</p> ) : ( + <button type="button" onClick={handleEmailClick} disabled={!isAuthorized} className={classes['data-block__field--show--email']}>Показати ел. пошту</button> + )} + </div> + + </> + ) : null ); } From cf14b4d1afda630eeb923b38ff016f2f77cac393 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Fri, 27 Oct 2023 19:05:18 +0200 Subject: [PATCH 20/51] empty data component added --- .../components/ProfileDetail/EmptyData.jsx | 13 ++++++++++++ .../ProfileDetail/EmptyData.module.css | 20 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/EmptyData.jsx create mode 100644 FrontEnd/src/components/ProfileDetail/EmptyData.module.css diff --git a/FrontEnd/src/components/ProfileDetail/EmptyData.jsx b/FrontEnd/src/components/ProfileDetail/EmptyData.jsx new file mode 100644 index 000000000..20dc43e84 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/EmptyData.jsx @@ -0,0 +1,13 @@ +import classes from './EmptyData.module.css'; + +function EmptyData () { + return ( + <div className={classes['empty-data-wrapper']}> + <p className={classes['empty-data']}> + Інформація не заповнена + </p> + </div> + ); +} + +export default EmptyData; diff --git a/FrontEnd/src/components/ProfileDetail/EmptyData.module.css b/FrontEnd/src/components/ProfileDetail/EmptyData.module.css new file mode 100644 index 000000000..88b677666 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/EmptyData.module.css @@ -0,0 +1,20 @@ +.empty-data-wrapper { + 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); + font-feature-settings: 'calt' off; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 22px; + letter-spacing: -0.14px; +} \ No newline at end of file From c50220dcb1d60576270f62768062c1336de58212 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Fri, 27 Oct 2023 20:01:38 +0200 Subject: [PATCH 21/51] main info component upd, renamed --- .../{MainInfo.jsx => MainInfoSection.jsx} | 15 +++++++++------ ...Info.module.css => MainInfoSection.module.css} | 0 2 files changed, 9 insertions(+), 6 deletions(-) rename FrontEnd/src/components/ProfileDetail/MainInfo/{MainInfo.jsx => MainInfoSection.jsx} (67%) rename FrontEnd/src/components/ProfileDetail/MainInfo/{MainInfo.module.css => MainInfoSection.module.css} (100%) diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.jsx similarity index 67% rename from FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.jsx rename to FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.jsx index d5097cead..7e6b39194 100644 --- a/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.jsx +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.jsx @@ -1,22 +1,24 @@ import { PropTypes } from 'prop-types'; -import Title from './Title'; +import TitleInfo from './TitleInfo'; import ProfileDetailNavBar from './ProfileDetailNavBar'; -import classes from './MainInfo.module.css'; +import classes from './MainInfoSection.module.css'; -function MainInfo ({ isAuthorized, data }) { +function MainInfoSection ({ isAuthorized, data, containsNotRequiredData }) { return ( <div className={classes['basic-info-content']}> - <Title isAuthorized={isAuthorized} data={data}/> + <TitleInfo isAuthorized={isAuthorized} data={data}/> + {containsNotRequiredData ? ( <ProfileDetailNavBar /> + ) : null} </div> ); } -export default MainInfo; +export default MainInfoSection; -MainInfo.propTypes = { +MainInfoSection.propTypes = { isAuthorized: PropTypes.bool, data: PropTypes.shape({ id: PropTypes.number.isRequired, @@ -38,4 +40,5 @@ MainInfo.propTypes = { common_info: PropTypes.string, is_saved: PropTypes.bool.isRequired, }).isRequired, + containsNotRequiredData: PropTypes.bool, }; diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.module.css b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.module.css similarity index 100% rename from FrontEnd/src/components/ProfileDetail/MainInfo/MainInfo.module.css rename to FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.module.css From 9a8e4de40e2adb211c5ff75ee49f6826e1bed4f8 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Fri, 27 Oct 2023 20:02:31 +0200 Subject: [PATCH 22/51] title component upd, renamed --- .../MainInfo/{Title.jsx => TitleInfo.jsx} | 31 +++++++++++++++---- ...{Title.module.css => TitleInfo.module.css} | 0 2 files changed, 25 insertions(+), 6 deletions(-) rename FrontEnd/src/components/ProfileDetail/MainInfo/{Title.jsx => TitleInfo.jsx} (83%) rename FrontEnd/src/components/ProfileDetail/MainInfo/{Title.module.css => TitleInfo.module.css} (100%) diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx similarity index 83% rename from FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx rename to FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx index 618db3880..a702adf3b 100644 --- a/FrontEnd/src/components/ProfileDetail/MainInfo/Title.jsx +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx @@ -1,18 +1,19 @@ import { useState, useMemo } from 'react'; - +import useSWR from 'swr'; import { Badge } from 'antd'; import { StarOutlined, StarFilled } from '@ant-design/icons'; import { PropTypes } from 'prop-types'; import useSWRMutation from 'swr/mutation'; import DefaultLogo from './DefaultLogo'; -import classes from './Title.module.css'; +import classes from './TitleInfo.module.css'; -function Title({ isAuthorized, data }) { +function TitleInfo({ isAuthorized, data }) { 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 @@ -26,6 +27,20 @@ function Title({ isAuthorized, data }) { }; }, [data]); + // TODO: change the logic of getting user.id when PR with hooks will be merged + + const authToken = localStorage.getItem('Token'); + const { data: userData } = useSWR( + authToken ? `${process.env.REACT_APP_BASE_API_URL}/api/auth/users/me/` : null, + url => + fetch(url, { + method: 'GET', + headers: { + 'Authorization': `Token ${authToken}`, + }, + }).then(res => res.json()), + ); + async function sendRequest(url, { arg: data }) { const authToken = localStorage.getItem('Token'); return fetch(url, { @@ -115,8 +130,11 @@ function Title({ isAuthorized, data }) { </div> <div className={classes['title-block__company_region']}>{profile.region}</div> </div> - {isAuthorized && (<button onClick={handleClick} + {isAuthorized && ( + <button + onClick={handleClick} type="button" + disabled={userData && userData.id === profile.personId} className={`${classes['title-block__button']} ${isSaved && classes['added_to_saved__button']}`} > <span className={`${classes['title-block__button--text']} ${isSaved && classes['added_to_saved__button--text']}`}>{!isSaved ? 'Додати в збережені' : 'Додано в збережені'}</span> @@ -126,13 +144,14 @@ function Title({ isAuthorized, data }) { ); } -export default Title; +export default TitleInfo; -Title.propTypes = { +TitleInfo.propTypes = { isAuthorized: PropTypes.bool, data: PropTypes.shape({ id: PropTypes.number.isRequired, name: PropTypes.string.isRequired, + person: PropTypes.number, address: PropTypes.string, region_display: PropTypes.string, categories: PropTypes.arrayOf( diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/Title.module.css b/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.module.css similarity index 100% rename from FrontEnd/src/components/ProfileDetail/MainInfo/Title.module.css rename to FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.module.css From ddd252ca3e6522a6feb8f23a53755619ab7b8f65 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Fri, 27 Oct 2023 20:04:52 +0200 Subject: [PATCH 23/51] phone email component upd --- .../src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx index a54c157d1..ebc564e2b 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx @@ -8,6 +8,8 @@ function PhoneEmail ({ isAuthorized, profileId }) { const [isEmailShown, setEmailShown] = useState(false); const authToken = localStorage.getItem('Token'); + // TODO: change the logic of getting user.id when PR with hooks will be merged + const { data: userData } = useSWR( authToken ? `${process.env.REACT_APP_BASE_API_URL}/api/auth/users/me/` : null, url => From b820bfa3e29c9c173754cc168b74072206acab96 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Fri, 27 Oct 2023 20:07:15 +0200 Subject: [PATCH 24/51] svg files for icons added --- .../ProfileDetail/DetailedInfo/SvgFiles/facebook.svg | 3 +++ .../ProfileDetail/DetailedInfo/SvgFiles/instagram.svg | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/facebook.svg create mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/instagram.svg diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/facebook.svg b/FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/facebook.svg new file mode 100644 index 000000000..d264339f3 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/facebook.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> + <path d="M14 13.5H16.5L17.5 9.5H14V7.5C14 6.47 14 5.5 16 5.5H17.5V2.14C17.174 2.097 15.943 2 14.643 2C11.928 2 10 3.657 10 6.7V9.5H7V13.5H10V22H14V13.5Z" fill="black"/> +</svg> \ No newline at end of file diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/instagram.svg b/FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/instagram.svg new file mode 100644 index 000000000..7671d15b7 --- /dev/null +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/instagram.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> + <path d="M13.0286 2.00123C13.7583 1.99843 14.488 2.00576 15.2176 2.02323L15.4116 2.03023C15.6356 2.03823 15.8566 2.04823 16.1236 2.06023C17.1876 2.11023 17.9136 2.27823 18.5506 2.52523C19.2106 2.77923 19.7666 3.12323 20.3226 3.67923C20.831 4.17884 21.2244 4.78318 21.4756 5.45023C21.7226 6.08723 21.8906 6.81423 21.9406 7.87823C21.9526 8.14423 21.9626 8.36623 21.9706 8.59023L21.9766 8.78423C21.9943 9.51342 22.002 10.2428 21.9996 10.9722L22.0006 11.7182V13.0282C22.003 13.758 21.9954 14.4877 21.9776 15.2172L21.9716 15.4112C21.9636 15.6352 21.9536 15.8562 21.9416 16.1232C21.8916 17.1872 21.7216 17.9132 21.4756 18.5502C21.2252 19.218 20.8317 19.8228 20.3226 20.3222C19.8225 20.8306 19.2179 21.224 18.5506 21.4752C17.9136 21.7222 17.1876 21.8902 16.1236 21.9402C15.8566 21.9522 15.6356 21.9622 15.4116 21.9702L15.2176 21.9762C14.4881 21.994 13.7583 22.0017 13.0286 21.9992L12.2826 22.0002H10.9736C10.2438 22.0027 9.5141 21.995 8.78458 21.9772L8.59058 21.9712C8.35319 21.9626 8.11585 21.9526 7.87858 21.9412C6.81458 21.8912 6.08858 21.7212 5.45058 21.4752C4.78326 21.2246 4.17881 20.8311 3.67958 20.3222C3.17062 19.8225 2.7768 19.2178 2.52558 18.5502C2.27858 17.9132 2.11058 17.1872 2.06058 16.1232C2.04944 15.8859 2.03944 15.6486 2.03058 15.4112L2.02558 15.2172C2.00714 14.4877 1.99881 13.758 2.00058 13.0282V10.9722C1.99779 10.2428 2.00512 9.51343 2.02258 8.78423L2.02958 8.59023C2.03758 8.36623 2.04758 8.14423 2.05958 7.87823C2.10958 6.81323 2.27758 6.08823 2.52458 5.45023C2.77595 4.78285 3.17054 4.17868 3.68058 3.68023C4.17947 3.17098 4.78354 2.7768 5.45058 2.52523C6.08858 2.27823 6.81358 2.11023 7.87858 2.06023L8.59058 2.03023L8.78458 2.02523C9.51376 2.0068 10.2432 1.99847 10.9726 2.00023L13.0286 2.00123ZM12.0006 7.00123C11.3381 6.99186 10.6803 7.11425 10.0656 7.3613C9.45077 7.60834 8.89122 7.97511 8.41942 8.44029C7.94762 8.90546 7.57298 9.45977 7.31726 10.071C7.06155 10.6822 6.92987 11.3382 6.92987 12.0007C6.92987 12.6633 7.06155 13.3192 7.31726 13.9305C7.57298 14.5417 7.94762 15.096 8.41942 15.5612C8.89122 16.0264 9.45077 16.3931 10.0656 16.6402C10.6803 16.8872 11.3381 17.0096 12.0006 17.0002C13.3267 17.0002 14.5984 16.4734 15.5361 15.5358C16.4738 14.5981 17.0006 13.3263 17.0006 12.0002C17.0006 10.6741 16.4738 9.40238 15.5361 8.4647C14.5984 7.52701 13.3267 7.00123 12.0006 7.00123ZM12.0006 9.00123C12.3991 8.99389 12.7951 9.06603 13.1654 9.21344C13.5357 9.36085 13.8729 9.58057 14.1574 9.85978C14.4418 10.139 14.6678 10.4721 14.822 10.8396C14.9763 11.2071 15.0558 11.6016 15.0558 12.0002C15.0559 12.3988 14.9766 12.7934 14.8224 13.1609C14.6683 13.5285 14.4424 13.8617 14.1581 14.141C13.8737 14.4203 13.5366 14.6401 13.1663 14.7876C12.796 14.9352 12.4001 15.0074 12.0016 15.0002C11.2059 15.0002 10.4429 14.6842 9.88026 14.1216C9.31765 13.5589 9.00158 12.7959 9.00158 12.0002C9.00158 11.2046 9.31765 10.4415 9.88026 9.87891C10.4429 9.3163 11.2059 9.00023 12.0016 9.00023L12.0006 9.00123ZM17.2506 5.50123C16.928 5.51414 16.6229 5.65138 16.3992 5.8842C16.1755 6.11702 16.0506 6.42736 16.0506 6.75023C16.0506 7.0731 16.1755 7.38344 16.3992 7.61626C16.6229 7.84908 16.928 7.98632 17.2506 7.99923C17.5821 7.99923 17.9 7.86753 18.1345 7.63311C18.3689 7.39869 18.5006 7.08075 18.5006 6.74923C18.5006 6.41771 18.3689 6.09977 18.1345 5.86535C17.9 5.63093 17.5821 5.49923 17.2506 5.49923V5.50123Z" fill="black"/> +</svg> \ No newline at end of file From 7d47febdd1d51c6a513cfe88767c37718d0008d3 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Fri, 27 Oct 2023 20:08:07 +0200 Subject: [PATCH 25/51] data contacts component upd --- .../DetailedInfo/DataContacts.jsx | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx index 0188dbc8d..57cbafa82 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx @@ -1,5 +1,8 @@ -import { useMemo } from 'react'; +import React, { useMemo } from 'react'; +import { PropTypes } from 'prop-types'; import PhoneEmail from './PhoneEmail'; +import { ReactComponent as FacebookSvg } from './SvgFiles/facebook.svg'; +import { ReactComponent as InstagramSvg } from './SvgFiles/instagram.svg'; import classes from './DataContacts.module.css'; function DataContacts ({ isAuthorized, data }) { @@ -29,26 +32,18 @@ function DataContacts ({ isAuthorized, data }) { { name: 'facebook', url: '', - svgPath: - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> - <path d="M14 13.5H16.5L17.5 9.5H14V7.5C14 6.47 14 5.5 16 5.5H17.5V2.14C17.174 2.097 15.943 2 14.643 2C11.928 2 10 3.657 10 6.7V9.5H7V13.5H10V22H14V13.5Z" fill="black"/> - </svg> - , + svgPath: <FacebookSvg />, }, { name: 'instagram', url: '', - svgPath: - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> - <path d="M13.0286 2.00123C13.7583 1.99843 14.488 2.00576 15.2176 2.02323L15.4116 2.03023C15.6356 2.03823 15.8566 2.04823 16.1236 2.06023C17.1876 2.11023 17.9136 2.27823 18.5506 2.52523C19.2106 2.77923 19.7666 3.12323 20.3226 3.67923C20.831 4.17884 21.2244 4.78318 21.4756 5.45023C21.7226 6.08723 21.8906 6.81423 21.9406 7.87823C21.9526 8.14423 21.9626 8.36623 21.9706 8.59023L21.9766 8.78423C21.9943 9.51342 22.002 10.2428 21.9996 10.9722L22.0006 11.7182V13.0282C22.003 13.758 21.9954 14.4877 21.9776 15.2172L21.9716 15.4112C21.9636 15.6352 21.9536 15.8562 21.9416 16.1232C21.8916 17.1872 21.7216 17.9132 21.4756 18.5502C21.2252 19.218 20.8317 19.8228 20.3226 20.3222C19.8225 20.8306 19.2179 21.224 18.5506 21.4752C17.9136 21.7222 17.1876 21.8902 16.1236 21.9402C15.8566 21.9522 15.6356 21.9622 15.4116 21.9702L15.2176 21.9762C14.4881 21.994 13.7583 22.0017 13.0286 21.9992L12.2826 22.0002H10.9736C10.2438 22.0027 9.5141 21.995 8.78458 21.9772L8.59058 21.9712C8.35319 21.9626 8.11585 21.9526 7.87858 21.9412C6.81458 21.8912 6.08858 21.7212 5.45058 21.4752C4.78326 21.2246 4.17881 20.8311 3.67958 20.3222C3.17062 19.8225 2.7768 19.2178 2.52558 18.5502C2.27858 17.9132 2.11058 17.1872 2.06058 16.1232C2.04944 15.8859 2.03944 15.6486 2.03058 15.4112L2.02558 15.2172C2.00714 14.4877 1.99881 13.758 2.00058 13.0282V10.9722C1.99779 10.2428 2.00512 9.51343 2.02258 8.78423L2.02958 8.59023C2.03758 8.36623 2.04758 8.14423 2.05958 7.87823C2.10958 6.81323 2.27758 6.08823 2.52458 5.45023C2.77595 4.78285 3.17054 4.17868 3.68058 3.68023C4.17947 3.17098 4.78354 2.7768 5.45058 2.52523C6.08858 2.27823 6.81358 2.11023 7.87858 2.06023L8.59058 2.03023L8.78458 2.02523C9.51376 2.0068 10.2432 1.99847 10.9726 2.00023L13.0286 2.00123ZM12.0006 7.00123C11.3381 6.99186 10.6803 7.11425 10.0656 7.3613C9.45077 7.60834 8.89122 7.97511 8.41942 8.44029C7.94762 8.90546 7.57298 9.45977 7.31726 10.071C7.06155 10.6822 6.92987 11.3382 6.92987 12.0007C6.92987 12.6633 7.06155 13.3192 7.31726 13.9305C7.57298 14.5417 7.94762 15.096 8.41942 15.5612C8.89122 16.0264 9.45077 16.3931 10.0656 16.6402C10.6803 16.8872 11.3381 17.0096 12.0006 17.0002C13.3267 17.0002 14.5984 16.4734 15.5361 15.5358C16.4738 14.5981 17.0006 13.3263 17.0006 12.0002C17.0006 10.6741 16.4738 9.40238 15.5361 8.4647C14.5984 7.52701 13.3267 7.00123 12.0006 7.00123ZM12.0006 9.00123C12.3991 8.99389 12.7951 9.06603 13.1654 9.21344C13.5357 9.36085 13.8729 9.58057 14.1574 9.85978C14.4418 10.139 14.6678 10.4721 14.822 10.8396C14.9763 11.2071 15.0558 11.6016 15.0558 12.0002C15.0559 12.3988 14.9766 12.7934 14.8224 13.1609C14.6683 13.5285 14.4424 13.8617 14.1581 14.141C13.8737 14.4203 13.5366 14.6401 13.1663 14.7876C12.796 14.9352 12.4001 15.0074 12.0016 15.0002C11.2059 15.0002 10.4429 14.6842 9.88026 14.1216C9.31765 13.5589 9.00158 12.7959 9.00158 12.0002C9.00158 11.2046 9.31765 10.4415 9.88026 9.87891C10.4429 9.3163 11.2059 9.00023 12.0016 9.00023L12.0006 9.00123ZM17.2506 5.50123C16.928 5.51414 16.6229 5.65138 16.3992 5.8842C16.1755 6.11702 16.0506 6.42736 16.0506 6.75023C16.0506 7.0731 16.1755 7.38344 16.3992 7.61626C16.6229 7.84908 16.928 7.98632 17.2506 7.99923C17.5821 7.99923 17.9 7.86753 18.1345 7.63311C18.3689 7.39869 18.5006 7.08075 18.5006 6.74923C18.5006 6.41771 18.3689 6.09977 18.1345 5.86535C17.9 5.63093 17.5821 5.49923 17.2506 5.49923V5.50123Z" fill="black"/> - </svg> - , + svgPath: <InstagramSvg />, }, ], 'Співпрацюємо з': '' }; - const hasSocialLinks = companyContacts['Соціальні мережі'].some(socialLink => socialLink.url !== null); + 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']; @@ -69,24 +64,28 @@ function DataContacts ({ isAuthorized, data }) { const renderedContactSections = Object.entries(companyContacts).map(([key, value]) => { if (value) { - if (key === 'Соціальні мережі' && hasSocialLinks) { + if (key === 'Соціальні мережі') { return ( - <div key={key} className={classes['data-block__field--social-networks']}> + hasSocialLinks ? + (<div key={key} className={classes['data-block__field--social-networks']}> <p className={classes['data-block__field--title']}>{key}</p> - {companyContacts['Соціальні мережі'].map((socialLink, index) => { - if (socialLink.url) { + {value.map((contact, index) => { + if (contact.url) { return ( - <a key={index} href={socialLink.url}> - {socialLink.svgPath} + <a key={index} href={contact.url}> + {contact.svgPath} </a> ); } return null; })} - </div> + </div>) : null ); } else if (key === 'PhoneEmail') { - return value; + return ( + <React.Fragment key={key}> + {value } + </React.Fragment>); } 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']; @@ -122,3 +121,13 @@ function DataContacts ({ isAuthorized, data }) { } export default DataContacts; + +DataContacts.propTypes = { + isAuthorized: PropTypes.bool, + data: PropTypes.shape({ + id: PropTypes.number.isRequired, + edrpou: PropTypes.number, + founded: PropTypes.number, + address: PropTypes.string, + }), +}; From 2fb8c4c385ead14cc5ef700d89e860be504b4b48 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Fri, 27 Oct 2023 20:09:09 +0200 Subject: [PATCH 26/51] detailed info component upd, renamed --- .../{DetailedInfo.jsx => DetailedInfoSection.jsx} | 6 +++--- ...tailedInfo.module.css => DetailedInfoSection.module.css} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename FrontEnd/src/components/ProfileDetail/DetailedInfo/{DetailedInfo.jsx => DetailedInfoSection.jsx} (69%) rename FrontEnd/src/components/ProfileDetail/DetailedInfo/{DetailedInfo.module.css => DetailedInfoSection.module.css} (100%) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfoSection.jsx similarity index 69% rename from FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.jsx rename to FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfoSection.jsx index 9c9e4e27e..1a956f1fc 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfoSection.jsx @@ -1,8 +1,8 @@ -import classes from './DetailedInfo.module.css'; +import classes from './DetailedInfoSection.module.css'; import CompanyDescription from './CompanyDescription'; import DataContacts from './DataContacts'; -function DetailedInfo ({ isAuthorized, data }) { +function DetailedInfoSection ({ isAuthorized, data }) { return ( <div className={classes['detail-info-page']}> <CompanyDescription isAuthorized={isAuthorized} data={data} /> @@ -11,4 +11,4 @@ function DetailedInfo ({ isAuthorized, data }) { ); } -export default DetailedInfo; +export default DetailedInfoSection; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfoSection.module.css similarity index 100% rename from FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfo.module.css rename to FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfoSection.module.css From 9633657592824a9998a87117fd7e1845b98140ff Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Fri, 27 Oct 2023 20:10:16 +0200 Subject: [PATCH 27/51] some components updated --- .../ProfileDetail/DetailedInfo/Company.jsx | 15 +++++++++++---- .../ProfileDetail/DetailedInfo/Cooperation.jsx | 4 ++-- .../ProfileDetail/DetailedInfo/Logistics.jsx | 4 ++-- .../DetailedInfo/ProductsServices.jsx | 10 +++++----- .../ProfileDetail/DetailedInfo/Startup.jsx | 4 ++-- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx index 32031fc18..d2c406cc3 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx @@ -1,4 +1,5 @@ import { useMemo } from 'react'; +import { PropTypes } from 'prop-types'; import classes from './Company.module.css'; import ReadMore from './ReadMore'; @@ -26,20 +27,20 @@ function Company ({ data }) { </div> <div className={classes['about-company__content']}> {profile.common_info ? ( - <p className={classes['about-company__content--common']}> + <div className={classes['about-company__content--common']}> <ReadMore > {profile.common_info} </ReadMore> - </p> + </div> ) : null} {competitiveEdge ? ( <div className={classes['about-company__content--advantage']}> <p className={classes['about-company__content--advantage--title']}>Конкурентна перевага</p> - <p className={classes['about-company__content--advantage--description']}> + <div className={classes['about-company__content--advantage--description']}> <ReadMore> {competitiveEdge} </ReadMore> - </p> + </div> </div> ) : null} {slogan ? ( @@ -55,3 +56,9 @@ function Company ({ data }) { } export default Company; + +Company.propTypes = { + data: PropTypes.shape({ + common_info: PropTypes.string, + }), + }; diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.jsx index d58d4dde2..d5c0e695e 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Cooperation.jsx @@ -17,11 +17,11 @@ function Cooperation () { <div className={classes['cooperation__title--divider']}></div> </div> <div className={classes['cooperation__content--block']}> - <p className={classes['cooperation__content--description']}> + <div className={classes['cooperation__content--description']}> <ReadMore> {cooperationData} </ReadMore> - </p> + </div> </div> </div> </div> diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.jsx index ac5204926..f306ce8c5 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Logistics.jsx @@ -17,11 +17,11 @@ function Logistics () { <div className={classes['logistics__title--divider']}></div> </div> <div className={classes['logistics__content--block']}> - <p className={classes['logistics__content--description']}> + <div className={classes['logistics__content--description']}> <ReadMore> {logisticsData} </ReadMore> - </p> + </div> </div> </div> </div> diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.jsx index b7fb2d2e8..54137411c 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/ProductsServices.jsx @@ -24,20 +24,20 @@ function ProductsServices ({ data }) { {profile.products && <div className={classes['products-services__content--block']}> <p className={classes['products-services__content--title']}>Товари</p> - <p className={classes['products-services__content--description']}> + <div className={classes['products-services__content--description']}> <ReadMore> {profile.products} </ReadMore> - </p> + </div> </div>} {profile.services && <div className={classes['products-services__content--block']}> <p className={classes['products-services__content--title']}>Послуги</p> - <p className={classes['products-services__content--description']}> + <div className={classes['products-services__content--description']}> <ReadMore> {profile.services} </ReadMore> - </p> + </div> </div>} </div> </div> @@ -47,7 +47,7 @@ function ProductsServices ({ data }) { export default ProductsServices; -ProductsServices.PropTypes = { +ProductsServices.propTypes = { data: PropTypes.shape({ product_info: PropTypes.string, service_info: PropTypes.string, diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.jsx index 1fbda7413..3cd3d367f 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Startup.jsx @@ -27,9 +27,9 @@ function Startup ({ data }) { return ( <div key={key} className={classes['startup__content--block']}> <p className={classes['startup__content--title']}>{key}</p> - <p className={classes['startup__content--description']}> + <div className={classes['startup__content--description']}> <ReadMore>{value}</ReadMore> - </p> + </div> </div> ); } From ec07b06f0b3b1b97e2e090c87650ea1bf17a537e Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Fri, 27 Oct 2023 20:10:54 +0200 Subject: [PATCH 28/51] profile detail page upd --- .../ProfileDetail/ProfileDetailPage.jsx | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.jsx b/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.jsx index aa768bc17..c7551c9c1 100644 --- a/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.jsx +++ b/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.jsx @@ -4,8 +4,9 @@ import { PropTypes } from 'prop-types'; import Loader from '../loader/Loader'; import ErrorPage404 from '../errorPages/ErrorPage404'; -import MainInfo from './MainInfo/MainInfo'; -import DetailedInfo from './DetailedInfo/DetailedInfo'; +import EmptyData from './EmptyData'; +import MainInfoSection from './MainInfo/MainInfoSection'; +import DetailedInfoSection from './DetailedInfo/DetailedInfoSection'; import BannerImage from './BannerImage'; import classes from './ProfileDetailPage.module.css'; @@ -34,6 +35,8 @@ function ProfileDetailPage({ isAuthorized }) { } = useSWR(urlProfile, fetcher); console.log('DATA', fetchedProfile); + const notRequiredData = ['address', 'banner_image', 'common_info', 'edrpou', 'founded', 'official_name', 'phone', 'product_info', 'service_info', 'startup_idea']; + const containsNotRequiredData = fetchedProfile ? Object.keys(fetchedProfile).some(key => notRequiredData.includes(key) && fetchedProfile[key] !== null) : false; return error ? ( <ErrorPage404 /> @@ -43,13 +46,16 @@ function ProfileDetailPage({ isAuthorized }) { ) : ( <> <BannerImage data={fetchedProfile}/> <div className={classes['profile-page']}> - <MainInfo + <MainInfoSection + containsNotRequiredData={containsNotRequiredData} isAuthorized={isAuthorized} data={fetchedProfile} /> - <DetailedInfo - isAuthorized={isAuthorized} - data={fetchedProfile}/> + {containsNotRequiredData ? ( + <DetailedInfoSection + isAuthorized={isAuthorized} + data={fetchedProfile}/> + ) : <EmptyData /> } </div> </> ) From 6edd775bf9eb0a436ec6caff04832956298bf8c9 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Fri, 27 Oct 2023 20:12:44 +0200 Subject: [PATCH 29/51] styles fixed --- FrontEnd/src/App.css | 7 +++--- .../HeaderFooter/footer/Footer.module.css | 2 +- .../src/components/landing-page/MainPage.jsx | 4 ++-- .../landing-page/MainPage.module.css | 24 +++++++++---------- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/FrontEnd/src/App.css b/FrontEnd/src/App.css index 000afd8a0..ec7e5326f 100644 --- a/FrontEnd/src/App.css +++ b/FrontEnd/src/App.css @@ -1,8 +1,8 @@ .App { /*for footer correct work*/ - /* min-height: 100vh; + min-height: 100vh; flex-direction: column; - display: flex; */ + display: flex; } .App-logo { @@ -35,7 +35,8 @@ from { transform: rotate(0deg); } + to { transform: rotate(360deg); } -} +} \ No newline at end of file diff --git a/FrontEnd/src/components/HeaderFooter/footer/Footer.module.css b/FrontEnd/src/components/HeaderFooter/footer/Footer.module.css index 7928c06b7..94008bb93 100644 --- a/FrontEnd/src/components/HeaderFooter/footer/Footer.module.css +++ b/FrontEnd/src/components/HeaderFooter/footer/Footer.module.css @@ -1,3 +1,3 @@ -.footer-сontent { +.footer-content { margin-top: auto; } \ No newline at end of file diff --git a/FrontEnd/src/components/landing-page/MainPage.jsx b/FrontEnd/src/components/landing-page/MainPage.jsx index 3a48cba69..0b27e87b9 100644 --- a/FrontEnd/src/components/landing-page/MainPage.jsx +++ b/FrontEnd/src/components/landing-page/MainPage.jsx @@ -10,8 +10,8 @@ import css from './MainPage.module.css'; const MainPage = () => { const [modalActive, setModalActive] = useState(true); return ( - <div className="main-app"> - <div className="main-app-header"> + <div className={css['main-app']}> + <div className={css['main-app-header']}> <MainBanner /> <div className={css['main-app-body']}> <MainPartners /> diff --git a/FrontEnd/src/components/landing-page/MainPage.module.css b/FrontEnd/src/components/landing-page/MainPage.module.css index 4024f1a0e..17c8fe84f 100644 --- a/FrontEnd/src/components/landing-page/MainPage.module.css +++ b/FrontEnd/src/components/landing-page/MainPage.module.css @@ -1,13 +1,13 @@ .main-app { - width: 1512px; - border-radius: 8px; - background: #FFF; - margin-left: auto; - margin-right: auto; - } - .main-app-body { - display: flex; - flex-direction: column; - align-items: center; - } - \ No newline at end of file + width: 1512px; + border-radius: 8px; + background: #FFF; + margin-left: auto; + margin-right: auto; +} + +.main-app-body { + display: flex; + flex-direction: column; + align-items: center; +} \ No newline at end of file From 337eda31a706b2a78d46fbdd7c82083f5e8dca79 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Mon, 30 Oct 2023 20:29:51 +0100 Subject: [PATCH 30/51] previous implementation of page removed --- .../ProfileMenu/ProfileInfo/ProfileInfo.jsx | 70 ------ .../ProfileInfo/ProfileInfo.module.css | 120 ---------- .../ProfileView/ProfileMenu/ProfileMenu.jsx | 24 -- .../ProfileMenu/ProfileMenu.module.css | 11 - .../ProfileMenuAbout/ProfileMenuAbout.jsx | 44 ---- .../ProfileMenuAbout.module.css | 104 --------- .../ProfileMenuCooperation.jsx | 24 -- .../ProfileMenuCooperation.module.css | 54 ----- .../ProfileMenuLogistics.jsx | 24 -- .../ProfileMenuLogistics.module.css | 54 ----- .../ProfileMenuServices.jsx | 33 --- .../ProfileMenuServices.module.css | 71 ------ .../ProfileMenuStartup/ProfileMenuStartup.jsx | 79 ------- .../ProfileMenuStartup.module.css | 87 ------- .../ProfileView/ProfileMenu/ProfileText.jsx | 24 -- .../ProfileNavBar/ProfileNavBar.jsx | 61 ----- .../ProfileNavBar/ProfileNavBar.module.css | 49 ---- .../components/ProfileView/ProfileView.jsx | 93 -------- .../ProfileView/ProfileView.module.css | 217 ------------------ 19 files changed, 1243 deletions(-) delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileInfo/ProfileInfo.jsx delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileInfo/ProfileInfo.module.css delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenu.jsx delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenu.module.css delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuAbout/ProfileMenuAbout.jsx delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuAbout/ProfileMenuAbout.module.css delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuCooperation/ProfileMenuCooperation.jsx delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuCooperation/ProfileMenuCooperation.module.css delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuLogistics/ProfileMenuLogistics.jsx delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuLogistics/ProfileMenuLogistics.module.css delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuServices/ProfileMenuServices.jsx delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuServices/ProfileMenuServices.module.css delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuStartup/ProfileMenuStartup.jsx delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuStartup/ProfileMenuStartup.module.css delete mode 100644 FrontEnd/src/components/ProfileView/ProfileMenu/ProfileText.jsx delete mode 100644 FrontEnd/src/components/ProfileView/ProfileNavBar/ProfileNavBar.jsx delete mode 100644 FrontEnd/src/components/ProfileView/ProfileNavBar/ProfileNavBar.module.css delete mode 100644 FrontEnd/src/components/ProfileView/ProfileView.jsx delete mode 100644 FrontEnd/src/components/ProfileView/ProfileView.module.css diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileInfo/ProfileInfo.jsx b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileInfo/ProfileInfo.jsx deleted file mode 100644 index f5e161832..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileInfo/ProfileInfo.jsx +++ /dev/null @@ -1,70 +0,0 @@ -import classes from './ProfileInfo.module.css'; - -const ProfileInfo = ({ dataItems }) => { - - return ( - <div className={classes['profile-info-block']}> - <div className={classes['profile-info-block__main']}> - <div className={classes['profile-info-block__main-content']}> - <div className={classes['profile-info-block__main-content-data']}> - <div className={classes['profile-info-block__main-content-bold-title']}>ЄДРПОУ</div> - <div className={classes['profile-info-block__main-content-text']}>11223344</div> - </div> - <div> - {dataItems.map((item, index) => ( - <div key={index} className={classes['profile-info-block__main-content-data']}> - <div className={classes['profile-info-block__main-content-title']}> - {item.title} - </div> - <div className={classes['profile-info-block__main-content-text']}> - {item.text} - </div> - </div> - ))} - </div> - </div> - <div className={classes['profile-info-block__main-content']}> - <div className={classes['profile-info-block__main-content-data2']}> - <div className={classes['profile-info-block__main-content-title']}>Сайт</div> - <div className={classes['profile-info-block__main-content-url']}>stakhovskywines.com</div> - </div> - <div className={classes['profile-info-block__main-content-data']}> - <div className={classes['profile-info-block__main-content-title']}>Телефон</div> - <div className={classes['profile-info-block__main-content-text']}>201232323236</div> - <div className={classes['profile-info__button']}> - <div className={classes['profile-info__button-text']}>Показати телефон</div> - </div> - </div> - <div className={classes['profile-info-block__main-content-data']}> - <div className={classes['profile-info-block__main-content-title']}>Електронна пошта</div> - <div className={classes['profile-info-block__main-content-text']}>2232323232323</div> - <div className={classes['profile-info__button']}> - <div className={classes['profile-info__button-text']}>Показати ел. пошту</div> - </div> - </div> - <div className={classes['profile-info-block__main-content-data2']}> - <div className={classes['profile-info-block__main-content-title']}>Адрес(и)</div> - <div className={classes['profile-info-block__main-content-text']}> - Офіс: - 90260, Україна, Закарпатська обл., - Берегівський р-н,с. Мужієво, - </div> - </div> - <div className={classes['profile-info-block__main-content-data2']}> - <div className={classes['profile-info-block__main-content-title']}>Соціальні мережі</div> - <div className={classes['profile-info-block__main-content-icons']}> - <img src={`${process.env.PUBLIC_URL}/svg/facebook.svg`} alt="facebook"/> - <img src={`${process.env.PUBLIC_URL}/svg/instagram.svg`} alt="instagram"/> - </div> - </div> - <div className={classes['profile-info-block__main-content-data']}> - <div className={classes['profile-info-block__main-content-title']}>Співпрацюємо з </div> - <div className={classes['profile-info-block__main-content-text']}>Сільпо, Rozetka, Бюро Вин</div> - </div> - </div> - </div> - </div> - ); -}; - -export default ProfileInfo; diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileInfo/ProfileInfo.module.css b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileInfo/ProfileInfo.module.css deleted file mode 100644 index 2f6ee8d03..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileInfo/ProfileInfo.module.css +++ /dev/null @@ -1,120 +0,0 @@ -:root { - --dark-gray: #292E32; - --white: #F8F8F8; - --blue: #4A73E2; - --green: #1F9A7C; - -} - -.profile-info-block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 16px; - position: absolute; - left: 930px; -} -.profile-info-block__main { - display: flex; - padding: 16px; - flex-direction: column; - align-items: flex-start; - gap: 36px; - border-radius: 2px; - border: 1px solid var(--white); - background: var(--white); -} -.profile-info-block__main-content { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 6px; -} -.profile-info-block__main-content-data { - display: flex; - height: 32px; - align-items: center; - gap: 8px; -} -.profile-info-block__main-content-data2 { - display: flex; - align-items: center; - gap: 8px; -} -.profile-info-block__main-content-bold-title { - width: 130px; - color: var(--dark-gray); - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 600; - line-height: 22px; /* 157.143% */ - letter-spacing: -0.14px; -} -.profile-info-block__main-content-title { - width: 130px; - color: var(--dark-gray); - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; /* 157.143% */ - letter-spacing: -0.14px; -} -.profile-info-block__main-content-text { - width: 200px; - color: var(--dark-gray); - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 600; - line-height: 22px; /* 157.143% */ - letter-spacing: -0.14px; -} -.profile-info-block__main-content-url { - width: 200px; - color: var(--blue); - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 600; - line-height: 22px; /* 157.143% */ - letter-spacing: -0.14px; -} - -.profile-info__button { - display: flex; - width: 160px; - /* height: 32px; */ - max-width: 200px; - padding: 5px 15px; - justify-content: center; - align-items: center; - gap: 4px; - border-radius: 4px; - border: 1px solid var(--green); - background: var(--white); - position: absolute; - left: 154px; -} -.profile-info__button-text { - flex: 1 0 0; - color: var(--green); - text-align: center; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; /* 125% */ - letter-spacing: -0.16px; -} -.profile-info-block__main-content-icons { - width: 24px; - height: 24px; - display: flex; -} diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenu.jsx b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenu.jsx deleted file mode 100644 index 57556969b..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenu.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import classes from './ProfileMenu.module.css'; -import ProfileMenuAbout from './ProfileMenuAbout/ProfileMenuAbout'; -import ProfileMenuStartupName from './ProfileMenuStartup/ProfileMenuStartup'; -import ProfileMenuServices from './ProfileMenuServices/ProfileMenuServices'; -import ProfileMenuLogistics from './ProfileMenuLogistics/ProfileMenuLogistics'; -import ProfileMenuCooperation from './ProfileMenuCooperation/ProfileMenuCooperation'; -import ProfileInfo from './ProfileInfo/ProfileInfo'; - -const ProfileMenu = () => { - return ( - <div className={classes['profile-menu-main-block']}> - <div className={classes['profile-menu-main']}> - <ProfileMenuAbout /> - <ProfileMenuStartupName /> - <ProfileMenuServices /> - <ProfileMenuLogistics /> - <ProfileMenuCooperation /> - </div> - <ProfileInfo /> - </div> - ); -}; - -export default ProfileMenu; diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenu.module.css b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenu.module.css deleted file mode 100644 index 5b8c3fcf1..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenu.module.css +++ /dev/null @@ -1,11 +0,0 @@ -.profile-menu-main-block { - display: flex; - align-items: flex-start; - gap: 134px; -} -.profile-menu-main-block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 16px; -} diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuAbout/ProfileMenuAbout.jsx b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuAbout/ProfileMenuAbout.jsx deleted file mode 100644 index 9e231f647..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuAbout/ProfileMenuAbout.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import classes from './ProfileMenuAbout.module.css'; -import { profileInfo } from '../ProfileText.jsx'; - -const ProfileMenuAbout = () => { - return ( - <div id="about-company" className={classes['profile-menu-main__about']}> - <div className={classes['profile-menu-main__about-title']}> - <div className={classes['profile-menu-main__about-title-block']}> - <div className={classes['profile-menu-main__about-title-text']}>ПРО КОМПАНІЮ</div> - </div> - <div className={classes['profile-menu-divider']}/> - </div> - <div className={classes['profile-menu-main__about-content']}> - <div className={classes['profile-menu-main__about-first-text']}> - {profileInfo.sections[0].about1} - <span className={classes['profile-menu-more-text']}> - {profileInfo.more} - </span> - </div> - <div className={classes['profile-menu-main__about-second-text-block']}> - <div className={classes['profile-menu-main__about-second-title']}> - Конкурентна перевага - </div> - <div className={classes['profile-menu-main__about-second-text']}> - {profileInfo.sections[0].about2} - <span className={classes['profile-menu-more-text']}> - {profileInfo.more} - </span> - </div> - </div> - <div className={classes['profile-menu-main__about-second-text-block']}> - <div className={classes['profile-menu-main__about-second-title']}> - Візія, слоган - </div> - <div className={classes['profile-menu-main__about-third-text']}> - {profileInfo.sections[0].about3} - </div> - </div> - </div> - </div> - ); -}; - -export default ProfileMenuAbout; diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuAbout/ProfileMenuAbout.module.css b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuAbout/ProfileMenuAbout.module.css deleted file mode 100644 index 8b1b07816..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuAbout/ProfileMenuAbout.module.css +++ /dev/null @@ -1,104 +0,0 @@ -.profile-menu-main__about { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; - border-radius: 8px; -} -.profile-menu-main__about-title { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - box-shadow: 0 4px 8px 0 rgba(65, 64, 69, 0.10); -} -.profile-menu-main__about-title-block { - display: flex; - padding: 8px 12px; - align-items: flex-start; - gap: 10px; - align-self: stretch; - border-radius: 4px; -} -.profile-menu-main__about-title-text { - width: 742px; - color: #25292C; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 700; - line-height: 20px; /* 125% */ - text-transform: uppercase; -} -.profile-menu-main__about-content { - display: flex; - padding: 12px; - flex-direction: column; - align-items: flex-start; - gap: 24px; -} - -.profile-menu-divider { - align-self: stretch; - height: 1px; - background: #DEE1E8; -} -.profile-menu-main__about-first-text { - width: 776px; - height: 132px; - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; /* 157.143% */ - letter-spacing: -0.14px; -} -.profile-menu-more-text { - color: #1F9A7C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; - letter-spacing: -0.14px; -} -.profile-menu-main__about-second-text-block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; -} -.profile-menu-main__about-second-title { - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; /* 125% */ - letter-spacing: -0.16px; -} -.profile-menu-main__about-second-text { - width: 776px; - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; /* 157.143% */ - letter-spacing: -0.14px; -} -.profile-menu-main__about-third-text { - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; /* 125% */ - letter-spacing: -0.16px; -} diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuCooperation/ProfileMenuCooperation.jsx b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuCooperation/ProfileMenuCooperation.jsx deleted file mode 100644 index 63b0cec8b..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuCooperation/ProfileMenuCooperation.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import classes from './ProfileMenuCooperation.module.css'; -import { profileInfo } from '../ProfileText.jsx'; - -const ProfileMenuCooperation = () => { - return ( - <div id="cooperation" className={classes['profile-menu-cooperation-block']}> - <div className={classes['profile-menu-cooperation']}> - <div className={classes['profile-menu-cooperation__title']}> - <div className={classes['profile-menu-cooperation__title-text']}> - Формат співпраці - </div> - </div> - <div className={classes['profile-cooperation-divider']}/> - </div> - <div className={classes['profile-menu-cooperation__content']}> - <div className={classes['profile-menu-cooperation__content-text']}> - {profileInfo.sections[2].services1} - </div> - </div> - </div> - ); -}; - -export default ProfileMenuCooperation; diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuCooperation/ProfileMenuCooperation.module.css b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuCooperation/ProfileMenuCooperation.module.css deleted file mode 100644 index c9b0585ed..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuCooperation/ProfileMenuCooperation.module.css +++ /dev/null @@ -1,54 +0,0 @@ -.profile-menu-cooperation-block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; - border-radius: 8px; -} -.profile-menu-cooperation { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - box-shadow: 0 4px 8px 0 rgba(65, 64, 69, 0.10); -} -.profile-menu-cooperation__title { - display: flex; - padding: 8px 12px; - align-items: flex-start; - gap: 10px; - align-self: stretch; - border-radius: 4px; -} -.profile-menu-cooperation__title-text { - width: 742px; - color: #25292C; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 700; - line-height: 20px; /* 125% */ - text-transform: uppercase; -} -.profile-cooperation-divider { - align-self: stretch; - height: 1px; - background: #DEE1E8; -} -.profile-menu-cooperation__content { - display: flex; - padding: 12px; - align-items: flex-start; - gap: 10px; -} -.profile-menu-cooperation__content-text { - width: 776px; - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; /* 157.143% */ - letter-spacing: -0.14px; -} diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuLogistics/ProfileMenuLogistics.jsx b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuLogistics/ProfileMenuLogistics.jsx deleted file mode 100644 index 2b9945ae4..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuLogistics/ProfileMenuLogistics.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import classes from './ProfileMenuLogistics.module.css'; -import { profileInfo } from '../ProfileText.jsx'; - -const ProfileMenuLogistics = () => { - return ( - <div id="logistics" className={classes['profile-menu-logistics-block']}> - <div className={classes['profile-menu-logistics']}> - <div className={classes['profile-menu-logistics__title']}> - <div className={classes['profile-menu-logistics__title-text']}> - Логістика товарів / послуг - </div> - </div> - <div className={classes['profile-logistics-divider']}/> - </div> - <div className={classes['profile-menu-logistics__content']}> - <div className={classes['profile-menu-logistics__content-text']}> - {profileInfo.sections[2].services1} - </div> - </div> - </div> - ); -}; - -export default ProfileMenuLogistics; diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuLogistics/ProfileMenuLogistics.module.css b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuLogistics/ProfileMenuLogistics.module.css deleted file mode 100644 index 1427bcc84..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuLogistics/ProfileMenuLogistics.module.css +++ /dev/null @@ -1,54 +0,0 @@ -.profile-menu-logistics-block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; - border-radius: 8px; -} -.profile-menu-logistics { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - box-shadow: 0 4px 8px 0 rgba(65, 64, 69, 0.10); -} -.profile-menu-logistics__title { - display: flex; - padding: 8px 12px; - align-items: flex-start; - gap: 10px; - align-self: stretch; - border-radius: 4px; -} -.profile-menu-logistics__title-text { - width: 742px; - color: #25292C; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 700; - line-height: 20px; /* 125% */ - text-transform: uppercase; -} -.profile-logistics-divider { - align-self: stretch; - height: 1px; - background: #DEE1E8; -} -.profile-menu-logistics__content { - display: flex; - padding: 12px; - align-items: flex-start; - gap: 10px; -} -.profile-menu-logistics__content-text { - width: 776px; - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; /* 157.143% */ - letter-spacing: -0.14px; -} diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuServices/ProfileMenuServices.jsx b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuServices/ProfileMenuServices.jsx deleted file mode 100644 index a38420bc9..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuServices/ProfileMenuServices.jsx +++ /dev/null @@ -1,33 +0,0 @@ -import classes from './ProfileMenuServices.module.css'; -import { profileInfo } from '../ProfileText.jsx'; - -const ProfileMenuServices = () => { - return ( - <div id="goods-services" className={classes['profile-menu-services-block']}> - <div className={classes['profile-menu-services']}> - <div className={classes['profile-menu-services__title']}> - <div className={classes['profile-menu-services__title-text']}> - Товари / послуги - </div> - </div> - <div className={classes['profile-services-divider']}/> - </div> - <div className={classes['profile-menu-services__content-block']}> - <div className={classes['profile-menu-services__content']}> - <div className={classes['profile-menu-services__content-title']}>Товари</div> - <div className={classes['profile-menu-services__content-text']}> - {profileInfo.sections[2].services1} - </div> - </div> - <div className={classes['profile-menu-services__content']}> - <div className={classes['profile-menu-services__content-title']}>Послуги</div> - <div className={classes['profile-menu-services__content-text']}> - {profileInfo.sections[1].startup3} - </div> - </div> - </div> - </div> - ); -}; - -export default ProfileMenuServices; diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuServices/ProfileMenuServices.module.css b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuServices/ProfileMenuServices.module.css deleted file mode 100644 index ef25d3a31..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuServices/ProfileMenuServices.module.css +++ /dev/null @@ -1,71 +0,0 @@ -.profile-menu-services-block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; - border-radius: 8px; -} -.profile-menu-services { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - box-shadow: 0 4px 8px 0 rgba(65, 64, 69, 0.10); -} -.profile-menu-services__title { - display: flex; - padding: 8px 12px; - align-items: flex-start; - gap: 10px; - align-self: stretch; - border-radius: 4px; -} -.profile-menu-services__title-text { - width: 742px; - color: #25292C; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 700; - line-height: 20px; /* 125% */ - text-transform: uppercase; -} -.profile-services-divider { - align-self: stretch; - height: 1px; - background: #DEE1E8; -} -.profile-menu-services__content-block { - display: flex; - padding: 12px; - flex-direction: column; - align-items: flex-start; - gap: 24px; -} -.profile-menu-services__content { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; -} -.profile-menu-services__content-title { - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; /* 125% */ - letter-spacing: -0.16px; -} -.profile-menu-services__content-text { - width: 776px; - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; /* 157.143% */ - letter-spacing: -0.14px; -} diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuStartup/ProfileMenuStartup.jsx b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuStartup/ProfileMenuStartup.jsx deleted file mode 100644 index 7e94a4b9a..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuStartup/ProfileMenuStartup.jsx +++ /dev/null @@ -1,79 +0,0 @@ -import classes from './ProfileMenuStartup.module.css'; -import { profileInfo } from '../ProfileText.jsx'; - -const ProfileMenuStartupName = () => { - return ( - <div id="startup" className={classes['profile-menu-startup-block']}> - <div className={classes['profile-menu-startup-main']}> - <div className={classes['profile-menu-startup-main__title']}> - <div className={classes['profile-menu-startup-main__title']}> - <div className={classes['profile-menu-startup-main__title-block']}> - <div className={classes['profile-menu-startup-main__title-text']}> - Стартап “Назва стартапу” - </div> - </div> - <div className={classes['profile-startup-divider']}/> - </div> - </div> - <div className={classes['profile-menu-startup-main__content']}> - <div className={classes['profile-menu-main__content-block']}> - <div className={classes['profile-menu-main__content-block-title']}>Ідея стартапу</div> - <div className={classes['profile-menu-main__content-block-text']}> - {profileInfo.sections[1].startup1} - </div> - </div> - <div className={classes['profile-menu-main__content-block']}> - <div className={classes['profile-menu-main__content-block-title']}>Розмір інвестиції</div> - <div className={classes['profile-menu-main__content-block-text']}> - {profileInfo.sections[1].startup2} - </div> - </div> - <div className={classes['profile-menu-main__content-block']}> - <div className={classes['profile-menu-main__content-block-title']}>Ціль співпраці</div> - <div className={classes['profile-menu-main__content-block-text']}> - {profileInfo.sections[1].startup3} - </div> - </div> - <div className={classes['profile-menu-main__content-block']}> - <div className={classes['profile-menu-main__content-block-title']}>Кінцевий результат</div> - <div className={classes['profile-menu-main__content-block-text']}> - {profileInfo.sections[1].startup4} - <span className={classes['profile-menu-more-text']}> - {profileInfo.more} - </span> - </div> - </div> - <div className={classes['profile-menu-main__content-block']}> - <div className={classes['profile-menu-main__content-block-title']}>Конкурентна перевага ідеї</div> - <div className={classes['profile-menu-main__content-block-text']}> - {profileInfo.sections[1].startup4} - <span className={classes['profile-menu-more-text']}> - {profileInfo.more} - </span> - </div> - </div> - <div className={classes['profile-menu-main__content-block']}> - <div className={classes['profile-menu-main__content-block-title']}>Ризики</div> - <div className={classes['profile-menu-main__content-block-text']}> - {profileInfo.sections[1].startup4} - <span className={classes['profile-menu-more-text']}> - {profileInfo.more} - </span> - </div> - </div> - <div className={classes['profile-menu-main__content-block']}> - <div className={classes['profile-menu-main__content-block-title']}>Пошук партнерів</div> - <div className={classes['profile-menu-main__content-block-text']}> - {profileInfo.sections[1].startup5} - <span className={classes['profile-menu-more-text']}> - {profileInfo.more} - </span> - </div> - </div> - </div> - </div> - </div> - ); -}; - -export default ProfileMenuStartupName; diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuStartup/ProfileMenuStartup.module.css b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuStartup/ProfileMenuStartup.module.css deleted file mode 100644 index c46cdd678..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileMenuStartup/ProfileMenuStartup.module.css +++ /dev/null @@ -1,87 +0,0 @@ -.profile-menu-startup-block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 24px; - border-radius: 8px; -} -.profile-menu-startup-main { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; -} -.profile-menu-startup-main__title { - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - box-shadow: 0 4px 8px 0 rgba(65, 64, 69, 0.10); -} -.profile-menu-startup-main__title-block { - display: flex; - padding: 8px 12px; - align-items: flex-start; - gap: 10px; - align-self: stretch; - border-radius: 4px; -} -.profile-menu-startup-main__title-text { - width: 742px; - color: #25292C; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 700; - line-height: 20px; /* 125% */ - text-transform: uppercase; -} -.profile-menu-startup-main__content { - display: flex; - padding: 12px; - flex-direction: column; - align-items: flex-start; - gap: 12px; -} -.profile-menu-main__content-block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 12px; -} -.profile-menu-main__content-block-title { - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; /* 125% */ - letter-spacing: -0.16px; -} -.profile-menu-main__content-block-text { - width: 776px; - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; /* 157.143% */ - letter-spacing: -0.14px; -} -.profile-startup-divider { - align-self: stretch; - height: 1px; - background: #DEE1E8; -} -.profile-menu-more-text { - color: #1F9A7C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; - letter-spacing: -0.14px; -} diff --git a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileText.jsx b/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileText.jsx deleted file mode 100644 index b49114ecd..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileMenu/ProfileText.jsx +++ /dev/null @@ -1,24 +0,0 @@ -export const profileInfo = { - more: 'читати далі', - sections: [ - { - about1: '«Ace&W by Stakhovsky» – авторське вино від легенди українського тенісу Сергія Стаховського!\n' + - 'Опанувати виноробство українець вирішив наприкінці 2015 року – після тривалої роботи у Франції. Саме тоді видатний тенісист Сергій Стаховський узяв в оренду 20 гектарів землі на Закарпатті та почав вирощувати мерло, сапераві й трамінер рожевий. Опанувати виноробство українець вирішив наприкінці 2015 року – після тривалої роботи у Франції. Два роки команда Stakhovsky wines культивувала ґрунт, пересаджувала виноград, поливала. І лише у 2018-му новоспечений винороб зібрав свій перший уро... ', - about2: 'Опанувати виноробство українець вирішив наприкінці 2015 року – після тривалої роботи у Франції. Саме тоді видатний тенісист Сергій Стаховський узяв в оренду 20 гектарів землі на Закарпатті та почав вирощувати мерло, сапераві й трамінер рожевий. Опанувати виноробство українець вирішив наприкінці 2015 року – після тривалої роботи у Франції. Два роки команда Stakhovsky wines культивувала ґрунт, пересаджувала виноград, поливала. І лише у 2018-му новоспечений винороб зібравІ лише у 2018-му новоспечений винороб зібрав свій перший урожай...', - about3: '“Good to the Last Drop”' - }, - { - startup1: 'Опанувати виноробство українець вирішив наприкінці 2015 року – після тривалої роботи у Франції. Саме тоді видатний тенісист Сергій Стаховський узяв в оренду 20 гектарів землі на Закарпатті та почав вирощувати мерло, сапераві й трамінер рожевий.', - startup2: '150 000 тисяч (грн)', - startup3: 'Що може бути банальнішим за черговий маркетплейс.\n' + - 'Що може бути банальнішим за черговий маркетплейс.\n' + - 'Що може бути банальнішим за черговий маркетплейс.', - startup4: 'Опанувати виноробство українець вирішив наприкінці 2015 року – після тривалої роботи у Франції. Саме тоді видатний тенісист Сергій Стаховський узяв в оренду 20 гектарів землі на Закарпатті та почав вирощувати мерло, сапераві й трамінер рожевий. Опанувати виноробство українець вирішив наприкінці 2015 року – після тривалої роботи у Франції. Два роки команда Stakhovsky wines культивувала ґрунт, пересаджувала виноград, поливала. І лише у 2018-му новоспечений винороб зібравІ лише у 2018-му новоспечений винороб зібрав свій перший урожай...', - startup5: 'Опанувати виноробство українець вирішив наприкінці 2015 року – після тривалої роботи у Франції. Саме тоді видатний тенісист Сергій Стаховський узяв в оренду 20 гектарів землі на Закарпатті та почав вирощувати мерло, сапераві й трамінер рожевий.', - }, - { - services1: 'Що може бути банальнішим за черговий маркетплейс? Однак, відкриття нового торгового інтернет-майданчика лише на перший погляд здається поганою ідеєю. ', - - } - ] -}; diff --git a/FrontEnd/src/components/ProfileView/ProfileNavBar/ProfileNavBar.jsx b/FrontEnd/src/components/ProfileView/ProfileNavBar/ProfileNavBar.jsx deleted file mode 100644 index 210f6280f..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileNavBar/ProfileNavBar.jsx +++ /dev/null @@ -1,61 +0,0 @@ -import React, { Component } from 'react'; -import classes from './ProfileNavBar.module.css'; - -class ProfileNavBar extends Component { - constructor(props) { - super(props); - this.state = { - activeIndex: 0, - }; - } - - onMenuItemClick(index) { - this.setState({ activeIndex: index }); - - const anchors = ['about-company', 'startup', 'goods-services', 'logistics', 'cooperation']; - const targetAnchorId = anchors[index]; - const targetAnchor = document.getElementById(targetAnchorId); - - if (targetAnchor) { - window.scrollTo({ - top: targetAnchor.offsetTop, - behavior: 'smooth', - }); - } - } - - renderMenuItem(text, index) { - const { activeIndex } = this.state; - const isActive = activeIndex === index; - const menuItemClass = isActive ? classes['active-nav-bar-item'] : classes['inactive-nav-bar-item']; - const dividerClass = isActive ? classes['active-divider'] : classes['inactive-divider']; - - return ( - <div> - <div className={`${classes['profile-view-nav-bar__item']}`} key={index} - onClick={() => this.onMenuItemClick(index)}> - <div className={menuItemClass}>{text}</div> - </div> - <div className={`${classes['divider']} ${dividerClass}`} /> - </div> - ); - } - - render() { - const menuItems = [ - 'Про компанію', - 'Стартап', - 'Товари / послуги', - 'Логістика товарів / послуг', - 'Формат співпраці', - ]; - - return ( - <div className={classes['profile-view-nav-bar']}> - {menuItems.map(this.renderMenuItem)} - </div> - ); - } -} - -export default ProfileNavBar; diff --git a/FrontEnd/src/components/ProfileView/ProfileNavBar/ProfileNavBar.module.css b/FrontEnd/src/components/ProfileView/ProfileNavBar/ProfileNavBar.module.css deleted file mode 100644 index ec1b1b18d..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileNavBar/ProfileNavBar.module.css +++ /dev/null @@ -1,49 +0,0 @@ -.profile-view-nav-bar { - display: flex; - align-items: flex-start; -} - -.profile-view-nav-bar__item { - flex-direction: column; - justify-content: flex-start; - align-items: flex-start; - display: inline-flex; - padding: 8px 12px; - border-radius: 4px; - gap: 10px; -} - -.active-nav-bar-item { - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; /* 125% */ - letter-spacing: -0.16px; -} - -.inactive-nav-bar-item { - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 400; - line-height: 20px; /* 125% */ - letter-spacing: -0.16px; -} - -.divider { - align-self: stretch; - height: 1px; -} - -.active-divider { - background: #1F9A7C; -} - -.inactive-divider { - background: #DEE1E8; -} diff --git a/FrontEnd/src/components/ProfileView/ProfileView.jsx b/FrontEnd/src/components/ProfileView/ProfileView.jsx deleted file mode 100644 index 80d5b45fb..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileView.jsx +++ /dev/null @@ -1,93 +0,0 @@ -import classes from './ProfileView.module.css'; -import { useLocation } from 'react-router-dom'; -import ProfileNavBar from './ProfileNavBar/ProfileNavBar'; -import ProfileMenu from './ProfileMenu/ProfileMenu'; - - -const ProfileView = () => { - const location = useLocation(); - const { data } = location.state; - const { category, name, address, logoSrc, photoSrc } = data; - - const isProfileFilled = true; - return ( - <div> - {photoSrc ? ( - <img - className={classes['profile-view-image']} - src={photoSrc} - alt="filled profile" - /> - ) : ( - <div className={classes['image-placeholder']}> - <div className={classes['image-placeholder__rectangle']}/> - <div className={classes['profile-view-empty-image']}> - <img src={`${process.env.PUBLIC_URL}/svg/profile-view-image-empty.svg`} alt="empty profile"/> - </div> - </div> - )} - <div className={classes['profile-view-title__empty']}> - <div className={classes['profile-view-title-block__empty']}> - <div className={classes['profile-view-title-content__empty']}> - <div className={classes['profile-view__logo']}> - <div className={classes['profile-view__logo-ellipse']}> - <img - className={classes['profile-view__logo-image']} - src={logoSrc} - alt="company logo"/> - </div> - </div> - <div className={classes['profile-view-company-data-block']}> - <div className={classes['profile-view-company-data-block__services']}> - <div className={classes['profile-view-company-data-block__services-text']}>Виробник</div> - </div> - <div className={classes['profile-view-company-data-block__company']}> - <div className={classes['profile-view-company-data-block__company-name']}> - <div className={classes['profile-view-company-data-block__company-name-text']}> - {name} - </div> - </div> - <div className={classes['profile-view-company-data-block__company-badges']}> - <div className={classes['profile-view-company-data-block__company-badges-count']}> - <div className={classes['profile-view-company-data-block__company-badge']}> - <div className={classes['profile-view-company-data-block__badge-text']}> - {category} - </div> - </div> - </div> - </div> - </div> - <div className={classes['profile-view-company-data-block__address']}> - <div className={classes['profile-view-company-data-block__address-text']}> - {address} - </div> - </div> - </div> - <div className={classes['profile-view__like-button']}> - <div className={classes['profile-view__like-button-text']}>Додати в збережені</div> - <div className={classes['profile-view__like-button-icon']}> - <img src={`${process.env.PUBLIC_URL}/svg/star-icon.svg`} alt="like profile"/> - </div> - </div> - </div> - </div> - {isProfileFilled ? ( - <div className={classes['profile-view-title__empty']}> - <div className={classes['profile-view-title-block__empty']}> - <ProfileNavBar /> - </div> - <ProfileMenu /> - </div> - ) : ( - <div className={classes['profile-view-info__empty']}> - <div className={classes['profile-view-info-content__empty']}> - <div className={classes['profile-view-info-text__empty']}>Інформація не заповнена</div> - </div> - </div> - )} - </div> - </div> - ); -}; - -export default ProfileView; diff --git a/FrontEnd/src/components/ProfileView/ProfileView.module.css b/FrontEnd/src/components/ProfileView/ProfileView.module.css deleted file mode 100644 index 4cad0173a..000000000 --- a/FrontEnd/src/components/ProfileView/ProfileView.module.css +++ /dev/null @@ -1,217 +0,0 @@ -.profile-view-image { - width: 1512px; - height: 200px; - flex-shrink: 0; - object-fit: cover; -} -.image-placeholder { - width: 1512px; - height: 200px; - flex-shrink: 0; -} -.image-placeholder__rectangle { - width: 1512px; - height: 200px; - flex-shrink: 0; - background: #DEE1E8; -} -.profile-view-empty-image { - width: 102.588px; - height: 80px; - flex-shrink: 0; - fill: #BFC6CF; - left: 705px; - top: 160px; - position: absolute; -} -.profile-view-title__empty { - left: 50px; - display: inline-flex; - flex-direction: column; - align-items: flex-start; - gap: 16px; - position: relative; -} -.profile-view-title-block__empty { - left: 50px; - position: relative; - display: flex; - flex-direction: column; - align-items: flex-start; -} -.profile-view-title-content__empty { - display: flex; - /*width: 1304px;*/ - padding: 16px 12px 8px 12px; - align-items: flex-start; - gap: 12px; -} - -.profile-view__logo { - width: 40px; - height: 40px; - flex-shrink: 0; -} -.profile-view__logo-ellipse { - width: 40px; - height: 40px; - flex-shrink: 0; - fill: #FFF; -} -.profile-view__logo-image { - width: 33.75px; - height: 33.75px; - flex-shrink: 0; - border-radius: 26px; - background: lightgray 50% / cover no-repeat; -} -.profile-view-company-data-block { - display: flex; - width: 1010px; - flex-direction: column; - align-items: flex-start; - flex-shrink: 0; -} -.profile-view-company-data-block__services { - display: flex; - align-items: center; -} -.profile-view-company-data-block__services-text { - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; /* 157.143% */ - letter-spacing: -0.14px; -} -.profile-view-company-data-block__company { - display: flex; - align-items: center; - gap: 16px; -} -.profile-view-company-data-block__company-name { - display: flex; - align-items: flex-start; - gap: 4px; -} -.profile-view-company-data-block__company-name-text { - color: #25292C; - font-family: Inter, sans-serif; - font-size: 20px; - font-style: normal; - font-weight: 700; - line-height: 120%; /* 24px */ - text-transform: uppercase; -} -.profile-view-company-data-block__company-badges { - display: flex; - align-items: flex-start; - gap: 6px; -} -.profile-view-company-data-block__company-badges-count { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - background: #FFF; -} -.profile-view-company-data-block__company-badge { - display: flex; - padding: 2px 8px; - justify-content: center; - align-items: center; - border-radius: 100px; - background: #1F9A7C; -} -.profile-view-company-data-block__badge-text { - color: #FFF; - text-align: center; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 10px; - font-style: normal; - font-weight: 600; - line-height: 16px; /* 160% */ - text-transform: uppercase; -} - -.profile-view__like-button { - display: flex; - height: 32px; - padding: 5px 15px; - justify-content: center; - align-items: center; - gap: 4px; - border-radius: 4px; - border: 1px solid #1F9A7C; - background: #FFF; -} - -.profile-view__like-button-text { - color: #1F9A7C; - text-align: center; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; /* 125% */ - letter-spacing: -0.16px; -} -.profile-view__like-button-icon { - width: 24px; - height: 24px; -} - -.profile-view-info__empty { - display: flex; - align-items: flex-start; - gap: 134px; -} -.profile-view-info-content__empty { - display: flex; - padding: 12px; - flex-direction: column; - align-items: flex-start; - gap: 24px; -} -.profile-view-info-text__empty { - width: 776px; - color: #A3AAB0; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 22px; /* 157.143% */ - letter-spacing: -0.14px; -} - -.profile-view-nav-bar { - display: flex; - align-items: flex-start; -} -.profile-view-nav-bar__item { - display: flex; - flex-direction: column; - align-items: flex-start; -} -.profile-view-nav-bar__item-content { - display: flex; - padding: 8px 12px; - align-items: flex-start; - gap: 10px; - border-radius: 4px; -} -.profile-view-nav-bar__item-text { - color: #25292C; - font-feature-settings: 'calt' off; - font-family: Inter, sans-serif; - font-size: 16px; - font-style: normal; - font-weight: 600; - line-height: 20px; /* 125% */ - letter-spacing: -0.16px; -} From 89e2cfa21716b6aec8313292c43888c34d55982f Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 2 Nov 2023 12:23:42 +0100 Subject: [PATCH 31/51] navbar component updated --- .../MainInfo/ProfileDetailNavBar.jsx | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx index 82eb3f877..2f8c2b575 100644 --- a/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx @@ -1,46 +1,46 @@ import { HashLink } from 'react-router-hash-link'; +import { useLocation } from 'react-router-dom'; import classes from './ProfileDetailNavBar.module.css'; -function ProfileDetailNavBar() { - const menuItems = [ - 'Про компанію', - 'Стартап', - 'Товари / послуги', - 'Логістика товарів / послуг', - 'Формат співпраці', - ]; - const menuLinks = [ - 'about-company', - 'startup', - 'products-services', - 'logistics', - 'cooperation', - ]; +const MENU_LINKS = { + 'about-company': 'Про компанію', + 'startup': 'Стартап', + 'products-services': 'Товари / послуги', + 'logistics': 'Логістика товарів / послуг', + 'cooperation': 'Формат співпраці', +}; - const activeHash = window.location.hash.substring(1); +function ProfileDetailNavBar() { - const handleItemClick = (link) => { - window.location.hash = link; - }; + const { hash } = useLocation (); + console.log('HASH', hash); - return ( + return ( <div className={classes['navbar-menu']}> - {menuItems.map((item, index) => ( - <div key={index} className={classes['navbar-menu__block']}> - <div - onClick={() => handleItemClick(menuLinks[index])} - className={classes['navbar-menu__item']}> + {Object.entries(MENU_LINKS).map(([link, label]) => ( + <div key={link} className={classes['navbar-menu__block']}> + <div className={classes['navbar-menu__item']}> <HashLink smooth - to={`#${menuLinks[index]}`} - className={menuLinks[index] === activeHash ? `${classes['active-link']}` : `${classes['inactive-link']}`} + to={`#${link}`} + className={ + `#${link}` === hash + ? `${classes['active-link']}` + : `${classes['inactive-link']}` + } > - {item} + {label} </HashLink> </div> - <div className={menuLinks[index] === activeHash ? `${classes['active-devider']}` : `${classes['inactive-devider']}`}/> - </div> - ))} + <div + className={ + `#${link}` === hash + ? `${classes['active-devider']}` + : `${classes['inactive-devider']}` + } + /> + </div> + ))} </div> ); } From 9b1702e5af98f7a6fd0b818cbd715d4c1d5f0c05 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 2 Nov 2023 12:37:57 +0100 Subject: [PATCH 32/51] banner image component updated --- .../components/ProfileDetail/BannerImage.jsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/BannerImage.jsx b/FrontEnd/src/components/ProfileDetail/BannerImage.jsx index e1c252479..50e5be6f4 100644 --- a/FrontEnd/src/components/ProfileDetail/BannerImage.jsx +++ b/FrontEnd/src/components/ProfileDetail/BannerImage.jsx @@ -1,18 +1,13 @@ -import { useMemo } from 'react'; +import { PropTypes } from 'prop-types'; import classes from './BannerImage.module.css'; function BannerImage ({ data }) { - const profile = useMemo(() => { - return { - banner: data.banner_image, - }; - }, [data]); return ( <div className={classes['banner-image__block']}> <div className={classes['banner-image']}> - {profile.banner ? ( - <img src={profile.banner} alt="Company Banner" /> + {data.banner_image ? ( + <img src={data.banner_image} alt="Company Banner" /> ) : ( <svg xmlns="http://www.w3.org/2000/svg" @@ -30,3 +25,9 @@ function BannerImage ({ data }) { } export default BannerImage; + +BannerImage.PropTypes = { + data: PropTypes.shape({ + banner_image: PropTypes.string, + }), +}; From 37ad40e768f8d4db94387f4f3643c6bd2beec528 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 2 Nov 2023 12:56:32 +0100 Subject: [PATCH 33/51] company component updated --- .../ProfileDetail/DetailedInfo/Company.jsx | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx index d2c406cc3..4ce5e07c8 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/Company.jsx @@ -1,20 +1,14 @@ -import { useMemo } from 'react'; import { PropTypes } from 'prop-types'; import classes from './Company.module.css'; import ReadMore from './ReadMore'; function Company ({ data }) { - const profile = useMemo(() => { - return { - common_info: data.common_info, - }; - }, [data]); // TODO: implement logic for getting data from db when it's added on server side const competitiveEdge = ''; const slogan = ''; - const companyData = profile.common_info || competitiveEdge || slogan; + const companyData = data.common_info || competitiveEdge || slogan; return ( companyData ? ( @@ -26,10 +20,10 @@ function Company ({ data }) { <div className={classes['about-company__title--divider']}></div> </div> <div className={classes['about-company__content']}> - {profile.common_info ? ( + {data.common_info ? ( <div className={classes['about-company__content--common']}> <ReadMore > - {profile.common_info} + {data.common_info} </ReadMore> </div> ) : null} From 35f0d46516d72535a9c3f7971c7c9072d5a17d80 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 2 Nov 2023 13:00:42 +0100 Subject: [PATCH 34/51] prop-types added to company description --- .../ProfileDetail/DetailedInfo/CompanyDescription.jsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx index 7722324e1..4954484f9 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx @@ -1,3 +1,4 @@ +import { PropTypes } from 'prop-types'; import classes from './CompanyDescription.module.css'; import Company from './Company'; import Startup from './Startup'; @@ -18,3 +19,12 @@ function CompanyDescription ({ data }) { } export default CompanyDescription; + +CompanyDescription.PropTypes = { + data: PropTypes.shape({ + common_info: PropTypes.string, + startup_idea: PropTypes.string, + product_info: PropTypes.string, + service_info: PropTypes.string, + }), +}; From 3dfb7249fc5e1735a5172f12a3a3412a87763dd8 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 2 Nov 2023 13:07:43 +0100 Subject: [PATCH 35/51] useMemo removed from data contacts --- .../ProfileDetail/DetailedInfo/DataContacts.jsx | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx index 57cbafa82..136581c43 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React from 'react'; import { PropTypes } from 'prop-types'; import PhoneEmail from './PhoneEmail'; import { ReactComponent as FacebookSvg } from './SvgFiles/facebook.svg'; @@ -6,20 +6,12 @@ import { ReactComponent as InstagramSvg } from './SvgFiles/instagram.svg'; import classes from './DataContacts.module.css'; function DataContacts ({ isAuthorized, data }) { - const profile = useMemo(() => { - return { - id: data.id, - edrpou: data.edrpou, - founded: data.founded, - address: data.address, - }; - }, [data]); // TODO: implement logic for getting data from db when it's added on server side const companyData = { - 'ЄДРПОУ': profile.edrpou, - 'Рік заснування': profile.founded, + 'ЄДРПОУ': data.edrpou, + 'Рік заснування': data.founded, 'Розмір компанії': '', 'Аудит': '' }; @@ -27,7 +19,7 @@ function DataContacts ({ isAuthorized, data }) { const companyContacts = { 'Сайт': '', 'PhoneEmail': <PhoneEmail isAuthorized={isAuthorized} profileId={data.id}/>, - 'Адрес(и)': profile.address, + 'Адрес(и)': data.address, 'Соціальні мережі': [ { name: 'facebook', From f2d69fdbc2a2d621d7190eedbe3690b742ea9ecc Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 2 Nov 2023 13:09:59 +0100 Subject: [PATCH 36/51] console.log removed --- .../components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx index 2f8c2b575..ae4b789a0 100644 --- a/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/ProfileDetailNavBar.jsx @@ -13,7 +13,6 @@ const MENU_LINKS = { function ProfileDetailNavBar() { const { hash } = useLocation (); - console.log('HASH', hash); return ( <div className={classes['navbar-menu']}> From 41fb12b8cbf7a69e0eb123662cbffee4f90dcb02 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 2 Nov 2023 14:33:23 +0100 Subject: [PATCH 37/51] format code in main info section --- .../ProfileDetail/MainInfo/MainInfoSection.jsx | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.jsx index 7e6b39194..b2e8ec012 100644 --- a/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.jsx +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.jsx @@ -3,17 +3,13 @@ import TitleInfo from './TitleInfo'; import ProfileDetailNavBar from './ProfileDetailNavBar'; import classes from './MainInfoSection.module.css'; -function MainInfoSection ({ isAuthorized, data, containsNotRequiredData }) { - - return ( - <div className={classes['basic-info-content']}> - <TitleInfo isAuthorized={isAuthorized} data={data}/> - {containsNotRequiredData ? ( - <ProfileDetailNavBar /> - ) : null} - </div> - -); +function MainInfoSection({ isAuthorized, data, containsNotRequiredData }) { + return ( + <div className={classes['basic-info-content']}> + <TitleInfo isAuthorized={isAuthorized} data={data} /> + {containsNotRequiredData ? <ProfileDetailNavBar /> : null} + </div> + ); } export default MainInfoSection; From 5c6b452b7a8a2824b68273e3dc8b22abeb58bf7b Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 2 Nov 2023 20:05:26 +0100 Subject: [PATCH 38/51] misspelling fixed --- FrontEnd/src/components/ProfileDetail/BannerImage.jsx | 2 +- .../ProfileDetail/DetailedInfo/CompanyDescription.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/BannerImage.jsx b/FrontEnd/src/components/ProfileDetail/BannerImage.jsx index 50e5be6f4..562143cfd 100644 --- a/FrontEnd/src/components/ProfileDetail/BannerImage.jsx +++ b/FrontEnd/src/components/ProfileDetail/BannerImage.jsx @@ -26,7 +26,7 @@ function BannerImage ({ data }) { export default BannerImage; -BannerImage.PropTypes = { +BannerImage.propTypes = { data: PropTypes.shape({ banner_image: PropTypes.string, }), diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx index 4954484f9..bb934fe83 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.jsx @@ -20,7 +20,7 @@ function CompanyDescription ({ data }) { export default CompanyDescription; -CompanyDescription.PropTypes = { +CompanyDescription.propTypes = { data: PropTypes.shape({ common_info: PropTypes.string, startup_idea: PropTypes.string, From 7d6e58937d459c5e95b0eb40c1febb8c88cc30d0 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Fri, 3 Nov 2023 17:12:58 +0100 Subject: [PATCH 39/51] svg files import upd --- .../ProfileDetail/DetailedInfo/DataContacts.jsx | 10 ++++------ .../ProfileDetail/DetailedInfo/SvgFiles/facebook.svg | 3 --- .../ProfileDetail/DetailedInfo/SvgFiles/instagram.svg | 3 --- 3 files changed, 4 insertions(+), 12 deletions(-) delete mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/facebook.svg delete mode 100644 FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/instagram.svg diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx index 136581c43..6ddccb8bd 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx @@ -1,8 +1,6 @@ import React from 'react'; import { PropTypes } from 'prop-types'; import PhoneEmail from './PhoneEmail'; -import { ReactComponent as FacebookSvg } from './SvgFiles/facebook.svg'; -import { ReactComponent as InstagramSvg } from './SvgFiles/instagram.svg'; import classes from './DataContacts.module.css'; function DataContacts ({ isAuthorized, data }) { @@ -23,13 +21,13 @@ function DataContacts ({ isAuthorized, data }) { 'Соціальні мережі': [ { name: 'facebook', - url: '', - svgPath: <FacebookSvg />, + url: 's', + svgPath: <img src={`${process.env.PUBLIC_URL}/svg/facebook.svg`} />, }, { name: 'instagram', - url: '', - svgPath: <InstagramSvg />, + url: 'a', + svgPath: <img src={`${process.env.PUBLIC_URL}/svg/instagram.svg`} />, }, ], 'Співпрацюємо з': '' diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/facebook.svg b/FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/facebook.svg deleted file mode 100644 index d264339f3..000000000 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/facebook.svg +++ /dev/null @@ -1,3 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> - <path d="M14 13.5H16.5L17.5 9.5H14V7.5C14 6.47 14 5.5 16 5.5H17.5V2.14C17.174 2.097 15.943 2 14.643 2C11.928 2 10 3.657 10 6.7V9.5H7V13.5H10V22H14V13.5Z" fill="black"/> -</svg> \ No newline at end of file diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/instagram.svg b/FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/instagram.svg deleted file mode 100644 index 7671d15b7..000000000 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/SvgFiles/instagram.svg +++ /dev/null @@ -1,3 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> - <path d="M13.0286 2.00123C13.7583 1.99843 14.488 2.00576 15.2176 2.02323L15.4116 2.03023C15.6356 2.03823 15.8566 2.04823 16.1236 2.06023C17.1876 2.11023 17.9136 2.27823 18.5506 2.52523C19.2106 2.77923 19.7666 3.12323 20.3226 3.67923C20.831 4.17884 21.2244 4.78318 21.4756 5.45023C21.7226 6.08723 21.8906 6.81423 21.9406 7.87823C21.9526 8.14423 21.9626 8.36623 21.9706 8.59023L21.9766 8.78423C21.9943 9.51342 22.002 10.2428 21.9996 10.9722L22.0006 11.7182V13.0282C22.003 13.758 21.9954 14.4877 21.9776 15.2172L21.9716 15.4112C21.9636 15.6352 21.9536 15.8562 21.9416 16.1232C21.8916 17.1872 21.7216 17.9132 21.4756 18.5502C21.2252 19.218 20.8317 19.8228 20.3226 20.3222C19.8225 20.8306 19.2179 21.224 18.5506 21.4752C17.9136 21.7222 17.1876 21.8902 16.1236 21.9402C15.8566 21.9522 15.6356 21.9622 15.4116 21.9702L15.2176 21.9762C14.4881 21.994 13.7583 22.0017 13.0286 21.9992L12.2826 22.0002H10.9736C10.2438 22.0027 9.5141 21.995 8.78458 21.9772L8.59058 21.9712C8.35319 21.9626 8.11585 21.9526 7.87858 21.9412C6.81458 21.8912 6.08858 21.7212 5.45058 21.4752C4.78326 21.2246 4.17881 20.8311 3.67958 20.3222C3.17062 19.8225 2.7768 19.2178 2.52558 18.5502C2.27858 17.9132 2.11058 17.1872 2.06058 16.1232C2.04944 15.8859 2.03944 15.6486 2.03058 15.4112L2.02558 15.2172C2.00714 14.4877 1.99881 13.758 2.00058 13.0282V10.9722C1.99779 10.2428 2.00512 9.51343 2.02258 8.78423L2.02958 8.59023C2.03758 8.36623 2.04758 8.14423 2.05958 7.87823C2.10958 6.81323 2.27758 6.08823 2.52458 5.45023C2.77595 4.78285 3.17054 4.17868 3.68058 3.68023C4.17947 3.17098 4.78354 2.7768 5.45058 2.52523C6.08858 2.27823 6.81358 2.11023 7.87858 2.06023L8.59058 2.03023L8.78458 2.02523C9.51376 2.0068 10.2432 1.99847 10.9726 2.00023L13.0286 2.00123ZM12.0006 7.00123C11.3381 6.99186 10.6803 7.11425 10.0656 7.3613C9.45077 7.60834 8.89122 7.97511 8.41942 8.44029C7.94762 8.90546 7.57298 9.45977 7.31726 10.071C7.06155 10.6822 6.92987 11.3382 6.92987 12.0007C6.92987 12.6633 7.06155 13.3192 7.31726 13.9305C7.57298 14.5417 7.94762 15.096 8.41942 15.5612C8.89122 16.0264 9.45077 16.3931 10.0656 16.6402C10.6803 16.8872 11.3381 17.0096 12.0006 17.0002C13.3267 17.0002 14.5984 16.4734 15.5361 15.5358C16.4738 14.5981 17.0006 13.3263 17.0006 12.0002C17.0006 10.6741 16.4738 9.40238 15.5361 8.4647C14.5984 7.52701 13.3267 7.00123 12.0006 7.00123ZM12.0006 9.00123C12.3991 8.99389 12.7951 9.06603 13.1654 9.21344C13.5357 9.36085 13.8729 9.58057 14.1574 9.85978C14.4418 10.139 14.6678 10.4721 14.822 10.8396C14.9763 11.2071 15.0558 11.6016 15.0558 12.0002C15.0559 12.3988 14.9766 12.7934 14.8224 13.1609C14.6683 13.5285 14.4424 13.8617 14.1581 14.141C13.8737 14.4203 13.5366 14.6401 13.1663 14.7876C12.796 14.9352 12.4001 15.0074 12.0016 15.0002C11.2059 15.0002 10.4429 14.6842 9.88026 14.1216C9.31765 13.5589 9.00158 12.7959 9.00158 12.0002C9.00158 11.2046 9.31765 10.4415 9.88026 9.87891C10.4429 9.3163 11.2059 9.00023 12.0016 9.00023L12.0006 9.00123ZM17.2506 5.50123C16.928 5.51414 16.6229 5.65138 16.3992 5.8842C16.1755 6.11702 16.0506 6.42736 16.0506 6.75023C16.0506 7.0731 16.1755 7.38344 16.3992 7.61626C16.6229 7.84908 16.928 7.98632 17.2506 7.99923C17.5821 7.99923 17.9 7.86753 18.1345 7.63311C18.3689 7.39869 18.5006 7.08075 18.5006 6.74923C18.5006 6.41771 18.3689 6.09977 18.1345 5.86535C17.9 5.63093 17.5821 5.49923 17.2506 5.49923V5.50123Z" fill="black"/> -</svg> \ No newline at end of file From e86c01206f3f48d3f364efd0c8419c4903f62801 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Fri, 3 Nov 2023 20:33:12 +0100 Subject: [PATCH 40/51] useUser hook added --- FrontEnd/src/hooks/index.js | 3 ++- FrontEnd/src/hooks/useUser.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 FrontEnd/src/hooks/useUser.js diff --git a/FrontEnd/src/hooks/index.js b/FrontEnd/src/hooks/index.js index 797acf3f8..4a0469168 100644 --- a/FrontEnd/src/hooks/index.js +++ b/FrontEnd/src/hooks/index.js @@ -1,4 +1,5 @@ import useAuth from './useAuth'; import useProvideAuth from './useProvideAuth'; +import useUser from './useUser'; -export { useAuth, useProvideAuth }; \ No newline at end of file +export { useAuth, useProvideAuth, useUser }; diff --git a/FrontEnd/src/hooks/useUser.js b/FrontEnd/src/hooks/useUser.js new file mode 100644 index 000000000..386b6a3b4 --- /dev/null +++ b/FrontEnd/src/hooks/useUser.js @@ -0,0 +1,30 @@ +import { useEffect, useState } from 'react'; +import useSWR from 'swr'; + +export default function useUser() { + const authToken = localStorage.getItem('Token'); + const [user, setUser] = useState(null); + + const { data, error, mutate } = useSWR( + authToken ? `${process.env.REACT_APP_BASE_API_URL}/api/auth/users/me/` : null, + url => + fetch(url, { + method: 'GET', + headers: { + 'Authorization': `Token ${authToken}`, + }, + }).then(res => res.json()), + { revalidateOnFocus: false } + ); + + useEffect(() => { + if (data) { + setUser(data); + } + if (error) { + setUser(null); + } + }, [data, error]); + + return { user, mutate, error }; +} From cd76a8ff6a742781533eb66876a5dcd5caa50e38 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Sat, 4 Nov 2023 11:20:37 +0100 Subject: [PATCH 41/51] title info component upd --- .../ProfileDetail/MainInfo/TitleInfo.jsx | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx index a702adf3b..6ed316e86 100644 --- a/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx @@ -1,14 +1,17 @@ import { useState, useMemo } from 'react'; -import useSWR from 'swr'; +import { toast, ToastContainer } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; import { Badge } from 'antd'; import { StarOutlined, StarFilled } from '@ant-design/icons'; import { PropTypes } from 'prop-types'; import useSWRMutation from 'swr/mutation'; +import { useUser } from '../../../hooks'; import DefaultLogo from './DefaultLogo'; import classes from './TitleInfo.module.css'; function TitleInfo({ isAuthorized, data }) { + const { user } = useUser(); const [isSaved, setIsSaved] = useState(data.is_saved); const profile = useMemo(() => { return { @@ -27,20 +30,6 @@ function TitleInfo({ isAuthorized, data }) { }; }, [data]); - // TODO: change the logic of getting user.id when PR with hooks will be merged - - const authToken = localStorage.getItem('Token'); - const { data: userData } = useSWR( - authToken ? `${process.env.REACT_APP_BASE_API_URL}/api/auth/users/me/` : null, - url => - fetch(url, { - method: 'GET', - headers: { - 'Authorization': `Token ${authToken}`, - }, - }).then(res => res.json()), - ); - async function sendRequest(url, { arg: data }) { const authToken = localStorage.getItem('Token'); return fetch(url, { @@ -50,7 +39,18 @@ function TitleInfo({ isAuthorized, data }) { Authorization: `Token ${authToken}`, }, body: JSON.stringify(data), - }).then(); + }).then((res) => { + if (!res.ok && res.status === 403) { + const error = new Error('Ви не можете додати власну комапнію до списку збережених.'); + error.info = res.json(); + error.status = res.status; + throw error; + } + }) + .catch(error => { + console.error(error); + toast.error(error.message); + }); } const { trigger } = useSWRMutation( @@ -62,7 +62,11 @@ function TitleInfo({ isAuthorized, data }) { try { await trigger( { company_pk: profile.id }, - { optimisticData: () => setIsSaved(!isSaved) } + { optimisticData: () => { + if (user.id !== profile.personId) + {setIsSaved(!isSaved); + }} + } ); } catch (error) { console.error(error); @@ -134,11 +138,11 @@ function TitleInfo({ isAuthorized, data }) { <button onClick={handleClick} type="button" - disabled={userData && userData.id === profile.personId} className={`${classes['title-block__button']} ${isSaved && classes['added_to_saved__button']}`} > <span className={`${classes['title-block__button--text']} ${isSaved && classes['added_to_saved__button--text']}`}>{!isSaved ? 'Додати в збережені' : 'Додано в збережені'}</span> {isAuthorized ? (isSaved ? filledStar : outlinedStar) : null} + <ToastContainer position="top-right" autoClose={3000} /> </button>)} </div> ); From 8c73ecbc49d857b95d3627a0644f10ee9412f479 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Sat, 4 Nov 2023 11:21:41 +0100 Subject: [PATCH 42/51] prop type added --- .../src/components/ProfileDetail/MainInfo/MainInfoSection.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.jsx index b2e8ec012..0f8d7684c 100644 --- a/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.jsx +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/MainInfoSection.jsx @@ -36,5 +36,5 @@ MainInfoSection.propTypes = { common_info: PropTypes.string, is_saved: PropTypes.bool.isRequired, }).isRequired, - containsNotRequiredData: PropTypes.bool, + containsNotRequiredData: PropTypes.bool.isRequired, }; From eac7f2c91fccb1fe066885e6488f445364e77429 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Sat, 4 Nov 2023 11:24:24 +0100 Subject: [PATCH 43/51] empty data component moved --- .../DetailedInfo/DetailedInfoSection.jsx | 19 +++++++++++++++++-- .../ProfileDetail/ProfileDetailPage.jsx | 14 ++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfoSection.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfoSection.jsx index 1a956f1fc..03e18a384 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfoSection.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DetailedInfoSection.jsx @@ -1,14 +1,29 @@ +import { PropTypes } from 'prop-types'; import classes from './DetailedInfoSection.module.css'; import CompanyDescription from './CompanyDescription'; import DataContacts from './DataContacts'; +import EmptyData from '../EmptyData'; -function DetailedInfoSection ({ isAuthorized, data }) { +function DetailedInfoSection ({ isAuthorized, data, containsNotRequiredData }) { return ( <div className={classes['detail-info-page']}> - <CompanyDescription isAuthorized={isAuthorized} data={data} /> + {containsNotRequiredData ? <CompanyDescription isAuthorized={isAuthorized} data={data} /> : <EmptyData /> } <DataContacts isAuthorized={isAuthorized} data={data} /> </div> ); } 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, + }; diff --git a/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.jsx b/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.jsx index c7551c9c1..d931e2f92 100644 --- a/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.jsx +++ b/FrontEnd/src/components/ProfileDetail/ProfileDetailPage.jsx @@ -4,7 +4,6 @@ import { PropTypes } from 'prop-types'; import Loader from '../loader/Loader'; import ErrorPage404 from '../errorPages/ErrorPage404'; -import EmptyData from './EmptyData'; import MainInfoSection from './MainInfo/MainInfoSection'; import DetailedInfoSection from './DetailedInfo/DetailedInfoSection'; import BannerImage from './BannerImage'; @@ -34,8 +33,7 @@ function ProfileDetailPage({ isAuthorized }) { isLoading, } = useSWR(urlProfile, fetcher); - console.log('DATA', fetchedProfile); - const notRequiredData = ['address', 'banner_image', 'common_info', 'edrpou', 'founded', 'official_name', 'phone', 'product_info', 'service_info', 'startup_idea']; + const notRequiredData = ['address', 'banner_image', 'common_info', 'edrpou', 'founded', 'official_name', 'product_info', 'service_info', 'startup_idea']; const containsNotRequiredData = fetchedProfile ? Object.keys(fetchedProfile).some(key => notRequiredData.includes(key) && fetchedProfile[key] !== null) : false; return error ? ( @@ -51,11 +49,11 @@ function ProfileDetailPage({ isAuthorized }) { isAuthorized={isAuthorized} data={fetchedProfile} /> - {containsNotRequiredData ? ( - <DetailedInfoSection - isAuthorized={isAuthorized} - data={fetchedProfile}/> - ) : <EmptyData /> } + <DetailedInfoSection + containsNotRequiredData ={containsNotRequiredData } + isAuthorized={isAuthorized} + data={fetchedProfile} + /> </div> </> ) From 968409fdbba7a7eef86c4a877e5761d10c3b36a4 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Sat, 4 Nov 2023 11:26:01 +0100 Subject: [PATCH 44/51] empty data contacts component upd --- .../ProfileDetail/DetailedInfo/DataContacts.jsx | 9 +++++---- .../ProfileDetail/DetailedInfo/DataContacts.module.css | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx index 6ddccb8bd..068b36285 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx @@ -3,7 +3,7 @@ import { PropTypes } from 'prop-types'; import PhoneEmail from './PhoneEmail'; import classes from './DataContacts.module.css'; -function DataContacts ({ isAuthorized, data }) { +function DataContacts ({ data }) { // TODO: implement logic for getting data from db when it's added on server side @@ -16,17 +16,17 @@ function DataContacts ({ isAuthorized, data }) { const companyContacts = { 'Сайт': '', - 'PhoneEmail': <PhoneEmail isAuthorized={isAuthorized} profileId={data.id}/>, + 'PhoneEmail': <PhoneEmail profileId={data.id} personId={data.person}/>, 'Адрес(и)': data.address, 'Соціальні мережі': [ { name: 'facebook', - url: 's', + url: '', svgPath: <img src={`${process.env.PUBLIC_URL}/svg/facebook.svg`} />, }, { name: 'instagram', - url: 'a', + url: '', svgPath: <img src={`${process.env.PUBLIC_URL}/svg/instagram.svg`} />, }, ], @@ -116,6 +116,7 @@ DataContacts.propTypes = { isAuthorized: PropTypes.bool, data: PropTypes.shape({ id: PropTypes.number.isRequired, + person: PropTypes.number.isRequired, edrpou: PropTypes.number, founded: PropTypes.number, address: PropTypes.string, diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.module.css index 40343dfd4..3d43fe3c3 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.module.css +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.module.css @@ -21,6 +21,7 @@ flex-direction: column; align-items: flex-start; gap: 6px; + min-width: 338px; } .data-block__field { From 6f4d82364b29fb0844a9fa70d0942b2818deedd4 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Sat, 4 Nov 2023 11:26:51 +0100 Subject: [PATCH 45/51] styles fixed --- .../ProfileDetail/DetailedInfo/CompanyDescription.module.css | 1 + 1 file changed, 1 insertion(+) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.module.css b/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.module.css index f24aa4263..533023a58 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.module.css +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/CompanyDescription.module.css @@ -3,4 +3,5 @@ flex-direction: column; align-items: flex-start; gap: 16px; + min-width: 800px; } \ No newline at end of file From d37a8a208337e33d2a974122013860464ab795a6 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Sat, 4 Nov 2023 13:38:32 +0100 Subject: [PATCH 46/51] phone email component upd --- .../ProfileDetail/DetailedInfo/PhoneEmail.jsx | 76 ++++++++++--------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx index ebc564e2b..ddaec9819 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx @@ -1,41 +1,44 @@ import { useState } from 'react'; import useSWR from 'swr'; +import { useUser } from '../../../hooks'; import { PropTypes } from 'prop-types'; import classes from './PhoneEmail.module.css'; -function PhoneEmail ({ isAuthorized, profileId }) { +function PhoneEmail ({ profileId, personId }) { const [isPhoneShown, setPhoneShown] = useState(false); const [isEmailShown, setEmailShown] = useState(false); const authToken = localStorage.getItem('Token'); + const { user } = useUser(); - // TODO: change the logic of getting user.id when PR with hooks will be merged - - const { data: userData } = useSWR( - authToken ? `${process.env.REACT_APP_BASE_API_URL}/api/auth/users/me/` : null, - url => - fetch(url, { - method: 'GET', - headers: { - 'Authorization': `Token ${authToken}`, - }, - }).then(res => res.json()), - ); - - const { data: profileData} = useSWR( - authToken ? `${process.env.REACT_APP_BASE_API_URL}/api/profiles/${profileId}?with_contacts=True` : null, - url => - fetch(url, { - method: 'GET', - headers: { - 'Authorization': `Token ${authToken}`, - }, - }).then(res => res.json()), + const { data: profileData } = useSWR( + `${process.env.REACT_APP_BASE_API_URL}/api/profiles/${profileId}?with_contacts=True`, + (url) => + fetch(url, { + method: 'GET', + headers: { + Authorization: `Token ${authToken}`, + }, + }) + .then((res) => { + if (!res.ok && res.status === 401) { + const error = new Error('Unauthorized user'); + error.info = res.json(); + error.status = res.status; + throw error; + } + return res.json(); + }) + .catch((error) => { + if (error.status === 401) { + console.error(error); + } + }) ); const urlViewed = `${process.env.REACT_APP_BASE_API_URL}/api/viewed-list/`; - const viewedData = userData && {user: userData.id, company: profileId,}; + const viewedData = user && {user: user.id, company: profileId,}; - async function sendRequest(url, data ) { + async function addToViewed(url, data ) { return fetch(url, { method: 'POST', headers: { @@ -49,7 +52,7 @@ function PhoneEmail ({ isAuthorized, profileId }) { const handlePhoneClick = async () => { setPhoneShown(true); try { - await sendRequest( + await addToViewed( urlViewed, viewedData ); @@ -61,7 +64,7 @@ function PhoneEmail ({ isAuthorized, profileId }) { const handleEmailClick = async () => { setEmailShown(true); try { - await sendRequest( + await addToViewed( urlViewed, viewedData ); @@ -71,34 +74,35 @@ function PhoneEmail ({ isAuthorized, profileId }) { }; return ( - profileData ? ( <> + {profileData && profileData.phone ? ( <div className={classes['data-block__field']}> <p className={classes['data-block__field--title']}>Телефон</p> - {isPhoneShown ? + {(isPhoneShown || user && user.id === personId) ? ( <p className={classes['data-block__field--phone']}>{profileData.phone}</p> ) : ( - <button type="button" onClick={handlePhoneClick} disabled={!isAuthorized} className={classes['data-block__field--show--phone']}> + <button type="button" onClick={handlePhoneClick} className={classes['data-block__field--show--phone']}> Показати телефон </button> )} </div> + ) : null } + {profileData && profileData.email ? ( <div className={classes['data-block__field']}> <p className={classes['data-block__field--title']}>Електронна пошта</p> - {isEmailShown ? ( + {(isEmailShown || user && user.id === personId) ? ( <p className={classes['data-block__field--email']}>{profileData.email}</p> ) : ( - <button type="button" onClick={handleEmailClick} disabled={!isAuthorized} className={classes['data-block__field--show--email']}>Показати ел. пошту</button> + <button type="button" onClick={handleEmailClick} className={classes['data-block__field--show--email']}>Показати ел. пошту</button> )} </div> - + ) : null} </> - ) : null ); } export default PhoneEmail; PhoneEmail.propTypes = { - isAuthorized: PropTypes.bool.isRequired, - profileId: PropTypes.number.isRequired + profileId: PropTypes.number.isRequired, + personId: PropTypes.number.isRequired, }; From 3134c8bbc46f7c3d2979c6922c9bc5e48fef395f Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Sat, 4 Nov 2023 14:38:27 +0100 Subject: [PATCH 47/51] toast error message removed --- .../src/components/ProfileDetail/MainInfo/TitleInfo.jsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx index 6ed316e86..10a41f20b 100644 --- a/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx @@ -1,6 +1,4 @@ import { useState, useMemo } from 'react'; -import { toast, ToastContainer } from 'react-toastify'; -import 'react-toastify/dist/ReactToastify.css'; import { Badge } from 'antd'; import { StarOutlined, StarFilled } from '@ant-design/icons'; import { PropTypes } from 'prop-types'; @@ -41,7 +39,7 @@ function TitleInfo({ isAuthorized, data }) { body: JSON.stringify(data), }).then((res) => { if (!res.ok && res.status === 403) { - const error = new Error('Ви не можете додати власну комапнію до списку збережених.'); + const error = new Error('Own company cannot be added to the saved list.'); error.info = res.json(); error.status = res.status; throw error; @@ -49,7 +47,6 @@ function TitleInfo({ isAuthorized, data }) { }) .catch(error => { console.error(error); - toast.error(error.message); }); } @@ -142,7 +139,6 @@ function TitleInfo({ isAuthorized, data }) { > <span className={`${classes['title-block__button--text']} ${isSaved && classes['added_to_saved__button--text']}`}>{!isSaved ? 'Додати в збережені' : 'Додано в збережені'}</span> {isAuthorized ? (isSaved ? filledStar : outlinedStar) : null} - <ToastContainer position="top-right" autoClose={3000} /> </button>)} </div> ); From 58fc07edb543209923073122006cb3c7101e0049 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 9 Nov 2023 10:56:57 +0100 Subject: [PATCH 48/51] error handling added --- FrontEnd/src/hooks/useUser.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/FrontEnd/src/hooks/useUser.js b/FrontEnd/src/hooks/useUser.js index 386b6a3b4..59054aea0 100644 --- a/FrontEnd/src/hooks/useUser.js +++ b/FrontEnd/src/hooks/useUser.js @@ -13,7 +13,24 @@ export default function useUser() { headers: { 'Authorization': `Token ${authToken}`, }, - }).then(res => res.json()), + }).then((res) => { + if (!res.ok && res.status === 401) { + const error = new Error('Unauthorized user.'); + error.info = res.json(); + error.status = res.status; + throw error; + } + if (!res.ok) { + const error = new Error('An error occurred while fetching the data.'); + error.info = res.json(); + error.status = res.status; + throw error; + } + return res.json(); + }) + .catch(error => { + console.error(error); + }), { revalidateOnFocus: false } ); From a54e80b24c30f9ccf8a5c6cbd0d795eb3b74e23a Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 9 Nov 2023 10:58:22 +0100 Subject: [PATCH 49/51] isrequired removed in props --- .../src/components/ProfileDetail/DetailedInfo/DataContacts.jsx | 2 +- .../src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx index 068b36285..3320c67fe 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/DataContacts.jsx @@ -116,7 +116,7 @@ DataContacts.propTypes = { isAuthorized: PropTypes.bool, data: PropTypes.shape({ id: PropTypes.number.isRequired, - person: PropTypes.number.isRequired, + person: PropTypes.number, edrpou: PropTypes.number, founded: PropTypes.number, address: PropTypes.string, diff --git a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx index ddaec9819..6c8fcc10c 100644 --- a/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx +++ b/FrontEnd/src/components/ProfileDetail/DetailedInfo/PhoneEmail.jsx @@ -104,5 +104,5 @@ export default PhoneEmail; PhoneEmail.propTypes = { profileId: PropTypes.number.isRequired, - personId: PropTypes.number.isRequired, + personId: PropTypes.number, }; From 63ffc4f892e03e99236044d953892a632c2f57f9 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 9 Nov 2023 10:58:53 +0100 Subject: [PATCH 50/51] bug fixed --- .../src/components/ProfileDetail/MainInfo/TitleInfo.jsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx b/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx index 10a41f20b..da737edda 100644 --- a/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx +++ b/FrontEnd/src/components/ProfileDetail/MainInfo/TitleInfo.jsx @@ -16,11 +16,12 @@ function TitleInfo({ isAuthorized, data }) { id: data.id, personId: data.person, name: data.name, - activities: !data.activities.length - ? null - : data.activities.map((activity) => activity.name).join(', '), + activities: data.activities && data.activities.length + ? data.activities.map((activity) => activity.name).join(', ') + : null, region: data.region_display ? data.region_display : '', categories: + data.categories && data.categories.length > 4 ? data.categories.slice(0, 4) : data.categories, From f3ff1259f33f0c0d3dc33ad5a245c43df07b35a2 Mon Sep 17 00:00:00 2001 From: Lvyshnevska <lilia.vyshnevska@gmail.com> Date: Thu, 9 Nov 2023 11:00:17 +0100 Subject: [PATCH 51/51] styles fixed --- .../UI/ProfileFormButton/ProfileFormButton.module.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FrontEnd/src/components/ProfilePage/UI/ProfileFormButton/ProfileFormButton.module.css b/FrontEnd/src/components/ProfilePage/UI/ProfileFormButton/ProfileFormButton.module.css index bfb150ed6..470bbf070 100644 --- a/FrontEnd/src/components/ProfilePage/UI/ProfileFormButton/ProfileFormButton.module.css +++ b/FrontEnd/src/components/ProfilePage/UI/ProfileFormButton/ProfileFormButton.module.css @@ -2,8 +2,8 @@ display: flex; align-items: flex-start; padding: 6px 0px; - background: #EFFFF6; - margin-top: 24px; + background: #EFFFF6; + margin-top: 140px; width: 1513px; } @@ -32,4 +32,4 @@ text-align: center; cursor: pointer; margin-left: 430px; -} +} \ No newline at end of file