@autobusal/common 0.0.39 → 0.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Autocomplete/Autocomplete.tsx +1 -1
- package/Calendar/Calendar.tsx +1 -1
- package/File/File.tsx +84 -0
- package/File/styles.ts +23 -0
- package/Passengers/Passengers.tsx +1 -1
- package/Password/Password.tsx +3 -2
- package/Viewer/Actions.tsx +98 -0
- package/Viewer/Data.tsx +59 -0
- package/Viewer/Item.tsx +106 -0
- package/Viewer/Items/CheckboxList.tsx +30 -0
- package/Viewer/Items/Dropdown.tsx +39 -0
- package/Viewer/Items/TextareaHtml.tsx +29 -0
- package/Viewer/Viewer.tsx +64 -0
- package/Viewer/styles.ts +38 -0
- package/Viewer/types.ts +19 -0
- package/index.ts +3 -1
- package/package.json +1 -1
|
@@ -27,7 +27,7 @@ const Autocomplete = ({ name, defaultValue, data, validation, t, refs, onUpdate
|
|
|
27
27
|
const [ selected, setSelected ] = useState<number>(-1);
|
|
28
28
|
const [ value, setValue ] = useState<string>(defaultValue);
|
|
29
29
|
|
|
30
|
-
const ref = useRef(null);
|
|
30
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
31
31
|
|
|
32
32
|
useOutside(ref, () => setShow(false));
|
|
33
33
|
|
package/Calendar/Calendar.tsx
CHANGED
|
@@ -21,7 +21,7 @@ const Calendar = ({ type, name, defaultValue, t, validation, refs, onUpdate }: P
|
|
|
21
21
|
const [ prepared, setPrepared ] = useState<string>(defaultValue ?? prepareDate(new Date()));
|
|
22
22
|
const [ selected, setSelected ] = useState<string>(prepared);
|
|
23
23
|
|
|
24
|
-
const ref = useRef(null);
|
|
24
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
25
25
|
|
|
26
26
|
useOutside(ref, () => setShow(false));
|
|
27
27
|
|
package/File/File.tsx
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { TFunction } from 'i18next';
|
|
2
|
+
import { useState, useRef } from 'react';
|
|
3
|
+
import { UseFormRegister } from 'react-hook-form';
|
|
4
|
+
import { HiOutlineCloudUpload, HiCheck } from 'react-icons/hi';
|
|
5
|
+
import { Modal } from '@autobusal/common';
|
|
6
|
+
import { validate } from '@autobusal/utilities';
|
|
7
|
+
import { Button } from '../Button/Button';
|
|
8
|
+
import { Container, ImgView, ImgPreview } from './styles';
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
name: string
|
|
12
|
+
value?: string
|
|
13
|
+
validation?: string
|
|
14
|
+
t: TFunction<'comon'>
|
|
15
|
+
refs: UseFormRegister<any>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const File = ({ name, value, validation, t, refs }: Props): JSX.Element => {
|
|
19
|
+
const [ uploaded, setUploaded ] = useState<boolean>(false);
|
|
20
|
+
const [ preview, setPreview ] = useState<boolean>(false);
|
|
21
|
+
|
|
22
|
+
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
23
|
+
|
|
24
|
+
const rules = validate(String(validation), t);
|
|
25
|
+
|
|
26
|
+
const onChange = (): void => {
|
|
27
|
+
setUploaded(true);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// we listen for the change
|
|
31
|
+
rules.onChange = onChange;
|
|
32
|
+
|
|
33
|
+
const { ref, ...rest } = refs(name, rules);
|
|
34
|
+
|
|
35
|
+
const onClick = (): void => {
|
|
36
|
+
if (inputRef.current !== null) {
|
|
37
|
+
inputRef.current.click();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<>
|
|
43
|
+
<Container>
|
|
44
|
+
<input
|
|
45
|
+
{ ...rest }
|
|
46
|
+
type="file"
|
|
47
|
+
name={ name }
|
|
48
|
+
style={{ display: 'none' }}
|
|
49
|
+
ref={ (e) => {
|
|
50
|
+
ref(e);
|
|
51
|
+
inputRef.current = e;
|
|
52
|
+
} }
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<Button
|
|
56
|
+
type="button"
|
|
57
|
+
size="small"
|
|
58
|
+
text={
|
|
59
|
+
uploaded
|
|
60
|
+
? <><HiCheck /> { t('file.done', { ns: 'common' }) }</>
|
|
61
|
+
: <><HiOutlineCloudUpload /> { t('file.ready', { ns: 'common' }) }</>
|
|
62
|
+
}
|
|
63
|
+
noMargin
|
|
64
|
+
onClick={ onClick }
|
|
65
|
+
/>
|
|
66
|
+
|
|
67
|
+
{ value && <ImgView src={ value } onClick={ () => setPreview(true) } /> }
|
|
68
|
+
</Container>
|
|
69
|
+
|
|
70
|
+
{ preview && (
|
|
71
|
+
<Modal
|
|
72
|
+
width={ 500 }
|
|
73
|
+
title={ t('file.preview', { ns: 'common' }) }
|
|
74
|
+
content={ (
|
|
75
|
+
<ImgPreview src={ value } />
|
|
76
|
+
) }
|
|
77
|
+
onClose={ () => setPreview(false) }
|
|
78
|
+
/>
|
|
79
|
+
) }
|
|
80
|
+
</>
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export default File;
|
package/File/styles.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
export const Container = styled.div`
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
justify-content: space-between;
|
|
7
|
+
gap: 10px;
|
|
8
|
+
height: 38px;
|
|
9
|
+
`;
|
|
10
|
+
|
|
11
|
+
export const ImgView = styled.img`
|
|
12
|
+
display: block;
|
|
13
|
+
height: 38px;
|
|
14
|
+
padding: 4px;
|
|
15
|
+
border: 1px solid ${ props => props.theme.background.neutral };
|
|
16
|
+
border-radius: ${ props => props.theme.borderRadius };
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
export const ImgPreview = styled.img`
|
|
21
|
+
display: block;
|
|
22
|
+
width: 100%;
|
|
23
|
+
`;
|
|
@@ -24,7 +24,7 @@ const Passengers = ({ defaultAdults, defaultChildren, defaultBabies, t, refs, on
|
|
|
24
24
|
getText(adults, children, babies, t)
|
|
25
25
|
);
|
|
26
26
|
|
|
27
|
-
const ref = useRef(null);
|
|
27
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
28
28
|
|
|
29
29
|
useEffect(() => {
|
|
30
30
|
const text = getText(adults, children, babies, t);
|
package/Password/Password.tsx
CHANGED
|
@@ -7,11 +7,12 @@ import { Container } from './styles';
|
|
|
7
7
|
|
|
8
8
|
interface Props {
|
|
9
9
|
name: string
|
|
10
|
+
tabIndex?: number
|
|
10
11
|
t: TFunction<'common'>
|
|
11
12
|
refs: UseFormRegister<any>
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
const Password = ({ name,
|
|
15
|
+
const Password = ({ name, tabIndex, t, refs }: Props): JSX.Element => {
|
|
15
16
|
const [ show, setShow ] = useState<boolean>(false);
|
|
16
17
|
|
|
17
18
|
const toggle = (): void => {
|
|
@@ -20,7 +21,7 @@ const Password = ({ name, refs, t }: Props): JSX.Element => {
|
|
|
20
21
|
|
|
21
22
|
return (
|
|
22
23
|
<Container>
|
|
23
|
-
<input type={ show ? 'text' : 'password' } { ...refs(name, validate('required|min_length:6|max_length:20', t)) } />
|
|
24
|
+
<input type={ show ? 'text' : 'password' } tabIndex={ tabIndex } { ...refs(name, validate('required|min_length:6|max_length:20', t)) } />
|
|
24
25
|
|
|
25
26
|
{ show
|
|
26
27
|
? <AiFillEye onClick={ toggle } />
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { TFunction } from 'i18next';
|
|
2
|
+
import { BiEditAlt, BiTrash, BiSend } from 'react-icons/bi';
|
|
3
|
+
// import { RiSave2Line, RiCheckFill, RiSearchLine } from 'react-icons/ri';
|
|
4
|
+
// import { BsPlusCircleFill } from 'react-icons/bs';
|
|
5
|
+
import { ContainerActions } from './styles';
|
|
6
|
+
import { ActionData } from './types';
|
|
7
|
+
import { Button } from '@autobusal/common';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
available: string[]
|
|
11
|
+
loading?: boolean
|
|
12
|
+
t: TFunction<'common'>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const Actions = ({ available, loading, t }: Props): JSX.Element => {
|
|
16
|
+
|
|
17
|
+
// function Actions({ id, actions, status, t, deleter }) {
|
|
18
|
+
let options: ActionData[] = [];
|
|
19
|
+
|
|
20
|
+
// const askDeletion = () => {
|
|
21
|
+
// if (window.confirm(t('general:table.confirm'))) {
|
|
22
|
+
// deleter();
|
|
23
|
+
// }
|
|
24
|
+
// };
|
|
25
|
+
|
|
26
|
+
// if (actions.includes('add')) {
|
|
27
|
+
// options.push({
|
|
28
|
+
// label: t('general:table.action.add'),
|
|
29
|
+
// icon: <BsPlusCircleFill />
|
|
30
|
+
// });
|
|
31
|
+
// }
|
|
32
|
+
|
|
33
|
+
// if (actions.includes('save')) {
|
|
34
|
+
// options.push({
|
|
35
|
+
// label: t('general:table.action.save'),
|
|
36
|
+
// icon: <RiSave2Line />
|
|
37
|
+
// });
|
|
38
|
+
// }
|
|
39
|
+
|
|
40
|
+
// if (actions.includes('send')) {
|
|
41
|
+
// options.push({
|
|
42
|
+
// label: t('general:table.action.send'),
|
|
43
|
+
// icon: <BiSend />
|
|
44
|
+
// });
|
|
45
|
+
// }
|
|
46
|
+
|
|
47
|
+
if (available.includes('update')) {
|
|
48
|
+
options.push({
|
|
49
|
+
label: t('table.actions.update', { ns: 'common' }),
|
|
50
|
+
icon: <BiEditAlt />,
|
|
51
|
+
type: 'submit'
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// if (actions.includes('approve')) {
|
|
56
|
+
// options.push({
|
|
57
|
+
// label: t('general:table.action.approve'),
|
|
58
|
+
// icon: <RiCheckFill />
|
|
59
|
+
// });
|
|
60
|
+
// }
|
|
61
|
+
|
|
62
|
+
// if (actions.includes('delete') && id > 0) {
|
|
63
|
+
// options.push({
|
|
64
|
+
// label: t('general:table.action.delete'),
|
|
65
|
+
// icon: <BiTrash />,
|
|
66
|
+
// type: 'button',
|
|
67
|
+
// className: "delete",
|
|
68
|
+
// handler: askDeletion
|
|
69
|
+
// });
|
|
70
|
+
// }
|
|
71
|
+
|
|
72
|
+
// if (actions.includes('search')) {
|
|
73
|
+
// options.push({
|
|
74
|
+
// label: t('general:table.action.search'),
|
|
75
|
+
// icon: <RiSearchLine />
|
|
76
|
+
// });
|
|
77
|
+
// }
|
|
78
|
+
|
|
79
|
+
const items = options.map((item, index) => (
|
|
80
|
+
<Button
|
|
81
|
+
key={ index }
|
|
82
|
+
type={ item.type === 'submit' ? 'submit' : 'button' }
|
|
83
|
+
text={
|
|
84
|
+
<>{ item.icon } { item.label }</>
|
|
85
|
+
}
|
|
86
|
+
loading={ loading }
|
|
87
|
+
noMargin
|
|
88
|
+
/>
|
|
89
|
+
));
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<ContainerActions>
|
|
93
|
+
{ items }
|
|
94
|
+
</ContainerActions>
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export default Actions;
|
package/Viewer/Data.tsx
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { UseFormRegister, UseFormSetValue } from 'react-hook-form';
|
|
2
|
+
import Dropdown from './Items/Dropdown';
|
|
3
|
+
import { ViewData } from './types';
|
|
4
|
+
import Calendar from '../Calendar/Calendar';
|
|
5
|
+
import File from '../File/File';
|
|
6
|
+
import { validate } from '@autobusal/utilities';
|
|
7
|
+
import { TFunction } from 'i18next';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
item: ViewData
|
|
11
|
+
refs: UseFormRegister<any>
|
|
12
|
+
t: TFunction<'common'>
|
|
13
|
+
onUpdate: UseFormSetValue<any>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const Data = ({ item, refs, t, onUpdate }: Props): (JSX.Element | null) => {
|
|
17
|
+
if (item.name === undefined) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
switch (item.type) {
|
|
22
|
+
case 'dob':
|
|
23
|
+
return (
|
|
24
|
+
<Calendar
|
|
25
|
+
type={ item.type }
|
|
26
|
+
name={ item.name }
|
|
27
|
+
defaultValue={ item.value !== null ? String(item.value) : undefined }
|
|
28
|
+
t={ t }
|
|
29
|
+
validation={ item.rules }
|
|
30
|
+
refs={ refs }
|
|
31
|
+
onUpdate={ onUpdate }
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
case 'file':
|
|
36
|
+
return (
|
|
37
|
+
<File
|
|
38
|
+
name={ item.name }
|
|
39
|
+
value={ item.value !== undefined ? String(item.value) : undefined }
|
|
40
|
+
validation={ item.rules }
|
|
41
|
+
t={ t }
|
|
42
|
+
refs={ refs }
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
case 'select':
|
|
47
|
+
return <Dropdown item={ item } refs={ refs } t={ t } />;
|
|
48
|
+
|
|
49
|
+
case 'text':
|
|
50
|
+
return <input type="text" defaultValue={ item.value } { ...refs(item.name, validate(String(item.rules), t)) } />;
|
|
51
|
+
|
|
52
|
+
case 'textarea':
|
|
53
|
+
return <textarea defaultValue={ item.value } { ...refs(item.name, validate(String(item.rules), t)) }></textarea>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return null;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export default Data;
|
package/Viewer/Item.tsx
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { FieldErrors, UseFormRegister, UseFormSetValue } from 'react-hook-form';
|
|
2
|
+
import { display } from '@autobusal/utilities';
|
|
3
|
+
import Data from './Data';
|
|
4
|
+
import { ViewData } from './types';
|
|
5
|
+
import { TFunction } from 'i18next';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
data: ViewData
|
|
9
|
+
refs: UseFormRegister<any>
|
|
10
|
+
t: TFunction<'common'>
|
|
11
|
+
errors: FieldErrors<any>
|
|
12
|
+
onUpdate: UseFormSetValue<any>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const Item = ({ data, refs, t, errors, onUpdate }: Props): JSX.Element => (
|
|
16
|
+
<div className={ `row ${ data.label === undefined && 'spacer' }` }>
|
|
17
|
+
{ data.label }
|
|
18
|
+
|
|
19
|
+
<Data
|
|
20
|
+
item={ data }
|
|
21
|
+
refs={ refs }
|
|
22
|
+
t={ t }
|
|
23
|
+
onUpdate={ onUpdate }
|
|
24
|
+
/>
|
|
25
|
+
|
|
26
|
+
{ data.name && display(errors[data.name]) }
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
export default Item;
|
|
31
|
+
|
|
32
|
+
// function Input({ data, refs, onUpdate, errors, t }) {
|
|
33
|
+
// let input;
|
|
34
|
+
|
|
35
|
+
// switch (data.type) {
|
|
36
|
+
// case 'display':
|
|
37
|
+
// input = <div className="display">{ data.value }</div>;
|
|
38
|
+
// break;
|
|
39
|
+
|
|
40
|
+
// case 'email':
|
|
41
|
+
// input = <input type="email" defaultValue={ data.value } { ...refs(data.name, data.validation) } />;
|
|
42
|
+
// break;
|
|
43
|
+
|
|
44
|
+
// case 'number':
|
|
45
|
+
// input = <input type="number" defaultValue={ data.value } { ...refs(data.name, data.validation) } />
|
|
46
|
+
// break;
|
|
47
|
+
|
|
48
|
+
// case 'float':
|
|
49
|
+
// input = <input type="number" defaultValue={ data.value } { ...refs(data.name, data.validation) } step="0.01" />
|
|
50
|
+
// break;
|
|
51
|
+
|
|
52
|
+
// case 'checkbox':
|
|
53
|
+
// input = <input type="checkbox" value="1" defaultChecked={ data.value == 1 } { ...refs(data.name, data.validation) } />;
|
|
54
|
+
// break;
|
|
55
|
+
|
|
56
|
+
// case 'checkbox-list':
|
|
57
|
+
// input = <CheckboxList name={ data.name } values={ data.values } selected={ data.selected } hasAll={ data?.hasAll ?? true } refs={ refs } t={ t } />;
|
|
58
|
+
// break;
|
|
59
|
+
|
|
60
|
+
// case 'textarea-html':
|
|
61
|
+
// input = <TextareaHtml data={ data } onUpdate={ onUpdate } refs={ refs } />;
|
|
62
|
+
// break;
|
|
63
|
+
|
|
64
|
+
// case 'password':
|
|
65
|
+
// input = <Password refs={ refs(data.name, data.validation) } />
|
|
66
|
+
// break;
|
|
67
|
+
|
|
68
|
+
// case 'picker':
|
|
69
|
+
//
|
|
70
|
+
// case 'date':
|
|
71
|
+
// input = (
|
|
72
|
+
// <div className="display">
|
|
73
|
+
// <Calendar type={ data.type } name={ data.name } value={ data.value } refs={ refs } validation={ data.validation } t={ t } onUpdate={ onUpdate } />
|
|
74
|
+
// </div>
|
|
75
|
+
// );
|
|
76
|
+
// break;
|
|
77
|
+
|
|
78
|
+
// case 'extra':
|
|
79
|
+
// input = data.value;
|
|
80
|
+
// break;
|
|
81
|
+
// }
|
|
82
|
+
|
|
83
|
+
// let extra;
|
|
84
|
+
|
|
85
|
+
// switch (data.type) {
|
|
86
|
+
// case 'password':
|
|
87
|
+
// extra = ' item-password';
|
|
88
|
+
// break;
|
|
89
|
+
|
|
90
|
+
// case 'textarea-html':
|
|
91
|
+
// extra = ' full';
|
|
92
|
+
// break;
|
|
93
|
+
// }
|
|
94
|
+
|
|
95
|
+
// if (data.extra) {
|
|
96
|
+
// extra = ' ' + data.extra;
|
|
97
|
+
// }
|
|
98
|
+
|
|
99
|
+
// return (
|
|
100
|
+
// <div className={ `item${ extra ?? '' }` }>
|
|
101
|
+
// { input }
|
|
102
|
+
|
|
103
|
+
// { data.notice ? <div className="notice">* { data.notice }</div> : null }
|
|
104
|
+
// </div>
|
|
105
|
+
// );
|
|
106
|
+
// }
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// function CheckboxList({ name, values, selected, hasAll, refs, t }) {
|
|
2
|
+
// const [ all, setAll ] = useState(selected?.includes('all') ?? true);
|
|
3
|
+
|
|
4
|
+
// const checkboxes = values.map((item, index) => {
|
|
5
|
+
// if (all) {
|
|
6
|
+
// return null;
|
|
7
|
+
// }
|
|
8
|
+
|
|
9
|
+
// return (
|
|
10
|
+
// <label key={ index }>
|
|
11
|
+
// <input type="checkbox" value={ item.value } defaultChecked={ selected?.includes(item.value + '') } { ...refs(name + '[' + (index + 1) + ']') } /> { item.name }
|
|
12
|
+
// </label>
|
|
13
|
+
// );
|
|
14
|
+
// });
|
|
15
|
+
|
|
16
|
+
// const onAll = () => {
|
|
17
|
+
// setAll(all ? false : true);
|
|
18
|
+
// };
|
|
19
|
+
|
|
20
|
+
// return (
|
|
21
|
+
// <div className="display list">
|
|
22
|
+
// { hasAll ? <label key={ -1 }><input type="checkbox" value="all" defaultChecked={ all } onClick={ () => onAll() } { ...refs(name + '[' + 0 + ']') } /> { t('general:table.checkbox.all') }</label> : null }
|
|
23
|
+
|
|
24
|
+
// { checkboxes }
|
|
25
|
+
|
|
26
|
+
// <div className="clear"></div>
|
|
27
|
+
// </div>
|
|
28
|
+
// );
|
|
29
|
+
// }
|
|
30
|
+
// }
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { TFunction } from 'i18next';
|
|
2
|
+
import { UseFormRegister } from 'react-hook-form';
|
|
3
|
+
import { validate } from '@autobusal/utilities';
|
|
4
|
+
import { ViewData } from '../types';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
item: ViewData
|
|
8
|
+
refs: UseFormRegister<any>
|
|
9
|
+
t: TFunction<'common'>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const Dropdown = ({ item, refs, t }: Props): (JSX.Element | null) => {
|
|
13
|
+
if (item.name === undefined) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const values = item.values?.map((item, index) => (
|
|
18
|
+
<option
|
|
19
|
+
key={ index }
|
|
20
|
+
value={ item.id }
|
|
21
|
+
// disabled={ item.disabled === true }
|
|
22
|
+
>
|
|
23
|
+
{ item.name }
|
|
24
|
+
</option>
|
|
25
|
+
));
|
|
26
|
+
|
|
27
|
+
// // add a custom onchange listener
|
|
28
|
+
// if (item.onChange) {
|
|
29
|
+
// item.validation.onChange = (e) => data.onChange(e.target.value);
|
|
30
|
+
// }
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<select defaultValue={ item.value } { ...refs(item.name, validate(String(item.rules), t)) }>
|
|
34
|
+
{ values }
|
|
35
|
+
</select>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default Dropdown;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// import { EditorState, ContentState, convertToRaw } from 'draft-js';
|
|
2
|
+
// import { Editor } from 'react-draft-wysiwyg';
|
|
3
|
+
// import htmlToDraft from 'html-to-draftjs';
|
|
4
|
+
// import draftToHtml from 'draftjs-to-html';
|
|
5
|
+
// import '../../../../../node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
|
|
6
|
+
|
|
7
|
+
// function TextareaHtml({ data, onUpdate, refs }) {
|
|
8
|
+
// const [ value, setValue ] = useState('');
|
|
9
|
+
|
|
10
|
+
// useEffect(() => {
|
|
11
|
+
// let html = data.value ?? '';
|
|
12
|
+
// const content = htmlToDraft(html);
|
|
13
|
+
|
|
14
|
+
// const contentHtml = ContentState.createFromBlockArray(content);
|
|
15
|
+
// setValue(EditorState.createWithContent(contentHtml));
|
|
16
|
+
// }, []);
|
|
17
|
+
|
|
18
|
+
// const onEditorChange = (state) => {
|
|
19
|
+
// setValue(state);
|
|
20
|
+
// onUpdate(data.name, draftToHtml(convertToRaw(value.getCurrentContent())));
|
|
21
|
+
// };
|
|
22
|
+
|
|
23
|
+
// return (
|
|
24
|
+
// <>
|
|
25
|
+
// <Editor editorState={ value } onEditorStateChange={ onEditorChange } />
|
|
26
|
+
// <textarea defaultValue={ data.value } { ...refs(data.name, data.validation) } style={{ display: 'none' }}></textarea>
|
|
27
|
+
// </>
|
|
28
|
+
// );
|
|
29
|
+
// }
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useForm } from 'react-hook-form';
|
|
2
|
+
import { TFunction } from 'i18next';
|
|
3
|
+
import Item from './Item';
|
|
4
|
+
import Actions from './Actions';
|
|
5
|
+
import { Container } from './styles';
|
|
6
|
+
import { ViewData } from './types';
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
data: ViewData[]
|
|
10
|
+
loading?: boolean
|
|
11
|
+
actions?: string[]
|
|
12
|
+
t: TFunction<'common'>
|
|
13
|
+
onSave: (data: any) => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const Viewer = ({ data, loading, actions, t, onSave }: Props): JSX.Element => {
|
|
17
|
+
const { register, handleSubmit, formState: { errors }, setValue, reset } = useForm<any>();
|
|
18
|
+
|
|
19
|
+
// reset on id change
|
|
20
|
+
// useEffect(() => {
|
|
21
|
+
// reset();
|
|
22
|
+
// }, [id]);
|
|
23
|
+
|
|
24
|
+
const items = data.map((item, index) => (
|
|
25
|
+
<Item
|
|
26
|
+
key={ index }
|
|
27
|
+
data={ item }
|
|
28
|
+
refs={ register }
|
|
29
|
+
t={ t }
|
|
30
|
+
errors={ errors }
|
|
31
|
+
onUpdate={ setValue }
|
|
32
|
+
/>
|
|
33
|
+
));
|
|
34
|
+
|
|
35
|
+
const onSubmit = (data: any): void => {
|
|
36
|
+
onSave(data);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// return (
|
|
40
|
+
// <div className="box">
|
|
41
|
+
// { actions.length > 0 ? <form className="form form-viewer" onSubmit={ handleSubmit(onSubmit) }>{ display }</form> : <div className="form form-viewer">{ display }</div> }
|
|
42
|
+
// </div>
|
|
43
|
+
// );
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div className="box">
|
|
47
|
+
<form onSubmit={ handleSubmit(onSubmit) }>
|
|
48
|
+
<Container>
|
|
49
|
+
{ items }
|
|
50
|
+
</Container>
|
|
51
|
+
|
|
52
|
+
{ (actions !== undefined && actions.length > 0) && (
|
|
53
|
+
<Actions
|
|
54
|
+
available={ actions }
|
|
55
|
+
loading={ loading }
|
|
56
|
+
t={ t }
|
|
57
|
+
/>
|
|
58
|
+
) }
|
|
59
|
+
</form>
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export default Viewer;
|
package/Viewer/styles.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
export const Container = styled.div`
|
|
4
|
+
@media (min-width: 480px) {
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-wrap: wrap;
|
|
7
|
+
gap: 20px;
|
|
8
|
+
|
|
9
|
+
& > div.row {
|
|
10
|
+
margin-bottom: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
& > div {
|
|
14
|
+
flex-basis: calc(50% - 10px);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
& > div.spacer {
|
|
18
|
+
flex-basis: 100%;
|
|
19
|
+
height: 1px;
|
|
20
|
+
background: ${ props => props.theme.background.neutral };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@media (min-width: 1300px) {
|
|
25
|
+
& > div {
|
|
26
|
+
flex-basis: calc(33.33333% - 14px);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
export const ContainerActions = styled.div`
|
|
32
|
+
display: flex;
|
|
33
|
+
justify-content: center;
|
|
34
|
+
margin-top: 25px;
|
|
35
|
+
padding: 15px 10px;
|
|
36
|
+
background: ${ props => props.theme.background.neutral };
|
|
37
|
+
border-radius: ${ props => props.theme.borderRadius };
|
|
38
|
+
`;
|
package/Viewer/types.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ViewData {
|
|
2
|
+
label?: string
|
|
3
|
+
name?: string
|
|
4
|
+
type?: 'text' | 'select' | 'dob' | 'textarea' | 'file'
|
|
5
|
+
value?: string | number
|
|
6
|
+
values?: ValuesData[]
|
|
7
|
+
rules?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ValuesData {
|
|
11
|
+
id: number
|
|
12
|
+
name: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ActionData {
|
|
16
|
+
label: string
|
|
17
|
+
icon: any
|
|
18
|
+
type?: 'submit'
|
|
19
|
+
}
|
package/index.ts
CHANGED
|
@@ -17,6 +17,7 @@ import Password from './Password/Password';
|
|
|
17
17
|
import Policy from './Policy/Policy';
|
|
18
18
|
import RouteFeature from './RouteFeature/RouteFeature';
|
|
19
19
|
import RouteItem from './RouteItem/RouteItem';
|
|
20
|
+
import Viewer from './Viewer/Viewer';
|
|
20
21
|
|
|
21
22
|
export {
|
|
22
23
|
Autocomplete,
|
|
@@ -39,5 +40,6 @@ export {
|
|
|
39
40
|
Password,
|
|
40
41
|
Policy,
|
|
41
42
|
RouteFeature,
|
|
42
|
-
RouteItem
|
|
43
|
+
RouteItem,
|
|
44
|
+
Viewer
|
|
43
45
|
};
|