Merge branch 'newPoyrazUı' of https://github.com/poyrazavsever/poyraz-portfolio into newPoyrazUı

This commit is contained in:
Poyraz
2026-07-22 09:33:12 +03:00
10 changed files with 262 additions and 127 deletions
+1 -3
View File
@@ -2,7 +2,6 @@ import { HomeHero } from "@/components/home-hero";
import { HomeProjectsSection } from "@/components/home-projects-section"; import { HomeProjectsSection } from "@/components/home-projects-section";
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 { SponsorsSection } from "@/components/sponsors-section";
import { getHomeBlogNews } from "@/data/blog"; import { getHomeBlogNews } from "@/data/blog";
export default async function Home({ export default async function Home({
@@ -14,12 +13,11 @@ export default async function Home({
const homeNews = await getHomeBlogNews(locale, 6); const homeNews = await getHomeBlogNews(locale, 6);
return ( return (
<section className="flex h-full flex-col gap-12 overflow-y-auto overflow-x-hidden md:gap-14"> <section className="flex h-full flex-col overflow-y-auto overflow-x-hidden">
<HomeHero news={homeNews} /> <HomeHero news={homeNews} />
<HomeProjectsSection /> <HomeProjectsSection />
<ReferencesSection /> <ReferencesSection />
<HomeVideosSection /> <HomeVideosSection />
<SponsorsSection />
</section> </section>
); );
} }
+229 -108
View File
@@ -1,133 +1,254 @@
"use client"; "use client";
import { Icon } from "@iconify/react";
import Image from "next/image"; import Image from "next/image";
import { Link } from "@/i18n/routing"; import { useLocale, useTranslations } from "next-intl";
import { Badge, Card, Typography } from "poyraz-ui/atoms"; import { Badge, Button, ButtonIcon, ButtonLabel, Card, Typography } from "poyraz-ui/atoms";
import { Sheet, SheetContent, SheetTitle, SheetTrigger } from "poyraz-ui/molecules"; import { Sheet, SheetContent, SheetTitle, SheetTrigger } from "poyraz-ui/molecules";
import { StaggerContainer, StaggerItem } from "@/components/motion-wrapper"; import { Link, useRouter } from "@/i18n/routing";
import { BOOKMARKS } from "@/data/bookmarks"; import { BOOKMARKS } from "@/data/bookmarks";
import { certificates } from "@/data/certificates"; import { certificates } from "@/data/certificates";
import { EDUCATION } from "@/data/education"; import { EDUCATION } from "@/data/education";
import { EXPERIENCE } from "@/data/experience"; import { EXPERIENCE } from "@/data/experience";
import { useTranslations, useLocale } from "next-intl";
import { getLocalizedValue } from "@/lib/locale"; import { getLocalizedValue } from "@/lib/locale";
type TimelineItem = {
id: string;
title: string;
subtitle: string;
period: string;
description?: string;
};
function SectionHeading({
title,
action,
}: {
title: string;
action?: React.ReactNode;
}) {
return (
<div className="flex items-center justify-between gap-4">
<Typography
variant="h3"
component="h2"
className="tracking-[-0.035em]"
>
{title}
</Typography>
{action}
</div>
);
}
function TimelineList({ items }: { items: TimelineItem[] }) {
return (
<div className="relative space-y-4 before:absolute before:top-3 before:bottom-3 before:left-3 before:w-px before:bg-border">
{items.map((item) => (
<div
key={item.id}
className="relative grid grid-cols-[1.5rem_1fr] gap-3"
>
<span className="mt-1 size-6 rounded-full border border-border bg-background p-1">
<span className="block size-full rounded-full bg-primary" />
</span>
<div className="border-b border-border pb-4">
<div className="flex flex-wrap items-start justify-between gap-3">
<div className="min-w-0 flex-1">
<Typography variant="large" className="text-base leading-tight">
{item.title}
</Typography>
<Typography
variant="small"
className="mt-0.5 text-muted-foreground"
>
{item.subtitle}
</Typography>
</div>
<Typography
variant="display"
className="shrink-0 text-right font-medium text-primary"
>
{item.period}
</Typography>
</div>
{item.description ? (
<Typography
variant="small"
className="mt-3 leading-relaxed text-muted-foreground"
>
{item.description}
</Typography>
) : null}
</div>
</div>
))}
</div>
);
}
export function AboutContent() { export function AboutContent() {
const t = useTranslations("About"); const t = useTranslations("About");
const locale = useLocale(); const locale = useLocale();
const router = useRouter();
const educationItems: TimelineItem[] = EDUCATION.map((item) => ({
id: item.id,
title: getLocalizedValue(item.title, locale),
subtitle: item.institution,
period: getLocalizedValue(item.period, locale),
}));
const experienceItems: TimelineItem[] = EXPERIENCE.map((item) => ({
id: item.id,
title: getLocalizedValue(item.role, locale),
subtitle: item.company,
period: getLocalizedValue(item.period, locale),
}));
return ( return (
<section className="flex h-full flex-col gap-3 overflow-hidden"> <section className="flex h-full flex-col gap-12 overflow-y-auto overflow-x-hidden">
<div className="grid gap-3 md:grid-cols-2"> <section className="space-y-3">
<Card className="rounded-sm border-border p-4"> <SectionHeading
<Typography variant="p" className="text-sm leading-relaxed text-muted-foreground"> title={t("title")}
{t("aboutText")} action={
</Typography> <Button
</Card>
<div>
<StaggerContainer className="grid gap-2">
{EDUCATION.map((item) => (
<StaggerItem key={item.id}>
<Card className="rounded-sm border-border p-3">
<Typography variant="large" className="text-base leading-tight">
{getLocalizedValue(item.title, locale)}
</Typography>
<Typography variant="small" className="mt-0.5 text-muted-foreground">
{item.institution}
</Typography>
<Typography variant="small" className="mt-1 text-red-600">
{getLocalizedValue(item.period, locale)}
</Typography>
</Card>
</StaggerItem>
))}
</StaggerContainer>
</div>
</div>
<div className="grid gap-3 md:grid-cols-2 md:items-start">
<Sheet>
<SheetTrigger asChild>
<button
type="button" type="button"
className="cursor-pointer text-left" size="sm"
aria-label="Tüm sertifikaları" radius="sm"
effect="swap"
swapTarget="both"
onClick={() => router.push("/contact")}
> >
<Card className="rounded-sm border-border p-4 transition-colors hover:border-zinc-700"> <ButtonLabel>{t("contactCta")}</ButtonLabel>
<div className="grid grid-cols-2 gap-2"> <ButtonIcon>
{certificates.slice(0, 4).map((item) => ( <Icon icon="mdi:arrow-right" width={15} height={15} />
<div </ButtonIcon>
key={getLocalizedValue(item.name, locale)} </Button>
className="relative aspect-4/3 overflow-hidden rounded-sm border border-border" }
/>
<Typography
variant="p"
className="max-w-3xl text-sm leading-7 text-muted-foreground"
>
{t("aboutText")}
</Typography>
</section>
<section className="space-y-10">
<div className="space-y-3">
<SectionHeading title={t("educationTitle")} />
<TimelineList items={educationItems} />
</div>
<div className="space-y-3">
<SectionHeading title={t("experienceTitle")} />
<TimelineList items={experienceItems} />
</div>
</section>
<section className="space-y-3">
<SectionHeading
title={t("certificatesTitle")}
action={
<Sheet>
<SheetTrigger asChild>
<Button
type="button"
size="sm"
radius="sm"
effect="swap"
swapTarget="both"
>
<ButtonLabel>{t("allCertificates")}</ButtonLabel>
<ButtonIcon>
<Icon icon="mdi:arrow-right" width={15} height={15} />
</ButtonIcon>
</Button>
</SheetTrigger>
<SheetContent side="right" className="w-full max-w-xl p-4">
<SheetTitle>{t("allCertificates")}</SheetTitle>
<div className="mt-4 grid max-h-[90dvh] gap-3 overflow-y-auto pr-1">
{certificates.map((item) => (
<Card
key={`${getLocalizedValue(item.name, locale)}-${getLocalizedValue(item.date, locale)}`}
className="rounded-sm border-border p-3"
> >
<Image <div className="flex gap-3">
src={item.image} <div className="relative h-20 w-28 shrink-0 overflow-hidden rounded-sm border border-border">
alt={getLocalizedValue(item.name, locale)} <Image
fill src={item.image}
sizes="(max-width: 768px) 45vw, 22vw" alt={getLocalizedValue(item.name, locale)}
className="object-cover" fill
/> sizes="112px"
</div> className="object-cover"
/>
</div>
<div className="min-w-0">
<Typography variant="large" className="leading-tight">
{getLocalizedValue(item.name, locale)}
</Typography>
<Typography
variant="small"
className="text-muted-foreground"
>
{item.organization}
</Typography>
<Typography variant="small" className="text-primary">
{getLocalizedValue(item.date, locale)}
</Typography>
</div>
</div>
</Card>
))} ))}
</div> </div>
</SheetContent>
</Sheet>
}
/>
<div className="relative overflow-hidden py-1">
<div className="flex w-max items-stretch gap-3">
{certificates.slice(0, 8).map((item) => (
<Card
key={`${getLocalizedValue(item.name, locale)}-${getLocalizedValue(item.date, locale)}`}
className="w-56 shrink-0 overflow-hidden rounded-sm border-border p-0"
>
<div className="relative aspect-4/3 overflow-hidden border-b border-border">
<Image
src={item.image}
alt={getLocalizedValue(item.name, locale)}
fill
sizes="224px"
className="object-cover"
/>
</div>
<div className="p-3">
<Typography variant="large" className="line-clamp-2 text-sm leading-tight">
{getLocalizedValue(item.name, locale)}
</Typography>
<Typography
variant="small"
className="mt-1 text-muted-foreground"
>
{item.organization}
</Typography>
</div>
</Card> </Card>
</button>
</SheetTrigger>
<SheetContent side="right" className="w-full max-w-xl p-4">
<SheetTitle>{t("allCertificates")}</SheetTitle>
<div className="mt-4 grid max-h-[90dvh] gap-3 overflow-y-auto pr-1">
{certificates.map((item) => (
<Card key={`${getLocalizedValue(item.name, locale)}-${getLocalizedValue(item.date, locale)}`} className="rounded-sm border-border p-3">
<div className="flex gap-3">
<div className="relative h-20 w-28 shrink-0 overflow-hidden rounded-sm border border-border">
<Image
src={item.image}
alt={getLocalizedValue(item.name, locale)}
fill
sizes="112px"
className="object-cover"
/>
</div>
<div className="min-w-0">
<Typography variant="large" className="leading-tight">
{getLocalizedValue(item.name, locale)}
</Typography>
<Typography variant="small" className="text-muted-foreground">
{item.organization}
</Typography>
<Typography variant="small" className="text-red-600">
{getLocalizedValue(item.date, locale)}
</Typography>
</div>
</div>
</Card>
))}
</div>
</SheetContent>
</Sheet>
<div className="h-full">
<StaggerContainer className="grid gap-2">
{EXPERIENCE.map((item) => (
<StaggerItem key={item.id}>
<Card className="rounded-sm border-border p-3">
<Typography variant="large" className="text-base leading-tight">
{getLocalizedValue(item.role, locale)}
</Typography>
<Typography variant="small" className="mt-0.5 text-muted-foreground">
{item.company}
</Typography>
<Typography variant="small" className="mt-1 text-red-600">
{getLocalizedValue(item.period, locale)}
</Typography>
</Card>
</StaggerItem>
))} ))}
</StaggerContainer> </div>
<div
aria-hidden="true"
className="pointer-events-none absolute top-0 right-0 h-full w-24 bg-gradient-to-l from-background via-background/80 to-transparent"
/>
</div> </div>
</div> </section>
<div className="grid gap-3 md:grid-cols-3"> <div className="grid gap-3 md:grid-cols-3">
<Link href="/about/references" className="block"> <Link href="/about/references" className="block">
@@ -190,7 +311,7 @@ export function AboutContent() {
href={item.href} href={item.href}
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
className="mt-2 inline-flex text-sm text-red-600 hover:underline" className="mt-2 inline-flex text-sm text-primary hover:underline"
> >
{item.href.replace("https://", "")} {item.href.replace("https://", "")}
</Link> </Link>
+2 -2
View File
@@ -31,7 +31,7 @@ export function HomeHero({ news }: HomeHeroProps) {
const router = useRouter(); const router = useRouter();
return ( return (
<section className="space-y-4"> <section>
<div className="relative grid min-h-[150px] overflow-hidden border-b border-border py-4 sm:grid-cols-[1fr_180px] sm:py-5"> <div className="relative grid min-h-[150px] overflow-hidden border-b border-border py-4 sm:grid-cols-[1fr_180px] sm:py-5">
<div className="flex max-w-2xl flex-col justify-center gap-2"> <div className="flex max-w-2xl flex-col justify-center gap-2">
<Typography <Typography
@@ -105,7 +105,7 @@ export function HomeHero({ news }: HomeHeroProps) {
</div> </div>
</div> </div>
<section className="space-y-3"> <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
variant="h3" variant="h3"
+5 -5
View File
@@ -12,10 +12,10 @@ export function HomeProjectsSection() {
const t = useTranslations("Home"); const t = useTranslations("Home");
const locale = useLocale(); const locale = useLocale();
const router = useRouter(); const router = useRouter();
const projects = WEB_APPS.slice(0, 4); const projects = WEB_APPS.slice(0, 5);
return ( return (
<section className="space-y-3"> <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
variant="h3" variant="h3"
@@ -41,7 +41,7 @@ export function HomeProjectsSection() {
</div> </div>
<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-2">
{projects.map((project) => ( {projects.map((project) => (
<ImageCard <ImageCard
key={project.id} key={project.id}
@@ -54,14 +54,14 @@ export function HomeProjectsSection() {
: undefined : undefined
} }
href={project.href} href={project.href}
className="aspect-square w-72 shrink-0 rounded-sm border-border" className="aspect-square w-56 shrink-0 rounded-sm border-border md:w-[calc((100vw-8rem)/4)] md:max-w-56"
/> />
))} ))}
</div> </div>
<div <div
aria-hidden="true" aria-hidden="true"
className="pointer-events-none absolute top-0 right-0 h-full w-24 bg-linear-to-l from-background via-background/80 to-transparent" className="pointer-events-none absolute top-0 right-0 h-full w-24 bg-gradient-to-l from-background via-background/80 to-transparent"
/> />
</div> </div>
</section> </section>
+1 -1
View File
@@ -10,7 +10,7 @@ export function HomeVideosSection() {
const t = useTranslations("Content"); const t = useTranslations("Content");
return ( return (
<section className="space-y-3"> <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
variant="h3" variant="h3"
+8 -2
View File
@@ -8,9 +8,15 @@ type ReferenceCardsProps = {
className?: string; className?: string;
cardClassName?: string; cardClassName?: string;
lineClamp?: boolean; lineClamp?: boolean;
showRating?: boolean;
}; };
export function ReferenceCards({ className, cardClassName, lineClamp }: ReferenceCardsProps) { export function ReferenceCards({
className,
cardClassName,
lineClamp,
showRating = true,
}: ReferenceCardsProps) {
const locale = useLocale(); const locale = useLocale();
const hoverClassName = const hoverClassName =
"transition-colors duration-200 group-hover:border-red-600/40 group-hover:bg-muted/30"; "transition-colors duration-200 group-hover:border-red-600/40 group-hover:bg-muted/30";
@@ -26,7 +32,7 @@ export function ReferenceCards({ className, cardClassName, lineClamp }: Referenc
author={item.author} author={item.author}
role={getLocalizedValue(item.role, locale)} role={getLocalizedValue(item.role, locale)}
avatar={item.avatar} avatar={item.avatar}
rating={item.rating} rating={showRating ? item.rating : undefined}
className={`flex flex-col rounded-sm ${lineClamp ? "[&_blockquote]:line-clamp-4" : ""} ${hoverClassName} ${cardClassName || "w-70 shrink-0"}`} className={`flex flex-col rounded-sm ${lineClamp ? "[&_blockquote]:line-clamp-4" : ""} ${hoverClassName} ${cardClassName || "w-70 shrink-0"}`}
/> />
); );
+3 -3
View File
@@ -11,7 +11,7 @@ export function ReferencesSection() {
const router = useRouter(); const router = useRouter();
return ( return (
<section className="space-y-3"> <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
variant="h3" variant="h3"
@@ -39,8 +39,8 @@ export function ReferencesSection() {
<div className="relative overflow-hidden py-1"> <div className="relative overflow-hidden py-1">
{/* We use two sets of cards for seamless infinite marquee effect */} {/* We use two sets of cards for seamless infinite marquee effect */}
<div className="flex w-max items-start gap-4 animate-marquee pause-on-hover"> <div className="flex w-max items-start gap-4 animate-marquee pause-on-hover">
<ReferenceCards className="flex items-start gap-4 shrink-0" lineClamp={true} cardClassName="w-80" /> <ReferenceCards className="flex items-start gap-4 shrink-0" lineClamp={true} showRating={false} cardClassName="w-80" />
<ReferenceCards className="flex items-start gap-4 shrink-0" lineClamp={true} cardClassName="w-80" /> <ReferenceCards className="flex items-start gap-4 shrink-0" lineClamp={true} showRating={false} cardClassName="w-80" />
</div> </div>
<div <div
+1 -1
View File
@@ -7,7 +7,7 @@ export function SponsorsSection() {
if (!SPONSORS || SPONSORS.length === 0) return null; if (!SPONSORS || SPONSORS.length === 0) return null;
return ( return (
<section> <section className="pt-12 md:pt-14">
<div className="grid grid-cols-2 justify-start gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6"> <div className="grid grid-cols-2 justify-start gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6">
{SPONSORS.map((sponsor) => { {SPONSORS.map((sponsor) => {
const logoContent = ( const logoContent = (
+6 -1
View File
@@ -32,12 +32,17 @@
} }
}, },
"About": { "About": {
"title": "About me",
"contactCta": "Contact me",
"educationTitle": "Education",
"experienceTitle": "Experience",
"certificatesTitle": "My certificates",
"aboutText": "Ever since I met software in middle school, I've been constantly learning and improving. My passion for learning grew in high school, where I explored different web development technologies. Near the end of high school, I stepped into the mobile world. Today, I actively build, develop, and most importantly, I am still learning.", "aboutText": "Ever since I met software in middle school, I've been constantly learning and improving. My passion for learning grew in high school, where I explored different web development technologies. Near the end of high school, I stepped into the mobile world. Today, I actively build, develop, and most importantly, I am still learning.",
"allCertificates": "All Certificates", "allCertificates": "All Certificates",
"referencesTitle": "References", "referencesTitle": "References",
"referencesDesc": "View all references on a separate detail page.", "referencesDesc": "View all references on a separate detail page.",
"volunteerTitle": "Volunteering & Community", "volunteerTitle": "Volunteering & Community",
"volunteerDesc": "Inspect timeline and contribution details on a separate page.", "volunteerDesc": "Explore my community work and timeline.",
"bookmarksTitle": "Bookmarks", "bookmarksTitle": "Bookmarks",
"bookmarksDesc": "View quick access links inside a sheet.", "bookmarksDesc": "View quick access links inside a sheet.",
"timelineLabel": "Timeline:", "timelineLabel": "Timeline:",
+6 -1
View File
@@ -32,12 +32,17 @@
} }
}, },
"About": { "About": {
"title": "Hakkımda",
"contactCta": "İletişime geç",
"educationTitle": "Eğitim",
"experienceTitle": "Deneyim",
"certificatesTitle": "Sertifikalarım",
"aboutText": "Ortaokulda yazılımla tanıştığımdan beri sürekli öğrenmeye ve kendimi geliştirmeye çalışıyorum. Lise yıllarında öğrenme hevesim daha da arttı ve web geliştirme tarafında farklı teknolojileri keşfetme fırsatı buldum. Lisenin sonlarına doğru mobil dünyasına da adım attım. Şu an aktif olarak üretiyor, geliştiriyor ve en önemlisi hâlâ öğrenmeye devam ediyorum.", "aboutText": "Ortaokulda yazılımla tanıştığımdan beri sürekli öğrenmeye ve kendimi geliştirmeye çalışıyorum. Lise yıllarında öğrenme hevesim daha da arttı ve web geliştirme tarafında farklı teknolojileri keşfetme fırsatı buldum. Lisenin sonlarına doğru mobil dünyasına da adım attım. Şu an aktif olarak üretiyor, geliştiriyor ve en önemlisi hâlâ öğrenmeye devam ediyorum.",
"allCertificates": "Tüm Sertifikalar", "allCertificates": "Tüm Sertifikalar",
"referencesTitle": "Referanslar", "referencesTitle": "Referanslar",
"referencesDesc": "Tüm referansları ayrı bir detay sayfasında görüntüle.", "referencesDesc": "Tüm referansları ayrı bir detay sayfasında görüntüle.",
"volunteerTitle": "Gönüllülük ve Topluluk", "volunteerTitle": "Gönüllülük ve Topluluk",
"volunteerDesc": "Zaman çizelgesi ve katkı detaylarını ayrı bir detay sayfasında incele.", "volunteerDesc": "Topluluk katkılarımı ve zaman çizelgemi incele.",
"bookmarksTitle": "Yer İmleri", "bookmarksTitle": "Yer İmleri",
"bookmarksDesc": "Hızlı erişim bağlantılarını bir sheet içinde görüntüle.", "bookmarksDesc": "Hızlı erişim bağlantılarını bir sheet içinde görüntüle.",
"timelineLabel": "Zaman Çizelgesi:", "timelineLabel": "Zaman Çizelgesi:",