Files
personalsite/app/seyir-defteri/page.tsx
2026-04-03 16:20:51 +03:00

153 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Kaptanın Seyir Defteri" };
interface Goal {
id: string;
title: string;
description: string;
status: "completed" | "in-progress" | "planned" | "paused";
progress: number;
category: string;
deadline?: string;
notes?: string;
}
const goals: Goal[] = [
{
id: "1",
title: "OSCP Sertifikası",
description: "Offensive Security Certified Professional sınavını geçmek",
status: "in-progress",
progress: 35,
category: "Sertifika",
deadline: "2026-12-31",
notes: "Active Directory modüllerine odaklanılıyor",
},
{
id: "2",
title: "denizbektas.com.tr Yayına Almak",
description: "Kişisel siteyi oluşturmak ve yayına almak",
status: "completed",
progress: 100,
category: "Proje",
},
{
id: "3",
title: "50 HTB Makinesi",
description: "HackTheBox'ta 50 makine çözmek",
status: "in-progress",
progress: 47,
category: "Pratik",
},
{
id: "4",
title: "Podcast Başlatmak",
description: "Türkçe siber güvenlik podcast'i yayınlamak",
status: "planned",
progress: 10,
category: "İçerik",
deadline: "2026-09-01",
},
{
id: "5",
title: "Red Team Araç Geliştirme",
description: "Kendi C2 implant'ımı yazmak (Rust ile)",
status: "paused",
progress: 15,
category: "Geliştirme",
},
{
id: "6",
title: "10 Infosec Yazısı",
description: "Kaliteli teknik yazılar yayınlamak",
status: "in-progress",
progress: 10,
category: "İçerik",
},
];
const statusConfig = {
completed: { label: "Tamamlandı", color: "#00d4aa", icon: "✓" },
"in-progress": { label: "Devam Ediyor", color: "#f59e0b", icon: "◉" },
planned: { label: "Planlandı", color: "#64748b", icon: "◎" },
paused: { label: "Durduruldu", color: "#ef4444", icon: "⏸" },
};
export default function SeyirDefteriPage() {
const byCategory = goals.reduce((acc, g) => {
if (!acc[g.category]) acc[g.category] = [];
acc[g.category].push(g);
return acc;
}, {} as Record<string, Goal[]>);
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Kaptanın Seyir Defteri</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Hedeflerim ve ilerleme durumum
</p>
{/* Summary */}
<div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: "0.5rem", marginBottom: "2rem" }}>
{(["completed", "in-progress", "planned", "paused"] as const).map((s) => {
const count = goals.filter((g) => g.status === s).length;
const cfg = statusConfig[s];
return (
<div key={s} className="card" style={{ textAlign: "center", padding: "0.75rem" }}>
<div style={{ fontSize: "1.2rem", fontWeight: 700, color: cfg.color }}>{count}</div>
<div style={{ fontSize: "0.65rem", color: "var(--text-muted)", marginTop: "0.2rem" }}>{cfg.label}</div>
</div>
);
})}
</div>
{/* Goals by category */}
{Object.entries(byCategory).map(([cat, catGoals]) => (
<div key={cat} style={{ marginBottom: "1.5rem" }}>
<div className="section-header">{cat}</div>
<div style={{ display: "flex", flexDirection: "column", gap: "0.75rem" }}>
{catGoals.map((goal) => {
const cfg = statusConfig[goal.status];
return (
<div key={goal.id} className="card">
<div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: "1rem", marginBottom: "0.4rem" }}>
<div>
<div style={{ display: "flex", alignItems: "center", gap: "0.4rem", marginBottom: "0.2rem" }}>
<span style={{ color: cfg.color, fontSize: "0.7rem" }}>{cfg.icon}</span>
<h3 style={{ fontSize: "0.9rem", fontWeight: 600, color: "var(--text)" }}>{goal.title}</h3>
</div>
<p style={{ fontSize: "0.78rem", color: "var(--text-muted)" }}>{goal.description}</p>
</div>
<span style={{ fontSize: "0.65rem", background: "var(--bg)", border: `1px solid ${cfg.color}`, color: cfg.color, padding: "0.15rem 0.4rem", borderRadius: "3px", flexShrink: 0 }}>
{cfg.label}
</span>
</div>
{/* Progress bar */}
<div style={{ marginTop: "0.75rem" }}>
<div style={{ display: "flex", justifyContent: "space-between", fontSize: "0.7rem", color: "var(--text-muted)", marginBottom: "0.25rem" }}>
<span>İlerleme</span>
<span style={{ color: cfg.color, fontWeight: 600 }}>{goal.progress}%</span>
</div>
<div style={{ height: "4px", background: "var(--bg)", borderRadius: "2px", overflow: "hidden" }}>
<div style={{ height: "100%", width: `${goal.progress}%`, background: cfg.color, borderRadius: "2px", transition: "width 0.3s" }} />
</div>
</div>
{(goal.deadline || goal.notes) && (
<div style={{ marginTop: "0.5rem", fontSize: "0.72rem", color: "var(--text-muted)", display: "flex", gap: "1rem", flexWrap: "wrap" }}>
{goal.deadline && <span>🗓 {new Date(goal.deadline).toLocaleDateString("tr-TR", { year: "numeric", month: "long" })}</span>}
{goal.notes && <span>📝 {goal.notes}</span>}
</div>
)}
</div>
);
})}
</div>
</div>
))}
</div>
);
}