From 40526e115ed85b48d2d32c777056a10230547437 Mon Sep 17 00:00:00 2001 From: Space-Banane Date: Wed, 3 Jun 2026 15:45:02 +0200 Subject: [PATCH] feat: Major update --- src/app/admin/page.tsx | 158 ++++++++++++++++++++++++-- src/app/page.tsx | 58 +++------- src/components/TimezoneClockBlock.tsx | 127 +++++++++++++++++++++ src/context/ProfileContext.tsx | 10 +- src/sections/Activity.tsx | 61 +++++++++- src/sections/Affiliates.tsx | 45 +++++++- src/sections/AgentSkills.tsx | 86 ++++++++++++++ src/sections/Goals.tsx | 93 --------------- src/sections/Hero.tsx | 12 +- src/sections/SkillsExperience.tsx | 63 ++++++++++ src/sections/TechStack.tsx | 51 ++++++--- src/sections/Uptime.tsx | 5 +- src/sections/WorkExperience.tsx | 2 +- src/types.ts | 10 ++ 14 files changed, 611 insertions(+), 170 deletions(-) create mode 100644 src/components/TimezoneClockBlock.tsx create mode 100644 src/sections/AgentSkills.tsx delete mode 100644 src/sections/Goals.tsx create mode 100644 src/sections/SkillsExperience.tsx diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 1fc4992..0878624 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -3,11 +3,11 @@ import { useState, useEffect } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { useRouter } from "next/navigation"; -import type { Project, MiniProject, Experience, RealWork } from "../../types"; +import type { Project, MiniProject, Experience, RealWork, Skill } from "../../types"; const API_BASE = "https://shsf-api.reversed.dev/api/exec/4/e942538c-caa1-49d1-8953-dfab1e62f8cb"; -type EditableFile = "projects.json" | "mini_projects.json" | "experience.json" | "real_work.json"; +type EditableFile = "projects.json" | "mini_projects.json" | "experience.json" | "real_work.json" | "skills.json"; export default function AdminPage() { const [password, setPassword] = useState(""); @@ -21,10 +21,12 @@ export default function AdminPage() { const [isSaving, setIsSaving] = useState(false); const [saveStatus, setSaveStatus] = useState<{ type: "success" | "error"; message: string } | null>(null); const [newTagDrafts, setNewTagDrafts] = useState>({}); + const [newSkillListDrafts, setNewSkillListDrafts] = useState>({}); // Import state const [importFileName, setImportFileName] = useState(""); const [importFileContent, setImportFileContent] = useState(null); const [importError, setImportError] = useState(""); + const getSectionLabel = (file: EditableFile) => (file === "skills.json" ? "Agent Skills" : file.replace(".json", "").replace("_", " ")); // Handle file import const handleImportFile = async (e: React.ChangeEvent) => { setImportError(""); @@ -54,7 +56,7 @@ export default function AdminPage() { try { const parsed = JSON.parse(importFileContent); setData(Array.isArray(parsed) ? parsed : []); - if (importFileName && ["projects.json", "mini_projects.json", "experience.json", "real_work.json"].includes(importFileName)) { + if (importFileName && ["projects.json", "mini_projects.json", "experience.json", "real_work.json", "skills.json"].includes(importFileName)) { setSelectedFile(importFileName as EditableFile); } setImportFileContent(null); @@ -160,7 +162,8 @@ export default function AdminPage() { "projects.json": { name: "", description: "", link: "", open_source: false }, "mini_projects.json": { title: "", description: "", why: "" }, "experience.json": { name: "", type: "experience", description: "" }, - "real_work.json": { company: "", role: "", from: "", until: "", summary: "" } + "real_work.json": { company: "", role: "", from: "", until: "", summary: "" }, + "skills.json": { name: "", description: "", purpose: "", what_it_solves: "", link: "", emojis: [], tags: [] } }; setData([templates[selectedFile], ...data]); }; @@ -192,6 +195,27 @@ export default function AdminPage() { setNewTagDrafts((prev) => ({ ...prev, [index]: "" })); }; + const updateSkillArrayItem = (index: number, field: "emojis" | "tags", itemIndex: number, value: string) => { + const current = [...((data[index] as Skill)?.[field] || [])]; + current[itemIndex] = value; + updateEntry(index, field, current); + }; + + const removeSkillArrayItem = (index: number, field: "emojis" | "tags", itemIndex: number) => { + const current = [...((data[index] as Skill)?.[field] || [])]; + updateEntry(index, field, current.filter((_, i) => i !== itemIndex)); + }; + + const addSkillArrayItem = (index: number, field: "emojis" | "tags") => { + const key = `${index}:${field}`; + const draft = (newSkillListDrafts[key] || "").trim(); + if (!draft) return; + + const current = [...((data[index] as Skill)?.[field] || []), draft]; + updateEntry(index, field, current); + setNewSkillListDrafts((prev) => ({ ...prev, [key]: "" })); + }; + const renderProjectEditor = (item: Project, idx: number) => (
@@ -327,6 +351,123 @@ export default function AdminPage() {
); + const renderSkillEditor = (item: Skill, idx: number) => ( +
+
+ + updateEntry(idx, "name", e.target.value)} className="w-full bg-black/40 border border-white/10 rounded-lg p-2 text-sm" /> +
+
+ + updateEntry(idx, "link", e.target.value)} className="w-full bg-black/40 border border-white/10 rounded-lg p-2 text-sm" /> +
+
+ +