Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 21 additions & 55 deletions app/segments/[id]/retention/page.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,25 @@
"use client";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { getRepositoryRetentionData } from "@/lib/services/repository-sublists-service";
import { RepositoryActivityHeatmap } from "@/components/charts/repository-activity-heatmap";

import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { useSegment } from "@/lib/react-query/segments";
import { use } from "react";
const RetentionPage = () => {
const router = useRouter();
const { id } = router.query;
const [retentionData, setRetentionData] = useState([]);

export default function RetentionPage({ params }: { params: Promise<{ id: string }> }) {
const resolvedParams = use(params);
const { data: segment, isLoading, error } = useSegment(resolvedParams.id);
useEffect(() => {
if (id) {
getRepositoryRetentionData(id).then((data) => setRetentionData(data));
}
}, [id]);

if (isLoading) {
return (
<div>
<Card>
<CardHeader>
<Skeleton className="h-8 w-1/3 mb-2" />
<Skeleton className="h-4 w-2/3" />
</CardHeader>
<CardContent>
<Skeleton className="h-4 w-full mb-4" />
<Skeleton className="h-4 w-full mb-4" />
<Skeleton className="h-4 w-2/3" />
</CardContent>
</Card>
</div>
);
}
return (
<div>
<h1>Repository Retention</h1>
<RepositoryActivityHeatmap data={retentionData} />
</div>
);
};

if (error || !segment) {
return (
<Card className="bg-red-50">
<CardHeader>
<CardTitle className="text-red-600">Error</CardTitle>
<CardDescription>{error ? error.message : "Segment not found"}</CardDescription>
</CardHeader>
</Card>
);
}

return (
<Card>
<CardHeader>
<CardTitle>Retention Analysis</CardTitle>
<CardDescription>Contributor retention metrics and analysis</CardDescription>
</CardHeader>
<CardContent>
<p className="text-muted-foreground">Retention analysis will be displayed here in a future update.</p>

<div className="mt-8 p-6 border border-dashed rounded-lg flex flex-col items-center justify-center">
<div className="text-muted-foreground text-center mb-4">
<p className="mb-2">This feature is still under development</p>
<p>Retention analysis will show metrics about contributor engagement over time</p>
</div>
</div>
</CardContent>
</Card>
);
}
export default RetentionPage;
30 changes: 30 additions & 0 deletions components/charts/repository-activity-heatmap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import { HeatMapGrid } from 'react-grid-heatmap';

const RepositoryActivityHeatmap = ({ data }) => {
const months = [
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
];

const repoNames = data.map((repo) => repo.repositoryName);
const heatmapData = data.map((repo) => repo.monthlyActivity);

return (
<div>
<h2>Repository Activity Heatmap</h2>
<HeatMapGrid
data={heatmapData}
xLabels={months}
yLabels={repoNames}
cellRender={(x, y, value) => `${value} commits`}
cellStyle={(x, y, ratio) => ({
background: `rgba(0, 255, 0, ${ratio})`,
fontSize: '.8rem',
})}
/>
</div>
);
};

export default RepositoryActivityHeatmap;
32 changes: 32 additions & 0 deletions lib/services/repository-activity-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { dbFactory } from "@/lib/drizzle";
import { repositories } from "@/lib/drizzle/schema/repositories";
import { sql } from "drizzle-orm";

// Service to fetch repository activity data
export async function getRepositoryActivityData() {
try {
const activityData = await dbFactory.getClient().execute(sql`
SELECT
r.name AS repository_name,
DATE_TRUNC('month', c.committed_at) AS month,
COUNT(c.id) AS commit_count
FROM
indexer_exp.github_commits c
JOIN
indexer_exp.github_repos r ON c.repo_id = r.id
GROUP BY
r.name, DATE_TRUNC('month', c.committed_at)
ORDER BY
r.name, DATE_TRUNC('month', c.committed_at)
`);

return activityData.map(row => ({
repositoryName: row.repository_name,
month: row.month,
commitCount: row.commit_count
}));
} catch (error) {
console.error("Error fetching repository activity data:", error);
return [];
}
}
Loading