feat: complete TanStack dashboard acceptance
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { Link, useParams } from "react-router";
|
||||
import { useDataProvider } from "@refinedev/core";
|
||||
import { Link, useParams } from "../../shared/router.jsx";
|
||||
import { useDataProvider } from "../../shared/hooks/dataHooks.js";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Link, useNavigate, useParams } from "react-router";
|
||||
import { useDataProvider, useList, useOne } from "@refinedev/core";
|
||||
import { Link, useNavigate, useParams } from "../../shared/router.jsx";
|
||||
import { useDataProvider, useList, useOne } from "../../shared/hooks/dataHooks.js";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
waitFor,
|
||||
} from "@testing-library/react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Refine } from "@refinedev/core";
|
||||
import { MemoryRouter, Route, Routes } from "react-router";
|
||||
import { TestDataProvider } from "../../test/providerCompat.jsx";
|
||||
import { MemoryRouter, Route, Routes } from "../../test/routerCompat.jsx";
|
||||
import {
|
||||
AccountCreatePage,
|
||||
AccountDetail,
|
||||
@@ -85,11 +85,11 @@ const queryClient = () =>
|
||||
function renderList(dataProvider) {
|
||||
return render(
|
||||
<QueryClientProvider client={queryClient()}>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter>
|
||||
<AccountList />
|
||||
</MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
}
|
||||
@@ -97,13 +97,13 @@ function renderList(dataProvider) {
|
||||
function renderDetail(dataProvider) {
|
||||
return render(
|
||||
<QueryClientProvider client={queryClient()}>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter initialEntries={["/accounts/account-a"]}>
|
||||
<Routes>
|
||||
<Route path="/accounts/:id" element={<AccountDetail />} />
|
||||
</Routes>
|
||||
</MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
}
|
||||
@@ -111,13 +111,13 @@ function renderDetail(dataProvider) {
|
||||
function renderCreate(dataProvider) {
|
||||
return render(
|
||||
<QueryClientProvider client={queryClient()}>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter initialEntries={["/accounts/new"]}>
|
||||
<Routes>
|
||||
<Route path="/accounts/new" element={<AccountCreatePage />} />
|
||||
</Routes>
|
||||
</MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
waitFor,
|
||||
} from "@testing-library/react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Refine } from "@refinedev/core";
|
||||
import { MemoryRouter, Route, Routes } from "react-router";
|
||||
import { TestDataProvider } from "../../test/providerCompat.jsx";
|
||||
import { MemoryRouter, Route, Routes } from "../../test/routerCompat.jsx";
|
||||
import { AccountEditPage } from "../accounts/AccountEditPage";
|
||||
import { AccountList } from "../accounts/AccountsPage";
|
||||
import { CreatorCompetitorsPage } from "./competitors/CreatorCompetitorsPage";
|
||||
@@ -90,9 +90,9 @@ function provider(overrides = {}) {
|
||||
function renderPage(element, dataProvider) {
|
||||
return render(
|
||||
<QueryClientProvider client={new QueryClient()}>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter>{element}</MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
}
|
||||
@@ -100,13 +100,13 @@ function renderPage(element, dataProvider) {
|
||||
function renderAccountPage(dataProvider) {
|
||||
return render(
|
||||
<QueryClientProvider client={new QueryClient()}>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter initialEntries={["/accounts/account-a/edit"]}>
|
||||
<Routes>
|
||||
<Route path="/accounts/:id/edit" element={<AccountEditPage />} />
|
||||
</Routes>
|
||||
</MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
}
|
||||
@@ -498,7 +498,6 @@ describe("creator pages", () => {
|
||||
expect.objectContaining({
|
||||
resource: "creator-competitor-preview",
|
||||
variables: {
|
||||
account_id: "account-a",
|
||||
platform: "douyin",
|
||||
share_url: "https://v.douyin.com/share-a/",
|
||||
},
|
||||
@@ -511,7 +510,6 @@ describe("creator pages", () => {
|
||||
expect.objectContaining({
|
||||
resource: "creator-competitors",
|
||||
variables: {
|
||||
account_id: "account-a",
|
||||
platform: "douyin",
|
||||
share_url: "https://v.douyin.com/share-a/",
|
||||
tags: ["重点监测"],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDataProvider } from "@refinedev/core";
|
||||
import { useDataProvider } from "../../../shared/hooks/dataHooks.js";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
@@ -64,7 +64,6 @@ export function CreatorCompetitorsPage() {
|
||||
total: 0,
|
||||
hasNext: false,
|
||||
});
|
||||
const [accounts, setAccounts] = useState([]);
|
||||
const [platform, setPlatform] = useState("");
|
||||
const [createOpen, setCreateOpen] = useState(false);
|
||||
const [shareText, setShareText] = useState("");
|
||||
@@ -81,7 +80,6 @@ export function CreatorCompetitorsPage() {
|
||||
const [previewConfirmed, setPreviewConfirmed] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
const [notice, setNotice] = useState(null);
|
||||
const [accountError, setAccountError] = useState(null);
|
||||
const [material, setMaterial] = useState(null);
|
||||
const [materialPending, setMaterialPending] = useState(false);
|
||||
const [rewriteRequirement, setRewriteRequirement] = useState("");
|
||||
@@ -154,15 +152,6 @@ export function CreatorCompetitorsPage() {
|
||||
publishedAfter,
|
||||
publishedBefore,
|
||||
]);
|
||||
useEffect(() => {
|
||||
dataProvider
|
||||
.getList({ resource: "creator-accounts" })
|
||||
.then((result) => {
|
||||
setAccountError(null);
|
||||
setAccounts(result.data);
|
||||
})
|
||||
.catch((loadError) => setAccountError(loadError));
|
||||
}, [dataProvider]);
|
||||
const extractedShareURL = extractShareURL(shareText);
|
||||
const sharePlatform = platformForShareURL(extractedShareURL);
|
||||
const closeCreate = () => {
|
||||
@@ -183,33 +172,18 @@ export function CreatorCompetitorsPage() {
|
||||
setNotice({ variant: "warning", text: "链接不是支持的平台分享链接。" });
|
||||
return;
|
||||
}
|
||||
const account = accounts.find(
|
||||
(value) =>
|
||||
value.platform === sharePlatform &&
|
||||
value.authorization_status === "authorized" &&
|
||||
(value.business_status === "normal" || value.business_status === "muted") &&
|
||||
value.login_status === "logged_in",
|
||||
);
|
||||
if (!account) {
|
||||
setNotice({
|
||||
variant: "warning",
|
||||
text: `没有可用于解析${sharePlatform === "douyin" ? "抖音" : "小红书"}分享内容的已登录账号。`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
setBusy(true);
|
||||
setNotice(null);
|
||||
try {
|
||||
const result = await dataProvider.create({
|
||||
resource: "creator-competitor-preview",
|
||||
variables: {
|
||||
account_id: account.id,
|
||||
platform: sharePlatform,
|
||||
share_url: extractedShareURL,
|
||||
},
|
||||
});
|
||||
const verified = result.data;
|
||||
setPreview({ ...verified, account_id: account.id, share_url: extractedShareURL });
|
||||
setPreview({ ...verified, share_url: extractedShareURL });
|
||||
setPreviewConfirmed(false);
|
||||
setNotice({
|
||||
variant: "info",
|
||||
@@ -233,7 +207,6 @@ export function CreatorCompetitorsPage() {
|
||||
setNotice(null);
|
||||
try {
|
||||
const variables = {
|
||||
account_id: preview.account_id,
|
||||
platform: preview.platform,
|
||||
share_url: preview.share_url || extractedShareURL,
|
||||
};
|
||||
@@ -610,12 +583,6 @@ export function CreatorCompetitorsPage() {
|
||||
/>
|
||||
</Field>
|
||||
</div>
|
||||
{accountError ? (
|
||||
<Alert variant="warning" className="mb-4">
|
||||
同平台账号读取失败:
|
||||
{conflictMessage(accountError, "请重试账号列表")}
|
||||
</Alert>
|
||||
) : null}
|
||||
<PageState
|
||||
pending={pending}
|
||||
error={error}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDataProvider } from "@refinedev/core";
|
||||
import { useDataProvider } from "../../../shared/hooks/dataHooks.js";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useDataProvider } from "@refinedev/core";
|
||||
import { useDataProvider } from "../../../shared/hooks/dataHooks.js";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from "react";
|
||||
import { useDataProvider, useList } from "@refinedev/core";
|
||||
import { useDataProvider, useList } from "../../shared/hooks/dataHooks.js";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
within,
|
||||
} from "@testing-library/react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Refine } from "@refinedev/core";
|
||||
import { MemoryRouter } from "react-router";
|
||||
import { TestDataProvider } from "../../test/providerCompat.jsx";
|
||||
import { MemoryRouter } from "../../test/routerCompat.jsx";
|
||||
import { BrowserVersionList } from "./BrowserVersionsPage";
|
||||
|
||||
afterEach(() => {
|
||||
@@ -59,11 +59,11 @@ const renderVersions = (dataProvider) =>
|
||||
new QueryClient({ defaultOptions: { queries: { retry: false } } })
|
||||
}
|
||||
>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter>
|
||||
<BrowserVersionList />
|
||||
</MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Link, useNavigate, useParams } from "react-router";
|
||||
import { useDataProvider, useList, useOne } from "@refinedev/core";
|
||||
import { Link, useNavigate, useParams } from "../../shared/router.jsx";
|
||||
import { useDataProvider, useList, useOne } from "../../shared/hooks/dataHooks.js";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
within,
|
||||
} from "@testing-library/react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Refine } from "@refinedev/core";
|
||||
import { MemoryRouter } from "react-router";
|
||||
import { TestDataProvider } from "../../test/providerCompat.jsx";
|
||||
import { MemoryRouter } from "../../test/routerCompat.jsx";
|
||||
import { BrowserCreatePage, BrowserList } from "./BrowsersPage";
|
||||
|
||||
afterEach(() => {
|
||||
@@ -126,22 +126,22 @@ const queryClient = () =>
|
||||
const renderList = (dataProvider) =>
|
||||
render(
|
||||
<QueryClientProvider client={queryClient()}>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter>
|
||||
<BrowserList />
|
||||
</MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
|
||||
const renderCreate = (dataProvider) =>
|
||||
render(
|
||||
<QueryClientProvider client={queryClient()}>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter initialEntries={["/browsers/new"]}>
|
||||
<BrowserCreatePage />
|
||||
</MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDataProvider, useList } from "@refinedev/core";
|
||||
import { useDataProvider, useList } from "../../shared/hooks/dataHooks.js";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
within,
|
||||
} from "@testing-library/react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Refine } from "@refinedev/core";
|
||||
import { MemoryRouter } from "react-router";
|
||||
import { TestDataProvider } from "../../test/providerCompat.jsx";
|
||||
import { MemoryRouter } from "../../test/routerCompat.jsx";
|
||||
import { GatewayList } from "./GatewaysPage";
|
||||
|
||||
afterEach(() => {
|
||||
@@ -63,11 +63,11 @@ const renderGateways = (dataProvider) =>
|
||||
new QueryClient({ defaultOptions: { queries: { retry: false } } })
|
||||
}
|
||||
>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter>
|
||||
<GatewayList />
|
||||
</MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Link, useParams } from "react-router";
|
||||
import { useDataProvider, useList, useOne } from "@refinedev/core";
|
||||
import { Link, useParams } from "../../shared/router.jsx";
|
||||
import { useDataProvider, useList, useOne } from "../../shared/hooks/dataHooks.js";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
within,
|
||||
} from "@testing-library/react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Refine } from "@refinedev/core";
|
||||
import { MemoryRouter } from "react-router";
|
||||
import { TestDataProvider } from "../../test/providerCompat.jsx";
|
||||
import { MemoryRouter } from "../../test/routerCompat.jsx";
|
||||
import { NetworkExitList } from "./NetworkExitsPage";
|
||||
|
||||
afterEach(() => {
|
||||
@@ -60,11 +60,11 @@ const renderExits = (dataProvider) =>
|
||||
new QueryClient({ defaultOptions: { queries: { retry: false } } })
|
||||
}
|
||||
>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter>
|
||||
<NetworkExitList />
|
||||
</MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Link, useSearchParams } from 'react-router'
|
||||
import { useList } from '@refinedev/core'
|
||||
import { Link, useSearchParams } from '../../shared/router.jsx'
|
||||
import { useList } from '../../shared/hooks/dataHooks.js'
|
||||
import { Alert, Button, PageHeader, PageState, Table } from '../../shared/ui/ui.jsx'
|
||||
import { useTitle } from '../../shared/hooks/hooks.js'
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { cleanup, fireEvent, render, screen, waitFor, within } from '@testing-library/react'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { Refine } from '@refinedev/core'
|
||||
import { MemoryRouter } from 'react-router'
|
||||
import { TestDataProvider } from '../../test/providerCompat.jsx'
|
||||
import { MemoryRouter } from '../../test/routerCompat.jsx'
|
||||
import { AuditPage, auditCSV } from './AuditPage'
|
||||
|
||||
afterEach(() => { cleanup(); vi.restoreAllMocks() })
|
||||
@@ -12,9 +12,9 @@ const httpQuery = () => new QueryClient({ defaultOptions: { queries: { retry: fa
|
||||
function renderAudit(dataProvider, initialEntry = '/audit?task_id=task-a') {
|
||||
return render(
|
||||
<QueryClientProvider client={httpQuery()}>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter initialEntries={[initialEntry]}><AuditPage /></MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from 'react'
|
||||
import { useNavigate, useParams } from 'react-router'
|
||||
import { useDataProvider, useList, useOne } from '@refinedev/core'
|
||||
import { useNavigate, useParams } from '../../shared/router.jsx'
|
||||
import { useDataProvider, useList, useOne } from '../../shared/hooks/dataHooks.js'
|
||||
import {
|
||||
Alert, Button, Card, CardContent, Checkbox, ConfirmDialog, DetailList, Field, Input, Modal,
|
||||
PageHeader, PageState, StatusPill, conflictMessage,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { Refine } from '@refinedev/core'
|
||||
import { MemoryRouter, Route, Routes } from 'react-router'
|
||||
import { TestDataProvider } from '../../test/providerCompat.jsx'
|
||||
import { MemoryRouter, Route, Routes } from '../../test/routerCompat.jsx'
|
||||
import { DraftPage } from './DraftPage'
|
||||
|
||||
afterEach(() => { cleanup(); vi.restoreAllMocks() })
|
||||
@@ -30,9 +30,9 @@ function provider(record = draft, overrides = {}) {
|
||||
|
||||
const renderDraft = (dataProvider, id = 'draft-a') => render(
|
||||
<QueryClientProvider client={new QueryClient({ defaultOptions: { queries: { retry: false } } })}>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter initialEntries={[`/drafts/${id}`]}><Routes><Route path="/drafts/:id" element={<DraftPage />} /></Routes></MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from 'react'
|
||||
import { Link, useNavigate, useParams } from 'react-router'
|
||||
import { useDataProvider, useList, useOne } from '@refinedev/core'
|
||||
import { Link, useNavigate, useParams } from '../../shared/router.jsx'
|
||||
import { useDataProvider, useList, useOne } from '../../shared/hooks/dataHooks.js'
|
||||
import {
|
||||
Alert, Button, Card, CardContent, DetailList, Field, PageHeader, PageState, Select, StatusPill,
|
||||
} from '../../shared/ui/ui.jsx'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { Refine } from '@refinedev/core'
|
||||
import { MemoryRouter, Route, Routes } from 'react-router'
|
||||
import { TestDataProvider } from '../../test/providerCompat.jsx'
|
||||
import { MemoryRouter, Route, Routes } from '../../test/routerCompat.jsx'
|
||||
import { TaskDetail, TaskList } from './TasksPage'
|
||||
|
||||
afterEach(() => { cleanup(); vi.restoreAllMocks() })
|
||||
@@ -27,19 +27,19 @@ const queryClient = () => new QueryClient({ defaultOptions: { queries: { retry:
|
||||
|
||||
const renderTask = dataProvider => render(
|
||||
<QueryClientProvider client={queryClient()}>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter initialEntries={['/tasks/task-a']}>
|
||||
<Routes><Route path="/tasks/:id" element={<TaskDetail />} /></Routes>
|
||||
</MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
)
|
||||
|
||||
const renderTasks = dataProvider => render(
|
||||
<QueryClientProvider client={queryClient()}>
|
||||
<Refine dataProvider={dataProvider}>
|
||||
<TestDataProvider dataProvider={dataProvider}>
|
||||
<MemoryRouter><TaskList /></MemoryRouter>
|
||||
</Refine>
|
||||
</TestDataProvider>
|
||||
</QueryClientProvider>,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Link, useParams } from 'react-router'
|
||||
import { useOne } from '@refinedev/core'
|
||||
import { Link, useParams } from '../../shared/router.jsx'
|
||||
import { useOne } from '../../shared/hooks/dataHooks.js'
|
||||
import { Alert, Button, Card, CardContent, DetailList, PageHeader, PageState } from '../../shared/ui/ui.jsx'
|
||||
import { useTitle } from '../../shared/hooks/hooks.js'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user