Skip to content
Merged
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
Expand Up @@ -3,14 +3,43 @@ import { getServerTranslation } from '@/shared/i18n';
import { ClanRoomSubPageProps } from '@/preparedPages/ClanPages';
import { envHelper } from '@/shared/const/envHelper';
import { notFound } from 'next/navigation';
import { getRouteOneClanPage } from '@/shared/appLinks/RoutePaths';
import type { IClan } from '@/entities/Clan';
import { baseUrl, defaultOpenGraph } from '@/shared/seoConstants';

const toAbsolute = (src?: string | null) =>
!src ? null : /^https?:\/\//i.test(src) ? src : `${baseUrl}${src}`;

// Use fallback only, no clan-specific logo image exists
function getOgImageUrl(_: Partial<IClan>) {
const fallback = defaultOpenGraph.images?.[0]?.url ?? null;
return toAbsolute(fallback);
}

export async function _getPage(lng: string, id: string) {
const { t } = await getServerTranslation(lng, 'clan');
const response = await fetch(`${envHelper.apiLink}/clan/${id}`);
if (!response.ok) {
return notFound();
notFound();
}
const clanData = await response.json();

const payload = await response.json();
const clan = payload?.data?.Clan ?? {};

const name = (clan.name as string | undefined)?.trim() || id;
const desc = (clan.phrase as string | undefined)?.trim() || t('head-description');

// Routes & SEO
const relPath = getRouteOneClanPage(encodeURIComponent(id));
const path = `/${lng}${relPath}`;
const title = `${t('head-title')} β€” ${name}`;
const keywords = `${t('head-keywords')}${clan.tag ? `, ${clan.tag}` : ''}`;

const ogUrl = getOgImageUrl(clan);
const ogImages = ogUrl
? [{ url: ogUrl, alt: `${name} β€” ${t('head-title')}` }]
: (defaultOpenGraph.images ?? []);

return createPage<ClanRoomSubPageProps>({
buildPage: () => ({
translations: {
Expand Down Expand Up @@ -40,9 +69,18 @@ export async function _getPage(lng: string, id: string) {
},
}),
buildSeo: () => ({
title: `${t('head-title')}: ${clanData.data.Clan.name}`,
description: `${clanData.data.Clan.phrase}`,
keywords: `${t('head-keywords')}, ${clanData.data.Clan.tag}`,
title,
description: desc,
keywords,
openGraph: {
...defaultOpenGraph,
type: 'website',
title,
description: desc,
url: path,
images: ogImages,
},
alternates: { canonical: path },
}),
});
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,65 @@
import { createPage } from '@/app/_helpers';
import { getServerTranslation } from '@/shared/i18n';
import { notFound } from 'next/navigation';
import { SingleFurnitureCollectionPageProps } from '@/preparedPages/FurnitureCollectionsPages';
import { baseUrl, defaultOpenGraph } from '@/shared/seoConstants';
import { FurnitureManager } from '@/entities/Furniture';
import React from 'react';

type Props = React.ComponentProps<typeof SingleFurnitureCollectionPageProps>;

function getOgImageUrl(set: ReturnType<FurnitureManager['getFurnitureSet']>) {
const img = set?.coverWebp ?? set?.cover;
if (!img) return null;
const src = typeof img === 'string' ? img : img.src;
return /^https?:\/\//i.test(src) ? src : `${baseUrl}${src}`;
}

export async function _getPage(lng: string, group: string) {
const { t } = await getServerTranslation(lng, 'furniture');
const manager = new FurnitureManager();
const set = manager.getFurnitureSet(group);
if (!set) notFound();

// Title-casing fallback (e.g. "neuro" -> "Neuro")
const toTitleCase = (text: string) =>
text
.trim()
.replace(/[-_]+/g, ' ')
.replace(/\b[a-z]/gi, (ch) => ch.toLocaleUpperCase());

const setName = t(`sets.${group}.name`, toTitleCase(group));
const setDesc = t(`sets.${group}.description`, t('head-description'));

// Routes & SEO
const relPath = `/collections/furniture/set/${encodeURIComponent(group)}`;
const path = `/${lng}${relPath}`;
const title = `${setName} - ${t('head-title')}`;
const keywords = `${t('head-keywords')}, ${setName}`;
const ogImageUrl = getOgImageUrl(set);
const ogImage = ogImageUrl
? ({ url: ogImageUrl, alt: `${setName} - ${t('furniture-collections-title')}` } as const)
: null;

const ogImages = ogImage ? [ogImage] : (defaultOpenGraph.images ?? []);

return createPage<Props>({
buildPage: () => ({
collectionId: group,
}),
buildSeo: () => ({
title: t('head-title'),
description: t('head-description'),
keywords: t('head-keywords'),
title,
description: setDesc,
keywords,
openGraph: {
...defaultOpenGraph,
type: 'website',
title,
description: setDesc,
url: path,
images: ogImages,
},
alternates: { canonical: path },
}),
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,22 @@ import { createPage } from '@/app/_helpers';
import { getServerTranslation } from '@/shared/i18n';
import { notFound } from 'next/navigation';
import { HeroGroup } from '@/entities/Hero';
import { initializeHeroGroups } from '@/entities/Hero/model/initializeHeroGroups';
import { StaticImageData } from 'next/image';
import { SingleDefensePageProps } from '@/preparedPages/DefenseGalleryPages';
import { getRouteDefenseGalleryGroupPage } from '@/shared/appLinks/RoutePaths';
import defenceGalleryImage from '@/shared/assets/images/descriptionCard/defense_gallery.png';
import { baseUrl, defaultOpenGraph } from '@/shared/seoConstants';

function getOgImageUrl(info?: ReturnType<typeof initializeHeroGroups>[HeroGroup]) {
const candidate =
(info?.srcImg as string | StaticImageData | undefined) ??
(info?.heroes?.[0]?.srcImg as string | StaticImageData | undefined) ??
(defaultOpenGraph.images?.[0]?.url as string | undefined);

const src = typeof candidate === 'string' ? candidate : candidate?.src;
if (!src) return null;
return /^https?:\/\//i.test(src) ? src : `${baseUrl}${src}`;
}

export async function _getPage(lng: string, heroGroup: string) {
const { t } = await getServerTranslation(lng, 'heroes');
Expand All @@ -13,27 +26,39 @@ export async function _getPage(lng: string, heroGroup: string) {
notFound();
}

const group = heroGroup as HeroGroup;
const groups = initializeHeroGroups(t);
const info = groups[group];

const groupName = info?.name ?? group;
const groupDesc = info?.description ?? t('defense-gallery-description');

// Routes & SEO
const relPath = getRouteDefenseGalleryGroupPage(encodeURIComponent(group));
const path = `/${lng}${relPath}`;
const title = `${t('og-title')} - ${groupName}`;
const keywords = `${t('head-keywords')}, ${groupName}`;

const ogImageUrl = getOgImageUrl(info);
const ogImages = ogImageUrl
? [{ url: ogImageUrl, alt: `${groupName} - ${t('defense-gallery')}` }]
: (defaultOpenGraph.images ?? []);

return createPage<SingleDefensePageProps>({
buildPage: () => ({
heroGroup: heroGroup as HeroGroup,
}),
buildPage: () => ({ heroGroup: group }),
buildSeo: () => ({
title: heroGroup,
description: heroGroup,
keywords: `${t('head-keywords')}, ${heroGroup}`,
title,
description: groupDesc,
keywords,
openGraph: {
images: [
{
url: defenceGalleryImage.src,
},
],
title: `${t('og-title')} - ${heroGroup}`,
description: t('og-description'),
url: `/${lng}${getRouteDefenseGalleryGroupPage(heroGroup as HeroGroup)}`,
},
alternates: {
canonical: `/${lng}${getRouteDefenseGalleryGroupPage(heroGroup as HeroGroup)}`,
...defaultOpenGraph,
type: 'website',
title,
description: groupDesc,
url: path,
images: ogImages,
},
alternates: { canonical: path },
}),
});
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { createPage } from '@/app/_helpers';
import { getServerTranslation } from '@/shared/i18n';
import { notFound } from 'next/navigation';
import { color, HeroManager, HeroSlug } from '@/entities/Hero';
import { color, HeroManager, HeroSlug, HeroWithGroup } from '@/entities/Hero';
import { HeroDevelopmentPageProps } from '@/preparedPages/HeroDevelopmentPage';
import { getRouteOneHeroDevPage } from '@/shared/appLinks/RoutePaths';
import { baseUrl, defaultOpenGraph } from '@/shared/seoConstants';

function getOgImageUrl(hero: HeroWithGroup) {
const src = typeof hero.srcImg === 'string' ? hero.srcImg : hero.srcImg.src;
return /^https?:\/\//i.test(src) ? src : `${baseUrl}${src}`;
}

export async function _getPage(lng: string, slug: string) {
const { t } = await getServerTranslation(lng, 'heroes');
Expand All @@ -15,14 +22,35 @@ export async function _getPage(lng: string, slug: string) {
stat.color = color[stat.name];
});

// Routes & SEO
const relPath = getRouteOneHeroDevPage(encodeURIComponent(currentHero.slug));
const path = `/${lng}${relPath}`;
const title = currentHero.title;
const description = currentHero.description;
const keywords = `${t('head-keywords')}, ${currentHero.title}, ${currentHero.groupEnum}, ${currentHero.groupName}`;
const ogImageUrl = getOgImageUrl(currentHero);
const ogImage = ogImageUrl
? ({ url: ogImageUrl, alt: `${title} - ${currentHero.groupName}` } as const)
: null;
const ogImages = ogImage ? [ogImage] : (defaultOpenGraph.images ?? []);

return createPage<HeroDevelopmentPageProps>({
buildPage: () => ({
hero: currentHero,
}),
buildSeo: () => ({
title: currentHero.title,
description: currentHero.description,
keywords: `${t('head-keywords')}, ${currentHero.title}, ${currentHero.groupEnum}, ${currentHero.groupName}`,
title,
description,
keywords,
openGraph: {
...defaultOpenGraph,
type: 'website',
title,
description,
url: path,
images: ogImages,
},
alternates: { canonical: path },
}),
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import { notFound } from 'next/navigation';
import { HeroManager, HeroSlug, HeroWithGroup } from '@/entities/Hero';
import { getRouteOneHeroPage } from '@/shared/appLinks/RoutePaths';
import { SingleHeroPageProps } from '@/preparedPages/HeroesPages';
import { baseUrl, defaultOpenGraph } from '@/shared/seoConstants';

function getOgImageUrl(hero: HeroWithGroup) {
const src = typeof hero.srcImg === 'string' ? hero.srcImg : hero.srcImg.src;
return /^https?:\/\//i.test(src) ? src : `${baseUrl}${src}`;
}

export async function _getPage(lng: string, slug: string) {
const { t } = await getServerTranslation(lng, 'heroes');
Expand All @@ -14,14 +20,47 @@ export async function _getPage(lng: string, slug: string) {
notFound();
}

const heroes = heroManager.getAllHeroes();
const prevHero =
heroManager.getHeroBeforeSpecificHero(currentHero.id) || (heroes.at(-1) as HeroWithGroup);
const nextHero =
heroManager.getHeroAfterSpecificHero(currentHero.id) || (heroes.at(0) as HeroWithGroup);

const prevHeroLink = getRouteOneHeroPage(prevHero.slug);
const nextHeroLink = getRouteOneHeroPage(nextHero.slug);

// Routes & SEO
const relPath = getRouteOneHeroPage(encodeURIComponent(currentHero.slug));
const path = `/${lng}${relPath}`;
const title = currentHero.title;
const description = currentHero.description;
const keywords = `${t('head-keywords')}, ${currentHero.title}, ${currentHero.groupEnum}, ${currentHero.groupName}`;
const ogImageUrl = getOgImageUrl(currentHero);
const ogImage = ogImageUrl
? ({ url: ogImageUrl, alt: `${title} - ${currentHero.groupName}` } as const)
: null;
const ogImages = ogImage ? [ogImage] : (defaultOpenGraph.images ?? []);

return createPage<SingleHeroPageProps>({
buildPage: () => ({
slug: slug as HeroSlug,
slug: currentHero.slug,
newSelectedHero: currentHero,
prevHeroLink: prevHeroLink,
nextHeroLink: nextHeroLink,
}),
buildSeo: () => ({
title: currentHero.title,
description: currentHero.description,
keywords: `${t('head-keywords')}, ${currentHero.title}, ${currentHero.groupEnum}, ${currentHero.groupName}`,
title,
description,
keywords,
openGraph: {
...defaultOpenGraph,
type: 'website',
title,
description,
url: path,
images: ogImages,
},
alternates: { canonical: path },
}),
});
}
Loading