From 1ce743e06aaa5ce486d1d2abd905373d895acd3a Mon Sep 17 00:00:00 2001 From: imnyang Date: Tue, 3 Feb 2026 21:17:53 +0000 Subject: [PATCH] feat: update configuration, styles, and components for improved UI and functionality --- next.config.ts | 3 ++ src/app/globals.css | 6 +++- src/app/not-found.tsx | 18 ++++++++++ src/app/page.tsx | 71 +++++++++---------------------------- src/components/Projects.tsx | 48 ++++++++++++++++++------- src/components/dday.tsx | 26 ++++++++++++++ src/components/timeline.tsx | 11 ++++-- src/lib/events.ts | 5 +++ 8 files changed, 118 insertions(+), 70 deletions(-) create mode 100644 src/app/not-found.tsx create mode 100644 src/components/dday.tsx diff --git a/next.config.ts b/next.config.ts index 3cd7310..f5c1fb6 100644 --- a/next.config.ts +++ b/next.config.ts @@ -8,6 +8,9 @@ const nextConfig: NextConfig = { turbopack: { root: path.join(__dirname, '.'), }, + images: { + remotePatterns: [new URL('https://api.imnya.ng/**')], + }, output: 'standalone', }; diff --git a/src/app/globals.css b/src/app/globals.css index ed8efdd..f0f6203 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -208,4 +208,8 @@ body { .snap-section { scroll-snap-align: start; scroll-snap-stop: always; -} \ No newline at end of file +} + +strong { + font-weight: 600; +} \ No newline at end of file diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx new file mode 100644 index 0000000..5289f34 --- /dev/null +++ b/src/app/not-found.tsx @@ -0,0 +1,18 @@ +import { Button } from "@/components/ui/button"; +import Image from "next/image"; + +export default function NotFound() { + return ( +
+
+ + Not Found Image + +
+

404

+

괜찮아요. 이런날도 있는거죠

+
+ ← Go Home +
+ ) +} \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx index a719779..0875114 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,73 +1,36 @@ -'use client'; import Projects from "@/components/Projects"; import TimelineComponent from "@/components/timeline"; import Image from "next/image"; import DraggableWindow from "@/components/DraggableWindow"; import ReadmeWindow from "@/components/ReadmeWindow"; -// import Snowfall from 'react-snowfall'; -import { useTheme } from "next-themes"; -// import { Banner } from "@/components/ui/banner"; -import { LinkIcon, TreeDeciduous, TreePalmIcon, TreesIcon } from "lucide-react"; -import { useState } from "react"; import Contact from "@/components/Contact"; -// import DraggableWindose from "@/components/DraggableWindose"; +import DDayComponent from "@/components/dday"; export default function Page() { - const { theme } = useTheme(); - // const [show, setShow] = useState(true); - // const [targetPosition, setTargetPosition] = useState<{ x: number; y: number } | null>(null); - // const [windowVisible, setWindowVisible] = useState(true); - - // const handleTXTHover = (position: { x: number; y: number } | null) => { - // setTargetPosition(position); - // if (position) { - // setWindowVisible(true); - // } - // }; - return (
- {/* */} - -
- logo -

- me@imnya.ng -

+
+
+ logo +

+ me@imnya.ng +

+
+
- {/*
- setShow(false)} - icon={ - - } - title={ - <> - 제 크리스마스 트리를 꾸며주세요! - - } - action={{ - label: "트리 꾸미러 가기", - onClick: () => window.open("https://imnya.ng/tree", "_blank"), - }} - /> -
*/} - - {/* setWindowVisible(false)} onDragStart={() => setTargetPosition(null)} /> */} -
-

나의 어두움이 다른 사람들에겐 이 되길 바라는 개발자, 정보보안전문가 암냥입니다.

+
+

더 멋진 세상을 만들기 위해 노력하는 암냥입니다.

초등학교 시절 운영체제에 흥미를 느껴 컴퓨터를 시작했고, 이후 프로그래밍에 관심을 갖게 되었습니다.

초등학교 4학년 때 Python으로 프로그래밍을 시작했으며, 현재는 TypeScript를 주로 사용합니다.

최근에는 정보보안 분야 중 웹 해킹에 관심이 많습니다.

diff --git a/src/components/Projects.tsx b/src/components/Projects.tsx index 1a142df..09b991e 100644 --- a/src/components/Projects.tsx +++ b/src/components/Projects.tsx @@ -1,31 +1,45 @@ +"use client"; import { SquareArrowOutUpRight } from 'lucide-react'; -import { url } from 'node:inspector'; - -{/* Effect Playing Contest 2025 Broadcast Develop
-today.isangjeong */} +import React from 'react'; const projects = [ { name: 'EPC 2025 Broadcast Manager', - url: 'https://www.youtube.com/@adofaigg', - desc: '얼불춤 끼얏호우', + url: 'https://www.youtube.com/playlist?list=PLZeYZotn5_IOJDek6e35NKzUtJm09yxZD', + desc: 'ADOFAI is web-scale', detail: '달성이 주관하고 ADOFAI.gg가 공동 주최하는 Effect Playing Contest 2025 방송 화면의 대부분의 기능을 개발하였습니다.', tags: ['React', 'ElysiaJS'], }, { - name: 'NYL', - url: 'https://nyl.ny64.kr', - desc: '상위 호환', - detail: '전국의 중고등학교의 시간표와 급식을 쉽게 확인할 수 있는 앱을 유지보수하고 있습니다.', - tags: ['React Native', 'ElysiaJS'] + name: 'newsletter', + url: 'https://github.com/imnyang/newsletter', + desc: 'For Memos', + detail: '그저 이메일이 오면 Discord 웹훅으로 포워딩합니다.', + tags: ['Rust', 'IMAP'] + }, + { + name: 'memos-rss', + url: 'https://github.com/imnyang/memos-rss', + desc: 'For Memos', + detail: 'Discord 포럼 채널에 RSS 피드에 올라온 내용을 포워딩합니다.', + tags: ['Rust', 'Discord Bot', 'RSS'] + }, + { + name: 'today.isangjeong', + url: 'https://instagram.com/today.isangjeong', + desc: 'Instagram Bot', + detail: '매일 학교의 급식 메뉴를 자동으로 업로드하는 인스타그램 봇입니다.', + tags: ['TypeScript', 'Instagram', '@napi-rs/canvas'] } ]; export default function Projects() { + const [visibleCount, setVisibleCount] = React.useState(3); + return (
- {projects.map((project, idx) => ( + {projects.slice(0, visibleCount).map((project, idx) => (
@@ -35,7 +49,7 @@ export default function Projects() { ) : ( - {project.name} + {project.name} )} {project.desc}
@@ -51,6 +65,14 @@ export default function Projects() {
))}
+ {visibleCount < projects.length && ( + + )}
); } diff --git a/src/components/dday.tsx b/src/components/dday.tsx new file mode 100644 index 0000000..54c13de --- /dev/null +++ b/src/components/dday.tsx @@ -0,0 +1,26 @@ +"use client"; + +interface DDayComponentProps { + targetDate: Date; + label: string; + +} + +export default function DDayComponent({ targetDate, label }: DDayComponentProps) { + const today = new Date(); + const diffTime = targetDate.getTime() - today.getTime(); + const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + + const getLabel = () => { + if (diffDays > 0) return `D-${diffDays}`; + if (diffDays < 0) return `D+${Math.abs(diffDays)}`; + return `D-Day`; + }; + + return ( +
+ {getLabel()} + {label} | {targetDate.toDateString()} +
+ ); +} \ No newline at end of file diff --git a/src/components/timeline.tsx b/src/components/timeline.tsx index 3cfe562..f83936f 100644 --- a/src/components/timeline.tsx +++ b/src/components/timeline.tsx @@ -19,8 +19,8 @@ export default function TimelineComponent() { const filteredEvents = selectedYear ? events.filter( - (event) => new Date(event.date).getFullYear() === selectedYear - ) + (event) => new Date(event.date).getFullYear() === selectedYear + ) : []; return ( @@ -75,6 +75,13 @@ export default function TimelineComponent() { )}
))} + {selectedYear === new Date().getFullYear() && ( +
+
+ ✨ | D-{Math.ceil((new Date(new Date().getFullYear() + 1, 0, 1).getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24))}동안 만들어나갈 멋진 것들을 기대해주세요. +
+
+ )}
diff --git a/src/lib/events.ts b/src/lib/events.ts index 475b5f9..47efdb8 100644 --- a/src/lib/events.ts +++ b/src/lib/events.ts @@ -1,4 +1,9 @@ export const events = [ + { + description: "선린인터넷고등학교 121기 입학", + category: "Education", + date: "2026-03-03" + }, { description: "리눅스 마스터 2급", category: "License",