Skip to content

Commit

Permalink
EPMGCIP-164: Implement Footer (#38)
Browse files Browse the repository at this point in the history
* feature/EPMGCIP-164/Implement feature

* feature/EPMGCIP-164/Added tests

* feature/EPMGCIP-164/Added routes label enum and updated 'Contacts' route

* feature/EPMGCIP-164/Added translation

* feature/EPMGCIP-164/Components converted to arrow functions

* feature/EPMGCIP-164/Add new unit test

---------

Co-authored-by: Siarhei Balonikau <[email protected]>
  • Loading branch information
gordoney and Siarhei Balonikau authored Jan 8, 2025
1 parent 68efd62 commit 106ada9
Show file tree
Hide file tree
Showing 15 changed files with 206 additions and 4 deletions.
4 changes: 4 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,9 @@
"success": "Email sent successfully",
"error": "Failed to send email"
}
},
"copyright": {
"message": "All copyrights reserved. Copying website content allowed only on permission of the Museum&apos;s Administration.",
"contact": "Contact details."
}
}
4 changes: 4 additions & 0 deletions messages/ka.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,9 @@
"success": "Email sent successfully",
"error": "Failed to send email"
}
},
"copyright": {
"message": "All copyrights reserved. Copying website content allowed only on permission of the Museum&apos;s Administration.",
"contact": "Contact details."
}
}
4 changes: 4 additions & 0 deletions messages/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,9 @@
"success": "Электронное письмо успешно отправлено",
"error": "Не удалось отправить электронное письмо"
}
},
"copyright": {
"message": "Все права защищены. Копирование содержимого сайта разрешено только с разрешения администрации музея.",
"contact": "Контакты."
}
}
4 changes: 4 additions & 0 deletions messages/uz.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,9 @@
"success": "Elektron pochta muvaffaqiyatli yuborildi",
"error": "Elektron pochtani yuborib bo'lmadi"
}
},
"copyright": {
"message": "Barcha huquqlar himoyalangan. Veb-sayt mazmunini nusxalash faqat muzey ma'muriyati ruxsati bilan amalga oshiriladi.",
"contact": "Aloqa ma'lumotlari."
}
}
2 changes: 2 additions & 0 deletions src/app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Montserrat } from 'next/font/google';
import { NextIntlClientProvider } from 'next-intl';
import { getMessages } from 'next-intl/server';

import { Footer } from '@/components/organisms/Footer/Footer';
import Header from '@/components/organisms/Header/Header';
import { THEME_BREAKPOINTS } from '@/constants/breakpoints';
import { APP_ROUTES } from '@/constants/routes';
Expand Down Expand Up @@ -53,6 +54,7 @@ export default async function RootLayout({
<NextIntlClientProvider messages={messages}>
<Header links={APP_ROUTES} />
{children}
<Footer />
</NextIntlClientProvider>
</MantineProvider>
</body>
Expand Down
18 changes: 18 additions & 0 deletions src/components/atoms/CircleLink/CircleLink.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@use 'sass:map';
@import '../../../variables.scss';

.link {
display: inline-flex;
justify-content: center;
align-items: center;
width: 32px;
height: 32px;
background-color: $circleLinkBackgroundColor;
border-radius: 50%;
transition: background-color 0.1s;
cursor: pointer;

&:hover {
background-color: $colorLink;
}
}
19 changes: 19 additions & 0 deletions src/components/atoms/CircleLink/CircleLink.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { IconBrandTelegram } from '@tabler/icons-react';
import { render, screen } from '@testing-library/react';

import { CircleLink } from './CircleLink';

describe('CircleLink', () => {
it('renders the CircleLink component with an icon and a link', () => {
const link = 'https://test.com';
const icon = <IconBrandTelegram color="white" size="20" data-testid="icon" />;

render(<CircleLink link={link} icon={icon} />);

const circleLinkElement = screen.getByRole('link');

expect(circleLinkElement).toBeInTheDocument();
expect(circleLinkElement).toHaveAttribute('href', link);
expect(circleLinkElement).toContainElement(screen.getByTestId('icon'));
});
});
14 changes: 14 additions & 0 deletions src/components/atoms/CircleLink/CircleLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import styles from './CircleLink.module.scss';

interface Props {
link: string;
icon: JSX.Element;
}

export const CircleLink = ({ link, icon }: Props) => {
return (
<a href={link} className={styles.link}>
{icon}
</a>
);
};
31 changes: 31 additions & 0 deletions src/components/organisms/Footer/Footer.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@use 'sass:map';
@import '../../../variables.scss';

.footer {
padding: 40px 16px;
background-color: $secondaryBackgroundColor;
text-align: center;
}

.socialLinks {
display: flex;
justify-content: center;
gap: 24px;
padding-bottom: 40px;
}

.copyright {
max-width: 530px;
margin: 0 auto;
font-size: $fontSizeDefault;
font-weight: 500;
}

.contactsLink {
color: $mainFontColor;
text-decoration: underline;

&:hover {
text-decoration: none;
}
}
36 changes: 36 additions & 0 deletions src/components/organisms/Footer/Footer.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { MantineProvider } from '@mantine/core';
import { render, screen } from '@testing-library/react';
import { NextIntlClientProvider } from 'next-intl';

import messages from 'messages/en.json';

import { Footer } from './Footer';

const wrapper = ({ children }: { children: React.ReactNode }) => (
<NextIntlClientProvider locale="en" messages={messages}>
<MantineProvider>{children}</MantineProvider>
</NextIntlClientProvider>
);

describe('Footer', () => {
it('renders correctly and show copyrights', () => {
const { getByText } = render(<Footer />, { wrapper });

expect(getByText(new RegExp('All copyrights reserved', 'i'))).toBeInTheDocument();
expect(getByText(new RegExp('Contact details', 'i'))).toBeInTheDocument();
});

it('has social network links', () => {
render(<Footer />, { wrapper });

const socialNetworkLinks = 4;
expect(screen.getAllByTestId('social-network').length).toBe(socialNetworkLinks);
});

it('show current year', () => {
render(<Footer />, { wrapper });

const currentYear = new Date().getFullYear();
expect(screen.getByText(new RegExp(currentYear.toString(), 'i'))).toBeInTheDocument();
});
});
51 changes: 51 additions & 0 deletions src/components/organisms/Footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {
IconBrandTelegram,
IconBrandFacebook,
IconBrandInstagram,
IconBrandYoutube,
} from '@tabler/icons-react';
import Link from 'next/link';
import { useTranslations } from 'next-intl';

import { CircleLink } from '@/components/atoms/CircleLink/CircleLink';
import { APP_ROUTES } from '@/constants/routes';
import { RouteLabelsEnum } from '@/enums';

import styles from './Footer.module.scss';

export const Footer = () => {
const t = useTranslations();
const currentYear = new Date().getFullYear();
const contactRoute = APP_ROUTES.find((r) => r.label === RouteLabelsEnum.Contacts);

return (
<div className={styles.footer}>
<div className={styles.socialLinks}>
<CircleLink
link="https://www.facebook.com/savitskymuseum/"
icon={<IconBrandTelegram color="white" size="20" data-testid="social-network" />}
/>
<CircleLink
link="https://www.instagram.com/museumsavitsky1/"
icon={<IconBrandInstagram color="white" size="20" data-testid="social-network" />}
/>
<CircleLink
link="https://t.me/museumsavitsky"
icon={<IconBrandFacebook color="white" size="20" data-testid="social-network" />}
/>
<CircleLink
link="https://www.youtube.com/channel/UCshZAh9gVGMv_gFQJo3IXyQ"
icon={<IconBrandYoutube color="white" size="19" data-testid="social-network" />}
/>
</div>
<div className={styles.copyright}>
&copy;{currentYear}. {t('copyright.message')}{' '}
{contactRoute?.url && (
<Link className={styles.contactsLink} href={contactRoute.url}>
{t('copyright.contact')}
</Link>
)}
</div>
</div>
);
};
14 changes: 10 additions & 4 deletions src/constants/routes.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { RouteLabelsEnum } from '@/enums';
import { ILink } from '@/interfaces/ILink';

export const BASE_URL = '/';
Expand All @@ -7,25 +8,30 @@ export const EXHIBIT_URL = `/exhibit`;
export const APP_ROUTES: ILink[] = [
{
isEnabled: true,
label: 'Home',
label: RouteLabelsEnum.Home,
url: '/',
},
{
isEnabled: true,
label: 'Museum',
label: RouteLabelsEnum.Museum,
subLinks: [
{ isEnabled: true, label: 'History', url: '/history' },
{ isEnabled: true, label: 'Architecture', url: '/architecture' },
],
},
{
isEnabled: true,
label: 'Exposition',
label: RouteLabelsEnum.Exposition,
url: '/exposition',
},
{
isEnabled: true,
label: 'News',
label: RouteLabelsEnum.News,
url: '/news',
},
{
isEnabled: true,
label: RouteLabelsEnum.Contacts,
url: '/contacts',
},
];
7 changes: 7 additions & 0 deletions src/enums/RouteLabelsEnum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export enum RouteLabelsEnum {
Home = 'Home',
Museum = 'Museum',
Exposition = 'Exposition',
News = 'News',
Contacts = 'Contacts',
}
1 change: 1 addition & 0 deletions src/enums/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { NotificationType } from './app-notifications';
export { ContactFormValidationErrors } from './validation-errors';
export { RouteLabelsEnum } from './RouteLabelsEnum';
1 change: 1 addition & 0 deletions src/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ $secondaryBackgroundColor: $colorLightGray;
$colorAudioMain: $colorOrange;
$colorAudioSecondary: $colorPink;
$colorLink: $colorOrange;
$circleLinkBackgroundColor: $colorBlack;
$colorMenuLink: $graphite;

$mainFontSize: $fontSizeDefault;
Expand Down

0 comments on commit 106ada9

Please sign in to comment.