Skip to content
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
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ReactNode } from 'react';
import { Footer } from '@/widgets/Footer';
import { Navbar } from '@/widgets/Navbar';
import { Navbar } from '@/widgets/NavbarV3';
import { ScrollTop } from '@/features/ScrollTop';
import LayoutDefault from '../../../preparedPages/Layouts/ui/LayoutDefault/LayoutDefault';

Expand Down
2 changes: 1 addition & 1 deletion frontend-next-migration/src/app/[lng]/(home)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';
import { ReactNode } from 'react';
import { Navbar } from '@/widgets/Navbar';
import { Navbar } from '@/widgets/NavbarV3';
import { Footer } from '@/widgets/Footer';
import { ScrollTop } from '@/features/ScrollTop';
import cls from './homeLayout.module.scss';
Expand Down
2 changes: 1 addition & 1 deletion frontend-next-migration/src/app/[lng]/(intro)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ReactNode } from 'react';
import { Footer } from '@/widgets/Footer';
import { Navbar } from '@/widgets/Navbar';
import { Navbar } from '@/widgets/NavbarV3';

type Props = {
children: ReactNode;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend-next-migration/src/shared/assets/images/altLogo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 7 additions & 4 deletions frontend-next-migration/src/shared/i18n/locales/en/navbar.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
"main": "Main page",
"forum": "Forum",
"heroes": "Heroes",
"team": "Team",
"team": "Contact us",
"art": "Art",
"artGame": "Game art",
"teachingPackage": "Teaching package",
"login": "Log in",
"profile": "Profile",
"logout": "Log out",
"community": "Community",
"community": "PRG",
"feedback": "Feedback",
"game": "Game",
"clans": "Clans",
Expand All @@ -21,7 +21,7 @@
"SignUpFirst!": "Sign up first!",
"join": "Join us",
"clanpage": "Clan Page",
"gameart": "Game Art",
"gameart": "Education",
"gallery": "Gallery",
"news": "News",
"dlPackage": "Education package",
Expand All @@ -32,5 +32,8 @@
"teachers": "Teachers",
"furnituresets": "Furniture",
"collections": "Collections",
"about": "About"
"about": "About",
"education": "Education",
"prg": "PRG",
"contactUs": "Contact us"
}
11 changes: 7 additions & 4 deletions frontend-next-migration/src/shared/i18n/locales/fi/navbar.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
"main": "PÀÀsivu",
"forum": "Foorumi",
"heroes": "Hahmot",
"team": "Tiimi",
"team": "Ota yhteyttΓ€",
"art": "Taide",
"artGame": "Pelitaide",
"teachingPackage": "Opetuspaketti",
"login": "Kirjaudu",
"profile": "Profiili",
"logout": "Kirjaudu ulos",
"community": "YhteisΓΆ",
"community": "PRG",
"feedback": "Palaute",
"game": "Peli",
"clans": "Klaanit",
Expand All @@ -19,7 +19,7 @@
"SignUpFirst!": "Kirjadu ensin!",
"join": "Tule mukaan",
"clanpage": "Klaanisivu",
"gameart": "Pelitaide",
"gameart": "Opetus",
"gallery": "Galleria",
"news": "Uutiset",
"dlPackage": "Opetuspaketti",
Expand All @@ -30,5 +30,8 @@
"teachers": "Opettajat",
"furnituresets": "Huonekalumallistot",
"collections": "Kokoelmat",
"about": "MeistΓ€"
"about": "MeistΓ€",
"education": "Opetus",
"prg": "PRG",
"contactUs": "Ota yhteyttΓ€"
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
}
.childrenWrapper {
display: flex;
inline-size: 110px;
inline-size: fit-content;
overflow-wrap: break-word;
}

Expand Down
1 change: 1 addition & 0 deletions frontend-next-migration/src/widgets/NavbarV3/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { NavbarMain as Navbar } from './ui/NavbarMain/NavbarMain';
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { ItemType, NamedMenu, NavbarBuild, NavbarMenuItem, NavLogoObject } from '../types';
import { DropDownElement } from '@/shared/ui/DropdownWrapper';

/** Helps build the navbar menu config step by step. */
export class NavbarBuilder {
private menu: NavbarMenuItem[] = [];
private namedMenu: NamedMenu = {};

/** Add a plain link. */
addLink(name: string, path: string): void {
this.menu.push({
name,
path,
type: ItemType.navLink,
});
}

/**
* Add a dropdown.
* @param path - If set, the label becomes a clickable link too.
*/
addDropDown(name: string, elements: Array<DropDownElement>, path?: string): void {
this.menu.push({
name,
path,
elements,
type: ItemType.navDropDown,
});
}

/** Add the logo. */
addLogo(name: string, src: string, path: string): void {
const logoObject = {
name,
src,
path,
type: ItemType.navLogo,
} as NavLogoObject;
this.namedMenu[ItemType.navLogo] = logoObject;
this.menu.push(logoObject);
}

/** Wrap up and return the built config. */
build(): NavbarBuild {
return { menu: this.menu, namedMenu: this.namedMenu };
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import img from '@/shared/assets/images/altLogo.png';
import { dropdowns } from '@/widgets/Navbar/model/data/dropdowns';
import {
getRouteTeamPage,
getRouteMainPage,
getRouteAllNewsPage,
getRouteGameArtPage,
} from '@/shared/appLinks/RoutePaths';
import { NavbarBuilder } from './NavbarBuilder';

const navbarBuilder = new NavbarBuilder();
navbarBuilder.addLogo('Nav logo', img as unknown as string, getRouteMainPage());
navbarBuilder.addLink('news', getRouteAllNewsPage());
navbarBuilder.addDropDown('game', dropdowns.game);
navbarBuilder.addDropDown('gallery', dropdowns.gallery);
navbarBuilder.addDropDown('education', dropdowns.gameart, getRouteGameArtPage());
navbarBuilder.addDropDown('community', dropdowns.community);
navbarBuilder.addLink('contactUs', getRouteTeamPage());

export const navbarMenuDesktop = navbarBuilder.build();
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { NavbarBuilder } from './NavbarBuilder';
import {
getRouteMainPage,
getRouteAllNewsPage,
getRouteDefenseGalleryPage,
getRouteGalleryPage,
getRouteGameArtPage,
getRouteTeamPage,
} from '@/shared/appLinks/RoutePaths';
import img from '@/shared/assets/images/altLogo.png';

const navbarBuilder = new NavbarBuilder();
navbarBuilder.addLink('news', getRouteAllNewsPage());
navbarBuilder.addLink('game', getRouteDefenseGalleryPage());
navbarBuilder.addLink('gallery', getRouteGalleryPage());
navbarBuilder.addLink('education', getRouteGameArtPage());
navbarBuilder.addLink('contactUs', getRouteTeamPage());
navbarBuilder.addLogo('main', img as unknown as string, getRouteMainPage());

export const navbarMenuMobile = navbarBuilder.build();
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { navbarMenuDesktop } from './data/navbarMenuDesktop';
import { navbarMenuMobile } from './data/navbarMenuMobile';

export const getNavbarBuildBySize = (size: 'mobile' | 'tablet' | 'desktop') => {
if (size === 'desktop') {
return navbarMenuDesktop;
}
return navbarMenuMobile;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { DropDownElement } from '@/shared/ui/DropdownWrapper';

/** Tells apart the different kinds of navbar items. */
export enum ItemType {
navLink = 'navLink',
navLogo = 'navLogo',
navDropDown = 'navDropDown',
}

/** A basic link that goes somewhere. */
export type NavbarLinkObject = {
name: string;
path: string;
type: ItemType.navLink;
};

/** A dropdown that shows a popup menu; can also act as a link if `path` is set. */
export type NavbarDropDownObject = {
name: string;
/** Where clicking the label takes you (optional). */
path?: string;
elements: Array<DropDownElement>;
type: ItemType.navDropDown;
};

/** The site logo in the navbar. */
export type NavLogoObject = {
name: string;
src: string;
path: string;
type: ItemType.navLogo;
};

/** Any item that can appear in the navbar menu. */
export type NavbarMenuItem = NavbarLinkObject | NavLogoObject | NavbarDropDownObject;

export type NavbarMenu = NavbarMenuItem[];

export type NamedMenu = {
[ItemType.navLogo]?: NavLogoObject;
};

export type NavbarBuild = {
menu: NavbarMenu;
namedMenu: NamedMenu;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
'use client';
import Image from 'next/image';
import { memo } from 'react';
import { useClientTranslation } from '@/shared/i18n';
import { AppLink, AppLinkTheme } from '@/shared/ui/AppLink/AppLink';
import { DropdownWrapper } from '@/shared/ui/DropdownWrapper';
import { NavbarMenuItem, ItemType } from '../../model/types';
import cls from './NavbarDesktop.module.scss';
import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

type NavItemProps = {
/** The menu item to render. */
item: NavbarMenuItem;
/** Is the navbar being hovered? (opens dropdowns). */
mouseOver?: boolean;
/** This dropdown's index among all dropdowns (for horizontal positioning). */
dropdownIndex?: number;
/** Total number of dropdowns (for horizontal centering). */
totalDropdowns?: number;
};

const CHEVRON_ITEMS = new Set(['game', 'gallery', 'gameart', 'community']);

/** Renders one navbar item β€” a link, a dropdown (optionally linked), or the logo. */
const NavItem = memo((props: NavItemProps) => {
const { item, mouseOver = false } = props;
const { type: itemType } = item;
const { t } = useClientTranslation('navbar');

if (itemType === ItemType.navDropDown) {
const { dropdownIndex = 0, totalDropdowns = 1 } = props;
const gap = 220;
const offset = (dropdownIndex - (totalDropdowns - 1) / 2) * gap;
const elements = item.elements.map((el) => {
if (el && typeof el === 'object' && 'elementText' in el) {
return { ...el, elementText: t(`${el.elementText}`) };
}
return el;
});

const trigger = (
<>
<span className={cls.col}>{t(`${item.name}`)}</span>
{CHEVRON_ITEMS.has(item.name) && (
<FontAwesomeIcon
icon={faChevronDown}
className={cls.chevron}
/>
)}
</>
);

return (
<li style={{ '--az-dropdown-left': `calc(50% + ${offset}px)` } as React.CSSProperties}>
<DropdownWrapper
elements={elements}
contentAbsolute={true}
disableClickToggle={true}
isOpen={mouseOver}
contentClassName={cls.navDropdownCenter}
contentItemClassName={cls.dropdownItem}
>
{item.path ? (
<AppLink
theme={AppLinkTheme.PRIMARY}
to={item.path}
>
{trigger}
</AppLink>
) : (
trigger
)}
</DropdownWrapper>
</li>
);
}

if (itemType === 'navLink') {
return (
<li>
<AppLink
theme={AppLinkTheme.PRIMARY}
to={item.path}
>
<span className={cls.col}>{t(`${item.name}`)}</span>
</AppLink>
</li>
);
}

if (itemType === 'navLogo') {
return (
<AppLink
theme={AppLinkTheme.PRIMARY}
to={item.path}
>
<Image
priority
loading="eager"
alt={item.name || ''}
src={item.src || ''}
width={109}
height={92}
style={{ objectFit: 'contain' }}
/>
</AppLink>
);
}

return null;
});

NavItem.displayName = 'NavItemV3';

export default NavItem;
Loading
Loading