@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.
@@ -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
 
@@ -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);
@@ -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, refs, t }: Props): JSX.Element => {
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;
@@ -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;
@@ -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;
@@ -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
+ `;
@@ -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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autobusal/common",
3
- "version": "0.0.39",
3
+ "version": "0.0.40",
4
4
  "type": "module",
5
5
  "main": "index.ts"
6
6
  }