Add Community Growth over Time

This commit is contained in:
MartinBraquet
2025-10-01 08:56:03 +02:00
parent f30cfffb86
commit 4dc2f3b9b9
3 changed files with 69 additions and 30 deletions

View File

@@ -1,6 +1,6 @@
// ChartComponent.jsx
import { useEffect, useState } from "react";
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from "recharts";
import {useEffect, useState} from "react";
import {CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis} from "recharts";
import {getUserCreations} from "web/lib/supabase/users";
export default function ChartComponent() {
const [data, setData] = useState([]);
@@ -8,28 +8,57 @@ export default function ChartComponent() {
useEffect(() => {
async function loadData() {
// Load some data from the backend API or Supabase
// const res = await fetch("http://localhost:5000/api/data");
// const json = await res.json();
const json: any = [
{ date: '2023-01-01', value: 400 },
{ date: '2023-02-01', value: 300 },
{ date: '2023-03-01', value: 500 },
{ date: '2023-04-01', value: 200 },
{ date: '2023-05-01', value: 600 },
]
const data = await getUserCreations()
let counts: { [date: string]: number } = {}
data.forEach((d) => {
const date = new Date(d.created_time).toISOString().split('T')[0]
counts[date] = (counts[date] || 0) + 1
})
const json: any = Object.entries(counts).map(([date, value]) => ({date, value}))
let prev = 0
for (let i = 0; i < json.length; i++) {
json[i].value += prev
prev = json[i].value
}
json.sort((a: any, b: any) => a.date.localeCompare(b.date))
// Example static data
// const json: any = [
// { date: '2023-01-01', value: 400 },
// { date: '2023-02-01', value: 300 },
// { date: '2023-03-01', value: 500 },
// { date: '2023-04-01', value: 200 },
// { date: '2023-05-01', value: 600 },
// ]
setData(json);
}
loadData();
}, []);
return (
<ResponsiveContainer width="100%" height={400}>
<LineChart data={data}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" />
<YAxis />
<Tooltip />
<Line type="monotone" dataKey="value" stroke="#2563eb" strokeWidth={2} />
<CartesianGrid strokeDasharray="3 3"/>
<XAxis dataKey="date" label={{value: "Date", position: "insideBottomRight", offset: -5}}/>
<YAxis label={{value: "Number of Members", angle: -90, position: "insideLeft"}}/>
<Tooltip
contentStyle={{
backgroundColor: "rgb(var(--color-canvas-100))",
border: "none",
borderRadius: "8px",
color: "rgb(var(--color-primary-900))",
}}
labelStyle={{
color: "rgb(var(--color-primary-900))",
}}
/>
<Line
type="monotone"
dataKey="value"
stroke="rgb(var(--color-primary-900))"
strokeWidth={2}
/>
</LineChart>
</ResponsiveContainer>
);

View File

@@ -1,9 +1,10 @@
import { db } from './db'
import { run } from 'common/supabase/utils'
import { APIError, api } from 'web/lib/api'
import { unauthedApi } from 'common/util/api'
import type { DisplayUser } from 'common/api/user-types'
export type { DisplayUser }
import {db} from './db'
import {run} from 'common/supabase/utils'
import {APIError, api} from 'web/lib/api'
import {unauthedApi} from 'common/util/api'
import type {DisplayUser} from 'common/api/user-types'
export type {DisplayUser}
export async function getUserSafe(userId: string) {
try {
@@ -25,27 +26,27 @@ export async function getPrivateUserSafe() {
}
export async function getUserById(id: string) {
return unauthedApi('user/by-id/:id/lite', { id })
return unauthedApi('user/by-id/:id/lite', {id})
}
export async function getUserByUsername(username: string) {
return unauthedApi('user/:username/lite', { username })
return unauthedApi('user/:username/lite', {username})
}
export async function getFullUserByUsername(username: string) {
return unauthedApi('user/:username', { username })
return unauthedApi('user/:username', {username})
}
export async function getFullUserById(id: string) {
return unauthedApi('user/by-id/:id', { id })
return unauthedApi('user/by-id/:id', {id})
}
export async function searchUsers(prompt: string, limit: number) {
return unauthedApi('search-users', { term: prompt, limit: limit })
return unauthedApi('search-users', {term: prompt, limit: limit})
}
export async function getDisplayUsers(userIds: string[]) {
const { data } = await run(
const {data} = await run(
db
.from('users')
.select(`id, name, username, data->avatarUrl, data->isBannedFromPosting`)
@@ -54,3 +55,12 @@ export async function getDisplayUsers(userIds: string[]) {
return data as unknown as DisplayUser[]
}
export async function getUserCreations() {
const {data} = await run(
db.from('users')
.select(`id, created_time`)
.order('created_time')
)
return data
}

View File

@@ -6,7 +6,7 @@ export default function Charts() {
<LovePage
trackPageView={'charts'}
>
<h1 className="text-3xl font-semibold text-center mb-6">An example of dynamic charts</h1>
<h1 className="text-3xl font-semibold text-center mb-6">Community Growth over Time</h1>
<ChartComponent/>
</LovePage>
);