diff --git a/src/components/CollapsibleIntro.jsx b/src/components/CollapsibleIntro.jsx new file mode 100644 index 0000000..d694672 --- /dev/null +++ b/src/components/CollapsibleIntro.jsx @@ -0,0 +1,45 @@ +import React, { useState, useEffect } from 'react'; + +export default function CollapsibleIntro({ text }) { + const STORAGE_KEY = 'devnet-intro-collapsed'; + const [collapsed, setCollapsed] = useState(false); + + useEffect(() => { + const stored = localStorage.getItem(STORAGE_KEY); + if (stored === 'true') setCollapsed(true); + }, []); + + useEffect(() => { + localStorage.setItem(STORAGE_KEY, collapsed ? 'true' : 'false'); + }, [collapsed]); + + return ( +
+ +
+ {text} +
+
+ ); +} \ No newline at end of file diff --git a/src/components/ContributionCalendar.jsx b/src/components/ContributionCalendar.jsx index 604bb6e..14badd6 100644 --- a/src/components/ContributionCalendar.jsx +++ b/src/components/ContributionCalendar.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; // Helper to get all days in the last 52 weeks, starting on Monday function getCalendarDays() { @@ -38,23 +38,45 @@ function getMonthLabels(days) { // Day labels for rows (Monday to Sunday) const DAY_LABELS = ['Mon', '', 'Wed', '', 'Fri', '', 'Sun']; -// Color scale (GitHub-like) -const COLORS = [ +// Color scales +const COLORS_LIGHT = [ '#ebedf0', // 0 '#c6e48b', // 1 '#7bc96f', // 2 '#239a3b', // 3 '#196127', // 4+ ]; -function getColor(count) { - if (!count) return COLORS[0]; - if (count >= 4) return COLORS[4]; - return COLORS[count]; +const COLORS_DARK = [ + '#23272e', // 0 + '#3c4d36', // 1 + '#4e7c4e', // 2 + '#399150', // 3 + '#6ee7b7', // 4+ +]; + +function getColor(count, isDark) { + const palette = isDark ? COLORS_DARK : COLORS_LIGHT; + if (!count) return palette[0]; + if (count >= 4) return palette[4]; + return palette[count]; } export default function ContributionCalendar({ data }) { const days = getCalendarDays(); const monthLabels = getMonthLabels(days); + const [isDark, setIsDark] = useState(false); + + useEffect(() => { + // Detect dark mode by checking for 'dark' class on + const checkDark = () => { + setIsDark(document.documentElement.classList.contains('dark')); + }; + checkDark(); + const observer = new MutationObserver(checkDark); + observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] }); + return () => observer.disconnect(); + }, []); + // Get max count for scaling (optional, for more dynamic color) // const max = Math.max(...Object.values(data)); @@ -66,11 +88,11 @@ export default function ContributionCalendar({ data }) { margin: '0 auto', padding: 0, borderRadius: '1rem', - background: 'rgba(255,255,255,0.7)', - boxShadow: '0 4px 24px 0 rgba(0,0,0,0.08)', + background: isDark ? 'rgba(30,41,59,0.85)' : 'rgba(255,255,255,0.7)', + boxShadow: isDark ? '0 4px 24px 0 rgba(0,0,0,0.32)' : '0 4px 24px 0 rgba(0,0,0,0.08)', backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)', - border: '1px solid rgba(255,255,255,0.3)', + border: isDark ? '1px solid rgba(51,65,85,0.5)' : '1px solid rgba(255,255,255,0.3)', overflowX: 'auto', display: 'flex', flexDirection: 'column', @@ -92,7 +114,7 @@ export default function ContributionCalendar({ data }) { flex: '0 0 14px', textAlign: 'center', fontSize: 12, - color: '#888', + color: isDark ? '#b6c2d1' : '#888', fontWeight: 500, minWidth: 14, }} @@ -111,7 +133,7 @@ export default function ContributionCalendar({ data }) { style={{ height: 14, fontSize: 12, - color: '#888', + color: isDark ? '#b6c2d1' : '#888', textAlign: 'right', lineHeight: '14px', marginBottom: 1, @@ -141,7 +163,7 @@ export default function ContributionCalendar({ data }) { width: 12, height: 12, margin: 1, - background: getColor(count), + background: getColor(count, isDark), borderRadius: 2, }} /> @@ -151,9 +173,9 @@ export default function ContributionCalendar({ data }) { ))} -
+
Less - {COLORS.map((color, i) => ( + {(isDark ? COLORS_DARK : COLORS_LIGHT).map((color, i) => ( ))} More diff --git a/src/pages/[lang]/development.astro b/src/pages/[lang]/development.astro index 72d4f13..0c6f484 100644 --- a/src/pages/[lang]/development.astro +++ b/src/pages/[lang]/development.astro @@ -5,6 +5,7 @@ import { getTranslation } from '../../i18n/translations'; import React, { useMemo } from 'react'; import dynamic from 'astro/dynamic'; import ContributionCalendar from '../../components/ContributionCalendar.jsx'; +import CollapsibleIntro from '../../components/CollapsibleIntro.jsx'; const metadata = { title: 'Development Progress | 365DevNet', @@ -42,11 +43,11 @@ try { // Format date to a readable format const formatDate = (dateString: string) => { - return new Date(dateString).toLocaleDateString(lang, { - year: 'numeric', - month: 'long', - day: 'numeric', - }); + const date = new Date(dateString); + const day = date.toLocaleString(lang, { day: '2-digit' }); + const month = date.toLocaleString(lang, { month: 'short' }).toLowerCase().replace('.', ''); + const year = date.getFullYear(); + return `${day}-${month}-${year}`; }; // Helper: Group commits by date (YYYY-MM-DD) @@ -67,9 +68,8 @@ const contributionData = getContributionData(commits);

{t.development.title || 'Development Progress'}

-

- {t.development.intro} -

+ {/* Collapsible Intro */} + {/* Contribution Calendar */}
@@ -80,26 +80,44 @@ const contributionData = getContributionData(commits); {Array.isArray(commits) && commits.length > 0 ? (
{commits.slice(0, 10).map((commit) => ( -
-
-
-

{commit.commit?.message?.split('\n')[0] || 'No message'}

-

{commit.commit?.message || ''}

-
- {commit.commit?.author?.date ? formatDate(commit.commit.author.date) : ''} +
+
+

{commit.commit?.message?.split('\n')[0] || 'No message'}

+ {/* Format commit description with bullet points on new lines */} + {commit.commit?.message ? ( + (() => { + const lines = commit.commit.message.split('\n'); + const bullets = lines.filter(line => line.trim().startsWith('- ')); + if (bullets.length > 0) { + // Render as a list if there are bullet points + return ( +
    + {lines.map((line, idx) => + line.trim().startsWith('- ') + ?
  • {line.trim().slice(2)}
  • + : line.trim() !== '' &&
  • {line}
  • + )} +
+ ); + } else { + // Render as a paragraph if no bullet points + return

{commit.commit.message}

; + } + })() + ) : null}
-