feat(technologies): add full stack directory and home preview
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
import { TechnologiesContent } from "@/components/technologies-content";
|
||||
import { getStaticPageMetadata } from "@/lib/seo";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>;
|
||||
}) {
|
||||
const { locale } = await params;
|
||||
|
||||
return getStaticPageMetadata({
|
||||
locale,
|
||||
page: "technologies",
|
||||
path: "/technologies",
|
||||
});
|
||||
}
|
||||
|
||||
export default function TechnologiesPage() {
|
||||
return <TechnologiesContent />;
|
||||
}
|
||||
@@ -25,6 +25,7 @@ const STATIC_ROUTES = [
|
||||
{ path: "/projects", changeFrequency: "monthly", priority: 0.8 },
|
||||
{ path: "/content", changeFrequency: "weekly", priority: 0.7 },
|
||||
{ path: "/gallery", changeFrequency: "monthly", priority: 0.6 },
|
||||
{ path: "/technologies", changeFrequency: "monthly", priority: 0.7 },
|
||||
{ path: "/contact", changeFrequency: "yearly", priority: 0.5 },
|
||||
{ path: "/media-kit", changeFrequency: "monthly", priority: 0.6 },
|
||||
{ path: "/links", changeFrequency: "monthly", priority: 0.4 },
|
||||
|
||||
@@ -1,61 +1,62 @@
|
||||
"use client";
|
||||
|
||||
import { Icon } from "@iconify/react";
|
||||
import { useLocale, useTranslations } from "next-intl";
|
||||
import { Badge, Typography } from "poyraz-ui/atoms";
|
||||
import { useTranslations } from "next-intl";
|
||||
import {
|
||||
Button,
|
||||
ButtonIcon,
|
||||
ButtonLabel,
|
||||
Typography,
|
||||
} from "poyraz-ui/atoms";
|
||||
import { TECHNOLOGY_STACK } from "@/data/technology-stack";
|
||||
import { getLocalizedValue } from "@/lib/locale";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import { TechnologyBadge } from "@/components/technology-badge";
|
||||
|
||||
export function HomeTechnologyStack() {
|
||||
const t = useTranslations("Home");
|
||||
const locale = useLocale();
|
||||
const technologies = TECHNOLOGY_STACK.flatMap((group) => group.items);
|
||||
|
||||
return (
|
||||
<section
|
||||
className="space-y-4 pb-4 pt-12 md:pt-14"
|
||||
className="space-y-4 pt-12 md:pt-14"
|
||||
aria-labelledby="home-technology-stack-title"
|
||||
>
|
||||
<Typography
|
||||
id="home-technology-stack-title"
|
||||
variant="h3"
|
||||
component="h2"
|
||||
className="tracking-[-0.035em]"
|
||||
>
|
||||
{t("technologiesTitle")}
|
||||
</Typography>
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<Typography
|
||||
id="home-technology-stack-title"
|
||||
variant="h3"
|
||||
component="h2"
|
||||
className="tracking-[-0.035em]"
|
||||
>
|
||||
{t("technologiesTitle")}
|
||||
</Typography>
|
||||
|
||||
<div className="grid gap-x-8 gap-y-6 md:grid-cols-2">
|
||||
{TECHNOLOGY_STACK.map((group) => (
|
||||
<div key={group.id} className="space-y-2.5 border-t border-border pt-3">
|
||||
<Typography
|
||||
variant="small"
|
||||
component="h3"
|
||||
className="text-xs font-medium uppercase tracking-[0.08em] text-muted-foreground"
|
||||
>
|
||||
{t(`technologyCategories.${group.id}`)}
|
||||
</Typography>
|
||||
<Button
|
||||
asChild
|
||||
size="sm"
|
||||
radius="sm"
|
||||
effect="swap"
|
||||
swapTarget="both"
|
||||
>
|
||||
<Link href="/technologies">
|
||||
<ButtonLabel>{t("allTechnologies")}</ButtonLabel>
|
||||
<ButtonIcon>
|
||||
<Icon icon="mdi:arrow-right" width={15} height={15} />
|
||||
</ButtonIcon>
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{group.items.map((technology) => (
|
||||
<Badge
|
||||
key={technology.id}
|
||||
variant="secondary"
|
||||
radius="sm"
|
||||
className="gap-1.5 px-2.5 py-1 text-xs font-medium text-foreground"
|
||||
>
|
||||
<Icon
|
||||
icon={technology.icon}
|
||||
width={14}
|
||||
height={14}
|
||||
aria-hidden="true"
|
||||
className="shrink-0"
|
||||
/>
|
||||
<span>{getLocalizedValue(technology.label, locale)}</span>
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div className="relative max-h-14 overflow-hidden border-t border-border pt-3">
|
||||
<div className="flex flex-wrap gap-2" aria-label={t("technologiesTitle")}>
|
||||
{technologies.map((technology) => (
|
||||
<TechnologyBadge key={technology.id} technology={technology} />
|
||||
))}
|
||||
</div>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute inset-x-0 bottom-0 h-6 bg-gradient-to-t from-background via-background/85 to-transparent backdrop-blur-[2px]"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslations } from "next-intl";
|
||||
import { Card, Typography } from "poyraz-ui/atoms";
|
||||
import { TechnologyBadge } from "@/components/technology-badge";
|
||||
import { TECHNOLOGY_STACK } from "@/data/technology-stack";
|
||||
|
||||
export function TechnologiesContent() {
|
||||
const t = useTranslations("Technologies");
|
||||
|
||||
return (
|
||||
<section className="flex h-full flex-col gap-10">
|
||||
<header className="border-b border-border py-4 sm:py-5">
|
||||
<Typography
|
||||
variant="h2"
|
||||
component="h1"
|
||||
className="font-secondary text-2xl font-semibold leading-none tracking-[-0.045em] text-foreground"
|
||||
>
|
||||
{t("title")}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="small"
|
||||
className="mt-2 max-w-2xl text-xs leading-5 text-muted-foreground sm:text-sm"
|
||||
>
|
||||
{t("description")}
|
||||
</Typography>
|
||||
</header>
|
||||
|
||||
<div className="grid gap-3 md:grid-cols-2">
|
||||
{TECHNOLOGY_STACK.map((group) => (
|
||||
<Card
|
||||
key={group.id}
|
||||
role="region"
|
||||
className="rounded-sm border-border p-4"
|
||||
aria-labelledby={`technology-group-${group.id}`}
|
||||
>
|
||||
<Typography
|
||||
id={`technology-group-${group.id}`}
|
||||
variant="large"
|
||||
component="h2"
|
||||
className="text-sm font-semibold tracking-[-0.02em]"
|
||||
>
|
||||
{t(`categories.${group.id}`)}
|
||||
</Typography>
|
||||
|
||||
<div className="mt-3 flex flex-wrap gap-2">
|
||||
{group.items.map((technology) => (
|
||||
<TechnologyBadge
|
||||
key={technology.id}
|
||||
technology={technology}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
"use client";
|
||||
|
||||
import { Icon } from "@iconify/react";
|
||||
import { useLocale } from "next-intl";
|
||||
import { Badge } from "poyraz-ui/atoms";
|
||||
import type { TechnologyStackItem } from "@/data/technology-stack";
|
||||
import { getLocalizedValue } from "@/lib/locale";
|
||||
|
||||
export function TechnologyBadge({
|
||||
technology,
|
||||
}: {
|
||||
technology: TechnologyStackItem;
|
||||
}) {
|
||||
const locale = useLocale();
|
||||
|
||||
return (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
radius="sm"
|
||||
className="shrink-0 gap-1.5 px-2.5 py-1 text-xs font-medium text-foreground"
|
||||
>
|
||||
<Icon
|
||||
icon={technology.icon}
|
||||
width={14}
|
||||
height={14}
|
||||
aria-hidden="true"
|
||||
className="shrink-0"
|
||||
/>
|
||||
<span>{getLocalizedValue(technology.label, locale)}</span>
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
@@ -7,7 +7,7 @@ export type TechnologyStackItem = {
|
||||
};
|
||||
|
||||
export type TechnologyStackGroup = {
|
||||
id: "frontend" | "backend" | "languages" | "designTools";
|
||||
id: "frontend" | "backend" | "databases" | "languages" | "designTools";
|
||||
items: readonly TechnologyStackItem[];
|
||||
};
|
||||
|
||||
@@ -56,7 +56,6 @@ export const TECHNOLOGY_STACK: readonly TechnologyStackGroup[] = [
|
||||
icon: "simple-icons:jsonwebtokens",
|
||||
},
|
||||
{ id: "prisma", label: "Prisma", icon: "simple-icons:prisma" },
|
||||
{ id: "mongoose", label: "Mongoose", icon: "simple-icons:mongoose" },
|
||||
{
|
||||
id: "socket-io",
|
||||
label: "Socket.io",
|
||||
@@ -64,6 +63,24 @@ export const TECHNOLOGY_STACK: readonly TechnologyStackGroup[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "databases",
|
||||
items: [
|
||||
{ id: "mongodb", label: "MongoDB", icon: "simple-icons:mongodb" },
|
||||
{ id: "mongoose", label: "Mongoose", icon: "simple-icons:mongoose" },
|
||||
{
|
||||
id: "postgresql",
|
||||
label: "PostgreSQL",
|
||||
icon: "simple-icons:postgresql",
|
||||
},
|
||||
{ id: "mysql", label: "MySQL", icon: "simple-icons:mysql" },
|
||||
{
|
||||
id: "mssql",
|
||||
label: "Microsoft SQL Server",
|
||||
icon: "simple-icons:microsoftsqlserver",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "languages",
|
||||
items: [
|
||||
|
||||
@@ -87,6 +87,21 @@ export const NAV_DROPDOWN_GROUPS = [
|
||||
external: false,
|
||||
keywords: ["animasyon", "animation", "kaynak", "resource", "motion"],
|
||||
},
|
||||
{
|
||||
id: "technologies",
|
||||
label: "Teknolojiler",
|
||||
href: "/technologies",
|
||||
icon: "mdi:layers-triple-outline",
|
||||
external: false,
|
||||
keywords: [
|
||||
"teknolojiler",
|
||||
"technologies",
|
||||
"tech stack",
|
||||
"araçlar",
|
||||
"tools",
|
||||
"skills",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
] as const;
|
||||
|
||||
@@ -30,6 +30,7 @@ type StaticSeoPage =
|
||||
| "projects"
|
||||
| "content"
|
||||
| "gallery"
|
||||
| "technologies"
|
||||
| "links"
|
||||
| "contact";
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"socialLinks": "Social Links",
|
||||
"others": "Others",
|
||||
"animationResources": "Animation Resources",
|
||||
"technologies": "Technologies",
|
||||
"links": "Links",
|
||||
"mediaKit": "Media Kit",
|
||||
"references": "References",
|
||||
@@ -34,9 +35,11 @@
|
||||
"reviewsAndReferences": "Reviews & References",
|
||||
"allReferences": "All references",
|
||||
"technologiesTitle": "Technologies I use",
|
||||
"allTechnologies": "Explore all technologies",
|
||||
"technologyCategories": {
|
||||
"frontend": "Front End",
|
||||
"backend": "Back End",
|
||||
"databases": "Databases",
|
||||
"languages": "Programming Languages",
|
||||
"designTools": "Design & Tools"
|
||||
},
|
||||
@@ -216,6 +219,17 @@
|
||||
"resources": "Resources"
|
||||
}
|
||||
},
|
||||
"Technologies": {
|
||||
"title": "Technologies I Use",
|
||||
"description": "The front-end, back-end, database, programming language, design, and development tools I use to build products.",
|
||||
"categories": {
|
||||
"frontend": "Front End",
|
||||
"backend": "Back End",
|
||||
"databases": "Databases",
|
||||
"languages": "Programming Languages",
|
||||
"designTools": "Design & Tools"
|
||||
}
|
||||
},
|
||||
"Gallery": {
|
||||
"empty": "No images added to the gallery yet.",
|
||||
"close": "Close",
|
||||
@@ -255,6 +269,10 @@
|
||||
"title": "Gallery",
|
||||
"description": "Selected images from Poyraz Avsever's events, presentations, projects, and community work."
|
||||
},
|
||||
"technologies": {
|
||||
"title": "Technologies I Use",
|
||||
"description": "Explore the front-end, back-end, database, programming language, and development tools Poyraz Avsever uses to build products."
|
||||
},
|
||||
"links": {
|
||||
"title": "Links",
|
||||
"description": "Access Poyraz Avsever's social profiles, projects, content, and essential links from one page."
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"socialLinks": "Sosyal Bağlantılar",
|
||||
"others": "Diğerleri",
|
||||
"animationResources": "Animasyon Kaynakları",
|
||||
"technologies": "Teknolojiler",
|
||||
"links": "Bağlantılar",
|
||||
"mediaKit": "Medya Kiti",
|
||||
"references": "Referanslar",
|
||||
@@ -34,9 +35,11 @@
|
||||
"reviewsAndReferences": "Yorumlar & Referanslar",
|
||||
"allReferences": "Tüm referanslar",
|
||||
"technologiesTitle": "Ben bu teknolojileri kullanıyorum",
|
||||
"allTechnologies": "Tüm teknolojileri incele",
|
||||
"technologyCategories": {
|
||||
"frontend": "Ön Yüz",
|
||||
"backend": "Arka Yüz",
|
||||
"databases": "Veritabanları",
|
||||
"languages": "Programlama Dilleri",
|
||||
"designTools": "Tasarım ve Araçlar"
|
||||
},
|
||||
@@ -216,6 +219,17 @@
|
||||
"resources": "Kaynaklar"
|
||||
}
|
||||
},
|
||||
"Technologies": {
|
||||
"title": "Kullandığım Teknolojiler",
|
||||
"description": "Ürün geliştirirken kullandığım ön yüz, arka yüz, veritabanı, programlama dili, tasarım ve geliştirme araçları.",
|
||||
"categories": {
|
||||
"frontend": "Ön Yüz",
|
||||
"backend": "Arka Yüz",
|
||||
"databases": "Veritabanları",
|
||||
"languages": "Programlama Dilleri",
|
||||
"designTools": "Tasarım ve Araçlar"
|
||||
}
|
||||
},
|
||||
"Gallery": {
|
||||
"empty": "Henüz galeriye görsel eklenmemiş.",
|
||||
"close": "Kapat",
|
||||
@@ -255,6 +269,10 @@
|
||||
"title": "Galeri",
|
||||
"description": "Poyraz Avsever'in etkinlik, sunum, proje ve topluluk çalışmalarından seçilmiş görseller."
|
||||
},
|
||||
"technologies": {
|
||||
"title": "Kullandığım Teknolojiler",
|
||||
"description": "Poyraz Avsever'in ürün geliştirirken kullandığı ön yüz, arka yüz, veritabanı, programlama dili ve geliştirme araçlarını inceleyin."
|
||||
},
|
||||
"links": {
|
||||
"title": "Bağlantılar",
|
||||
"description": "Poyraz Avsever'in sosyal medya hesaplarına, projelerine, içeriklerine ve hızlı erişim bağlantılarına tek sayfadan ulaşın."
|
||||
|
||||
Reference in New Issue
Block a user