Skip to content
Snippets Groups Projects
Users.tsx 6.12 KiB
Newer Older
  • Learn to ignore specific revisions
  • Valentino's avatar
    Valentino committed
    /* eslint-disable react-hooks/exhaustive-deps */
    import React, { useState, useCallback, useEffect, useMemo } from 'react';
    
    Valentino's avatar
    Valentino committed
    import { SearchIcon, PlusIcon } from '@heroicons/react/solid';
    
    Valentino's avatar
    Valentino committed
    import { CogIcon, TrashIcon } from '@heroicons/react/outline';
    
    Luka's avatar
    Luka committed
    import { useUsers } from 'src/services/users';
    import { Table } from 'src/components';
    import { ConfirmationModal } from 'src/components/Modal';
    
    Valentino's avatar
    Valentino committed
    import { debounce } from 'lodash';
    
    Luka's avatar
    Luka committed
    import { UserModal } from './components/UserModal';
    
    
    Valentino's avatar
    Valentino committed
    export const Users: React.FC = () => {
    
    Luka's avatar
    Luka committed
      const [selectedRowsIds, setSelectedRowsIds] = useState({});
      const [deleteModal, setDeleteModal] = useState(false);
      const [configureModal, setConfigureModal] = useState(false);
    
    Valentino's avatar
    Valentino committed
      const [userId, setUserId] = useState(null);
    
    Valentino's avatar
    Valentino committed
      const [search, setSearch] = useState('');
    
    Valentino's avatar
    Valentino committed
      const { users, loadUsers } = useUsers();
    
    Luka's avatar
    Luka committed
    
    
    Valentino's avatar
    Valentino committed
      const handleSearch = (event: any) => {
    
    Valentino's avatar
    Valentino committed
        setSearch(event.target.value);
    
    Valentino's avatar
    Valentino committed
      };
    
    Valentino's avatar
    Valentino committed
    
    
    Valentino's avatar
    Valentino committed
      const debouncedSearch = useCallback(debounce(handleSearch, 250), []);
    
    Luka's avatar
    Luka committed
    
      useEffect(() => {
    
    Valentino's avatar
    Valentino committed
        loadUsers();
    
    Luka's avatar
    Luka committed
    
    
    Valentino's avatar
    Valentino committed
        return () => {
          debouncedSearch.cancel();
        };
    
    Luka's avatar
    Luka committed
      }, []);
    
    
    Valentino's avatar
    Valentino committed
      const filterSearch = useMemo(() => {
    
    Valentino's avatar
    Valentino committed
        return users.filter((item: any) => item.email?.toLowerCase().includes(search.toLowerCase()));
      }, [search, users]);
    
    Valentino's avatar
    Valentino committed
    
    
    Luka's avatar
    Luka committed
      const deleteModalOpen = () => setDeleteModal(true);
      const deleteModalClose = () => setDeleteModal(false);
    
    
    Valentino's avatar
    Valentino committed
      const configureModalOpen = (id: any) => {
        setUserId(id);
        setConfigureModal(true);
      };
    
    Luka's avatar
    Luka committed
      const configureModalClose = () => setConfigureModal(false);
    
      const columns: any = React.useMemo(
        () => [
          {
            Header: 'Name',
            accessor: 'name',
            width: 'auto',
          },
          {
            Header: 'Email',
            accessor: 'email',
            width: 'auto',
          },
          {
            Header: 'Status',
            accessor: 'status',
            width: 'auto',
          },
          {
            Header: ' ',
    
    Valentino's avatar
    Valentino committed
            Cell: (props: any) => {
              const { row } = props;
    
    
    Luka's avatar
    Luka committed
              return (
                <div className="text-right opacity-0 group-hover:opacity-100 transition-opacity">
                  <button
    
    Valentino's avatar
    Valentino committed
                    onClick={() => configureModalOpen(row.original.id)}
    
    Luka's avatar
    Luka committed
                    type="button"
                    className="inline-flex items-center px-4 py-2 border border-gray-200 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
                  >
                    <CogIcon className="-ml-0.5 mr-2 h-4 w-4" aria-hidden="true" />
                    Configure
                  </button>
                </div>
              );
            },
            width: 'auto',
          },
        ],
        [],
      );
    
      const selectedRows = useCallback((rows: Record<string, boolean>) => {
        setSelectedRowsIds(rows);
      }, []);
    
      return (
    
    Valentino's avatar
    Valentino committed
        <div className="relative">
          <div className="max-w-7xl mx-auto py-4 sm:px-6 lg:px-8 h-full flex-grow">
            <div className="pb-5 mt-6 border-b border-gray-200 sm:flex sm:items-center sm:justify-between">
              <h1 className="text-3xl leading-6 font-bold text-gray-900">Users</h1>
              <div className="mt-3 sm:mt-0 sm:ml-4">
                <button
                  onClick={() => configureModalOpen(null)}
                  type="button"
                  className="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-primary-700 hover:bg-primary-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-800"
                >
                  <PlusIcon className="-ml-0.5 mr-2 h-4 w-4" aria-hidden="true" />
                  Add new user
                </button>
              </div>
    
    Luka's avatar
    Luka committed
            </div>
    
    
    Valentino's avatar
    Valentino committed
            <div className="flex justify-between w-100 my-3 items-center mb-5 ">
              <div className="flex items-center">
                <div className="inline-block">
                  <label htmlFor="email" className="block text-sm font-medium text-gray-700 sr-only">
                    Search candidates
                  </label>
                  <div className="mt-1 flex rounded-md shadow-sm">
                    <div className="relative flex items-stretch flex-grow focus-within:z-10">
                      <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
                        <SearchIcon className="h-5 w-5 text-gray-400" aria-hidden="true" />
                      </div>
                      <input
                        type="text"
                        name="email"
                        id="email"
                        className="focus:ring-primary-500 focus:border-primary-500 block w-full rounded-md pl-10 sm:text-sm border-gray-200"
                        placeholder="Search Users"
                        onChange={debouncedSearch}
                      />
    
    Luka's avatar
    Luka committed
                    </div>
                  </div>
                </div>
              </div>
    
    
    Valentino's avatar
    Valentino committed
              {selectedRowsIds && Object.keys(selectedRowsIds).length !== 0 && (
                <div className="flex items-center">
                  <button
                    onClick={deleteModalOpen}
                    type="button"
                    className="inline-flex items-center px-4 py-2 text-sm font-medium rounded-md text-red-700 bg-red-50 hover:bg-red-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
                  >
                    <TrashIcon className="-ml-0.5 mr-2 h-4 w-4" aria-hidden="true" />
                    Delete
                  </button>
                </div>
              )}
            </div>
    
    Luka's avatar
    Luka committed
    
    
    Valentino's avatar
    Valentino committed
            <div className="flex flex-col">
              <div className="-my-2 sm:-mx-6 lg:-mx-8">
                <div className="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
                  <div className="shadow border-b border-gray-200 sm:rounded-lg">
                    <Table data={filterSearch as any} columns={columns} getSelectedRowIds={selectedRows} selectable />
                  </div>
    
    Luka's avatar
    Luka committed
                </div>
              </div>
            </div>
    
    
    Valentino's avatar
    Valentino committed
            <ConfirmationModal
              open={deleteModal}
              onClose={deleteModalClose}
              title="Delete user"
              body="Are you sure you want to delete this user? All of your data will be permanently removed. This action cannot be undone."
            />
    
    Luka's avatar
    Luka committed
    
    
    Valentino's avatar
    Valentino committed
            <UserModal open={configureModal} onClose={configureModalClose} userId={userId} />
          </div>
    
    Luka's avatar
    Luka committed
        </div>
      );
    };