feat(forgejo): add create issue dialog and integrate with metric cards

This commit is contained in:
null 2026-05-22 22:14:51 -05:00
parent 463a75fdb7
commit 1076ca27bb
3 changed files with 40 additions and 11 deletions

View File

@ -19,6 +19,7 @@ import { DashboardSidebar } from "@/components/organisms/DashboardSidebar";
import { DashboardShell } from "@/components/templates/DashboardShell";
import { SignedOutPanel } from "@/components/auth/SignedOutPanel";
import { ForgejoIssueMetricCards } from "@/components/git/ForgejoIssueMetricCards";
import { CreateForgejoIssueDialog } from "@/components/git/CreateForgejoIssueDialog";
import { ForgejoHeatmap } from "@/components/git/ForgejoHeatmap";
import {
DashboardMetricCard,
@ -440,6 +441,7 @@ export default function DashboardPage() {
const [selectedForgejoRepositoryId, setSelectedForgejoRepositoryId] =
useState(ALL_FORGEJO_REPOSITORIES);
const [isRefreshingForgejoSync, setIsRefreshingForgejoSync] = useState(false);
const [createForgejoIssueOpen, setCreateForgejoIssueOpen] = useState(false);
const boardsQuery = useListBoardsApiV1BoardsGet<
listBoardsApiV1BoardsGetResponse,
@ -1325,10 +1327,30 @@ export default function DashboardPage() {
selectedRepositoryId={selectedForgejoRepositoryId}
onSelectedRepositoryChange={setSelectedForgejoRepositoryId}
onRefreshLastSync={handleRefreshForgejoLastSync}
onCreateIssue={() => setCreateForgejoIssueOpen(true)}
isRefreshingLastSync={isRefreshingForgejoSync}
isLoading={forgejoIssueMetricsLoading}
error={forgejoIssueMetricsError}
/>
<CreateForgejoIssueDialog
repositories={forgejoRepositories}
open={createForgejoIssueOpen}
onOpenChange={setCreateForgejoIssueOpen}
defaultRepositoryId={
selectedForgejoRepositoryId === ALL_FORGEJO_REPOSITORIES
? undefined
: selectedForgejoRepositoryId
}
onSuccess={() => {
setCreateForgejoIssueOpen(false);
void Promise.all([
forgejoRepositoriesQuery.refetch(),
forgejoMetricsQuery.refetch(),
forgejoHeatmapQuery.refetch(),
forgejoLastPushQuery.refetch(),
]);
}}
/>
</div>
<div className="mt-4">

View File

@ -1,6 +1,6 @@
"use client";
import { useState } from "react";
import { useEffect, useState } from "react";
import {
Dialog,
@ -43,6 +43,12 @@ export function CreateForgejoIssueDialog({
const [isSubmitting, setIsSubmitting] = useState(false);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
if (open && !isSubmitting) {
setRepositoryId(defaultRepositoryId ?? repositories[0]?.id ?? "");
}
}, [defaultRepositoryId, isSubmitting, open, repositories]);
const reset = () => {
setTitle("");
setBody(ISSUE_TEMPLATE);

View File

@ -8,6 +8,7 @@ import {
ArrowUpRight,
CheckCircle2,
Clock3,
PlusCircle,
RefreshCw,
ShieldAlert,
ShieldCheck,
@ -30,6 +31,7 @@ type ForgejoIssueMetricCardsProps = {
selectedRepositoryId: string;
onSelectedRepositoryChange: (repositoryId: string) => void;
onRefreshLastSync: () => void;
onCreateIssue: () => void;
isRefreshingLastSync?: boolean;
isLoading?: boolean;
error?: string | null;
@ -309,6 +311,7 @@ export function ForgejoIssueMetricCards({
selectedRepositoryId,
onSelectedRepositoryChange,
onRefreshLastSync,
onCreateIssue,
isRefreshingLastSync = false,
isLoading = false,
error,
@ -412,17 +415,15 @@ export function ForgejoIssueMetricCards({
))}
</SelectContent>
</Select>
<Link
href={
selectedRepositoryId === ALL_REPOSITORIES_VALUE
? "/git-projects/issues"
: `/git-projects/issues?repository_id=${encodeURIComponent(selectedRepositoryId)}`
}
className="inline-flex w-fit items-center gap-1 text-sm font-medium text-[color:var(--accent)] transition hover:text-[color:var(--accent-strong)]"
<button
type="button"
onClick={onCreateIssue}
disabled={repositories.length === 0}
className="inline-flex w-fit items-center gap-1 text-sm font-medium text-[color:var(--accent)] transition hover:text-[color:var(--accent-strong)] disabled:cursor-not-allowed disabled:opacity-50"
>
Open issues
<ArrowUpRight className="h-4 w-4" />
</Link>
Create issue
<PlusCircle className="h-4 w-4" />
</button>
</div>
</div>