diff --git a/FrontEnd/src/components/CookieAcception/CookieMod.jsx b/FrontEnd/src/components/CookieAcception/CookieMod.jsx index 7b8e0d0b..a87ae663 100644 --- a/FrontEnd/src/components/CookieAcception/CookieMod.jsx +++ b/FrontEnd/src/components/CookieAcception/CookieMod.jsx @@ -1,33 +1,11 @@ -import React, { useEffect } from 'react'; -import PropTypes from 'prop-types'; -import { useCookies } from 'react-cookie'; +import { useCookieContext } from '../../context/CookieContext'; import { Link } from 'react-router-dom'; import styles from './CookieMod.module.css'; -const CookieMod = ({ active, setActive }) => { - const [cookies, setCookie] = useCookies(['cookies']); +const CookieMod = () => { + const { allowCookies, declineCookies } = useCookieContext(); - useEffect(() => { - if (cookies.cookies !== undefined) { - setActive(false); - } - }, [cookies, setActive]); - - const allowCookies = () => { - const expirationDate = new Date(); - expirationDate.setTime(expirationDate.getTime() + 30 * 24 * 60 * 60 * 1000); - setCookie('cookies', true, { expires: expirationDate, sameSite: 'lax' }); - setActive(false); - }; - - const declineCookies = () => { - const expirationDate = new Date(); - expirationDate.setTime(expirationDate.getTime() + 30 * 24 * 60 * 60 * 1000); - setCookie('cookies', false, { expires: expirationDate, sameSite: 'lax' }); - setActive(false); - }; - - return active ? ( + return (
@@ -43,11 +21,11 @@ const CookieMod = ({ active, setActive }) => {

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

-
+
@@ -57,12 +35,7 @@ const CookieMod = ({ active, setActive }) => {
- ) : null; -}; - -CookieMod.propTypes = { - active: PropTypes.bool.isRequired, - setActive: PropTypes.func.isRequired, + ); }; export default CookieMod; diff --git a/FrontEnd/src/components/CookieAcception/tests/CookieModal.test.js b/FrontEnd/src/components/CookieAcception/tests/CookieModal.test.js index 62f7e822..3004e3de 100644 --- a/FrontEnd/src/components/CookieAcception/tests/CookieModal.test.js +++ b/FrontEnd/src/components/CookieAcception/tests/CookieModal.test.js @@ -1,56 +1,58 @@ import { render, screen, cleanup } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; -import CookieMod from '../CookieMod'; +import PageWrapper from '../../PageWrapper/PageWrapper'; +import { CookieProvider } from '../../../context/CookieContext'; +import { BurgerMenuProvider } from '../../../context/BurgerMenuContext'; +import { useCookies } from 'react-cookie'; + +jest.mock('react-cookie', () => ({ + useCookies: jest.fn(), +})); afterEach(cleanup); describe('CookieMod component unit tests', () => { - test('renders "Allow" button', () => { - render( + const renderWithProviders = (cookiesValue) => { + useCookies.mockReturnValue([cookiesValue, jest.fn()]); + return render( - {}} /> + + + +
Test Content
+
+
+
); + }; + + test('renders "Allow" button', () => { + renderWithProviders({ cookies: undefined }); const buttonElement = screen.getByText(/Дозволити/i); expect(buttonElement).toBeInTheDocument(); }); test('renders "Decline" button', () => { - render( - - {}} /> - - ); + renderWithProviders({ cookies: undefined }); const buttonElement = screen.getByText(/Відмовитись/i); expect(buttonElement).toBeInTheDocument(); }); test('renders link to cookie policy', () => { - render( - - {}} /> - - ); + renderWithProviders({ cookies: undefined }); const linkElement = screen.getByText(/про файли cookie/i); expect(linkElement).toBeInTheDocument(); }); test('does not render cookie banner when inactive', () => { - render( - - {}} /> - - ); + renderWithProviders({ cookies: true }); const cookieElement = screen.queryByTestId('cookiemodal'); expect(cookieElement).not.toBeInTheDocument(); }); test('renders cookie banner when active', () => { - render( - - {}} /> - - ); + renderWithProviders({ cookies: undefined }); const cookieElement = screen.getByTestId('cookiemodal'); expect(cookieElement).toBeInTheDocument(); }); diff --git a/FrontEnd/src/components/PageWrapper/PageWrapper.jsx b/FrontEnd/src/components/PageWrapper/PageWrapper.jsx index 88b052d2..b1383b2b 100644 --- a/FrontEnd/src/components/PageWrapper/PageWrapper.jsx +++ b/FrontEnd/src/components/PageWrapper/PageWrapper.jsx @@ -1,13 +1,16 @@ -import React from 'react'; import PropTypes from 'prop-types'; import { useBurgerMenu } from '../../context/BurgerMenuContext'; +import { useCookieContext } from '../../context/CookieContext'; +import CookieMod from '../CookieAcception/CookieMod'; import css from './PageWrapper.module.css'; const PageWrapper = ({ children }) => { const { isOpen } = useBurgerMenu(); + const { isCookieModalActive } = useCookieContext(); return (
+ {isCookieModalActive && } {children}
); diff --git a/FrontEnd/src/context/CookieContext.js b/FrontEnd/src/context/CookieContext.js new file mode 100644 index 00000000..b0754477 --- /dev/null +++ b/FrontEnd/src/context/CookieContext.js @@ -0,0 +1,46 @@ +import { createContext, useContext, useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import { useCookies } from 'react-cookie'; + +const CookieContext = createContext(); + +export const CookieProvider = ({ children }) => { + const [cookies, setCookie] = useCookies(['cookies']); + const [isCookieModalActive, setCookieModalActive] = useState(false); + + useEffect(() => { + setCookieModalActive(cookies.cookies === undefined); + }, [cookies]); + + const allowCookies = () => { + const expirationDate = new Date(); + expirationDate.setTime(expirationDate.getTime() + 30 * 24 * 60 * 60 * 1000); + setCookie('cookies', true, { expires: expirationDate, sameSite: 'lax' }); + setCookieModalActive(false); + }; + + const declineCookies = () => { + const expirationDate = new Date(); + expirationDate.setTime(expirationDate.getTime() + 24 * 60 * 60 * 1000); + setCookie('cookies', false, { expires: expirationDate, sameSite: 'lax' }); + setCookieModalActive(true); + }; + + return ( + + {children} + + ); +}; + +CookieProvider.propTypes = { + children: PropTypes.node.isRequired, +}; + +export const useCookieContext = () => useContext(CookieContext); diff --git a/FrontEnd/src/index.module.css b/FrontEnd/src/index.module.css index 34e14b30..58c06243 100644 --- a/FrontEnd/src/index.module.css +++ b/FrontEnd/src/index.module.css @@ -14,5 +14,5 @@ a { :root { display: flex; scroll-behavior: smooth; - font-family: 'Inter', sans-serif; + font-family: 'Geologica', sans-serif; } diff --git a/FrontEnd/src/pages/CookiesPolicyPage/RenderContent.jsx b/FrontEnd/src/pages/CookiesPolicyPage/RenderContent.jsx index d5712a28..b9fab36f 100644 --- a/FrontEnd/src/pages/CookiesPolicyPage/RenderContent.jsx +++ b/FrontEnd/src/pages/CookiesPolicyPage/RenderContent.jsx @@ -4,7 +4,12 @@ import styles from './cookiesPolicyComponent.module.css'; const renderContent = (Text) => ( Text.content.map((item) => ( - + )) ); diff --git a/FrontEnd/src/pages/CookiesPolicyPage/RenderingTextContainer.jsx b/FrontEnd/src/pages/CookiesPolicyPage/RenderingTextContainer.jsx index 9679da67..75083302 100644 --- a/FrontEnd/src/pages/CookiesPolicyPage/RenderingTextContainer.jsx +++ b/FrontEnd/src/pages/CookiesPolicyPage/RenderingTextContainer.jsx @@ -3,20 +3,44 @@ import PropTypes from 'prop-types'; const RenderingTextContainer = ({ item, styles }) => { const renderParagraph = () => ( -

{item.text}

+

+ {item.text} +

); const renderHeading = () => { const HeadingTag = `h${item.level}`; - return {item.text}; + return ( + + {item.text} + + ); }; const renderParagraphMarginBottom = () => ( -

{item.text}

+

+ {item.text} +

); const renderListItem = () => ( -
    +
    • {item.text}
    ); @@ -49,6 +73,7 @@ RenderingTextContainer.propTypes = { type: PropTypes.string.isRequired, text: PropTypes.string.isRequired, level: PropTypes.number, + sectionId: PropTypes.string, }).isRequired, styles: PropTypes.object.isRequired, }; diff --git a/FrontEnd/src/pages/LandingPage/MainPage.jsx b/FrontEnd/src/pages/LandingPage/MainPage.jsx index 2ef3e31e..6b35875c 100644 --- a/FrontEnd/src/pages/LandingPage/MainPage.jsx +++ b/FrontEnd/src/pages/LandingPage/MainPage.jsx @@ -1,9 +1,7 @@ -import { useState } from 'react'; import MainBanner from './Banner/Banner'; import MainCompanies from './Companies/Companies'; import JoinUs from './JoinUs/JoinUs'; import MainAboutSection from './AboutSection/About'; -import CookieMod from '../../components/CookieAcception/CookieMod'; import css from './MainPage.module.css'; import PropTypes from 'prop-types'; @@ -11,19 +9,15 @@ const MainPage = ({ isAuthorized }) => { MainPage.propTypes = { isAuthorized: PropTypes.bool, }; - const [modalActive, setModalActive] = useState(true); + return (
    {!isAuthorized ? : null} -
    ); }; -export default MainPage; \ No newline at end of file +export default MainPage; diff --git a/FrontEnd/src/pages/PrivacyPolicyPage/PrivacyPolicyPage.jsx b/FrontEnd/src/pages/PrivacyPolicyPage/PrivacyPolicyPage.jsx index 7269dd6f..1cead1b3 100644 --- a/FrontEnd/src/pages/PrivacyPolicyPage/PrivacyPolicyPage.jsx +++ b/FrontEnd/src/pages/PrivacyPolicyPage/PrivacyPolicyPage.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import { useEffect } from 'react'; import styles from './PrivacyPolicy.module.css'; import privacyPolicyText from './text'; import TEXT_CONTENT from './text'; @@ -9,6 +9,16 @@ import useScrollToTop from '../../hooks/useScrollToTop'; const PrivacyPolicy = () => { useScrollToTop(); + useEffect(() => { + const hash = window.location.hash.substring(1); + if (hash) { + const element = document.getElementById(hash); + if (element) { + element.scrollIntoView({ behavior: 'smooth' }); + } + } + }, []); + return (
    diff --git a/FrontEnd/src/pages/PrivacyPolicyPage/text.js b/FrontEnd/src/pages/PrivacyPolicyPage/text.js index ac17e48f..dd42c878 100644 --- a/FrontEnd/src/pages/PrivacyPolicyPage/text.js +++ b/FrontEnd/src/pages/PrivacyPolicyPage/text.js @@ -108,7 +108,8 @@ const privacyPolicyText = { id: 17, type: 'heading', level: 4, - text: '4. Використання файлів "cookies"' + text: '4. Використання файлів "cookies"', + sectionId: 'cookies-usage', }, { id: 18, diff --git a/FrontEnd/src/routes/ClientRouter.jsx b/FrontEnd/src/routes/ClientRouter.jsx index 217970bf..9f647e39 100644 --- a/FrontEnd/src/routes/ClientRouter.jsx +++ b/FrontEnd/src/routes/ClientRouter.jsx @@ -35,6 +35,7 @@ import Contact from '../pages/Contact/Contact.jsx'; import ErrorPage404 from '../pages/ErrorPages/ErrorPage404'; import { BurgerMenuProvider } from '../context/BurgerMenuContext'; +import { CookieProvider } from '../context/CookieContext'; import PageWrapper from '../components/PageWrapper/PageWrapper'; function ClientRouter() { @@ -52,110 +53,116 @@ function ClientRouter() { }, }} > - -
    - {isLoading ? ( - - ) : ( - - - } /> - } /> - {isAuth ? ( - } /> - ) : ( - } /> - )} - } - /> - } - /> - } - /> - {isAuth ? ( + + +
    + {isLoading ? ( + + ) : ( + + + } /> + } /> + {isAuth ? ( + } /> + ) : ( + } /> + )} } + path="/profile-detail/:id" + element={} /> - ) : ( - } /> - )} - {isAuth ? ( } + path="/profiles" + element={ + + } /> - ) : ( - } /> - )} - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } /> - } - /> - } - /> - } /> - } - /> - } - /> - } /> - - - )} -