@autobusal/common 0.0.40 → 1.0.0

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.
Files changed (77) hide show
  1. package/ApiDetails/ApiDetails.tsx +50 -0
  2. package/ApiDetails/Content.tsx +48 -0
  3. package/ApiDetails/Devpos.tsx +139 -0
  4. package/ApiDetails/services.ts +39 -0
  5. package/ApiDetails/types.ts +13 -0
  6. package/Autocomplete/Autocomplete.tsx +3 -3
  7. package/Avatar.tsx +28 -0
  8. package/{BackTo.tsx → Back/BackTo.tsx} +4 -3
  9. package/Back/BackWithTitle.tsx +30 -0
  10. package/Button/Button.tsx +4 -2
  11. package/Calendar/Calendar.tsx +2 -2
  12. package/{BrowseCompanyItem/BrowseCompanyItem.tsx → CompanyItem/CompanyItem.tsx} +2 -2
  13. package/ContactInfo/ContactInfo.tsx +40 -0
  14. package/ContactInfo/styles.ts +33 -0
  15. package/CookieNotification/CookieNotification.tsx +2 -2
  16. package/File/File.tsx +11 -7
  17. package/IpLogs/IpLogs.tsx +47 -0
  18. package/IpLogs/View.tsx +48 -0
  19. package/IpLogs/services.ts +27 -0
  20. package/IpLogs/styles.ts +10 -0
  21. package/Loading/Loading.tsx +25 -20
  22. package/Loading/Paragraph.tsx +62 -0
  23. package/Loading/styles.ts +34 -1
  24. package/Meta.tsx +1 -1
  25. package/Modal/Modal.tsx +1 -1
  26. package/Pagination/Pagination.tsx +2 -1
  27. package/Passengers/Passengers.tsx +6 -5
  28. package/Passengers/Persons.tsx +7 -7
  29. package/Passengers/{utilities/getText.ts → utilities.ts} +3 -5
  30. package/Password/Password.tsx +4 -3
  31. package/Password/styles.ts +1 -1
  32. package/Policy/services.ts +1 -3
  33. package/Report/Report.tsx +39 -0
  34. package/Report/Send.tsx +52 -0
  35. package/Report/services.ts +19 -0
  36. package/Report/styles.ts +31 -0
  37. package/Report/types.ts +3 -0
  38. package/RouteItem/styles.ts +0 -1
  39. package/Seats/ChooseSeat.tsx +3 -3
  40. package/Seats/Preview.tsx +3 -3
  41. package/Seats/styles.ts +1 -43
  42. package/Table/Actions/Actions.tsx +40 -0
  43. package/Table/Actions/Get.tsx +49 -0
  44. package/Table/Actions/Icon.tsx +54 -0
  45. package/Table/Actions/styles.ts +22 -0
  46. package/Table/Header/Header.tsx +46 -0
  47. package/Table/Header/Sort.tsx +33 -0
  48. package/Table/Header/styles.ts +48 -0
  49. package/Table/Paginate.tsx +34 -0
  50. package/Table/Row.tsx +22 -0
  51. package/Table/Rows/Loading.tsx +22 -0
  52. package/Table/Rows/NotFound.tsx +22 -0
  53. package/Table/Rows/Rows.tsx +63 -0
  54. package/Table/Rows/styles.ts +37 -0
  55. package/Table/Table.tsx +76 -0
  56. package/Table/Top/Search.tsx +36 -0
  57. package/Table/Top/Top.tsx +44 -0
  58. package/Table/Top/styles.ts +32 -0
  59. package/Table/browseUrl.ts +21 -0
  60. package/Table/styles.ts +28 -0
  61. package/Table/types.ts +11 -0
  62. package/Viewer/Actions.tsx +61 -53
  63. package/Viewer/Data.tsx +74 -8
  64. package/Viewer/Item.tsx +10 -81
  65. package/Viewer/Items/CheckboxList.tsx +53 -30
  66. package/Viewer/Items/DatePicker.tsx +70 -0
  67. package/Viewer/Items/Dropdown.tsx +14 -12
  68. package/Viewer/Items/Linked.tsx +27 -0
  69. package/Viewer/Items/TextareaHtml.tsx +51 -24
  70. package/Viewer/Items/styles.ts +73 -0
  71. package/Viewer/Viewer.tsx +24 -17
  72. package/Viewer/styles.ts +21 -1
  73. package/Viewer/types.ts +11 -8
  74. package/index.ts +30 -8
  75. package/package.json +1 -1
  76. package/Pagination/types.ts +0 -12
  77. /package/{BrowseCompanyItem → CompanyItem}/styles.ts +0 -0
package/Seats/styles.ts CHANGED
@@ -87,46 +87,4 @@ export const TitleUnavailable = styled.div`
87
87
  align-items: center;
88
88
  font-weight: 700;
89
89
  font-size: ${ props => props.theme.size.s };
90
- `;
91
-
92
- // // @todo: finish adding a seat
93
- // // .choose-seats {
94
- // // .bus-plan {
95
- // // .bus-seat {
96
- // // .remove {
97
- // // position: absolute;
98
- // // top: 0;
99
- // // right: 0;
100
- // // z-index: 1;
101
- // // width: 20px;
102
- // // height: 20px;
103
- // // background-color: $red;
104
- // // border-radius: $border-radius - 3;
105
-
106
- // // svg {
107
- // // margin: 1px auto 0;
108
- // // font-size: $size-info;
109
- // // color: $white;
110
- // // }
111
- // // }
112
- // // }
113
-
114
- // // .add-seat {
115
- // // display: block;
116
- // // position: absolute;
117
- // // z-index: 5;
118
- // // bottom: -58px;
119
- // // width: 50px;
120
- // // height: 38px;
121
- // // text-align: center;
122
- // // line-height: 32px;
123
- // // color: $blue;
124
- // // border: 3px solid $blue;
125
- // // border-radius: 100px;
126
-
127
- // // svg {
128
- // // margin: 0;
129
- // // }
130
- // // }
131
- // // }
132
- // // }
90
+ `;
@@ -0,0 +1,40 @@
1
+ import { TFunction } from 'i18next';
2
+ import { NavigateFunction } from 'react-router-dom';
3
+ import Get from './Get';
4
+ import { Container } from './styles';
5
+ import { Td } from '../styles';
6
+
7
+ interface Props {
8
+ id: number
9
+ url: string
10
+ urlWith?: string
11
+ available?: string[]
12
+ t: TFunction<'common'>
13
+ handlers?: any
14
+ navigate: NavigateFunction
15
+ }
16
+
17
+ const Actions = ({ id, url, urlWith, available, t, handlers, navigate }: Props): JSX.Element => {
18
+ const actions = available?.map((action, index) => (
19
+ <Get
20
+ key={ index }
21
+ id={ id }
22
+ url={ url }
23
+ urlWith={ urlWith }
24
+ type={ action }
25
+ t={ t }
26
+ handlers={ handlers }
27
+ navigate={ navigate }
28
+ />
29
+ ));
30
+
31
+ return (
32
+ <Td>
33
+ <Container>
34
+ { actions }
35
+ </Container>
36
+ </Td>
37
+ );
38
+ };
39
+
40
+ export default Actions;
@@ -0,0 +1,49 @@
1
+ import { TFunction } from 'i18next';
2
+ import { NavigateFunction } from 'react-router-dom';
3
+ import Icon from './Icon';
4
+ import { ButtonAction } from './styles';
5
+
6
+ interface Props {
7
+ id: number
8
+ url: string
9
+ urlWith?: string
10
+ type: string
11
+ t: TFunction<'common'>
12
+ handlers?: any
13
+ navigate: NavigateFunction
14
+ }
15
+
16
+ const Get = ({ id, url, urlWith, type, t, handlers, navigate }: Props): (JSX.Element | null) => {
17
+ if (['create', 'search'].includes(type)) {
18
+ return null;
19
+ }
20
+
21
+ const onAskDeletion = (): void => {
22
+ // ask for the deletion of the object
23
+ if (window.confirm(t('table.confirm', { ns: 'common' }))) {
24
+ handlers.delete(id);
25
+ }
26
+ };
27
+
28
+ const onClick = (event: React.MouseEvent<HTMLButtonElement>): void => {
29
+ event.stopPropagation();
30
+
31
+ if (type === 'view' || type === 'update') {
32
+ navigate(`${ url }/manage/${ id }${ urlWith ? `?${ urlWith }` : '' }`);
33
+ } else if (type === 'delete') {
34
+ onAskDeletion();
35
+ } else {
36
+ if (handlers[type]) {
37
+ handlers[type](id);
38
+ }
39
+ }
40
+ };
41
+
42
+ return (
43
+ <ButtonAction $type={ type } onClick={ (event) => onClick(event) }>
44
+ <Icon type={ type } t={ t } />
45
+ </ButtonAction>
46
+ );
47
+ };
48
+
49
+ export default Get;
@@ -0,0 +1,54 @@
1
+ import { TFunction } from 'i18next';
2
+ import { AiOutlineCheck, AiOutlineCloudDownload } from 'react-icons/ai';
3
+ import { BiEditAlt, BiTransfer, BiTrash } from 'react-icons/bi';
4
+ import { FaTrash } from 'react-icons/fa';
5
+ import { GiMoneyStack } from 'react-icons/gi';
6
+ import { IoDocumentLockOutline } from 'react-icons/io5';
7
+ import { RiBusLine, RiEyeLine, RiLoginCircleLine } from 'react-icons/ri';
8
+
9
+ interface Props {
10
+ type: string
11
+ t: TFunction<'common'>
12
+ }
13
+
14
+ const Icon = ({ type, t }: Props): (JSX.Element | null) => {
15
+ switch (type) {
16
+ case 'view':
17
+ case 'preview':
18
+ return <RiEyeLine title={ t('table.actions.view', { ns: 'common' }) } />;
19
+
20
+ case 'delete':
21
+ return <BiTrash title={ t('table.actions.delete', { ns: 'common' }) } />;
22
+
23
+ case 'login_as':
24
+ return <RiLoginCircleLine title={ t('table.actions.custom.login_as', { ns: 'common' }) } />;
25
+
26
+ case 'approve':
27
+ return <AiOutlineCheck title={ t('table.actions.custom.approve', { ns: 'common' }) } />;
28
+
29
+ case 'deny':
30
+ return <FaTrash title={ t('table.actions.custom.deny', { ns: 'common' }) } />;
31
+
32
+ case 'update':
33
+ return <BiEditAlt title={ t('table.actions.custom.update', { ns: 'common' }) } />;
34
+
35
+ case 'transactions':
36
+ return <BiTransfer title={ t('table.actions.custom.transactions', { ns: 'common' }) } />;
37
+
38
+ case 'comissions':
39
+ return <GiMoneyStack title={ t('table.actions.custom.comissions', { ns: 'common' }) } />;
40
+
41
+ case 'download':
42
+ return <AiOutlineCloudDownload title={ t('table.actions.custom.download', { ns: 'common' }) } />;
43
+
44
+ case 'bus':
45
+ return <RiBusLine title={ t('table.actions.custom.bus', { ns: 'common' }) } />;
46
+
47
+ case 'douane':
48
+ return <IoDocumentLockOutline title={ t('table.actions.custom.douane', { ns: 'common' }) } />;
49
+ }
50
+
51
+ return null;
52
+ };
53
+
54
+ export default Icon;
@@ -0,0 +1,22 @@
1
+ import styled, { css } from 'styled-components';
2
+
3
+ export const Container = styled.div`
4
+ display: flex;
5
+ gap: 10px;
6
+ justify-content: center;
7
+ `;
8
+
9
+ export const ButtonAction = styled.button<{ $type: string }>`
10
+ display: flex;
11
+ align-items: center;
12
+ font-size: ${ props => props.theme.size.xxl };
13
+ color: ${ props => props.theme.font.info };
14
+
15
+ ${ props => (props.$type === 'delete' || props.$type === 'deny') && css`
16
+ color: ${ props => props.theme.font.error };
17
+ ` }
18
+
19
+ ${ props => props.$type === 'approve' && css`
20
+ color: ${ props => props.theme.font.success };
21
+ ` }
22
+ `;
@@ -0,0 +1,46 @@
1
+ import { TFunction } from 'i18next';
2
+ import Sort from './Sort';
3
+ import { getUrl } from '../browseUrl';
4
+ import { Container, Td, Column, Text } from './styles';
5
+ import { ColumnData, SortingData } from '../types';
6
+
7
+ interface Props {
8
+ url: string
9
+ data: ColumnData[]
10
+ sorting?: SortingData
11
+ t: TFunction<'common'>
12
+ actions?: string[]
13
+ }
14
+
15
+ const Header = ({ url, data, sorting, t, actions }: Props): JSX.Element => {
16
+ const params = getUrl();
17
+
18
+ const columns = data.map((item, index) => (
19
+ <Td key={ index } $width={ item.width }>
20
+ <Column>
21
+ { item.slug
22
+ ? <Sort item={ item } url={ url } params={ params } sorting={ sorting } />
23
+ : <Text>{ item.name }</Text>
24
+ }
25
+ </Column>
26
+ </Td>
27
+ ));
28
+
29
+ return (
30
+ <Container>
31
+ <tr>
32
+ { columns }
33
+
34
+ { (actions !== undefined && actions.length > 0) && (
35
+ <Td $width={ 10 }>
36
+ <Column>
37
+ <Text>{ t('table.options', { ns: 'common' }) }</Text>
38
+ </Column>
39
+ </Td>
40
+ ) }
41
+ </tr>
42
+ </Container>
43
+ );
44
+ };
45
+
46
+ export default Header;
@@ -0,0 +1,33 @@
1
+ import { BiSortDown, BiSortUp } from 'react-icons/bi';
2
+ import { parseUrl } from '../browseUrl';
3
+ import { LinkHeader } from './styles';
4
+ import { ColumnData, SortingData } from '../types';
5
+
6
+ interface Props {
7
+ item: ColumnData
8
+ url: string
9
+ params: any
10
+ sorting?: SortingData
11
+ }
12
+
13
+ const Sort = ({ item, url, params, sorting }: Props): JSX.Element => {
14
+ const isCurrent = params.sort === item.slug || (params.sort === undefined && sorting?.slug === item.slug);
15
+
16
+ const order = params.order ?? (
17
+ isCurrent ? sorting?.order : (item.type === 'az' ? 'asc' : 'desc')
18
+ );
19
+
20
+ const sort = parseUrl({ page: 1, sort: item.slug, order: (
21
+ order === 'desc' ? 'asc' : 'desc'
22
+ ) });
23
+
24
+ return (
25
+ <LinkHeader to={ `${ url }${ sort }` }>
26
+ { item.name }
27
+
28
+ { isCurrent && (order == 'desc' ? <BiSortDown /> : <BiSortUp />) }
29
+ </LinkHeader>
30
+ );
31
+ };
32
+
33
+ export default Sort;
@@ -0,0 +1,48 @@
1
+ import styled, { css } from 'styled-components';
2
+ import { Link } from 'react-router-dom';
3
+
4
+ export const Container = styled.thead`
5
+ background: ${ props => props.theme.background.neutral };
6
+
7
+ & > tr > td:first-of-type > div {
8
+ justify-content: left;
9
+ }
10
+ `;
11
+
12
+ interface TdData {
13
+ $width?: number
14
+ }
15
+
16
+ export const Td = styled.td<TdData>`
17
+ ${ props => props.$width && css<TdData>`
18
+ width: ${ props => props.$width }%;
19
+ ` }
20
+ `;
21
+
22
+ export const Column = styled.div`
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: center;
26
+ padding: 8px 16px;
27
+ color: ${ props => props.theme.font.faded };
28
+ font-weight: 700;
29
+ text-transform: uppercase;
30
+ font-size: ${ props => props.theme.size.xs };
31
+ `;
32
+
33
+ export const Text = styled.span`
34
+ cursor: default;
35
+ `;
36
+
37
+ export const LinkHeader = styled(Link)`
38
+ display: flex;
39
+ align-items: center;
40
+ gap: 5px;
41
+ color: ${ props => props.theme.font.faded };
42
+ transition: all 0.3s ease;
43
+
44
+ &:hover {
45
+ opacity: .7;
46
+ text-decoration: none;
47
+ }
48
+ `;
@@ -0,0 +1,34 @@
1
+ import { TFunction } from 'i18next';
2
+ import Pagination from '../Pagination/Pagination';
3
+ import { ContainerPaginate } from './styles';
4
+ import { PaginationData } from '@autobusal/providers/types/pagination';
5
+
6
+ interface Props {
7
+ data?: PaginationData<unknown>
8
+ colLength: number
9
+ t: TFunction<'common'>
10
+ }
11
+
12
+ const Paginate = ({ data, colLength, t }: Props): (JSX.Element | null) => {
13
+ if (data === undefined) {
14
+ return null;
15
+ }
16
+
17
+ if (data.last_page < 2) {
18
+ return null;
19
+ }
20
+
21
+ return (
22
+ <tfoot>
23
+ <tr>
24
+ <td colSpan={ colLength }>
25
+ <ContainerPaginate>
26
+ <Pagination pages={ data } t={ t } />
27
+ </ContainerPaginate>
28
+ </td>
29
+ </tr>
30
+ </tfoot>
31
+ );
32
+ };
33
+
34
+ export default Paginate;
package/Table/Row.tsx ADDED
@@ -0,0 +1,22 @@
1
+ import { Td } from './styles';
2
+
3
+ interface Props {
4
+ id?: number
5
+ data: any[]
6
+ }
7
+
8
+ const Row = ({ id, data }: Props): JSX.Element[] => {
9
+ if (id === undefined) {
10
+ return [];
11
+ }
12
+
13
+ const columns = data.map((item, index) => (
14
+ <Td key={ index }>
15
+ { item }
16
+ </Td>
17
+ ));
18
+
19
+ return columns;
20
+ };
21
+
22
+ export default Row;
@@ -0,0 +1,22 @@
1
+ import { TFunction } from 'i18next';
2
+ import { Inline } from '../../Loading/Loading';
3
+ import { ContainerLoading } from './styles';
4
+
5
+ interface Props {
6
+ length: number
7
+ t: TFunction<'common'>
8
+ }
9
+
10
+ const Loading = ({ length, t }: Props): JSX.Element => (
11
+ <tbody>
12
+ <tr>
13
+ <td colSpan={ length }>
14
+ <ContainerLoading>
15
+ <Inline text={ t('table.loading_data', { ns: 'common' }) } />
16
+ </ContainerLoading>
17
+ </td>
18
+ </tr>
19
+ </tbody>
20
+ );
21
+
22
+ export default Loading;
@@ -0,0 +1,22 @@
1
+ import { TFunction } from 'i18next';
2
+ import { RiEmotionUnhappyLine } from 'react-icons/ri';
3
+ import { ContainerNotFound } from './styles';
4
+
5
+ interface Props {
6
+ length: number
7
+ t: TFunction<'common'>
8
+ }
9
+
10
+ const NotFound = ({ length, t }: Props): JSX.Element => (
11
+ <tbody>
12
+ <tr>
13
+ <td colSpan={ length }>
14
+ <ContainerNotFound>
15
+ <RiEmotionUnhappyLine />{ t('table.no_data', { ns: 'common' }) }
16
+ </ContainerNotFound>
17
+ </td>
18
+ </tr>
19
+ </tbody>
20
+ );
21
+
22
+ export default NotFound;
@@ -0,0 +1,63 @@
1
+ import { TFunction } from 'i18next';
2
+ import { NavigateFunction } from 'react-router-dom';
3
+ import Loading from './Loading';
4
+ import NotFound from './NotFound';
5
+ import Actions from '../Actions/Actions';
6
+ import { Tbody, Tr } from './styles';
7
+
8
+ interface Props {
9
+ url: string
10
+ urlWith?: string
11
+ data?: JSX.Element[]
12
+ loading: boolean
13
+ fetching: boolean
14
+ colLength: number
15
+ t: TFunction<'common'>
16
+ actions?: string[]
17
+ handlers?: any
18
+ navigate: NavigateFunction
19
+ }
20
+
21
+ const Rows = ({ url, urlWith, data, loading, fetching, colLength, t, actions, handlers, navigate }: Props): JSX.Element => {
22
+ if (loading) {
23
+ return <Loading length={ colLength } t={ t } />;
24
+ }
25
+
26
+ if (data?.length === 0) {
27
+ return <NotFound length={ colLength } t={ t } />;
28
+ }
29
+
30
+ const isViewable = actions?.includes('view');
31
+
32
+ const onClick = (id: number): void => {
33
+ if (isViewable) {
34
+ navigate(`${ url }/manage/${ id }${ urlWith ? `?${ urlWith }` : '' }`);
35
+ }
36
+ };
37
+
38
+ const columns = data?.map((item, index) => (
39
+ <Tr key={ index } $viewable={ isViewable } onClick={ () => onClick(item.props.id) }>
40
+ { item }
41
+
42
+ { (actions !== undefined && actions.length > 0) && (
43
+ <Actions
44
+ id={ item.props.id }
45
+ url={ url }
46
+ urlWith={ urlWith }
47
+ available={ actions }
48
+ t={ t }
49
+ handlers={ handlers }
50
+ navigate={ navigate }
51
+ />
52
+ ) }
53
+ </Tr>
54
+ ));
55
+
56
+ return (
57
+ <Tbody $fetching={ fetching }>
58
+ { columns }
59
+ </Tbody>
60
+ );
61
+ };
62
+
63
+ export default Rows;
@@ -0,0 +1,37 @@
1
+ import styled, { css } from 'styled-components';
2
+
3
+ export const ContainerLoading = styled.div`
4
+ padding: 25px 0;
5
+ `;
6
+
7
+ export const ContainerNotFound = styled(ContainerLoading)`
8
+ display: flex;
9
+ justify-content: center;
10
+ align-items: center;
11
+ gap: 8px;
12
+ font-size: ${ props => props.theme.size.s };
13
+ color: ${ props => props.theme.font.faded };
14
+ `;
15
+
16
+ export const Tbody = styled.tbody<{ $fetching: boolean }>`
17
+ ${ props => props.$fetching && css`
18
+ opacity: .5;
19
+ ` }
20
+ `;
21
+
22
+ export const Tr = styled.tr<{ $viewable?: boolean }>`
23
+ ${ props => props.$viewable && css`
24
+ cursor: pointer;
25
+ ` }
26
+
27
+ text-align: center;
28
+
29
+ & > td:first-of-type {
30
+ text-align: left;
31
+ font-weight: 700;
32
+ }
33
+
34
+ &:hover {
35
+ background: ${ props => props.theme.background.neutral };
36
+ }
37
+ `;
@@ -0,0 +1,76 @@
1
+ import { TFunction } from 'i18next';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import Top from './Top/Top';
4
+ import Header from './Header/Header';
5
+ import Rows from './Rows/Rows';
6
+ import Paginate from './Paginate';
7
+ import { Container, Content, Inner, ContainerTable } from './styles';
8
+ import { PaginationData } from '@autobusal/providers/types/pagination';
9
+ import { ColumnData, SortingData } from './types';
10
+
11
+ interface Props {
12
+ url: string
13
+ urlWith?: string
14
+ columns: ColumnData[]
15
+ rows?: JSX.Element[]
16
+ pages?: PaginationData<any>
17
+ sorting?: SortingData
18
+ search?: string | null
19
+ loading: boolean
20
+ fetching: boolean
21
+ t: TFunction<'common'>
22
+ actions?: string[]
23
+ extra?: JSX.Element
24
+ handlers?: any
25
+ }
26
+
27
+ const Table = ({ url, urlWith, columns, rows, pages, sorting, search, loading, fetching, t, actions, extra, handlers }: Props): JSX.Element => {
28
+ const navigate = useNavigate();
29
+
30
+ const colLength = columns.length + 1;
31
+
32
+ return (
33
+ <Container className="box">
34
+ <Top
35
+ url={ url }
36
+ urlWith={ urlWith }
37
+ search={ search }
38
+ t={ t }
39
+ actions={ actions }
40
+ extra={ extra }
41
+ navigate={ navigate }
42
+ />
43
+
44
+ <Content>
45
+ <Inner>
46
+ <ContainerTable cellPadding={ 0 } cellSpacing={ 0 }>
47
+ <Header
48
+ url={ url }
49
+ data={ columns }
50
+ sorting={ sorting }
51
+ t={ t }
52
+ actions={ actions }
53
+ />
54
+
55
+ <Rows
56
+ url={ url }
57
+ urlWith={ urlWith }
58
+ data={ rows }
59
+ loading={ loading }
60
+ fetching={ fetching }
61
+ colLength={ colLength }
62
+ t={ t }
63
+ actions={ actions }
64
+ handlers={ handlers }
65
+ navigate={ navigate }
66
+ />
67
+
68
+ <Paginate data={ pages } colLength={ colLength } t={ t } />
69
+ </ContainerTable>
70
+ </Inner>
71
+ </Content>
72
+ </Container>
73
+ );
74
+ };
75
+
76
+ export default Table;
@@ -0,0 +1,36 @@
1
+ import { FormEvent, useState } from 'react';
2
+ import { NavigateFunction } from 'react-router-dom';
3
+ import { TFunction } from 'i18next';
4
+ import { parseUrl } from '../browseUrl';
5
+
6
+ interface Props {
7
+ value?: string | null
8
+ url: string
9
+ t: TFunction<'common'>
10
+ navigate: NavigateFunction
11
+ }
12
+
13
+ const Search = ({ value, url, t, navigate }: Props): JSX.Element => {
14
+ const [ q, setQ ] = useState<string>(String(value ?? ''));
15
+
16
+ const handleSubmit = (event: FormEvent<HTMLFormElement>): void => {
17
+ event.preventDefault();
18
+
19
+ const search = parseUrl({ page: 1, q });
20
+
21
+ navigate(`${ url }${ search }`);
22
+ }
23
+
24
+ return (
25
+ <form onSubmit={ handleSubmit }>
26
+ <input
27
+ type="text"
28
+ value={ q }
29
+ placeholder={ t('table.search', { ns: 'common' }) }
30
+ onChange={ (event) => setQ(event.target.value) }
31
+ />
32
+ </form>
33
+ );
34
+ };
35
+
36
+ export default Search;