import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { DataTablePagination } from '@/components/ui/data-table-pagination'; import { DataTableRowActions } from '@/components/ui/data-table-row-actions'; import { DataTableViewOptions } from '@/components/ui/data-table-view-options'; import { QueryErrorView } from '@/components/ui/query-error-view'; import { Skeleton } from '@/components/ui/skeleton'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { type Credential3rdQueryDto, DELETE_CREDENTIAL_3RD, GET_CREDENTIAL_3RD, } from '@/domains/recorder/schema/credential3rd'; import { apolloErrorToMessage, getApolloQueryError, } from '@/infra/errors/apollo'; import type { GetCredential3rdQuery } from '@/infra/graphql/gql/graphql'; import type { RouteStateDataOption } from '@/infra/routes/traits'; import { useDebouncedSkeleton } from '@/presentation/hooks/use-debounded-skeleton'; import { useEvent } from '@/presentation/hooks/use-event'; import { cn } from '@/presentation/utils'; import { useMutation, useQuery } from '@apollo/client'; import { createFileRoute, useNavigate } from '@tanstack/react-router'; import { type ColumnDef, type PaginationState, type Row, type SortingState, type VisibilityState, flexRender, getCoreRowModel, getPaginationRowModel, useReactTable, } from '@tanstack/react-table'; import { format } from 'date-fns'; import { Eye, EyeOff, Plus } from 'lucide-react'; import { useMemo, useState } from 'react'; import { toast } from 'sonner'; export const Route = createFileRoute('/_app/credential3rd/manage')({ component: CredentialManageRouteComponent, staticData: { breadcrumb: { label: 'Manage' }, } satisfies RouteStateDataOption, }); function CredentialManageRouteComponent() { const navigate = useNavigate(); const [columnVisibility, setColumnVisibility] = useState({ createdAt: false, updatedAt: false, }); const [sorting, setSorting] = useState([]); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10, }); const [showPasswords, setShowPasswords] = useState>( {} ); const { loading, error, data, refetch } = useQuery( GET_CREDENTIAL_3RD, { variables: { filters: {}, orderBy: { createdAt: 'DESC', }, pagination: { page: { page: pagination.pageIndex, limit: pagination.pageSize, }, }, }, } ); const [deleteCredential] = useMutation(DELETE_CREDENTIAL_3RD, { onCompleted: async () => { const refetchResult = await refetch(); const error = getApolloQueryError(refetchResult); if (error) { toast.error('Failed to delete credential', { description: apolloErrorToMessage(error), }); return; } toast.success('Credential deleted'); }, onError: (error) => { toast.error('Failed to delete credential', { description: error.message, }); }, }); const { showSkeleton } = useDebouncedSkeleton({ loading }); const credentials = data?.credential3rd; const handleDeleteRecord = useEvent( (row: Row) => async () => { await deleteCredential({ variables: { filters: { id: { eq: row.original.id }, }, }, }); } ); const togglePasswordVisibility = useEvent((id: number) => { setShowPasswords((prev) => ({ ...prev, [id]: !prev[id], })); }); const columns = useMemo(() => { const cs: ColumnDef[] = [ { header: 'ID', accessorKey: 'id', cell: ({ row }) => { return
{row.original.id}
; }, }, { header: 'Credential Type', accessorKey: 'credentialType', cell: ({ row }) => { const type = row.original.credentialType; return ( {type} ); }, }, { header: 'Username', accessorKey: 'username', cell: ({ row }) => { const username = row.original.username; return (
{username || '-'}
); }, }, { header: 'Password', accessorKey: 'password', cell: ({ row }) => { const password = row.original.password; const isVisible = showPasswords[row.original.id]; return (
{isVisible ? password || '-' : '••••••••'}
); }, }, { header: 'User Agent', accessorKey: 'userAgent', cell: ({ row }) => { const userAgent = row.original.userAgent; return (
{userAgent || '-'}
); }, }, { header: 'Created At', accessorKey: 'createdAt', cell: ({ row }) => { const createdAt = row.original.createdAt; return (
{format(new Date(createdAt), 'yyyy-MM-dd HH:mm:ss')}
); }, }, { header: 'Updated At', accessorKey: 'updatedAt', cell: ({ row }) => { const updatedAt = row.original.updatedAt; return (
{format(new Date(updatedAt), 'yyyy-MM-dd HH:mm:ss')}
); }, }, { id: 'actions', cell: ({ row }) => ( row.original.id} showEdit showDelete showDetail onDetail={() => { navigate({ to: '/credential3rd/detail/$id', params: { id: `${row.original.id}` }, }); }} onEdit={() => { navigate({ to: '/credential3rd/edit/$id', params: { id: `${row.original.id}` }, }); }} onDelete={handleDeleteRecord(row)} /> ), }, ]; return cs; }, [handleDeleteRecord, navigate, showPasswords, togglePasswordVisibility]); const table = useReactTable({ data: data?.credential3rd?.nodes ?? [], columns, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), onPaginationChange: setPagination, onSortingChange: setSorting, onColumnVisibilityChange: setColumnVisibility, pageCount: credentials?.paginationInfo?.pages, rowCount: credentials?.paginationInfo?.total, state: { pagination, sorting, columnVisibility, }, enableColumnPinning: true, initialState: { columnPinning: { left: [], right: ['actions'], }, }, }); if (error) { return ; } return (

Credential 3rd Management

Manage your third-party platform login credentials

{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { return ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext() )} ); })} ))} {showSkeleton && Array.from(new Array(pagination.pageSize)).map((_, index) => ( {table.getVisibleLeafColumns().map((column) => ( ))} ))} {!showSkeleton && (table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => { const isPinned = cell.column.getIsPinned(); return ( {flexRender( cell.column.columnDef.cell, cell.getContext() )} ); })} )) ) : ( No Results ))}
); }