commit 9980241e28539883c0b78a3b57640aa99a211150
Author: Jaroslav Hrubý <hrubyj@students.zcu.cz>
Date:   Tue May 3 17:25:56 2022 +0200

    User filtering implemented

diff --git a/webapp/api/api.ts b/webapp/api/api.ts
index 7d2f506..608d4a9 100644
--- a/webapp/api/api.ts
+++ b/webapp/api/api.ts
@@ -787,6 +787,12 @@ export interface UserInfo {
      * @memberof UserInfo
      */
     'surname'?: string | null;
+    /**
+     * 
+     * @type {number}
+     * @memberof UserInfo
+     */
+    'assignedDocumentsCount'?: number;
 }
 /**
  * 
diff --git a/webapp/pages/users/index.tsx b/webapp/pages/users/index.tsx
index c924a85..4a87581 100644
--- a/webapp/pages/users/index.tsx
+++ b/webapp/pages/users/index.tsx
@@ -3,7 +3,7 @@ import React, { useContext, useEffect, useState } from 'react';
 
 import { useUnauthRedirect } from '../../hooks';
 import { useRouter } from 'next/router';
-import { Button, Space, Table, Typography } from 'antd';
+import { Badge, Button, Input, Space, Table, Typography } from 'antd';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { faUsers } from '@fortawesome/free-solid-svg-icons';
 import { LoggedUserContext } from '../../contexts/LoggedUserContext';
@@ -14,6 +14,7 @@ import AddUserModal from '../../components/modals/AddUserModal';
 import UserDocumentsModal from '../../components/modals/UserDocumentsModal';
 import { ShowConfirmDelete } from '../../utils/alerts';
 import EditUserModal from '../../components/modals/EditUserModal';
+import { SearchOutlined } from '@ant-design/icons';
 
 function UsersPage() {
     const redirecting = useUnauthRedirect('/login');
@@ -74,18 +75,105 @@ function UsersPage() {
         setEditVisible(false);
     };
 
+    const handleSearch = (
+        selectedKeys: React.SetStateAction<string>[],
+        confirm: () => void
+    ) => {
+        confirm();
+    };
+
+    const handleReset = (clearFilters: () => void) => {
+        clearFilters();
+    };
+
+    const getColumnSearchProps = (dataIndex: string, searchLabel: string) => ({
+        // @ts-ignore
+        filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
+            <div style={{ padding: 8 }}>
+                <Input
+                    placeholder={`Vyhledat ${searchLabel}`}
+                    value={selectedKeys[0]}
+                    onChange={(e) =>
+                        setSelectedKeys(e.target.value ? [e.target.value] : [])
+                    }
+                    onPressEnter={() => handleSearch(selectedKeys, confirm)}
+                    style={{ marginBottom: 8, display: 'block' }}
+                />
+                <Space>
+                    <Button
+                        type="primary"
+                        onClick={() => handleSearch(selectedKeys, confirm)}
+                        icon={<SearchOutlined />}
+                        style={{ width: 90 }}
+                    >
+                        Hledat
+                    </Button>
+                    <Button
+                        onClick={() => handleReset(clearFilters)}
+                        style={{ width: 90 }}
+                    >
+                        Smazat
+                    </Button>
+                </Space>
+            </div>
+        ),
+        filterIcon: (filtered: any) => (
+            <SearchOutlined style={{ color: filtered ? '#1890ff' : undefined }} />
+        ),
+        onFilter: (value: string, record: { [x: string]: { toString: () => string } }) =>
+            record[dataIndex]
+                ? record[dataIndex].toString().toLowerCase().includes(value.toLowerCase())
+                : '',
+    });
+
     const columns = [
-        { title: 'Jméno', dataIndex: 'name', key: 'name' },
-        { title: 'Příjmení', dataIndex: 'surname', key: 'surname' },
-        { title: 'Uživatelské jméno', dataIndex: 'username', key: 'username' },
+        {
+            title: 'Jméno',
+            dataIndex: 'name',
+            key: 'name',
+            ...getColumnSearchProps('name', 'jméno'),
+        },
+        {
+            title: 'Příjmení',
+            dataIndex: 'surname',
+            key: 'surname',
+            ...getColumnSearchProps('surname', 'příjmení'),
+        },
+        {
+            title: 'Uživatelské jméno',
+            dataIndex: 'username',
+            key: 'username',
+            ...getColumnSearchProps('username', 'uživatelské jméno'),
+        },
+        {
+            title: 'Přiřazeno dokumentů',
+            key: 'docCounts',
+            align: 'center' as 'center',
+            dataIndex: ['id', 'assignedDocumentsCount'],
+            // @ts-ignore
+            render: (text, row) => (
+                <div>
+                    <Space size={'middle'}>
+                        <Badge count={row.assignedDocumentsCount}>
+                            <Button onClick={() => showDocsModal(row.id)}>
+                                Dokumenty
+                            </Button>
+                        </Badge>
+                    </Space>
+                </div>
+            ),
+            // @ts-ignore
+            sorter: (a, b) => a.assignedDocumentsCount - b.assignedDocumentsCount,
+        },
         {
             title: '',
-            key: 'operation',
+            key: 'operations',
             dataIndex: 'id',
-            render: (id: string) => (
+            align: 'center' as 'center',
+            // @ts-ignore
+            render: (id) => (
                 <div>
                     <Space size={'middle'}>
-                        <Button onClick={() => showDocsModal(id)}>Dokumenty</Button>
                         <Button onClick={() => showEditModal(id)}>Upravit</Button>
                         <Button onClick={() => deleteUser(id)}>Smazat</Button>
                     </Space>
@@ -94,6 +182,7 @@ function UsersPage() {
         },
     ];
 
+    // @ts-ignore
     return redirecting || role !== 'ADMINISTRATOR' ? null : (
         <MainLayout>
             <Typography.Title level={2}>
@@ -107,9 +196,14 @@ function UsersPage() {
             {docsVisible && <UserDocumentsModal userId={user.id} onCancel={hideModals} />}
 
             <Table
+                locale={{
+                    triggerDesc: 'Seřadit sestupně',
+                    triggerAsc: 'Seřadit vzestupně',
+                    cancelSort: 'Vypnout řazení',
+                }}
+                // @ts-ignore
                 columns={columns}
                 dataSource={users}
-                size="small"
                 scroll={{ y: 500 }}
             />
         </MainLayout>
