Merge branch 'newPoyrazUı' of https://github.com/poyrazavsever/poyraz-portfolio into newPoyrazUı
This commit is contained in:
@@ -2,7 +2,6 @@ import { HomeHero } from "@/components/home-hero";
|
||||
import { HomeProjectsSection } from "@/components/home-projects-section";
|
||||
import { HomeVideosSection } from "@/components/home-videos-section";
|
||||
import { ReferencesSection } from "@/components/references-section";
|
||||
import { SponsorsSection } from "@/components/sponsors-section";
|
||||
import { getHomeBlogNews } from "@/data/blog";
|
||||
|
||||
export default async function Home({
|
||||
@@ -14,12 +13,11 @@ export default async function Home({
|
||||
const homeNews = await getHomeBlogNews(locale, 6);
|
||||
|
||||
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} />
|
||||
<HomeProjectsSection />
|
||||
<ReferencesSection />
|
||||
<HomeVideosSection />
|
||||
<SponsorsSection />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
+190
-69
@@ -1,85 +1,184 @@
|
||||
"use client";
|
||||
|
||||
import { Icon } from "@iconify/react";
|
||||
import Image from "next/image";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import { Badge, Card, Typography } from "poyraz-ui/atoms";
|
||||
import { useLocale, useTranslations } from "next-intl";
|
||||
import { Badge, Button, ButtonIcon, ButtonLabel, Card, Typography } from "poyraz-ui/atoms";
|
||||
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 { certificates } from "@/data/certificates";
|
||||
import { EDUCATION } from "@/data/education";
|
||||
import { EXPERIENCE } from "@/data/experience";
|
||||
import { useTranslations, useLocale } from "next-intl";
|
||||
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() {
|
||||
const t = useTranslations("About");
|
||||
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 (
|
||||
<section className="flex h-full flex-col gap-3 overflow-hidden">
|
||||
<div className="grid gap-3 md:grid-cols-2">
|
||||
<Card className="rounded-sm border-border p-4">
|
||||
<Typography variant="p" className="text-sm leading-relaxed text-muted-foreground">
|
||||
<section className="flex h-full flex-col gap-12 overflow-y-auto overflow-x-hidden">
|
||||
<section className="space-y-3">
|
||||
<SectionHeading
|
||||
title={t("title")}
|
||||
action={
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
radius="sm"
|
||||
effect="swap"
|
||||
swapTarget="both"
|
||||
onClick={() => router.push("/contact")}
|
||||
>
|
||||
<ButtonLabel>{t("contactCta")}</ButtonLabel>
|
||||
<ButtonIcon>
|
||||
<Icon icon="mdi:arrow-right" width={15} height={15} />
|
||||
</ButtonIcon>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
<Typography
|
||||
variant="p"
|
||||
className="max-w-3xl text-sm leading-7 text-muted-foreground"
|
||||
>
|
||||
{t("aboutText")}
|
||||
</Typography>
|
||||
</Card>
|
||||
</section>
|
||||
|
||||
<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>
|
||||
<section className="space-y-10">
|
||||
<div className="space-y-3">
|
||||
<SectionHeading title={t("educationTitle")} />
|
||||
<TimelineList items={educationItems} />
|
||||
</div>
|
||||
|
||||
<div className="grid gap-3 md:grid-cols-2 md:items-start">
|
||||
<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
|
||||
<Button
|
||||
type="button"
|
||||
className="cursor-pointer text-left"
|
||||
aria-label="Tüm sertifikaları aç"
|
||||
size="sm"
|
||||
radius="sm"
|
||||
effect="swap"
|
||||
swapTarget="both"
|
||||
>
|
||||
<Card className="rounded-sm border-border p-4 transition-colors hover:border-zinc-700">
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{certificates.slice(0, 4).map((item) => (
|
||||
<div
|
||||
key={getLocalizedValue(item.name, locale)}
|
||||
className="relative aspect-4/3 overflow-hidden rounded-sm border border-border"
|
||||
>
|
||||
<Image
|
||||
src={item.image}
|
||||
alt={getLocalizedValue(item.name, locale)}
|
||||
fill
|
||||
sizes="(max-width: 768px) 45vw, 22vw"
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</button>
|
||||
<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">
|
||||
<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
|
||||
@@ -94,10 +193,13 @@ export function AboutContent() {
|
||||
<Typography variant="large" className="leading-tight">
|
||||
{getLocalizedValue(item.name, locale)}
|
||||
</Typography>
|
||||
<Typography variant="small" className="text-muted-foreground">
|
||||
<Typography
|
||||
variant="small"
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
{item.organization}
|
||||
</Typography>
|
||||
<Typography variant="small" className="text-red-600">
|
||||
<Typography variant="small" className="text-primary">
|
||||
{getLocalizedValue(item.date, locale)}
|
||||
</Typography>
|
||||
</div>
|
||||
@@ -107,27 +209,46 @@ export function AboutContent() {
|
||||
</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)}
|
||||
<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-0.5 text-muted-foreground">
|
||||
{item.company}
|
||||
</Typography>
|
||||
<Typography variant="small" className="mt-1 text-red-600">
|
||||
{getLocalizedValue(item.period, locale)}
|
||||
<Typography
|
||||
variant="small"
|
||||
className="mt-1 text-muted-foreground"
|
||||
>
|
||||
{item.organization}
|
||||
</Typography>
|
||||
</div>
|
||||
</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>
|
||||
</section>
|
||||
|
||||
<div className="grid gap-3 md:grid-cols-3">
|
||||
<Link href="/about/references" className="block">
|
||||
@@ -190,7 +311,7 @@ export function AboutContent() {
|
||||
href={item.href}
|
||||
target="_blank"
|
||||
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://", "")}
|
||||
</Link>
|
||||
|
||||
@@ -31,7 +31,7 @@ export function HomeHero({ news }: HomeHeroProps) {
|
||||
const router = useRouter();
|
||||
|
||||
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="flex max-w-2xl flex-col justify-center gap-2">
|
||||
<Typography
|
||||
@@ -105,7 +105,7 @@ export function HomeHero({ news }: HomeHeroProps) {
|
||||
</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">
|
||||
<Typography
|
||||
variant="h3"
|
||||
|
||||
@@ -12,10 +12,10 @@ export function HomeProjectsSection() {
|
||||
const t = useTranslations("Home");
|
||||
const locale = useLocale();
|
||||
const router = useRouter();
|
||||
const projects = WEB_APPS.slice(0, 4);
|
||||
const projects = WEB_APPS.slice(0, 5);
|
||||
|
||||
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">
|
||||
<Typography
|
||||
variant="h3"
|
||||
@@ -41,7 +41,7 @@ export function HomeProjectsSection() {
|
||||
</div>
|
||||
|
||||
<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) => (
|
||||
<ImageCard
|
||||
key={project.id}
|
||||
@@ -54,14 +54,14 @@ export function HomeProjectsSection() {
|
||||
: undefined
|
||||
}
|
||||
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
|
||||
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>
|
||||
</section>
|
||||
|
||||
@@ -10,7 +10,7 @@ export function HomeVideosSection() {
|
||||
const t = useTranslations("Content");
|
||||
|
||||
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">
|
||||
<Typography
|
||||
variant="h3"
|
||||
|
||||
@@ -8,9 +8,15 @@ type ReferenceCardsProps = {
|
||||
className?: string;
|
||||
cardClassName?: string;
|
||||
lineClamp?: boolean;
|
||||
showRating?: boolean;
|
||||
};
|
||||
|
||||
export function ReferenceCards({ className, cardClassName, lineClamp }: ReferenceCardsProps) {
|
||||
export function ReferenceCards({
|
||||
className,
|
||||
cardClassName,
|
||||
lineClamp,
|
||||
showRating = true,
|
||||
}: ReferenceCardsProps) {
|
||||
const locale = useLocale();
|
||||
const hoverClassName =
|
||||
"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}
|
||||
role={getLocalizedValue(item.role, locale)}
|
||||
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"}`}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ export function ReferencesSection() {
|
||||
const router = useRouter();
|
||||
|
||||
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">
|
||||
<Typography
|
||||
variant="h3"
|
||||
@@ -39,8 +39,8 @@ export function ReferencesSection() {
|
||||
<div className="relative overflow-hidden py-1">
|
||||
{/* 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">
|
||||
<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} 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} showRating={false} cardClassName="w-80" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
||||
@@ -7,7 +7,7 @@ export function SponsorsSection() {
|
||||
if (!SPONSORS || SPONSORS.length === 0) return null;
|
||||
|
||||
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">
|
||||
{SPONSORS.map((sponsor) => {
|
||||
const logoContent = (
|
||||
|
||||
+6
-1
@@ -32,12 +32,17 @@
|
||||
}
|
||||
},
|
||||
"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.",
|
||||
"allCertificates": "All Certificates",
|
||||
"referencesTitle": "References",
|
||||
"referencesDesc": "View all references on a separate detail page.",
|
||||
"volunteerTitle": "Volunteering & Community",
|
||||
"volunteerDesc": "Inspect timeline and contribution details on a separate page.",
|
||||
"volunteerDesc": "Explore my community work and timeline.",
|
||||
"bookmarksTitle": "Bookmarks",
|
||||
"bookmarksDesc": "View quick access links inside a sheet.",
|
||||
"timelineLabel": "Timeline:",
|
||||
|
||||
+6
-1
@@ -32,12 +32,17 @@
|
||||
}
|
||||
},
|
||||
"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.",
|
||||
"allCertificates": "Tüm Sertifikalar",
|
||||
"referencesTitle": "Referanslar",
|
||||
"referencesDesc": "Tüm referansları ayrı bir detay sayfasında görüntüle.",
|
||||
"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",
|
||||
"bookmarksDesc": "Hızlı erişim bağlantılarını bir sheet içinde görüntüle.",
|
||||
"timelineLabel": "Zaman Çizelgesi:",
|
||||
|
||||
Reference in New Issue
Block a user