Refactor Projects and Timeline components: update project details and clean up code formatting

This commit is contained in:
암냥 2025-08-17 00:25:27 +09:00
commit e861279fb8
2 changed files with 30 additions and 30 deletions

View file

@ -1,18 +1,18 @@
import ProjectsComponents from "./ProjectsComponents";
const projects = [
{
name: "EPC/broadcast",
url: "https://www.youtube.com/playlist?list=PLZeYZotn5_IOJDek6e35NKzUtJm09yxZD",
description: "Effect Playing Contest 2025의 방송화면 기능 전체를 맡았습니다.",
techStack: ["Bun", "TypeScript", "React"]
},
{
name: "team-neko/two_hearts",
url: "https://chromewebstore.google.com/detail/fhbjjhpphmigcniggnhgoepaodgoobdk?utm_source=item-share-cb",
description: "Two Hearts는 Chrome 확장 프로그램으로, 새탭을 더 간단명료하게 보여줍니다.",
techStack: ["Bun", "Chrome", "TypeScript", "React"]
},
{
name: "imnyang/today.isangjeong",
url: "https://github.com/imnyang/today.isangjeong",
description: "친구들과 간단하게 학교의 급식을 공유하기 위해 고안한 프로젝트입니다.\n원래 Python으로 작성되었지만 현재는 TypeScript로 재작성되었습니다.",
techStack: ["Bun", "TypeScript", "Instagram"]
},
{
name: "team-neko/dynamic-kawaii",
url: "https://github.com/team-neko/dynamic-kawaii",

View file

@ -4,12 +4,12 @@ import { Plus } from "lucide-react";
import { useEffect, useState, useRef } from "react";
const events = [
{
{
date: "2025-07-26",
description:
"선린인터넷고 여름방학 중학생 특별교육 우수 이수 (프로그래밍)",
category: "Education",
link: "https://sunrint.sen.hs.kr/"
link: "https://sunrint.sen.hs.kr/"
},
{
date: "2025-02-27",
@ -30,14 +30,14 @@ const events = [
description:
"2024 Sunrin Layer7 CTF 중등부 2위",
category: "Award",
link: "https://layer7.kr"
link: "https://layer7.kr"
},
{
date: "2025-01-10",
description:
"선린인터넷고 겨울방학 중학생 특별교육 이수 (IT경영학과)",
category: "Education",
link: "https://sunrint.sen.hs.kr/"
link: "https://sunrint.sen.hs.kr/"
},
{
date: "2024-12-14",
@ -155,31 +155,31 @@ export default function Timeline() {
const TimelineRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
}
},
{ threshold: 0.1 }
);
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
}
},
{ threshold: 0.1 }
);
if (TimelineRef.current) {
observer.observe(TimelineRef.current);
}
return () => {
if (TimelineRef.current) {
observer.observe(TimelineRef.current);
observer.unobserve(TimelineRef.current);
}
return () => {
if (TimelineRef.current) {
observer.unobserve(TimelineRef.current);
}
};
};
}, []);
useEffect(() => {
if (isVisible && count < events.length) {
const timer = setTimeout(() => setCount(count + 1), count === 0 ? 300 : 25);
return () => clearTimeout(timer);
}
if (isVisible && count < events.length) {
const timer = setTimeout(() => setCount(count + 1), count === 0 ? 300 : 25);
return () => clearTimeout(timer);
}
}, [isVisible, count]);
return (
@ -187,7 +187,7 @@ export default function Timeline() {
<div className="w-full">
<h1 className="text-2xl font-bold mb-4 w-full">🌠 </h1>
<p> {count} !</p>
<br/>
<br />
<Accordion type="multiple" className="w-full space-y-2">
{Array.from(new Set(events.map(event => new Date(event.date).getFullYear()))).sort((a, b) => b - a).map(year => (
<AccordionItem