feat(home): add technology stack section
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { HomeHero } from "@/components/home-hero";
|
import { HomeHero } from "@/components/home-hero";
|
||||||
import { HomeProjectsSection } from "@/components/home-projects-section";
|
import { HomeProjectsSection } from "@/components/home-projects-section";
|
||||||
|
import { HomeTechnologyStack } from "@/components/home-technology-stack";
|
||||||
import { HomeVideosSection } from "@/components/home-videos-section";
|
import { HomeVideosSection } from "@/components/home-videos-section";
|
||||||
import { ReferencesSection } from "@/components/references-section";
|
import { ReferencesSection } from "@/components/references-section";
|
||||||
import { getHomeBlogNews } from "@/data/blog";
|
import { getHomeBlogNews } from "@/data/blog";
|
||||||
@@ -29,7 +30,9 @@ export default async function Home({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="flex h-full flex-col overflow-y-auto overflow-x-hidden">
|
<section className="flex h-full flex-col overflow-y-auto overflow-x-hidden">
|
||||||
<HomeHero news={homeNews} />
|
<HomeHero news={homeNews}>
|
||||||
|
<HomeTechnologyStack />
|
||||||
|
</HomeHero>
|
||||||
<HomeProjectsSection />
|
<HomeProjectsSection />
|
||||||
<ReferencesSection />
|
<ReferencesSection />
|
||||||
<HomeVideosSection />
|
<HomeVideosSection />
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import type { ReactNode } from "react";
|
||||||
import { Icon } from "@iconify/react";
|
import { Icon } from "@iconify/react";
|
||||||
import { useLocale, useTranslations } from "next-intl";
|
import { useLocale, useTranslations } from "next-intl";
|
||||||
import { useRouter } from "@/i18n/routing";
|
import { useRouter } from "@/i18n/routing";
|
||||||
@@ -10,10 +11,11 @@ import {
|
|||||||
TextEffect,
|
TextEffect,
|
||||||
Typography,
|
Typography,
|
||||||
} from "poyraz-ui/atoms";
|
} from "poyraz-ui/atoms";
|
||||||
import { NewsCard } from "poyraz-ui/molecules";
|
|
||||||
import { getResumeHref } from "@/lib/links";
|
import { getResumeHref } from "@/lib/links";
|
||||||
|
import { HomeNewsCard } from "@/components/home-news-card";
|
||||||
|
|
||||||
type HomeHeroProps = {
|
type HomeHeroProps = {
|
||||||
|
children?: ReactNode;
|
||||||
news: {
|
news: {
|
||||||
id: string;
|
id: string;
|
||||||
category: string;
|
category: string;
|
||||||
@@ -24,7 +26,7 @@ type HomeHeroProps = {
|
|||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export function HomeHero({ news }: HomeHeroProps) {
|
export function HomeHero({ children, news }: HomeHeroProps) {
|
||||||
const t = useTranslations("Home");
|
const t = useTranslations("Home");
|
||||||
const locale = useLocale();
|
const locale = useLocale();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -89,6 +91,8 @@ export function HomeHero({ news }: HomeHeroProps) {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{children}
|
||||||
|
|
||||||
<section className="space-y-3 pt-12 md:pt-14">
|
<section className="space-y-3 pt-12 md:pt-14">
|
||||||
<div className="flex items-center justify-between gap-4">
|
<div className="flex items-center justify-between gap-4">
|
||||||
<Typography
|
<Typography
|
||||||
@@ -116,15 +120,15 @@ export function HomeHero({ news }: HomeHeroProps) {
|
|||||||
|
|
||||||
<div className="relative overflow-hidden py-1">
|
<div className="relative overflow-hidden py-1">
|
||||||
<div className="flex w-max items-stretch gap-3">
|
<div className="flex w-max items-stretch gap-3">
|
||||||
{news.map((item) => (
|
{news.map((item, index) => (
|
||||||
<NewsCard
|
<HomeNewsCard
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className="w-72 shrink-0 rounded-sm border-border"
|
|
||||||
category={item.category}
|
category={item.category}
|
||||||
title={item.title}
|
title={item.title}
|
||||||
date={item.date}
|
date={item.date}
|
||||||
image={item.image}
|
image={item.image}
|
||||||
href={item.href}
|
href={item.href}
|
||||||
|
priority={index === 0}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import Image from "next/image";
|
||||||
|
import { Badge, Card } from "poyraz-ui/atoms";
|
||||||
|
import { Link } from "@/i18n/routing";
|
||||||
|
|
||||||
|
type HomeNewsCardProps = {
|
||||||
|
category: string;
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
image: string;
|
||||||
|
href: string;
|
||||||
|
priority?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function HomeNewsCard({
|
||||||
|
category,
|
||||||
|
title,
|
||||||
|
date,
|
||||||
|
image,
|
||||||
|
href,
|
||||||
|
priority = false,
|
||||||
|
}: HomeNewsCardProps) {
|
||||||
|
return (
|
||||||
|
<Link href={href} className="block w-72 shrink-0 text-inherit no-underline">
|
||||||
|
<Card
|
||||||
|
variant="interactive"
|
||||||
|
className="group h-fit self-start overflow-hidden rounded-sm border-border"
|
||||||
|
>
|
||||||
|
<div className="flex min-h-28">
|
||||||
|
<div className="relative w-28 shrink-0 overflow-hidden border-r border-border">
|
||||||
|
<Image
|
||||||
|
src={image}
|
||||||
|
alt=""
|
||||||
|
fill
|
||||||
|
sizes="112px"
|
||||||
|
preload={priority}
|
||||||
|
className="object-cover transition-transform duration-300 group-hover:scale-105"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex min-w-0 flex-col justify-center gap-2 p-4">
|
||||||
|
<Badge size="sm" variant="outline">
|
||||||
|
{category}
|
||||||
|
</Badge>
|
||||||
|
<h3 className="line-clamp-2 text-sm font-semibold leading-snug">
|
||||||
|
{title}
|
||||||
|
</h3>
|
||||||
|
<span className="text-xs text-muted-foreground">{date}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Icon } from "@iconify/react";
|
||||||
|
import { useLocale, useTranslations } from "next-intl";
|
||||||
|
import { Badge, Typography } from "poyraz-ui/atoms";
|
||||||
|
import { TECHNOLOGY_STACK } from "@/data/technology-stack";
|
||||||
|
import { getLocalizedValue } from "@/lib/locale";
|
||||||
|
|
||||||
|
export function HomeTechnologyStack() {
|
||||||
|
const t = useTranslations("Home");
|
||||||
|
const locale = useLocale();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
className="space-y-4 pb-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="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>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
import type { Localized } from "@/lib/locale";
|
||||||
|
|
||||||
|
export type TechnologyStackItem = {
|
||||||
|
id: string;
|
||||||
|
label: string | Localized;
|
||||||
|
icon: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TechnologyStackGroup = {
|
||||||
|
id: "frontend" | "backend" | "languages" | "designTools";
|
||||||
|
items: readonly TechnologyStackItem[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TECHNOLOGY_STACK: readonly TechnologyStackGroup[] = [
|
||||||
|
{
|
||||||
|
id: "frontend",
|
||||||
|
items: [
|
||||||
|
{ id: "react", label: "React.js", icon: "simple-icons:react" },
|
||||||
|
{ id: "nextjs", label: "Next.js", icon: "simple-icons:nextdotjs" },
|
||||||
|
{ id: "angular", label: "Angular", icon: "simple-icons:angular" },
|
||||||
|
{
|
||||||
|
id: "react-native",
|
||||||
|
label: "React Native",
|
||||||
|
icon: "mdi:react",
|
||||||
|
},
|
||||||
|
{ id: "electron", label: "Electron.js", icon: "simple-icons:electron" },
|
||||||
|
{
|
||||||
|
id: "tailwindcss",
|
||||||
|
label: "Tailwind CSS",
|
||||||
|
icon: "simple-icons:tailwindcss",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "bootstrap",
|
||||||
|
label: "Bootstrap",
|
||||||
|
icon: "simple-icons:bootstrap",
|
||||||
|
},
|
||||||
|
{ id: "redux", label: "Redux", icon: "simple-icons:redux" },
|
||||||
|
{ id: "zustand", label: "Zustand", icon: "devicon:zustand" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "backend",
|
||||||
|
items: [
|
||||||
|
{ id: "nodejs", label: "Node.js", icon: "simple-icons:nodedotjs" },
|
||||||
|
{ id: "express", label: "Express.js", icon: "simple-icons:express" },
|
||||||
|
{ id: "nestjs", label: "Nest.js", icon: "simple-icons:nestjs" },
|
||||||
|
{ id: "dotnet", label: ".NET", icon: "simple-icons:dotnet" },
|
||||||
|
{
|
||||||
|
id: "rest-api",
|
||||||
|
label: { tr: "REST API'ler", en: "REST APIs" },
|
||||||
|
icon: "mdi:api",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "jwt-auth",
|
||||||
|
label: "JWT Auth",
|
||||||
|
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",
|
||||||
|
icon: "simple-icons:socketdotio",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "languages",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: "javascript",
|
||||||
|
label: "JavaScript",
|
||||||
|
icon: "simple-icons:javascript",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "typescript",
|
||||||
|
label: "TypeScript",
|
||||||
|
icon: "simple-icons:typescript",
|
||||||
|
},
|
||||||
|
{ id: "csharp", label: "C#", icon: "mdi:language-csharp" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "designTools",
|
||||||
|
items: [
|
||||||
|
{ id: "figma", label: "Figma", icon: "simple-icons:figma" },
|
||||||
|
{
|
||||||
|
id: "wireframing",
|
||||||
|
label: "Wireframing",
|
||||||
|
icon: "mdi:vector-square",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "design-systems",
|
||||||
|
label: { tr: "Tasarım Sistemleri", en: "Design Systems" },
|
||||||
|
icon: "mdi:palette-swatch-outline",
|
||||||
|
},
|
||||||
|
{ id: "git", label: "Git", icon: "simple-icons:git" },
|
||||||
|
{ id: "github", label: "GitHub", icon: "simple-icons:github" },
|
||||||
|
{ id: "firebase", label: "Firebase", icon: "simple-icons:firebase" },
|
||||||
|
{ id: "supabase", label: "Supabase", icon: "simple-icons:supabase" },
|
||||||
|
{
|
||||||
|
id: "vercel-ai-sdk",
|
||||||
|
label: "Vercel AI SDK",
|
||||||
|
icon: "simple-icons:vercel",
|
||||||
|
},
|
||||||
|
{ id: "postman", label: "Postman", icon: "simple-icons:postman" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -33,6 +33,13 @@
|
|||||||
"allProjects": "All projects",
|
"allProjects": "All projects",
|
||||||
"reviewsAndReferences": "Reviews & References",
|
"reviewsAndReferences": "Reviews & References",
|
||||||
"allReferences": "All references",
|
"allReferences": "All references",
|
||||||
|
"technologiesTitle": "Technologies I use",
|
||||||
|
"technologyCategories": {
|
||||||
|
"frontend": "Front End",
|
||||||
|
"backend": "Back End",
|
||||||
|
"languages": "Programming Languages",
|
||||||
|
"designTools": "Design & Tools"
|
||||||
|
},
|
||||||
"sections": {
|
"sections": {
|
||||||
"recentPosts": "Recent Posts",
|
"recentPosts": "Recent Posts",
|
||||||
"references": "References",
|
"references": "References",
|
||||||
|
|||||||
@@ -33,6 +33,13 @@
|
|||||||
"allProjects": "Tüm projeler",
|
"allProjects": "Tüm projeler",
|
||||||
"reviewsAndReferences": "Yorumlar & Referanslar",
|
"reviewsAndReferences": "Yorumlar & Referanslar",
|
||||||
"allReferences": "Tüm referanslar",
|
"allReferences": "Tüm referanslar",
|
||||||
|
"technologiesTitle": "Ben bu teknolojileri kullanıyorum",
|
||||||
|
"technologyCategories": {
|
||||||
|
"frontend": "Ön Yüz",
|
||||||
|
"backend": "Arka Yüz",
|
||||||
|
"languages": "Programlama Dilleri",
|
||||||
|
"designTools": "Tasarım ve Araçlar"
|
||||||
|
},
|
||||||
"sections": {
|
"sections": {
|
||||||
"recentPosts": "Son Yazılar",
|
"recentPosts": "Son Yazılar",
|
||||||
"references": "Referanslar",
|
"references": "Referanslar",
|
||||||
|
|||||||
Reference in New Issue
Block a user