@autobusal/operator-routes 1.0.2 → 1.0.4
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/Transiting/Countries.tsx +42 -0
- package/Transiting/Manage.tsx +93 -0
- package/Transiting/services.ts +52 -0
- package/Transiting/styles.ts +28 -0
- package/Transiting/utilities.ts +11 -0
- package/Unavailable/Browse.tsx +72 -0
- package/Unavailable/Manage.tsx +91 -0
- package/Unavailable/services.ts +72 -0
- package/index.ts +7 -1
- package/package.json +1 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { TFunction } from 'i18next';
|
|
2
|
+
import { BiTrash } from 'react-icons/bi';
|
|
3
|
+
import { Container, Item, ButtonDelete } from './styles';
|
|
4
|
+
import { TransitingData } from '@autobusal/providers/types/routes';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
transiting: TransitingData[]
|
|
8
|
+
t: TFunction<'normal'>
|
|
9
|
+
onDelete: (id: number) => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const Countries = ({ transiting, t, onDelete }: Props): JSX.Element => {
|
|
13
|
+
if (transiting.length == 0) {
|
|
14
|
+
return (
|
|
15
|
+
<>-</>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const onDeleteConfirm = (id: number): void => {
|
|
20
|
+
if (window.confirm(t('private.transiting_manage.confirm'))) {
|
|
21
|
+
onDelete(id);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const items = transiting.map(item => (
|
|
26
|
+
<Item key={ item.id }>
|
|
27
|
+
{ item.country.name }
|
|
28
|
+
|
|
29
|
+
<ButtonDelete type="button" onClick={ () => onDeleteConfirm(item.country.id) }>
|
|
30
|
+
<BiTrash />
|
|
31
|
+
</ButtonDelete>
|
|
32
|
+
</Item>
|
|
33
|
+
));
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Container>
|
|
37
|
+
{ items }
|
|
38
|
+
</Container>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default Countries;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { TFunction } from 'i18next';
|
|
2
|
+
import { useParams, Navigate } from 'react-router-dom';
|
|
3
|
+
import { Meta, BackWithTitle, Viewer, Box } from '@autobusal/common';
|
|
4
|
+
import { usePage, useCountries } from '@autobusal/hooks';
|
|
5
|
+
import { success } from '@autobusal/utilities';
|
|
6
|
+
import Countries from './Countries';
|
|
7
|
+
import { filterCountries } from './utilities';
|
|
8
|
+
import { TransitingData } from '@autobusal/providers/types/routes';
|
|
9
|
+
import { GetTransiting, PostTransiting, DeleteTransiting } from './services';
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
url: string
|
|
13
|
+
t: TFunction<'common'>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const Manage = ({ url, t }: Props): JSX.Element => {
|
|
17
|
+
const params = useParams();
|
|
18
|
+
|
|
19
|
+
const id = Number(params.id);
|
|
20
|
+
|
|
21
|
+
url = url.replace('[id]', String(id));
|
|
22
|
+
|
|
23
|
+
usePage('routes');
|
|
24
|
+
|
|
25
|
+
const { data: CountriesData, isLoading } = useCountries('available');
|
|
26
|
+
|
|
27
|
+
const { data, refetch } = GetTransiting(id);
|
|
28
|
+
|
|
29
|
+
const { mutate: Update, isPending: isPendingSave } = PostTransiting(id);
|
|
30
|
+
|
|
31
|
+
const { mutate: Delete, isPending: isPendingDelete } = DeleteTransiting(id);
|
|
32
|
+
|
|
33
|
+
if (id === 0) {
|
|
34
|
+
return <Navigate to={ url } />;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (isLoading) {
|
|
38
|
+
return <Box />;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const onSave = (data: TransitingData): void => {
|
|
42
|
+
Update(data, {
|
|
43
|
+
onSuccess: () => {
|
|
44
|
+
success(t('transiting_manage.messages.saved', { ns: 'common' }));
|
|
45
|
+
|
|
46
|
+
refetch();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const onDelete = (id: number): void => {
|
|
52
|
+
Delete(id, {
|
|
53
|
+
onSuccess: () => {
|
|
54
|
+
success(t('transiting_manage.messages.deleted', { ns: 'common' }));
|
|
55
|
+
|
|
56
|
+
refetch();
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const title = t('transiting_manage.title', { name: data?.name, ns: 'common' });
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<Meta title={ title }>
|
|
65
|
+
<BackWithTitle title={ title } to={ url } t={ t } />
|
|
66
|
+
|
|
67
|
+
<Viewer
|
|
68
|
+
id={ id }
|
|
69
|
+
data={ [{
|
|
70
|
+
label: t('transiting_manage.transiting', { ns: 'common' }),
|
|
71
|
+
type: 'component',
|
|
72
|
+
name: 'transiting',
|
|
73
|
+
value: <Countries transiting={ data?.transiting ?? [] } t={ t } onDelete={ onDelete } />
|
|
74
|
+
}, {}, {
|
|
75
|
+
label: t('transiting_manage.countries', { ns: 'common' }),
|
|
76
|
+
name: 'country_id',
|
|
77
|
+
type: 'select',
|
|
78
|
+
values: filterCountries(data?.transiting ?? [], CountriesData),
|
|
79
|
+
value: 0,
|
|
80
|
+
rules: 'required|min:1'
|
|
81
|
+
}] }
|
|
82
|
+
pending={ isPendingSave || isPendingDelete }
|
|
83
|
+
t={ t }
|
|
84
|
+
actions={ [
|
|
85
|
+
'add'
|
|
86
|
+
]}
|
|
87
|
+
onSave={ onSave }
|
|
88
|
+
/>
|
|
89
|
+
</Meta>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export default Manage;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { UseMutationResult, UseSuspenseQueryResult, useMutation, useSuspenseQuery } from '@tanstack/react-query';
|
|
2
|
+
import { apiClient } from '@autobusal/providers';
|
|
3
|
+
import { RouteData, TransitingData } from '@autobusal/providers/types/routes';
|
|
4
|
+
|
|
5
|
+
export const GetTransiting = (id: number): UseSuspenseQueryResult<RouteData> => (
|
|
6
|
+
useSuspenseQuery({
|
|
7
|
+
queryKey: ['operator-transiting', { id }],
|
|
8
|
+
queryFn: async () => (
|
|
9
|
+
await apiClient
|
|
10
|
+
.get('/api/transiting/operator/browse', {
|
|
11
|
+
params: { id }
|
|
12
|
+
})
|
|
13
|
+
.then(response => (
|
|
14
|
+
response.data
|
|
15
|
+
))
|
|
16
|
+
)
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const PostTransiting = (id: number): UseMutationResult<void, Error, TransitingData, unknown> => (
|
|
21
|
+
useMutation({
|
|
22
|
+
mutationKey: ['operator-transiting-save', { id }],
|
|
23
|
+
mutationFn: async (data: TransitingData) => (
|
|
24
|
+
await apiClient
|
|
25
|
+
.post('/api/transiting/operator/update', {
|
|
26
|
+
...data,
|
|
27
|
+
id
|
|
28
|
+
})
|
|
29
|
+
.then(response => (
|
|
30
|
+
response.data
|
|
31
|
+
))
|
|
32
|
+
)
|
|
33
|
+
})
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
export const DeleteTransiting = (id: number): UseMutationResult<void, Error, number, unknown> => (
|
|
37
|
+
useMutation({
|
|
38
|
+
mutationKey: ['operator-transiting-delete'],
|
|
39
|
+
mutationFn: async (countryId: number) => (
|
|
40
|
+
await apiClient
|
|
41
|
+
.delete('/api/transiting/operator/delete', {
|
|
42
|
+
params: {
|
|
43
|
+
id,
|
|
44
|
+
country_id: countryId
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
.then(response => (
|
|
48
|
+
response.data
|
|
49
|
+
))
|
|
50
|
+
)
|
|
51
|
+
})
|
|
52
|
+
);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
export const Container = styled.div`
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
gap: 5px;
|
|
7
|
+
`;
|
|
8
|
+
|
|
9
|
+
export const Item = styled.div`
|
|
10
|
+
display: flex;
|
|
11
|
+
justify-content: space-between;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: 10px;
|
|
14
|
+
padding: 7px 10px;
|
|
15
|
+
font-weight: 700;
|
|
16
|
+
border: 1px solid ${ props => props.theme.background.neutral };
|
|
17
|
+
border-radius: ${ props => props.theme.borderRadius };
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
export const ButtonDelete = styled.button`
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
width: 24px;
|
|
25
|
+
height: 24px;
|
|
26
|
+
color: ${ props => props.theme.font.error };
|
|
27
|
+
font-size: ${ props => props.theme.size.l };
|
|
28
|
+
`;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CountryData } from '@autobusal/providers/types/locations';
|
|
2
|
+
import { DropdownData } from '@autobusal/providers/types/other';
|
|
3
|
+
import { TransitingData } from '@autobusal/providers/types/routes';
|
|
4
|
+
|
|
5
|
+
export const filterCountries = (transiting: TransitingData[], countries?: CountryData[]): DropdownData[] => {
|
|
6
|
+
const ids = transiting.map(item => item.country.id);
|
|
7
|
+
|
|
8
|
+
const available = countries?.filter(item => !ids.includes(item.id));
|
|
9
|
+
|
|
10
|
+
return available ?? [];
|
|
11
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { TFunction } from 'i18next';
|
|
2
|
+
import { useParams, Navigate } from 'react-router-dom';
|
|
3
|
+
import { Meta, BackWithTitle, Table, Row } from '@autobusal/common';
|
|
4
|
+
import { usePage } from '@autobusal/hooks';
|
|
5
|
+
import { GetUnavailableDates, DeleteUnavailable } from './services';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
url: string
|
|
9
|
+
t: TFunction<'common'>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const Browse = ({ url, t }: Props): JSX.Element => {
|
|
13
|
+
const params = useParams();
|
|
14
|
+
|
|
15
|
+
const id = Number(params.id);
|
|
16
|
+
|
|
17
|
+
url = url.replace('[id]', String(id));
|
|
18
|
+
|
|
19
|
+
usePage('routes');
|
|
20
|
+
|
|
21
|
+
const { data, isLoading, isFetching, refetch } = GetUnavailableDates(id);
|
|
22
|
+
|
|
23
|
+
const { mutate: Delete } = DeleteUnavailable(id);
|
|
24
|
+
|
|
25
|
+
if (id === 0) {
|
|
26
|
+
return <Navigate to={ url } />;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const onDelete = (id: number): void => {
|
|
30
|
+
Delete(id, {
|
|
31
|
+
onSuccess: () => refetch()
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const rows = data?.unavailable.map(item => (
|
|
36
|
+
<Row
|
|
37
|
+
key={ item.id }
|
|
38
|
+
id={ item.id }
|
|
39
|
+
data={ [
|
|
40
|
+
`${ item.start_inactive } - ${ item.end_inactive }`
|
|
41
|
+
] }
|
|
42
|
+
/>
|
|
43
|
+
));
|
|
44
|
+
|
|
45
|
+
const title = t('unavailable.browse.title', { name: data?.name, ns: 'common' });
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Meta title={ title }>
|
|
49
|
+
<BackWithTitle title={ title } to={ url } t={ t } />
|
|
50
|
+
|
|
51
|
+
<Table
|
|
52
|
+
url={ `/operator/routes/unavailable/${ id }` }
|
|
53
|
+
columns={ [{
|
|
54
|
+
name: t('unavailable.browse.date', { ns: 'common' }),
|
|
55
|
+
width: 90
|
|
56
|
+
}] }
|
|
57
|
+
rows={ rows }
|
|
58
|
+
loading={ isLoading }
|
|
59
|
+
fetching={ isFetching }
|
|
60
|
+
t={ t }
|
|
61
|
+
actions={ [
|
|
62
|
+
'create', 'view', 'delete'
|
|
63
|
+
] }
|
|
64
|
+
handlers={ {
|
|
65
|
+
delete: onDelete
|
|
66
|
+
} }
|
|
67
|
+
/>
|
|
68
|
+
</Meta>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default Browse;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { TFunction } from 'i18next';
|
|
2
|
+
import { useParams, Navigate, useNavigate } from 'react-router-dom';
|
|
3
|
+
import { Meta, BackWithTitle, Viewer } from '@autobusal/common';
|
|
4
|
+
import { usePage } from '@autobusal/hooks';
|
|
5
|
+
import { success } from '@autobusal/utilities';
|
|
6
|
+
import { UnavailableData } from '@autobusal/providers/types/routes';
|
|
7
|
+
import { GetUnavailable, PostUnavailable, DeleteUnavailable } from './services';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
url: string
|
|
11
|
+
t: TFunction<'common'>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const Manage = ({ url, t }: Props): JSX.Element => {
|
|
15
|
+
const params = useParams();
|
|
16
|
+
|
|
17
|
+
const id = Number(params.id);
|
|
18
|
+
const routeId = Number(params.route_id);
|
|
19
|
+
|
|
20
|
+
url = url.replace('[routeId]', String(routeId));
|
|
21
|
+
|
|
22
|
+
usePage('routes');
|
|
23
|
+
|
|
24
|
+
const navigate = useNavigate();
|
|
25
|
+
|
|
26
|
+
const { data } = GetUnavailable(routeId, id);
|
|
27
|
+
|
|
28
|
+
const { mutate: Update, isPending: isPendingSave } = PostUnavailable(routeId, id);
|
|
29
|
+
|
|
30
|
+
const { mutate: Delete, isPending: isPendingDelete } = DeleteUnavailable(routeId);
|
|
31
|
+
|
|
32
|
+
if (routeId === 0) {
|
|
33
|
+
return <Navigate to={ url } />;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const onSave = (data: UnavailableData): void => {
|
|
37
|
+
Update(data, {
|
|
38
|
+
onSuccess: () => {
|
|
39
|
+
success(t('unavailable.manage.messages.saved', { ns: 'common' }));
|
|
40
|
+
|
|
41
|
+
navigate(url);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const onDelete = (): void => {
|
|
47
|
+
Delete(id, {
|
|
48
|
+
onSuccess: () => {
|
|
49
|
+
success(t('unavailable.manage.messages.deleted', { ns: 'common' }));
|
|
50
|
+
|
|
51
|
+
navigate(url);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const title = id > 0 ? t('unavailable.manage.title.update', { name: data?.name, ns: 'common' }) : t('unavailable.manage.title.new', { name: data?.name, ns: 'common' });
|
|
57
|
+
|
|
58
|
+
const unavailable = data?.unavailable !== undefined && data.unavailable.length > 0 ? data.unavailable[0] : undefined;
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<Meta title={ title }>
|
|
62
|
+
<BackWithTitle title={ title } to={ url } t={ t } />
|
|
63
|
+
|
|
64
|
+
<Viewer
|
|
65
|
+
id={ id }
|
|
66
|
+
data={ [{
|
|
67
|
+
label: t('unavailable.manage.start_inactive', { ns: 'common' }),
|
|
68
|
+
name: 'start_inactive',
|
|
69
|
+
type: 'picker',
|
|
70
|
+
value: unavailable?.start_inactive,
|
|
71
|
+
rules: 'required'
|
|
72
|
+
}, {
|
|
73
|
+
label: t('unavailable.manage.end_inactive', { ns: 'common' }),
|
|
74
|
+
name: 'end_inactive',
|
|
75
|
+
type: 'picker',
|
|
76
|
+
value: unavailable?.end_inactive,
|
|
77
|
+
rules: 'required'
|
|
78
|
+
}] }
|
|
79
|
+
pending={ isPendingSave || isPendingDelete }
|
|
80
|
+
t={ t }
|
|
81
|
+
actions={ [
|
|
82
|
+
'save', 'delete'
|
|
83
|
+
]}
|
|
84
|
+
onSave={ onSave }
|
|
85
|
+
onDelete={ onDelete }
|
|
86
|
+
/>
|
|
87
|
+
</Meta>
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export default Manage;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { UseMutationResult, UseQueryResult, UseSuspenseQueryResult, useMutation, useQuery, useSuspenseQuery } from '@tanstack/react-query';
|
|
2
|
+
import { apiClient } from '@autobusal/providers';
|
|
3
|
+
import { RouteData } from '@autobusal/providers/types/routes';
|
|
4
|
+
import { UnavailableData } from '@autobusal/providers/types/routes';
|
|
5
|
+
|
|
6
|
+
export const GetUnavailableDates = (id: number): UseQueryResult<RouteData> => (
|
|
7
|
+
useQuery({
|
|
8
|
+
queryKey: ['operators-unavailable', { id }],
|
|
9
|
+
queryFn: async () => (
|
|
10
|
+
await apiClient
|
|
11
|
+
.get('/api/unavailable/operator/browse', {
|
|
12
|
+
params: { id }
|
|
13
|
+
})
|
|
14
|
+
.then(response => (
|
|
15
|
+
response.data
|
|
16
|
+
))
|
|
17
|
+
)
|
|
18
|
+
})
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export const GetUnavailable = (routeId: number, id: number): UseSuspenseQueryResult<RouteData> => (
|
|
22
|
+
useSuspenseQuery({
|
|
23
|
+
queryKey: ['operator-unavailable-manage', { routeId, id }],
|
|
24
|
+
queryFn: async () => (
|
|
25
|
+
await apiClient
|
|
26
|
+
.get('/api/unavailable/operator/get', {
|
|
27
|
+
params: {
|
|
28
|
+
route_id: routeId,
|
|
29
|
+
id
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
.then(response => (
|
|
33
|
+
response.data
|
|
34
|
+
))
|
|
35
|
+
)
|
|
36
|
+
})
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
export const PostUnavailable = (routeId: number, id: number): UseMutationResult<void, Error, UnavailableData, unknown> => (
|
|
40
|
+
useMutation({
|
|
41
|
+
mutationKey: ['unavailable-operator-save', { routeId, id }],
|
|
42
|
+
mutationFn: async (data: UnavailableData) => (
|
|
43
|
+
await apiClient
|
|
44
|
+
.post('/api/unavailable/operator/update', {
|
|
45
|
+
...data,
|
|
46
|
+
route_id: routeId,
|
|
47
|
+
id
|
|
48
|
+
})
|
|
49
|
+
.then(response => (
|
|
50
|
+
response.data
|
|
51
|
+
))
|
|
52
|
+
)
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
export const DeleteUnavailable = (routeId: number): UseMutationResult<void, Error, number, unknown> => (
|
|
57
|
+
useMutation({
|
|
58
|
+
mutationKey: ['unavailable-operator-delete', { routeId }],
|
|
59
|
+
mutationFn: async (id: number) => (
|
|
60
|
+
await apiClient
|
|
61
|
+
.delete('/api/unavailable/operator/delete', {
|
|
62
|
+
params: {
|
|
63
|
+
route_id: routeId,
|
|
64
|
+
id
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
.then(response => (
|
|
68
|
+
response.data
|
|
69
|
+
))
|
|
70
|
+
)
|
|
71
|
+
})
|
|
72
|
+
);
|
package/index.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import Browse from './Browse';
|
|
2
2
|
import Manage from './Manage';
|
|
3
3
|
import SchedulesManage from './Schedule/Manage';
|
|
4
|
+
import TransitingManage from './Transiting/Manage';
|
|
5
|
+
import UnavailableBrowse from './Unavailable/Browse';
|
|
6
|
+
import UnavailableManage from './Unavailable/Manage';
|
|
4
7
|
|
|
5
8
|
export {
|
|
6
9
|
Browse,
|
|
7
10
|
Manage,
|
|
8
|
-
SchedulesManage
|
|
11
|
+
SchedulesManage,
|
|
12
|
+
TransitingManage,
|
|
13
|
+
UnavailableBrowse,
|
|
14
|
+
UnavailableManage
|
|
9
15
|
};
|