Enhance frontend documentation and UI components; update frontend-shadcn.mdc to include UI patterns reference; improve navigation structure in AppSidebar by categorizing items; refactor DataTableCard to support empty states with EmptyState component; implement ConfirmDialog for delete actions in DnsRecordsTable and GroupsPage; add search functionality in CertificatesPage and GroupsPage for better user experience; update ServiceEditSheet to utilize tabs for organization.
Build, Test, and Push CFDM Docker Image / test (push) Has been cancelled
Build, Test, and Push CFDM Docker Image / build-and-push (push) Has been cancelled
Build, Test, and Push CFDM Docker Image / create-release (push) Has been cancelled
Build, Test, and Push CFDM Docker Image / update-wiki (push) Has been cancelled

This commit is contained in:
Denozordec
2026-06-19 12:15:29 +07:00
parent d11414666f
commit 4a70cf5854
32 changed files with 1546 additions and 435 deletions
+51 -68
View File
@@ -1,89 +1,72 @@
import { createFileRoute, Link } from '@tanstack/react-router'
import { createFileRoute } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@cfdm/ui/components/card'
import { Button } from '@cfdm/ui/components/button'
import { certificatesQueryOptions, certSummaryQueryOptions, domainsListQueryOptions } from '@/queries'
import { certificatesQueryOptions, certSummaryQueryOptions, domainsListQueryOptions, groupsQueryOptions, serviceGroupsQueryOptions } from '@/queries'
import { PageHeader } from '@/components/page-header'
import { PageShell } from '@/components/page-shell'
import { QueryState } from '@/components/query-state'
import { SectionCards } from '@/components/section-cards'
export const Route = createFileRoute('/_auth/')({
loader: ({ context: { queryClient } }) =>
Promise.all([
queryClient.ensureQueryData(domainsListQueryOptions()),
queryClient.ensureQueryData(certSummaryQueryOptions()),
queryClient.ensureQueryData(groupsQueryOptions()),
queryClient.ensureQueryData(serviceGroupsQueryOptions()),
]),
component: DashboardPage,
})
function DashboardPage() {
const { data: domains } = useQuery(domainsListQueryOptions())
const { data: summary } = useQuery(certSummaryQueryOptions())
const {
data: domains,
isLoading: domainsLoading,
isError: domainsError,
error: domainsErr,
refetch: refetchDomains,
} = useQuery(domainsListQueryOptions())
const {
data: summary,
isLoading: summaryLoading,
isError: summaryError,
error: summaryErr,
refetch: refetchSummary,
} = useQuery(certSummaryQueryOptions())
const { data: certs } = useQuery(certificatesQueryOptions())
const { data: groups } = useQuery(groupsQueryOptions())
const { data: serviceData } = useQuery(serviceGroupsQueryOptions())
const serviceCount =
(serviceData?.groups.reduce((sum, g) => sum + g.services.length, 0) ?? 0) +
(serviceData?.ungrouped.length ?? 0)
const isLoading = domainsLoading || summaryLoading
const isError = domainsError || summaryError
const error = domainsErr ?? summaryErr
return (
<div className="@container/main flex flex-col gap-4 py-4 md:gap-6 md:py-6">
<PageShell>
<PageHeader
title="Панель управления"
description="Обзор доменов и сертификатов Cloudflare"
description="Обзор доменов, групп, сервисов и сертификатов Cloudflare"
/>
<div className="grid gap-4 md:grid-cols-3">
<Card>
<CardHeader>
<CardDescription>Домены</CardDescription>
<CardTitle className="text-3xl font-semibold tabular-nums">
{domains?.length ?? 0}
</CardTitle>
</CardHeader>
<CardFooter>
<Button
variant="link"
className="h-auto p-0"
render={<Link to="/domains" />}
>
Управление доменами
</Button>
</CardFooter>
</Card>
<Card>
<CardHeader>
<CardDescription>Сертификаты</CardDescription>
<CardTitle className="text-3xl font-semibold tabular-nums">
{certs?.length ?? 0}
</CardTitle>
</CardHeader>
<CardFooter>
<Button
variant="link"
className="h-auto p-0"
render={<Link to="/certificates" />}
>
Мониторинг сертификатов
</Button>
</CardFooter>
</Card>
<Card>
<CardHeader>
<CardDescription>Статусы сертификатов</CardDescription>
<CardTitle className="text-base font-medium">Сводка</CardTitle>
</CardHeader>
<CardContent>
<ul className="flex flex-col gap-1 text-sm">
{summary?.map(([status, count]) => (
<li key={status} className="flex justify-between">
<span className="text-muted-foreground">{status}</span>
<span className="font-medium tabular-nums">{count}</span>
</li>
))}
</ul>
</CardContent>
</Card>
</div>
</div>
<QueryState
isLoading={isLoading}
isError={isError}
error={error}
onRetry={() => {
void refetchDomains()
void refetchSummary()
}}
>
<SectionCards
domainCount={domains?.length ?? 0}
certCount={certs?.length ?? 0}
groupCount={groups?.length ?? 0}
serviceCount={serviceCount}
certSummary={summary}
/>
</QueryState>
</PageShell>
)
}