|
1 |
| -import { createSvgIcon, Divider, TextField, ThemeProvider, Typography } from '@mui/material'; |
| 1 | +import { Divider, ThemeProvider, Typography } from '@mui/material'; |
2 | 2 | import { Box } from '@mui/system';
|
3 | 3 | import dayjs, { Dayjs } from 'dayjs';
|
4 | 4 | import React, { useEffect, useState } from 'react';
|
5 |
| -import { DatePicker, LocalizationProvider, TimeField } from '@mui/x-date-pickers'; |
| 5 | +import { LocalizationProvider } from '@mui/x-date-pickers'; |
6 | 6 | import { Button, ButtonStretch, ButtonVariant } from '../button';
|
7 | 7 | import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
8 | 8 | import theme from '../../../theme';
|
9 |
| -import PresetsContent from './Presets'; |
10 |
| -import { Icon } from '../../icons'; |
| 9 | +import PresetsContent, {PresetType} from './Presets'; |
| 10 | +import { SearchForm } from './SearchForm'; |
11 | 11 |
|
12 |
| -const NoResultsState = () => { |
13 |
| - return ( |
14 |
| - <Box display={'flex'} alignItems={'center'} justifyContent={'center'} flexDirection={'column'}> |
15 |
| - <Box> |
16 |
| - <Icon icon={'no-results'} /> |
17 |
| - </Box> |
18 |
| - <Typography variant={'mediumBold'}> |
19 |
| - There are no metadata versions that match the search criteria. <br /> Please double-check |
20 |
| - the timestamp you entered and try again. |
21 |
| - </Typography> |
22 |
| - </Box> |
23 |
| - ) |
| 12 | +export interface DateManagerProps { |
| 13 | + presets: PresetType[]; |
| 14 | + addClickedHandler: ({ alias, value }: { alias: string; value: number }) => void; |
| 15 | + close: () => void; |
| 16 | + loading: boolean; |
| 17 | +} |
| 18 | + |
| 19 | +const formattedDate = ( |
| 20 | + date: string | number | dayjs.Dayjs | Date | null | undefined, |
| 21 | + hour: string | number | dayjs.Dayjs | Date | null | undefined |
| 22 | +) => { |
| 23 | + return `${dayjs(date).format('YYYY-MM-DD')} ${dayjs(hour).format('HH:mm:ss')}`; |
24 | 24 | };
|
25 |
| -export const DateManager = ({ |
26 |
| - presets, |
27 |
| - showNoResults |
28 |
| -}: { |
29 |
| - presets: { name: string; value: Date }[]; |
30 |
| - showNoResults?: boolean; |
31 |
| -}) => { |
| 25 | + |
| 26 | +export const DateManager = ({ presets, addClickedHandler, close, loading }: DateManagerProps) => { |
32 | 27 | const defaultDisplayName = `as of ${dayjs().format('YYYY-MM-DD')} ${dayjs().format('HH:mm:ss')}`;
|
33 |
| - const [date, setDate] = useState<Dayjs | null>(dayjs()); |
34 |
| - const [hour, setHour] = useState<Dayjs | null>(dayjs()); |
| 28 | + |
| 29 | + const [date, setDate] = useState<null | Dayjs>(dayjs()); |
| 30 | + const [hour, setHour] = useState<null | Dayjs>(dayjs()); |
| 31 | + const [value, setValue] = useState<number>(dayjs(formattedDate(date, hour)).unix()); |
35 | 32 | const [displayName, setDisplayName] = useState(defaultDisplayName);
|
36 | 33 | const [displayNameTouched, setDisplayNameTouched] = useState(false);
|
| 34 | + const [errorDate, setErrorDate] = useState(false); |
37 | 35 |
|
38 | 36 | // update the display name unless the display name area is touched.
|
39 | 37 | useEffect(() => {
|
| 38 | + const value = formattedDate(date, hour); |
40 | 39 | if (!displayNameTouched) {
|
41 |
| - setDisplayName(`as of ${date?.format('YYYY-MM-DD')} ${hour?.format('HH:mm:ss')}`); |
| 40 | + setDisplayName(`as of ${value}`); |
42 | 41 | }
|
| 42 | + setValue(dayjs(value).unix()); |
43 | 43 | }, [hour, date]);
|
44 | 44 |
|
45 | 45 | return (
|
46 |
| - <LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={'en-gb'}> |
47 |
| - <ThemeProvider theme={theme}> |
48 |
| - <Box width={'530px'} height={'100%'} color={'#172D32'} px={1}> |
49 |
| - <Typography component={'div'} p={1} variant={'mediumBold'}> |
50 |
| - Compare to previous version |
51 |
| - </Typography> |
52 |
| - <Divider sx={{ backgroundColor: '#F8FAFC' }} /> |
| 46 | + <LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={'en-gb'}> |
| 47 | + <ThemeProvider theme={theme}> |
| 48 | + <Box width={'530px'} height={'100%'} color={'#172D32'} px={1}> |
| 49 | + <Typography component={'div'} p={1} variant={'mediumBold'}> |
| 50 | + Compare to previous version |
| 51 | + </Typography> |
| 52 | + <Divider sx={{ backgroundColor: '#F8FAFC' }} /> |
53 | 53 |
|
54 |
| - {showNoResults ? ( |
55 |
| - <NoResultsState /> |
56 |
| - ) : ( |
57 | 54 | <Box display={'flex'}>
|
58 |
| - <Box width={'50%'} py={2} px={1} display={'inline-grid'} gap={2}> |
59 |
| - <Box display={'inline-grid'} gap={1}> |
60 |
| - <Typography variant={'mediumBold'} component={'div'}> |
61 |
| - Date |
62 |
| - </Typography> |
63 |
| - <DatePicker |
64 |
| - slotProps={{ |
65 |
| - day: { |
66 |
| - sx: { |
67 |
| - '&.MuiPickersDay-root.Mui-selected': { |
68 |
| - backgroundColor: '#5467de' |
69 |
| - } |
70 |
| - } |
71 |
| - } |
72 |
| - }} |
73 |
| - format="YYYY-MM-DD" |
74 |
| - value={date} |
75 |
| - onChange={setDate} |
76 |
| - slots={{ |
77 |
| - openPickerIcon: createSvgIcon( |
78 |
| - <svg |
79 |
| - width="20" |
80 |
| - height="20" |
81 |
| - viewBox="0 0 20 20" |
82 |
| - fill="#64748B" |
83 |
| - xmlns="http://www.w3.org/2000/svg" |
84 |
| - > |
85 |
| - <path |
86 |
| - fill-rule="evenodd" |
87 |
| - clip-rule="evenodd" |
88 |
| - d="M6.66666 1.66663C7.1269 1.66663 7.5 2.03972 7.5 2.49996V3.33329H12.5V2.49996C12.5 2.03972 12.8731 1.66663 13.3333 1.66663C13.7936 1.66663 14.1667 2.03972 14.1667 2.49996V3.33329H15.8333C17.214 3.33329 18.3333 4.45258 18.3333 5.83329V15.8333C18.3333 17.214 17.214 18.3333 15.8333 18.3333H4.16666C2.78595 18.3333 1.66666 17.214 1.66666 15.8333V5.83329C1.66666 4.45258 2.78595 3.33329 4.16666 3.33329H5.83333V2.49996C5.83333 2.03972 6.20643 1.66663 6.66666 1.66663ZM5.83333 4.99996H4.16666C3.70643 4.99996 3.33333 5.37306 3.33333 5.83329V15.8333C3.33333 16.2935 3.70643 16.6666 4.16666 16.6666H15.8333C16.2936 16.6666 16.6667 16.2935 16.6667 15.8333V5.83329C16.6667 5.37306 16.2936 4.99996 15.8333 4.99996H14.1667V5.83329C14.1667 6.29353 13.7936 6.66663 13.3333 6.66663C12.8731 6.66663 12.5 6.29353 12.5 5.83329V4.99996H7.5V5.83329C7.5 6.29353 7.1269 6.66663 6.66666 6.66663C6.20643 6.66663 5.83333 6.29353 5.83333 5.83329V4.99996ZM5 9.16663C5 8.70639 5.37309 8.33329 5.83333 8.33329H14.1667C14.6269 8.33329 15 8.70639 15 9.16663C15 9.62686 14.6269 9.99996 14.1667 9.99996H5.83333C5.37309 9.99996 5 9.62686 5 9.16663Z" |
89 |
| - fill="#64748B" |
90 |
| - /> |
91 |
| - </svg>, |
92 |
| - 'calendar' |
93 |
| - ) |
94 |
| - }} |
95 |
| - /> |
96 |
| - </Box> |
97 |
| - |
98 |
| - <Box display={'inline-grid'} gap={1}> |
99 |
| - <Typography variant={'mediumBold'} component={'div'}> |
100 |
| - Time |
101 |
| - </Typography> |
102 |
| - <TimeField format="HH:mm:ss" value={hour} onChange={setHour} /> |
103 |
| - </Box> |
104 |
| - |
105 |
| - <Box display={'inline-grid'} gap={1}> |
106 |
| - <Typography variant={'mediumBold'} component={'div'}> |
107 |
| - Change display name |
108 |
| - </Typography> |
109 |
| - <TextField |
110 |
| - placeholder={'as of YYYY-MM-DD hh:mm:ss'} |
111 |
| - value={displayName} |
112 |
| - onChange={(e) => { |
113 |
| - setDisplayName(e?.target?.value); |
114 |
| - setDisplayNameTouched(true); |
115 |
| - }} |
116 |
| - /> |
117 |
| - <Typography variant={'small'} color={'#64748B'}> |
118 |
| - Optional |
119 |
| - </Typography> |
120 |
| - </Box> |
121 |
| - </Box> |
| 55 | + <SearchForm |
| 56 | + setErrorDate={setErrorDate} |
| 57 | + setDisplayName={setDisplayName} |
| 58 | + setDisplayNameTouched={setDisplayNameTouched} |
| 59 | + setHour={setHour} |
| 60 | + hour={hour} |
| 61 | + setDate={setDate} |
| 62 | + date={date} |
| 63 | + displayName={displayName} |
| 64 | + /> |
122 | 65 |
|
123 | 66 | <Divider flexItem orientation={'vertical'} sx={{ backgroundColor: '#F8FAFC' }} />
|
124 | 67 |
|
125 | 68 | <Box px={1} py={2} width={'50%'}>
|
126 |
| - <PresetsContent |
127 |
| - presets={presets} |
128 |
| - onPresetClick={(value) => setDate(dayjs(value))} |
129 |
| - /> |
| 69 | + <PresetsContent presets={presets} onPresetClick={(value) => setDate(dayjs(value))} /> |
130 | 70 | </Box>
|
131 | 71 | </Box>
|
132 |
| - )} |
133 | 72 |
|
134 |
| - <Divider sx={{ backgroundColor: '#F8FAFC' }} /> |
135 |
| - <Box p={1} display={'flex'} alignItems={'center'} justifyContent={'space-between'}> |
136 |
| - <Box display={'flex'} justifyContent={'flex-end'}> |
137 |
| - <Typography color={'#64748B'} component="div" variant={'small'}> |
138 |
| - Browser time: (GMT {dayjs(new Date()).format('Z')}) |
139 |
| - </Typography> |
140 |
| - </Box> |
| 73 | + <Divider sx={{ backgroundColor: '#F8FAFC' }} /> |
| 74 | + <Box p={1} display={'flex'} alignItems={'center'} justifyContent={'space-between'}> |
| 75 | + <Box display={'flex'} justifyContent={'flex-end'}> |
| 76 | + <Typography color={'#64748B'} component="div" variant={'small'}> |
| 77 | + Browser time: (GMT {dayjs(new Date()).format('Z')}) |
| 78 | + </Typography> |
| 79 | + </Box> |
141 | 80 |
|
142 |
| - <Box gap={1} display={'flex'} justifyContent={'flex-end'}> |
143 |
| - <Button |
144 |
| - stretch={ButtonStretch.Slim} |
145 |
| - variant={ButtonVariant.OutlineSecondary} |
146 |
| - onClick={() => {}} |
147 |
| - label={'Cancel'} |
148 |
| - /> |
149 |
| - <Button |
150 |
| - stretch={ButtonStretch.Slim} |
151 |
| - variant={ButtonVariant.Primary} |
152 |
| - onClick={() => {}} |
153 |
| - label={'Search'} |
154 |
| - /> |
| 81 | + <Box gap={1} display={'flex'} justifyContent={'flex-end'}> |
| 82 | + <Button |
| 83 | + stretch={ButtonStretch.Slim} |
| 84 | + variant={ButtonVariant.OutlineSecondary} |
| 85 | + onClick={close} |
| 86 | + label={'Cancel'} |
| 87 | + /> |
| 88 | + <Button |
| 89 | + stretch={ButtonStretch.Slim} |
| 90 | + variant={ButtonVariant.Primary} |
| 91 | + onClick={() => addClickedHandler({ alias: displayName, value })} |
| 92 | + disabled={!date || errorDate || loading} |
| 93 | + label={loading ? 'loading...' : 'Add Field'} |
| 94 | + /> |
| 95 | + </Box> |
155 | 96 | </Box>
|
156 | 97 | </Box>
|
157 |
| - </Box> |
158 |
| - </ThemeProvider> |
159 |
| - </LocalizationProvider> |
| 98 | + </ThemeProvider> |
| 99 | + </LocalizationProvider> |
160 | 100 | );
|
161 | 101 | };
|
0 commit comments