added side context panel and repo only search bar

This commit is contained in:
2026-05-17 21:13:45 +02:00
parent 5147c6bddb
commit ec9a286d33
7 changed files with 362 additions and 1 deletions
+34
View File
@@ -0,0 +1,34 @@
import { useQuery } from '@tanstack/react-query'
import { z } from 'zod'
import { api } from '../client'
const langStatSchema = z.object({
name: z.string(),
color: z.string(),
count: z.number(),
pct: z.number(),
})
const contributorSchema = z.object({
name: z.string(),
commits: z.number(),
})
const insightsSchema = z.object({
languages: z.array(langStatSchema),
contributors: z.array(contributorSchema),
totalCommits: z.number(),
})
export type LangStat = z.infer<typeof langStatSchema>
export type Contributor = z.infer<typeof contributorSchema>
export type RepoInsights = z.infer<typeof insightsSchema>
export function useRepoInsights(owner: string, repo: string) {
return useQuery<RepoInsights>({
queryKey: ['repos', owner, repo, 'insights'],
queryFn: () => api.get<RepoInsights>(`/api/v1/repos/${owner}/${repo}/insights`, insightsSchema),
enabled: !!owner && !!repo,
staleTime: 5 * 60 * 1000, // 5 min — git stats don't change on every page load
})
}
+36
View File
@@ -194,6 +194,42 @@ export function useCreateRepo() {
})
}
const latestDeploymentSchema = z.object({
envName: z.string(),
status: z.string(),
sha: z.string(),
finishedAt: z.string().nullable().optional(),
})
const pipelineRunSchema = z.object({
id: z.number(),
status: z.string(),
triggerRef: z.string().optional(),
startedAt: z.string().nullable().optional(),
finishedAt: z.string().nullable().optional(),
}).nullable()
const repoHealthSchema = z.object({
ciPassRate7d: z.number(),
totalRuns7d: z.number(),
latestRun: pipelineRunSchema.optional(),
latestDeployments: z.array(latestDeploymentSchema),
openDriftCount: z.number(),
openPRCount: z.number(),
})
export type RepoHealth = z.infer<typeof repoHealthSchema>
export function useRepoHealth(owner: string, repo: string) {
return useQuery<RepoHealth>({
queryKey: ['repos', owner, repo, 'health'],
queryFn: () =>
api.get<RepoHealth>(`/api/v1/repos/${owner}/${repo}/health`, repoHealthSchema),
enabled: Boolean(owner && repo),
staleTime: 60 * 1000, // 1 min
})
}
export function useImportRepo() {
const queryClient = useQueryClient()
return useMutation({
+14 -1
View File
@@ -6,6 +6,8 @@ import { useRepo, useRepoTree, useRepoBlob, useRepoBranches } from '../api/queri
import { useEnvironments } from '../api/queries/environments'
import { useInstance } from '../api/queries/instance'
import { TreeBrowser } from '../components/repos/TreeBrowser'
import { RepoContextPanel } from '../components/repos/RepoContextPanel'
import { RepoFileSearch } from '../components/repos/RepoFileSearch'
import { RepoListSkeleton } from '../ui/Skeleton'
import { RepoAvatar } from '../ui/RepoAvatar'
import { useRecentRepos } from '../hooks/useRecentRepos'
@@ -59,7 +61,9 @@ export default function RepoPage() {
}
return (
<div className="max-w-5xl mx-auto px-4 md:px-6 py-6 space-y-4">
<div className="max-w-[1400px] mx-auto px-4 md:px-6 py-6">
<div className="flex gap-6 items-start">
<div className="flex-1 min-w-0 space-y-4">
{/* Header row */}
<div className="flex items-start justify-between gap-4 flex-wrap">
@@ -261,6 +265,15 @@ export default function RepoPage() {
</>
)}
</div>
{/* Right sidebar — hidden below lg breakpoint */}
<div className="w-72 shrink-0 hidden lg:block space-y-3">
<RepoFileSearch owner={owner} repo={repoName} branch={branch} />
<RepoContextPanel owner={owner} repo={repoName} />
</div>
</div>
</div>
)
}