Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e04e91dd8 |
@@ -1,8 +1,10 @@
|
|||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import { Plus, SearchIcon, TagIcon } from 'lucide-react'
|
import type { ColumnDef } from '@tanstack/react-table'
|
||||||
|
import { Plus, SearchIcon, TagIcon, Trash2 } from 'lucide-react'
|
||||||
|
|
||||||
import { Button } from '@evobgp/ui/components/button'
|
import { Button } from '@evobgp/ui/components/button'
|
||||||
|
|
||||||
|
import { ConfirmDialog } from '@/components/confirm-dialog'
|
||||||
import { SpeakerFormDialog } from '@/components/network/speaker-form-dialog'
|
import { SpeakerFormDialog } from '@/components/network/speaker-form-dialog'
|
||||||
import {
|
import {
|
||||||
getSpeakerFilterFieldValue,
|
getSpeakerFilterFieldValue,
|
||||||
@@ -15,6 +17,7 @@ import {
|
|||||||
type FilterFieldConfig,
|
type FilterFieldConfig,
|
||||||
} from '@/components/reui/filters'
|
} from '@/components/reui/filters'
|
||||||
import { ResourcePage, renderSingleSelectedLabel } from '@/components/reui-kit'
|
import { ResourcePage, renderSingleSelectedLabel } from '@/components/reui-kit'
|
||||||
|
import { useDeleteSpeakerMutation } from '@/queries/network'
|
||||||
import type { SpeakerRow } from '@/types/api'
|
import type { SpeakerRow } from '@/types/api'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,6 +25,10 @@ import type { SpeakerRow } from '@/types/api'
|
|||||||
* @see https://reui.io/preview/base/data-grid-filtering-2
|
* @see https://reui.io/preview/base/data-grid-filtering-2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function speakerDeleteLabel(s: SpeakerRow): string {
|
||||||
|
return s.agent_domain ?? s.endpoint ?? s.id
|
||||||
|
}
|
||||||
|
|
||||||
const SPEAKER_TABS = [
|
const SPEAKER_TABS = [
|
||||||
{ id: 'all', label: 'Все' },
|
{ id: 'all', label: 'Все' },
|
||||||
{ id: 'online', label: 'Online' },
|
{ id: 'online', label: 'Online' },
|
||||||
@@ -75,7 +82,9 @@ export function NetworkSpeakersCard({
|
|||||||
error,
|
error,
|
||||||
onRetry,
|
onRetry,
|
||||||
}: NetworkSpeakersCardProps) {
|
}: NetworkSpeakersCardProps) {
|
||||||
|
const deleteMutation = useDeleteSpeakerMutation()
|
||||||
const [dialogOpen, setDialogOpen] = useState(false)
|
const [dialogOpen, setDialogOpen] = useState(false)
|
||||||
|
const [deleteTarget, setDeleteTarget] = useState<SpeakerRow | null>(null)
|
||||||
const [filters, setFilters] = useState<Filter[]>(createDefaultSpeakerFilters)
|
const [filters, setFilters] = useState<Filter[]>(createDefaultSpeakerFilters)
|
||||||
|
|
||||||
const addButton = useMemo(
|
const addButton = useMemo(
|
||||||
@@ -88,6 +97,33 @@ export function NetworkSpeakersCard({
|
|||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const columns = useMemo<ColumnDef<SpeakerRow, unknown>[]>(
|
||||||
|
() => [
|
||||||
|
...speakerColumns,
|
||||||
|
{
|
||||||
|
id: 'actions',
|
||||||
|
enableSorting: false,
|
||||||
|
header: () => <span className="sr-only">Действия</span>,
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="flex items-center justify-end">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon-sm"
|
||||||
|
type="button"
|
||||||
|
className="text-destructive"
|
||||||
|
aria-label="Удалить спикера"
|
||||||
|
title="Удалить"
|
||||||
|
onClick={() => setDeleteTarget(row.original)}
|
||||||
|
>
|
||||||
|
<Trash2 className="size-3.5" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ResourcePage
|
<ResourcePage
|
||||||
@@ -100,7 +136,7 @@ export function NetworkSpeakersCard({
|
|||||||
onFiltersChange={setFilters}
|
onFiltersChange={setFilters}
|
||||||
onClearFilters={() => setFilters(createDefaultSpeakerFilters())}
|
onClearFilters={() => setFilters(createDefaultSpeakerFilters())}
|
||||||
getFilterFieldValue={getSpeakerFilterFieldValue}
|
getFilterFieldValue={getSpeakerFilterFieldValue}
|
||||||
columns={speakerColumns}
|
columns={columns}
|
||||||
data={items}
|
data={items}
|
||||||
getRowId={(row) => row.id}
|
getRowId={(row) => row.id}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
@@ -116,6 +152,27 @@ export function NetworkSpeakersCard({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<SpeakerFormDialog open={dialogOpen} onOpenChange={setDialogOpen} />
|
<SpeakerFormDialog open={dialogOpen} onOpenChange={setDialogOpen} />
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
open={deleteTarget !== null}
|
||||||
|
onOpenChange={(open) => {
|
||||||
|
if (!open) setDeleteTarget(null)
|
||||||
|
}}
|
||||||
|
title="Удалить спикера?"
|
||||||
|
description={
|
||||||
|
deleteTarget
|
||||||
|
? `${speakerDeleteLabel(deleteTarget)} будет удалён. Привязки пиров к этому спикеру сбросятся.`
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
confirmLabel="Удалить"
|
||||||
|
confirmLoadingLabel="Удаление…"
|
||||||
|
destructive
|
||||||
|
confirmLoading={deleteMutation.isPending}
|
||||||
|
onConfirm={() => {
|
||||||
|
if (!deleteTarget) return
|
||||||
|
void deleteMutation.mutateAsync(deleteTarget.id).then(() => setDeleteTarget(null))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user