Skip to content

Jari/enhancement/425 update login component and language switcher #451

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why were these changes made and are you sure they wont cause problems?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From, what I understood, they are linked to the code editor WebStorm. I don't know why I have these folders. We can check them out on the call if you want.

Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,19 @@ dist-ssr
.vscode/*
!.vscode/extensions.json
.idea
.next
node_modules/
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.coverage
.swc
/frontend/.env
/frontend/storybook-static/*

/frontend-next-migration/analyze/nodejs.html
/strapi-cms/.env

4 changes: 4 additions & 0 deletions frontend-next-migration/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,7 @@ yarn-error.log*
*.tsbuildinfo
next-env.d.ts

#misc
.idea


Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ import { usePathname } from 'next/navigation';
import { useTranslation } from 'react-i18next';
import { LangSwitcher } from './LangSwitcher';

// Mock the usePathname hook to return a test path
jest.mock('next/navigation', () => ({
usePathname: jest.fn(),
}));

// Mock the useTranslation hook for test translations
jest.mock('react-i18next', () => ({
useTranslation: jest.fn(),
}));
Expand Down Expand Up @@ -57,37 +55,9 @@ describe('LangSwitcher', () => {
const langSwitcher = screen.getByTestId('language-switcher');
fireEvent.click(langSwitcher.firstElementChild!);

const englishOption = screen.getByRole('option', { name: 'ENG' });
fireEvent.click(englishOption);

expect(window.location.href).toBe('/en/some-path');
});

//THIS SHOULD BE WORKING, BUT COULDNT FIGURE IT OUT
// it('falls back to default language when current language is not in options', () => {
// (useTranslation as jest.Mock).mockReturnValue({
// t: (str: string) => (str === 'FIN' ? 'FIN' : 'ENG'),
// i18n: { language: 'es' },
// });

// render(<LangSwitcher />);

// const langDisplay = screen.getByText('FIN');
// expect(langDisplay).toBeInTheDocument();
// });

it('contains all available language options', () => {
render(<LangSwitcher />);

const langSwitcher = screen.getByTestId('language-switcher');
fireEvent.click(langSwitcher.firstElementChild!);

const options = screen.getAllByRole('option');
expect(options).toHaveLength(2);
expect(options[0]).toHaveTextContent('FIN');
expect(options[1]).toHaveTextContent('ENG');
});

it('renders with a custom class name', () => {
render(<LangSwitcher className="custom-class" />);
const switcher = screen.getByTestId('language-switcher');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use client';
import { usePathname } from 'next/navigation';
import { useState, useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -27,14 +28,11 @@ export const LangSwitcher = ({ className = '' }: LangSwitcherProps) => {
const options = [
{ label: t('FIN'), value: 'fi' },
{ label: t('ENG'), value: 'en' },
{ label: t('RUS'), value: 'ru' },
// Add more languages here
];

// Get the label of the current language
const [selected, setSelected] = useState<string>(
// options.find((option) => option.value === language)?.label || options[0]?.label || '',

//temporary fix
options.find((option) => option.value === language)?.value || options[0]?.value || '',
);

Expand All @@ -51,11 +49,9 @@ export const LangSwitcher = ({ className = '' }: LangSwitcherProps) => {

const toggleDropdown = () => setIsOpen(!isOpen);

// Selecting an option by pressing enter (for keyboard accessibility)
const handleEnter = (event: React.KeyboardEvent<HTMLLIElement>) => {
const items = Array.from(document.querySelectorAll('.selectable-item'));
const activeElement = document.activeElement;
// Active element is one of the options and the pressed key is enter
if (activeElement && event.key === 'Enter') {
const currentIndex = items.indexOf(activeElement);
if (currentIndex !== -1) {
Expand All @@ -70,7 +66,6 @@ export const LangSwitcher = ({ className = '' }: LangSwitcherProps) => {
}
};

// Close the menu if clicking outside of it
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
Expand All @@ -90,26 +85,27 @@ export const LangSwitcher = ({ className = '' }: LangSwitcherProps) => {
className={classNames('', {}, [className])}
>
<div
onClick={toggleDropdown}
style={{
display: 'flex',
flexDirection: 'column',
flexDirection: 'row',
alignItems: 'center',
marginLeft: 3,
cursor: 'pointer',
}}
onClick={toggleDropdown}
aria-haspopup="true"
aria-expanded={isOpen}
>
<Image
src={languageIcon}
alt="Language Menu Icon"
/>
</div>
<div>
{options
.filter((option) => option.value === language)
.map((option) => option.label)
.join(', ')}
<div style={{ marginLeft: 13 }}>
{options
.filter((option) => option.value === language)
.map((option) => option.label)
.join(', ')}
</div>
</div>
{isOpen && (
<ul>
Expand All @@ -118,7 +114,6 @@ export const LangSwitcher = ({ className = '' }: LangSwitcherProps) => {
className="selectable-item"
key={option.value}
onClick={() => handleOptionClick(option)}
// For screen readers
role="option"
aria-selected={option.value === language ? 'true' : 'false'}
tabIndex={0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@
transform: translateX(0) scaleX(1);
transform-origin: right;
transition:
transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
margin-top 0.4s cubic-bezier(0.4, 0, 0.2, 1),
color 0.2s ease-out;
transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
margin-top 0.4s cubic-bezier(0.4, 0, 0.2, 1),
color 0.2s ease-out;

&:hover .itemNavbarDropDownContent {
display: flex;
Expand Down Expand Up @@ -167,7 +167,6 @@

.itemNavbarDropDownContent {
gap: 0.2rem;

}

.appLinkLogo {
Expand Down Expand Up @@ -222,7 +221,7 @@
ul {
display: none;
position: absolute;
margin-top: 80px;
margin-top: 105px;
height: max-content;
width: max-content;
list-style-type: none;
Expand All @@ -231,6 +230,19 @@
flex-direction: column;
align-items: flex-start;
margin-left: 40px;

opacity: 0;
transform: translateY(-10px);
transition: opacity 0.3s ease, transform 0.3s ease;
pointer-events: none;
}

/* πŸ‘‡ Animate in when hovering .siteNavContentList */
&.open ul,
.siteNavContentList:hover & ul {
opacity: 1;
transform: translateY(0);
pointer-events: auto;
}

li {
Expand All @@ -239,6 +251,7 @@
display: flex;
align-items: center;
display: none;
color: white;
}

li:hover {
Expand Down Expand Up @@ -298,4 +311,42 @@
opacity: 0.5;
}
}
}

.loginFormWrapper {
position: absolute;
top: 100%;
right: 0;
background: white;
padding: 1rem;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
z-index: 100;
min-width: 250px;
display: none; /* Initially hidden */
opacity: 0;
transition: opacity 0.3s ease;

&.open {
display: block;
opacity: 1;
}

@media (max-width: 768px) {
min-width: 200px;
}
}

.loginToggle {
background: none;
border: none;
cursor: pointer;
padding: 10px;
display: flex;
align-items: center;
justify-content: center;

img {
width: 24px;
height: 24px;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ jest.mock('@/entities/Auth', () => ({
}));

jest.mock('@/shared/lib/hooks/useIsPageScrollbar');

jest.mock('react-i18next', () => ({
useTranslation: jest.fn().mockReturnValue({
t: jest.fn((key) => key),
Expand All @@ -34,17 +33,6 @@ jest.mock('next/navigation', () => ({
usePathname: jest.fn(),
}));

describe('Navbar', () => {
beforeEach(() => {
(useClientTranslation as jest.Mock).mockReturnValue({ t: jest.fn((key) => key) });
(useIsPageScrollbar as jest.Mock).mockReturnValue(true);
});

test('render components', async () => {
render(<div />);
});
});

describe('NavbarDesktop', () => {
const mockToggleCollapsed = jest.fn();
const mockToggleFixed = jest.fn();
Expand Down Expand Up @@ -107,8 +95,8 @@ describe('NavbarDesktop', () => {
test('applies collapsed styles when isCollapsed is true', () => {
renderNavbar({ isCollapsed: true });

const navList = screen.getByRole('list');
expect(navList).toHaveClass(cls.collapsed);
const navLists = screen.getAllByRole('list');
expect(navLists[0]).toHaveClass(cls.collapsed);
});

test('does not show collapse button when not fixed', () => {
Expand Down
Loading