2026-05-05 15:02:55 +03:00
|
|
|
|
import { Alert, Button, Group, Paper, Stack, Text, Title } from "@mantine/core"
|
|
|
|
|
|
import { useDisclosure } from "@mantine/hooks"
|
2026-05-05 14:28:17 +03:00
|
|
|
|
import cl from "clsx"
|
2026-05-05 15:02:55 +03:00
|
|
|
|
import { useState } from "react"
|
|
|
|
|
|
import { assetsFactory } from "business/assets"
|
2026-05-05 14:28:17 +03:00
|
|
|
|
|
2026-05-05 15:02:55 +03:00
|
|
|
|
import { DASHBOARD_PIPELINE } from "./config/dashboard.config"
|
|
|
|
|
|
import { AssetDetailPanel } from "./parts/asset-detail-panel"
|
|
|
|
|
|
import { AssetsTable } from "./parts/assets-table"
|
|
|
|
|
|
import { CreateAssetModal } from "./parts/create-asset-modal"
|
|
|
|
|
|
import { PresetsPanel } from "./parts/presets-panel"
|
|
|
|
|
|
import { SummaryCards } from "./parts/summary-cards"
|
2026-05-05 14:28:17 +03:00
|
|
|
|
import styles from "./styles/dashboard.module.css"
|
|
|
|
|
|
import type { DashboardScreenProps } from "./types/dashboard.type"
|
|
|
|
|
|
|
2026-05-05 15:02:55 +03:00
|
|
|
|
const assets = assetsFactory()
|
|
|
|
|
|
|
2026-05-05 14:28:17 +03:00
|
|
|
|
/**
|
|
|
|
|
|
* Стартовый dashboard admin-приложения.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Используется для:
|
|
|
|
|
|
* - отображения стартового состояния admin MVP
|
|
|
|
|
|
* - обзора будущих разделов и пайплайна генерации
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const DashboardScreen = (props: DashboardScreenProps) => {
|
|
|
|
|
|
const { className, ...rootAttrs } = props
|
2026-05-05 15:02:55 +03:00
|
|
|
|
const [selectedPublicId, setSelectedPublicId] = useState<string | null>(null)
|
|
|
|
|
|
const [isCreateAssetOpen, createAssetModal] = useDisclosure(false)
|
|
|
|
|
|
const dashboard = assets.useAssetsDashboard()
|
|
|
|
|
|
const createAsset = assets.useCreateAsset()
|
|
|
|
|
|
const effectivePublicId = selectedPublicId ?? dashboard.assets[0]?.publicId ?? null
|
|
|
|
|
|
const overview = assets.useAssetOverview(effectivePublicId)
|
2026-05-05 14:28:17 +03:00
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<section {...rootAttrs} className={cl(styles.root, className)}>
|
2026-05-05 15:02:55 +03:00
|
|
|
|
<Stack gap="lg">
|
|
|
|
|
|
<Paper className={styles.hero} p={{ base: "xl", md: 42 }} radius="xl" shadow="xs" withBorder>
|
|
|
|
|
|
<Group align="flex-end" justify="space-between" gap="xl">
|
|
|
|
|
|
<div className={styles.heroContent}>
|
|
|
|
|
|
<Text className={styles.eyebrow}>Image Platform Admin</Text>
|
|
|
|
|
|
<Title className={styles.title}>Control plane для image delivery</Title>
|
|
|
|
|
|
<Text className={styles.lead}>
|
|
|
|
|
|
Управление allowed hosts, assets, source versions, presets и variant generation без
|
|
|
|
|
|
прямого доступа к storage-слою.
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<Button className={styles.primaryAction} onClick={createAssetModal.open} radius="xl" size="md">
|
|
|
|
|
|
Create asset
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</Group>
|
|
|
|
|
|
</Paper>
|
|
|
|
|
|
|
|
|
|
|
|
<SummaryCards isLoading={dashboard.isLoading} summary={dashboard.summary} />
|
|
|
|
|
|
|
|
|
|
|
|
<Group gap="xs" role="list" aria-label="Пайплайн генерации изображений">
|
|
|
|
|
|
{DASHBOARD_PIPELINE.map((step) => (
|
|
|
|
|
|
<Text className={styles.pipelineStep} key={step} role="listitem">
|
|
|
|
|
|
{step}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</Group>
|
|
|
|
|
|
|
|
|
|
|
|
{dashboard.error ? (
|
|
|
|
|
|
<Alert color="red" radius="lg" title="Backend API недоступен">
|
|
|
|
|
|
Проверьте, что backend запущен на `localhost:3001`, а Vite proxy доступен по `/api`.
|
|
|
|
|
|
</Alert>
|
|
|
|
|
|
) : null}
|
|
|
|
|
|
|
|
|
|
|
|
<div className={styles.workbench}>
|
|
|
|
|
|
<AssetsTable
|
|
|
|
|
|
assets={dashboard.assets}
|
|
|
|
|
|
isLoading={dashboard.isLoading}
|
|
|
|
|
|
onSelect={setSelectedPublicId}
|
|
|
|
|
|
selectedPublicId={effectivePublicId}
|
|
|
|
|
|
/>
|
|
|
|
|
|
<AssetDetailPanel overview={overview} publicId={effectivePublicId} />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<PresetsPanel
|
|
|
|
|
|
allowedSourceHosts={dashboard.allowedSourceHosts}
|
|
|
|
|
|
custom={dashboard.custom}
|
|
|
|
|
|
isLoading={dashboard.isLoading}
|
|
|
|
|
|
presets={dashboard.presets}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Stack>
|
|
|
|
|
|
|
|
|
|
|
|
<CreateAssetModal
|
|
|
|
|
|
action={createAsset}
|
|
|
|
|
|
onClose={createAssetModal.close}
|
|
|
|
|
|
onCreated={setSelectedPublicId}
|
|
|
|
|
|
opened={isCreateAssetOpen}
|
|
|
|
|
|
/>
|
2026-05-05 14:28:17 +03:00
|
|
|
|
</section>
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|