diff --git a/src/App.tsx b/src/App.tsx index 5a88785..ac5b718 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import Contact from "@/components/Home/Contact"; import Project from "@/components/Home/Project"; import "./index.css"; +import Wakatime from "./components/Home/Wakatime"; export function App() { useEffect(() => { @@ -66,6 +67,9 @@ export function App() {
+
+ +
diff --git a/src/components/Home/About.tsx b/src/components/Home/About.tsx index 7845299..0614a50 100644 --- a/src/components/Home/About.tsx +++ b/src/components/Home/About.tsx @@ -1,13 +1,17 @@ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; export default function About() { - const [time, setTime] = useState(""); + const [wakatime, setWakatime] = useState(); + const [time, setTime] = useState(0); const [post, setPost] = useState({}); const [age, setAge] = useState(0); + const [totalSeconds, setTotalSeconds] = useState(0); + const [isVisible, setIsVisible] = useState(false); + const AboutRef = useRef(null); useEffect(() => { - // Calculate age based on reference date (2010-11-08) - const referenceDate = new Date(2010, 11, 8); // November is 10 because months are 0-indexed + // 나이 계산 + const referenceDate = new Date(2010, 10, 8); // 2010년 11월 8일 (0-indexed) const currentDate = new Date(); let calculatedAge = currentDate.getFullYear() - referenceDate.getFullYear(); if (currentDate < new Date(currentDate.getFullYear(), referenceDate.getMonth(), referenceDate.getDate())) { @@ -17,32 +21,57 @@ export default function About() { }, []); useEffect(() => { - fetch("https://api.imnya.ng/rss", { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }) + // 블로그 데이터 가져오기 + fetch("https://api.imnya.ng/rss") .then(response => response.json()) .then(data => { - if (data) { - setPost(data[0] || {}); - } else { - console.error("Error: data is undefined"); - } + if (data) setPost(data[0] || {}); }) .catch(error => console.error("Error fetching posts:", error)); }, []); useEffect(() => { - const interval = setInterval(() => { - setTime(new Date().toLocaleTimeString('en-US', { timeZone: 'Asia/Seoul', hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 })); - }, 1); - return () => clearInterval(interval); + // Intersection Observer로 isVisible 상태 변경 + const observer = new IntersectionObserver( + ([entry]) => { + if (entry.isIntersecting) { + setIsVisible(true); + } + }, + { threshold: 0.1 } + ); + + if (AboutRef.current) observer.observe(AboutRef.current); + + return () => { + if (AboutRef.current) observer.unobserve(AboutRef.current); + }; }, []); + useEffect(() => { + // Wakatime 데이터 가져오기 (한 번만 실행) + fetch("https://api.imnya.ng/wakatime") + .then(response => response.json()) + .then(data => { + if (data) { + const roundedSeconds = Math.round(data.data.total_seconds); // 반올림 + setTotalSeconds(roundedSeconds); + setWakatime(data.data); + } + }) + .catch(error => console.error("Error fetching Wakatime data:", error)); + }, []); + + useEffect(() => { + // isVisible이 true일 때 time 증가 + if (isVisible && time < totalSeconds) { + const timer = setTimeout(() => setTime(prevTime => prevTime + 1), time === 0 ? 300 : 0); + return () => clearTimeout(timer); + } + }, [isVisible, time, totalSeconds]); + return ( -
+

🤔 About

@@ -51,15 +80,21 @@ export default function About() {

삶을 더 간단명료하게 만들고 있는

학생 개발자 남현석입니다.

- +
-

{age}살의 어린 나이지만

-

저는 항상 제가 할 수 있는 최적의 코드를 목표로 하며

-

사용자의 경험을 중심적으로 고려하며

-

새로운 기술에 대한 관심이 높습니다.

- -

In South Korea : {time}

-

최근 블로그 보기 : {post.title}

+

{age}살의 어린 나이지만

+

저는 항상 제가 할 수 있는 최적의 코드를 목표로 하고

+

사용자의 경험을 중심적으로 고려하며

+

새로운 기술에 대한 관심이 높습니다.

+ +
+ + + Wakatime Mar 18th ~ : {time}s + +

+ 최근 블로그 보기 : {post.title} +

diff --git a/src/components/Home/Wakatime.tsx b/src/components/Home/Wakatime.tsx new file mode 100644 index 0000000..f61d751 --- /dev/null +++ b/src/components/Home/Wakatime.tsx @@ -0,0 +1,40 @@ +import React, { useEffect, useState } from "react"; + +export default function Wakatime() { + const [wakatime, setWakatime] = useState(); + useEffect(() => { + // Wakatime 데이터 가져오기 (한 번만 실행) + fetch("https://api.imnya.ng/wakatime") + .then(response => response.json()) + .then(data => { + if (data) { + setWakatime(data.data); + } + }) + .catch(error => console.error("Error fetching Wakatime data:", error)); + }, []); + + return ( +
+
+ 🍝 Wakatime +

Dashboards for developers

+
+ {wakatime && wakatime.languages && ( +
+

총 시간: {(wakatime.human_readable_total)}

+

하루 평균: {wakatime.human_readable_daily_average}

+
+ +

가장 많이 사용한 언어:

+
    + {wakatime.languages.slice(0, 3).map((language: any, index: number) => ( +
  • {index+1}. {language.name}: {language.percent}%
  • + ))} +
+
+ )} +
+
+ ) +} \ No newline at end of file diff --git a/src/index.html b/src/index.html index bf3b4b7..23838f7 100644 --- a/src/index.html +++ b/src/index.html @@ -1,13 +1,18 @@ + 남현석 | :two_hearts: - + '
diff --git a/styles/globals.css b/styles/globals.css index b520ce8..d004c06 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -185,6 +185,18 @@ } } +@layer utilities { + /* Hide scrollbar for Chrome, Safari and Opera */ + .no-scrollbar::-webkit-scrollbar { + display: none; + } + /* Hide scrollbar for IE, Edge and Firefox */ + .no-scrollbar { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + } +} + .fixed-width-number { font-feature-settings: "tnum"; } \ No newline at end of file