feat: render locale-aware portfolio routes

This commit is contained in:
2026-09-08 19:21:26 +03:30
parent 3bb6b4396c
commit 3af34dbd92
22 changed files with 797 additions and 186 deletions

View File

@@ -1,6 +1,6 @@
'use client';
import React, { useState } from 'react';
import { useState } from 'react';
import type { ContactItem, FooterContactId } from './IsoTypes';
import IsometricScene from './IsometricScene';
import {
@@ -11,6 +11,7 @@ import {
TelegramIcon,
} from './IsoElements';
import styles from './IsometricFooter.module.css';
import { messagesByLocale, type Locale } from '@/i18n/content';
export const contacts: ContactItem[] = [
{
@@ -43,7 +44,12 @@ export const contacts: ContactItem[] = [
},
];
export default function IsometricFooter() {
export default function IsometricFooter({ locale }: { locale: Locale }) {
const copy = messagesByLocale[locale].footer;
const localizedContacts = contacts.map((contact) => ({
...contact,
name: copy[contact.id],
}));
const [activePost, setActivePost] = useState<FooterContactId | null>(null);
const handlePostClick = (id: FooterContactId) => {
@@ -62,11 +68,11 @@ export default function IsometricFooter() {
{/* Top Header & Contact Section */}
<header className={styles.footerHeader}>
<h2 className={styles.headerTitle}>
Let&apos;s build something meaningful.
{copy.title}
</h2>
<p className={styles.headerSubtitle}>
Open to opportunities and interesting projects.
{copy.subtitle}
</p>
{/* Email Pill Button */}
@@ -74,12 +80,14 @@ export default function IsometricFooter() {
<a
href="mailto:amirhosseinkhalili901@gmail.com"
className={styles.emailPill}
aria-label="Send email to amirhosseinkhalili901@gmail.com"
aria-label={copy.emailLabel}
>
<span className={styles.emailIcon}>
<MailIcon size={16} color="currentColor" />
</span>
<span className={styles.emailText}>amirhosseinkhalili901@gmail.com</span>
<span className={styles.emailText} dir="ltr">
amirhosseinkhalili901@gmail.com
</span>
</a>
</div>
</header>
@@ -88,15 +96,16 @@ export default function IsometricFooter() {
<div className={styles.sceneContainer} data-footer-reveal>
<IsometricScene
activePost={activePost}
ariaLabel={copy.sceneLabel}
onPostHover={setActivePost}
onPostClick={handlePostClick}
/>
</div>
{/* Responsive Synchronized Contact Cards Section */}
<section className={styles.contactCardsSection} aria-label="Social and contact links">
<section className={styles.contactCardsSection} aria-label={copy.contactsLabel}>
<div className={styles.contactCardsGrid}>
{contacts.map((contact) => {
{localizedContacts.map((contact) => {
const IconComponent = contact.Icon;
const isHovered = activePost === contact.id;
return (
@@ -116,7 +125,9 @@ export default function IsometricFooter() {
</div>
<div className={styles.contactCardInfo}>
<span className={styles.contactCardName}>{contact.name}</span>
<span className={styles.contactCardLabel}>{contact.label}</span>
<span className={styles.contactCardLabel} dir="ltr">
{contact.label}
</span>
</div>
</a>
);