Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / packages / components / containers / organization / AuthenticationLogs.tsx
blob068007ab9d2e937cb05a7ebfd7e779d29c21d782
1 import { useMemo, useRef, useState } from 'react';
3 import { endOfDay } from 'date-fns';
4 import { c } from 'ttag';
6 import { useMembers } from '@proton/account/members/hooks';
7 import { Button } from '@proton/atoms';
8 import AddressesInput, { AddressesInputItem } from '@proton/components/components/addressesInput/AddressesInput';
9 import DateInput from '@proton/components/components/input/DateInput';
10 import Loader from '@proton/components/components/loader/Loader';
11 import Pagination from '@proton/components/components/pagination/Pagination';
12 import usePaginationAsync from '@proton/components/components/pagination/usePaginationAsync';
13 import AddressesAutocompleteTwo from '@proton/components/components/v2/addressesAutocomplete/AddressesAutocomplete';
14 import InputField from '@proton/components/components/v2/field/InputField';
15 import SettingsSectionExtraWide from '@proton/components/containers/account/SettingsSectionExtraWide';
16 import useApi from '@proton/components/hooks/useApi';
17 import useNotifications from '@proton/components/hooks/useNotifications';
18 import { validateEmailAddress } from '@proton/shared/lib/helpers/email';
19 import type { Recipient } from '@proton/shared/lib/interfaces';
20 import { type Organization } from '@proton/shared/lib/interfaces';
21 import clsx from '@proton/utils/clsx';
23 import { getLocalTimeStringFromDate } from '../b2bDashboard/Pass/helpers';
24 import B2BAuthLogsTable from '../logs/B2BAuthLogsTable';
25 import { convertEnhancedMembersToContactEmails } from './groups/NewGroupMemberInput';
26 import useAuthLogsDateFilter from './useAuthLogsFilter';
27 import useOrgAuthLogs from './useOrgAuthLogs';
29 interface Props {
30     organization?: Organization;
32 export interface AuthLogsQueryParams {
33     Emails: string[];
34     StartTime?: string;
35     EndTime?: string;
38 const AuthenticationLogs = ({ organization }: Props) => {
39     const api = useApi();
40     const [members] = useMembers();
41     const { createNotification } = useNotifications();
42     const { page, onNext, onPrevious, onSelect, reset } = usePaginationAsync(1);
43     const [query, setQuery] = useState<AuthLogsQueryParams>({ Emails: [] });
44     const { authLogs, total, loading, error } = useOrgAuthLogs(api, query, page);
45     const { filter, handleStartDateChange, handleEndDateChange } = useAuthLogsDateFilter();
46     const [recipients, setRecipient] = useState<Recipient[]>([]);
47     const addressesAutocompleteRef = useRef<HTMLInputElement>(null);
49     const items = useMemo(() => {
50         return recipients.map((recipient) => {
51             return (
52                 <AddressesInputItem
53                     key={recipient.Address}
54                     label={recipient.Address}
55                     onClick={(event) => event.stopPropagation()}
56                     onRemove={() => {
57                         setRecipient(recipients.filter((rec) => rec.Address !== recipient.Address));
58                     }}
59                 />
60             );
61         });
62     }, [recipients]);
64     const today = new Date();
66     if (!organization || !members) {
67         return <Loader />;
68     }
70     const handleAddEmail = (newRecipients: Recipient[]) => {
71         setRecipient([...recipients, ...newRecipients]);
72     };
74     const handleSearchSubmit = () => {
75         if (!recipients.length) {
76             createNotification({ text: c('error').t`Enter an email address` });
77             return;
78         }
79         reset();
80         const Emails = recipients.map((recipient) => recipient.Address);
81         const StartTime = filter.start ? getLocalTimeStringFromDate(filter.start) : undefined;
82         const EndTime = filter.end ? getLocalTimeStringFromDate(endOfDay(filter.end)) : undefined;
83         setQuery({ Emails, StartTime, EndTime });
84     };
86     return (
87         <SettingsSectionExtraWide>
88             <div className="flex flex-column md:flex-row gap-0 md:gap-4 flex-nowrap items-start justify-space-between *:min-size-auto my-6">
89                 <InputField
90                     as={AddressesInput}
91                     ref={addressesAutocompleteRef}
92                     rootClassName="flex-1"
93                     inputContainerClassName=""
94                     autocomplete={
95                         <AddressesAutocompleteTwo
96                             id="auth-log-autocomplete"
97                             anchorRef={addressesAutocompleteRef}
98                             recipients={recipients}
99                             onAddRecipients={handleAddEmail}
100                             contactEmails={members && convertEnhancedMembersToContactEmails(members)}
101                             inputClassName={clsx([
102                                 !recipients.length && 'my-0.5',
103                                 !!recipients.length && 'p-0 rounded-none',
104                             ])}
105                             validate={(email: string) => {
106                                 if (!validateEmailAddress(email)) {
107                                     return c('Input Error').t`Not a valid email address`;
108                                 }
109                             }}
110                             unstyled
111                             placeholder={recipients.length ? '' : c('Label').t`Search by email`}
112                             limit={10}
113                         />
114                     }
115                     items={items}
116                     className={clsx(['multi-select-container', !!recipients.length && 'px-2 py-0.5'])}
117                 />
118                 <div className="flex-1 flex flex-column gap-2 *:min-size-auto">
119                     <div className="flex flex-1 flex-row flex-nowrap gap-2">
120                         <DateInput
121                             id="start"
122                             placeholder={c('Placeholder').t`Start date`}
123                             value={filter.start}
124                             onChange={handleStartDateChange}
125                             className="flex-1"
126                             max={today}
127                         />
128                         <DateInput
129                             id="end"
130                             placeholder={c('Placeholder').t`End date`}
131                             value={filter.end}
132                             onChange={handleEndDateChange}
133                             className="flex-1"
134                             max={today}
135                         />
136                         <Button color="norm" onClick={handleSearchSubmit} disabled={loading}>
137                             {c('Action').t`Search`}
138                         </Button>
139                     </div>
140                     <div className="self-end">
141                         <Pagination
142                             page={page}
143                             total={total}
144                             limit={10}
145                             onSelect={onSelect}
146                             onNext={onNext}
147                             onPrevious={onPrevious}
148                         />
149                     </div>
150                 </div>
151             </div>
152             <B2BAuthLogsTable logs={authLogs} loading={loading} error={error} />
153         </SettingsSectionExtraWide>
154     );
157 export default AuthenticationLogs;