import React, { useCallback, useEffect, useRef, useState } from 'react'; import { Link } from 'react-router-dom'; import { navLinks } from '../../routes.jsx'; import { getBlogPosts } from '../../data/blog'; import { getTodos } from '../../api'; import { getCurrentTheme } from '../../data/heroConfig'; import myPhoto from '../../assets/myPhoto.jpg'; import { useIsMobile } from '../../hooks/useIsMobile'; import SwipeableView from '../../components/SwipeableView'; import PullToRefresh from '../../components/PullToRefresh'; import './Home.css'; const TODO_COLUMNS = [ { id: 'todo', label: '계획', color: 'var(--neon-purple)' }, { id: 'in_progress', label: '진행 중', color: '#f59e0b' }, { id: 'done', label: '완료', color: '#34d399' }, ]; const Home = () => { const posts = getBlogPosts().slice(0, 3); const highlights = navLinks.filter((link) => link.id !== 'home'); const theme = getCurrentTheme(); const isMobile = useIsMobile(); const [todosByStatus, setTodosByStatus] = useState({ todo: [], in_progress: [], done: [] }); const [portfolio, setPortfolio] = useState(null); useEffect(() => { fetch('/api/profile/public') .then(r => r.ok ? r.json() : null) .catch(() => null) .then(d => setPortfolio(d)); }, []); const loadTodos = useCallback(async () => { const data = await getTodos(); if (!Array.isArray(data)) return; setTodosByStatus({ todo: data.filter((t) => t.status === 'todo'), in_progress: data.filter((t) => t.status === 'in_progress'), done: data.filter((t) => t.status === 'done'), }); }, []); useEffect(() => { loadTodos().catch(() => { /* 조용히 실패 */ }); }, [loadTodos]); const totalTasks = todosByStatus.todo.length + todosByStatus.in_progress.length + todosByStatus.done.length; const doneTasks = todosByStatus.done.length; const inProgress = todosByStatus.in_progress.length; return (
Personal Archive
개발, 여행 스냅, 그리고 생각을 모아두는 공간입니다.
이번 달 집중 테마
{theme.desc}
전체 태스크
{totalTasks}개
진행 중 / 완료
{inProgress} / {doneTasks}
확장 가능한 구조로 구성해 이후에도 쉽게 페이지를 추가할 수 있습니다.
{item.label}
{item.description}
마크다운 파일을 추가하면 자동으로 목록에 반영됩니다.
{post.title}
{post.excerpt}
계획 · 진행 중 · 완료 태스크를 한눈에 확인합니다.
태스크가 없습니다.
) : (todosByStatus.todo || []).map((todo) => ({todo.title}
{todo.description &&{todo.description}
}{todo.updated_at ? new Date(todo.updated_at).toLocaleDateString('ko-KR', { month: 'short', day: 'numeric' }) : ''}
태스크가 없습니다.
) : (todosByStatus.in_progress || []).map((todo) => ({todo.title}
{todo.description &&{todo.description}
}{todo.updated_at ? new Date(todo.updated_at).toLocaleDateString('ko-KR', { month: 'short', day: 'numeric' }) : ''}
태스크가 없습니다.
) : (todosByStatus.done || []).map((todo) => ({todo.title}
{todo.description &&{todo.description}
}{todo.updated_at ? new Date(todo.updated_at).toLocaleDateString('ko-KR', { month: 'short', day: 'numeric' }) : ''}
페이지 주인 소개 영역입니다.
{portfolio?.profile?.role || 'Server Developer'}
{portfolio?.profile?.name || '박 재 오'}
{portfolio?.profile?.bio || '주변 동료와 함께 소통하며 성장하는걸 좋아합니다.'}
태스크가 없습니다.
) : ( items.map((todo) => ({todo.title}
{todo.description && ({todo.description}
)}{todo.updated_at ? new Date(todo.updated_at).toLocaleDateString('ko-KR', { month: 'short', day: 'numeric' }) : ''}