mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2026-03-13 02:01:57 +08:00
Compare commits
1 Commits
feat/xyflo
...
feat/progr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3771326cd8 |
@@ -28,6 +28,8 @@
|
||||
"@nanostores/preact": "^0.5.0",
|
||||
"astro": "^2.6.3",
|
||||
"astro-compress": "^1.1.47",
|
||||
"chart.js": "^4.3.0",
|
||||
"chartjs-plugin-datalabels": "^2.2.0",
|
||||
"jose": "^4.14.4",
|
||||
"js-cookie": "^3.0.5",
|
||||
"nanostores": "^0.9.1",
|
||||
|
||||
23
pnpm-lock.yaml
generated
23
pnpm-lock.yaml
generated
@@ -11,6 +11,8 @@ specifiers:
|
||||
'@types/js-cookie': ^3.0.3
|
||||
astro: ^2.6.3
|
||||
astro-compress: ^1.1.47
|
||||
chart.js: ^4.3.0
|
||||
chartjs-plugin-datalabels: ^2.2.0
|
||||
csv-parser: ^3.0.0
|
||||
gh-pages: ^5.0.0
|
||||
jose: ^4.14.4
|
||||
@@ -37,6 +39,8 @@ dependencies:
|
||||
'@nanostores/preact': 0.5.0_m2wbkjxz7237icvaxqi7ignbgm
|
||||
astro: 2.6.4
|
||||
astro-compress: 1.1.47
|
||||
chart.js: 4.3.0
|
||||
chartjs-plugin-datalabels: 2.2.0_chart.js@4.3.0
|
||||
jose: 4.14.4
|
||||
js-cookie: 3.0.5
|
||||
nanostores: 0.9.1
|
||||
@@ -696,6 +700,10 @@ packages:
|
||||
'@jridgewell/resolve-uri': 3.1.0
|
||||
'@jridgewell/sourcemap-codec': 1.4.14
|
||||
|
||||
/@kurkle/color/0.3.2:
|
||||
resolution: {integrity: sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==}
|
||||
dev: false
|
||||
|
||||
/@ljharb/has-package-exports-patterns/0.0.2:
|
||||
resolution: {integrity: sha512-4/RWEeXDO6bocPONheFe6gX/oQdP/bEpv0oL4HqjPP5DCenBSt0mHgahppY49N0CpsaqffdwPq+TlX9CYOq2Dw==}
|
||||
dev: false
|
||||
@@ -1553,6 +1561,21 @@ packages:
|
||||
resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
|
||||
dev: false
|
||||
|
||||
/chart.js/4.3.0:
|
||||
resolution: {integrity: sha512-ynG0E79xGfMaV2xAHdbhwiPLczxnNNnasrmPEXriXsPJGjmhOBYzFVEsB65w2qMDz+CaBJJuJD0inE/ab/h36g==}
|
||||
engines: {pnpm: '>=7'}
|
||||
dependencies:
|
||||
'@kurkle/color': 0.3.2
|
||||
dev: false
|
||||
|
||||
/chartjs-plugin-datalabels/2.2.0_chart.js@4.3.0:
|
||||
resolution: {integrity: sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==}
|
||||
peerDependencies:
|
||||
chart.js: '>=3.0.0'
|
||||
dependencies:
|
||||
chart.js: 4.3.0
|
||||
dev: false
|
||||
|
||||
/chokidar/3.5.3:
|
||||
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { useEffect, useState } from 'preact/hooks';
|
||||
import { useEffect, useMemo, useRef, useState } from 'preact/hooks';
|
||||
import { Chart as ChartJS, ChartTypeRegistry } from 'chart.js/auto';
|
||||
import ChartDataLabels from 'chartjs-plugin-datalabels'
|
||||
import { httpGet } from '../../lib/http';
|
||||
import { ActivityCounters } from './ActivityCounters';
|
||||
import { ResourceProgress } from './ResourceProgress';
|
||||
@@ -50,8 +52,15 @@ type ActivityResponse = {
|
||||
}[];
|
||||
};
|
||||
|
||||
type ChartLegendItem = {
|
||||
title: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export function ActivityPage() {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const [activity, setActivity] = useState<ActivityResponse>();
|
||||
const [chartLegend, setChartLegend] = useState<ChartLegendItem[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
async function loadActivity() {
|
||||
@@ -83,6 +92,56 @@ export function ActivityPage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
const chartData = useMemo(() => {
|
||||
return {
|
||||
labels: [...learningRoadmaps, ...learningBestPractices].map(resource => resource.title),
|
||||
data: [...learningRoadmaps, ...learningBestPractices].map(resource => resource.done)
|
||||
}
|
||||
}, [activity])
|
||||
|
||||
useEffect(() => {
|
||||
let chart: ChartJS<"pie", number[], string> | null = null
|
||||
const ctx = canvasRef.current?.getContext('2d');
|
||||
if (!ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!chart) {
|
||||
chart = new ChartJS(ctx, {
|
||||
type: 'pie',
|
||||
data: {
|
||||
labels: chartData.labels,
|
||||
datasets: [{
|
||||
data: chartData.data,
|
||||
hoverOffset: 4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
const legendItems = chart?.legend?.legendItems || []
|
||||
const enrichedLegendItems = legendItems.map((item, index) => {
|
||||
return {
|
||||
title: item.text,
|
||||
color: item.fillStyle?.toString() || ''
|
||||
}
|
||||
})
|
||||
console.log(enrichedLegendItems)
|
||||
setChartLegend(enrichedLegendItems)
|
||||
|
||||
return () => {
|
||||
chart?.destroy();
|
||||
};
|
||||
}, [chartData]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ActivityCounters
|
||||
@@ -91,6 +150,35 @@ export function ActivityPage() {
|
||||
streak={activity?.streak || { count: 0 }}
|
||||
/>
|
||||
|
||||
<div className="mx-0 px-0 py-5 md:-mx-10 md:px-8 md:py-8">
|
||||
<div className="bg-white shadow-lg rounded-2xl p-8">
|
||||
<h2 className="font-medium">Knowledge Structure</h2>
|
||||
<div className="grid grid-cols-4 gap-5 mt-6">
|
||||
<div className="w-full aspect-square flex items-center justify-center h-full">
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="col-span-3">
|
||||
<div className="flex flex-col gap-1.5 justify-center h-full">
|
||||
{chartLegend.map((data) => (
|
||||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
style={{
|
||||
background: `${data.color}`
|
||||
}}
|
||||
className="w-3 h-3 rounded-full"
|
||||
/>
|
||||
<span className="text-xs text-gray-500">{data.title}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mx-0 px-0 py-5 md:-mx-10 md:px-8 md:py-8">
|
||||
{learningRoadmaps.length === 0 &&
|
||||
learningBestPractices.length === 0 && <EmptyActivity />}
|
||||
|
||||
Reference in New Issue
Block a user