[] = useMemo(
+ () => [
+ {
+ accessorKey: 'name',
+ cell: ({ row }) => {
+ const token = row.original;
+ const isCreating = token.id === 'create-new';
+ const isEditing = editingTokenId === token.tokenId;
+
+ if (isCreating) {
+ return (
+ setCreateFormData((prev) => ({ ...prev, name: e.target.value }))}
+ placeholder="Token name (optional)"
+ value={createFormData.name}
+ />
+ );
+ }
+
+ if (isEditing) {
+ return (
+ setEditFormData((prev) => ({ ...prev, name: e.target.value }))}
+ placeholder="Token name (optional)"
+ value={editFormData.name}
+ />
+ );
+ }
+
+ return (
+
+ {token.name || (unnamed)}
+
+ );
+ },
+ header: ({ column }) => {
+ const sorted = column.getIsSorted();
+
+ return (
+
+ );
+ },
+ size: 300,
+ },
+ {
+ accessorKey: 'tokenId',
+ cell: ({ row }) => {
+ const token = row.original;
+ const isCreating = token.id === 'create-new';
+
+ if (isCreating) {
+ return N/A
;
+ }
+
+ const tokenId = row.getValue('tokenId') as string;
+
+ return (
+
+ {tokenId}
+
+
+ );
+ },
+ header: ({ column }) => {
+ const sorted = column.getIsSorted();
+
+ return (
+
+ );
+ },
+ size: 200,
+ },
+ {
+ accessorKey: 'status',
+ cell: ({ row }) => {
+ const token = row.original;
+ const isCreating = token.id === 'create-new';
+
+ if (isCreating) {
+ return active;
+ }
+
+ const isEditing = editingTokenId === token.tokenId;
+ const expired = isTokenExpired(token);
+ const statusDisplay = getStatusDisplay(token);
+
+ if (isEditing) {
+ if (expired) {
+ return {statusDisplay.label};
+ }
+
+ return (
+
+ );
+ }
+
+ return {statusDisplay.label};
+ },
+ header: ({ column }) => {
+ const sorted = column.getIsSorted();
+
+ return (
+
+ );
+ },
+ size: 120,
+ },
+ {
+ accessorKey: 'expires',
+ cell: ({ row }) => {
+ const token = row.original;
+ const isCreating = token.id === 'create-new';
+
+ if (isCreating) {
+ const tomorrow = new Date();
+
+ tomorrow.setDate(tomorrow.getDate() + 1);
+ tomorrow.setHours(0, 0, 0, 0);
+
+ return (
+
+
+
+
+
+ {
+ setCreateFormData((prev) => ({ ...prev, expiresAt: date || null }));
+ }}
+ selected={createFormData.expiresAt || undefined}
+ />
+
+
+ );
+ }
+
+ const expiresAt = getTokenExpirationDate(token);
+
+ return {expiresAt.toLocaleDateString()}
;
+ },
+ header: ({ column }) => {
+ const sorted = column.getIsSorted();
+
+ return (
+
+ );
+ },
+ size: 150,
+ sortingFn: (rowA, rowB) => {
+ const expiresA = getTokenExpirationDate(rowA.original);
+ const expiresB = getTokenExpirationDate(rowB.original);
+
+ return expiresA.getTime() - expiresB.getTime();
+ },
+ },
+ {
+ accessorKey: 'createdAt',
+ cell: ({ row }) => {
+ const token = row.original;
+ const isCreating = token.id === 'create-new';
+
+ if (isCreating) {
+ return N/A
;
+ }
+
+ const date = new Date(row.getValue('createdAt'));
+
+ return {date.toLocaleDateString()}
;
+ },
+ header: ({ column }) => {
+ const sorted = column.getIsSorted();
+
+ return (
+
+ );
+ },
+ size: 120,
+ },
+ {
+ cell: ({ row }) => {
+ const token = row.original;
+ const isCreating = token.id === 'create-new';
+ const isEditing = editingTokenId === token.tokenId;
+
+ if (isCreating) {
+ return (
+
+
+
+
+ );
+ }
+
+ if (isEditing) {
+ return (
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+ handleEdit(token)}>
+
+ Edit
+
+
+ handleDeleteDialogOpen(token)}
+ >
+ {isDeleteLoading && deletingToken?.tokenId === token.tokenId ? (
+ <>
+
+ Deleting...
+ >
+ ) : (
+ <>
+
+ Delete
+ >
+ )}
+
+
+
+
+ );
+ },
+ enableHiding: false,
+ header: () => null,
+ id: 'actions',
+ size: 48,
+ },
+ ],
+ [
+ createFormData.expiresAt,
+ createFormData.name,
+ editFormData.name,
+ editFormData.status,
+ editingTokenId,
+ handleCancelCreate,
+ handleCancelEdit,
+ handleCopyTokenId,
+ handleCreate,
+ handleDeleteDialogOpen,
+ handleEdit,
+ handleSave,
+ isCreateLoading,
+ isDeleteLoading,
+ isUpdateLoading,
+ deletingToken,
+ ],
+ );
+
+ if (isLoading) {
+ return (
+
+
+ }
+ title="Loading tokens..."
+ />
+
+ );
+ }
+
+ if (error) {
+ return (
+
+
+
+
+ Error loading tokens
+ {error.message}
+
+
+ );
+ }
+
+ const tokens = data?.apiTokens || [];
+
+ if (tokens.length === 0 && !creatingToken) {
+ return (
+
+
+
+
+ Create Token
+
+ }
+ description="Create your first API token to access PentAGI programmatically"
+ icon={}
+ title="No API tokens configured"
+ />
+
+ );
+ }
+
+ return (
+
+
+
+ {(createError || updateError || deleteError || deleteErrorMessage) && (
+
+
+ Error
+
+ {createError?.message || updateError?.message || deleteError?.message || deleteErrorMessage}
+
+
+ )}
+
+
+
+
+
+
handleDelete(deletingToken?.tokenId)}
+ handleOpenChange={setIsDeleteDialogOpen}
+ isOpen={isDeleteDialogOpen}
+ itemName={deletingToken?.name || deletingToken?.tokenId}
+ itemType="token"
+ />
+
+ );
+};
+
+export default SettingsAPITokens;