@autobusal/common 1.3.2 → 1.4.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.
- package/Drive/Drive.tsx +64 -0
- package/Drive/images/marker-icon.png +0 -0
- package/Drive/images/marker-shadow.png +0 -0
- package/Drive/services.ts +24 -0
- package/Drive/styles.ts +34 -0
- package/Drive/types.ts +11 -0
- package/Drive/utilities.ts +48 -0
- package/Viewer/services.ts +1 -1
- package/index.ts +2 -0
- package/package.json +1 -1
package/Drive/Drive.tsx
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { TFunction } from 'i18next';
|
|
2
|
+
import { MapContainer, TileLayer, Marker, Popup, Polyline } from 'react-leaflet';
|
|
3
|
+
import { getCoordinates, getPosition, autobusMarker } from './utilities';
|
|
4
|
+
import { Container, Loading, Disclaimer } from './styles';
|
|
5
|
+
import { LocationData } from '@autobusal/providers/types/locations';
|
|
6
|
+
import { useGetDriveData } from './services';
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
locations: LocationData[]
|
|
10
|
+
t: TFunction<'common'>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const Drive = ({ locations, t }: Props): JSX.Element => {
|
|
14
|
+
const coordinates = getCoordinates(locations);
|
|
15
|
+
|
|
16
|
+
const { data: MapData, isLoading } = useGetDriveData(coordinates);
|
|
17
|
+
|
|
18
|
+
if (isLoading) {
|
|
19
|
+
return (
|
|
20
|
+
<Container>
|
|
21
|
+
<Loading className="leaflet-container">{ t('drive.loading', { ns: 'common' }) }</Loading>
|
|
22
|
+
</Container>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// we get the coordinates for the roads to paint
|
|
27
|
+
const geometryData = MapData?.features[0].geometry.coordinates;
|
|
28
|
+
|
|
29
|
+
// we paint the drive lines
|
|
30
|
+
const lines = geometryData?.map((item, index) => {
|
|
31
|
+
const nextLocation = geometryData[index + 1] ?? item;
|
|
32
|
+
|
|
33
|
+
const from = getPosition(item, 'coordinates');
|
|
34
|
+
const to = getPosition(nextLocation, 'coordinates');
|
|
35
|
+
|
|
36
|
+
return <Polyline key={ index } positions={ [from, to] } color="#3388FF" />;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// we add the stop markers
|
|
40
|
+
const markers = locations.map((item, index) => (
|
|
41
|
+
<Marker key={ index } position={ getPosition(item.stop?.location) } icon={ autobusMarker }>
|
|
42
|
+
<Popup>
|
|
43
|
+
<strong>{ item.city.name }</strong> <br />
|
|
44
|
+
{ item.stop?.name }, { item.departure }
|
|
45
|
+
</Popup>
|
|
46
|
+
</Marker>
|
|
47
|
+
));
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Container>
|
|
51
|
+
<MapContainer center={ getPosition(locations[0].stop?.location) } minZoom={ 6 } maxZoom={ 13 } zoom={ 6 } scrollWheelZoom={ true }>
|
|
52
|
+
<TileLayer attribution="© <a href='http://osm.org/copyright'>OpenStreetMap</a> contributors" url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
|
|
53
|
+
|
|
54
|
+
{ markers }
|
|
55
|
+
|
|
56
|
+
{ lines }
|
|
57
|
+
</MapContainer>
|
|
58
|
+
|
|
59
|
+
<Disclaimer>{ t('drive.disclaimer', { ns: 'common' }) }</Disclaimer>
|
|
60
|
+
</Container>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export default Drive;
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useQuery, UseQueryResult } from '@tanstack/react-query';
|
|
2
|
+
import { apiClient } from '@autobusal/providers';
|
|
3
|
+
import { GeoJsonData } from './types';
|
|
4
|
+
|
|
5
|
+
export const useGetDriveData = (coordinates: number[][]): UseQueryResult<GeoJsonData> => (
|
|
6
|
+
useQuery({
|
|
7
|
+
queryKey: ['drive-data'],
|
|
8
|
+
queryFn: async () => (
|
|
9
|
+
await apiClient
|
|
10
|
+
.post('https://api.openrouteservice.org/v2/directions/driving-car/geojson', {
|
|
11
|
+
coordinates
|
|
12
|
+
}, {
|
|
13
|
+
headers: {
|
|
14
|
+
Authorization: import.meta.env.VITE_OPEN_ROUTE_SERVICE_KEY
|
|
15
|
+
},
|
|
16
|
+
withCredentials: false,
|
|
17
|
+
withXSRFToken: false
|
|
18
|
+
})
|
|
19
|
+
.then(response => (
|
|
20
|
+
response.data
|
|
21
|
+
))
|
|
22
|
+
)
|
|
23
|
+
})
|
|
24
|
+
);
|
package/Drive/styles.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
import 'leaflet/dist/leaflet.css';
|
|
3
|
+
|
|
4
|
+
export const Container = styled.div`
|
|
5
|
+
position: relative;
|
|
6
|
+
|
|
7
|
+
& > .leaflet-container {
|
|
8
|
+
width: 100%;
|
|
9
|
+
height: 100%;
|
|
10
|
+
}
|
|
11
|
+
`;
|
|
12
|
+
|
|
13
|
+
export const Loading = styled.div`
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
export const Disclaimer = styled.div`
|
|
20
|
+
position: absolute;
|
|
21
|
+
bottom: 20px;
|
|
22
|
+
left: 10px;
|
|
23
|
+
right: 10px;
|
|
24
|
+
z-index: 100000;
|
|
25
|
+
padding: 5px;
|
|
26
|
+
text-align: center;
|
|
27
|
+
font-size: ${ props => props.theme.size.xxs };
|
|
28
|
+
color: ${ props => props.theme.font.info };
|
|
29
|
+
background: ${ props => props.theme.menu.transparent };
|
|
30
|
+
border-radius: ${ props => props.theme.borderRadius };
|
|
31
|
+
box-shadow: ${ props => props.theme.boxShadow };
|
|
32
|
+
backdrop-filter: blur(15px);
|
|
33
|
+
-webkit-backdrop-filter: blur(15px);
|
|
34
|
+
`;
|
package/Drive/types.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import L, { LatLngExpression } from 'leaflet';
|
|
2
|
+
import markerIcon from './images/marker-icon.png';
|
|
3
|
+
import markerShadow from './images/marker-shadow.png';
|
|
4
|
+
import { LocationData } from '@autobusal/providers/types/locations';
|
|
5
|
+
|
|
6
|
+
const STOP_UNDEFINED = ['0', '0'];
|
|
7
|
+
|
|
8
|
+
export const getCoordinates = (locations: LocationData[]): number[][] => {
|
|
9
|
+
const coordinates: number[][] = [];
|
|
10
|
+
|
|
11
|
+
locations.forEach((item, index) => {
|
|
12
|
+
const nextLocation = locations[index + 1] ?? item;
|
|
13
|
+
|
|
14
|
+
const from = getPosition(item.stop?.location ?? STOP_UNDEFINED, 'coordinates') as number[];
|
|
15
|
+
const to = getPosition(nextLocation.stop?.location ?? STOP_UNDEFINED, 'coordinates') as number[];
|
|
16
|
+
|
|
17
|
+
// we push both coordinates
|
|
18
|
+
coordinates.push(from)
|
|
19
|
+
coordinates.push(to)
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return coordinates;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const getPosition = (position: string[] | undefined, type: string = 'normal'): LatLngExpression => {
|
|
26
|
+
if (position === undefined) {
|
|
27
|
+
return [0, 0];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// for the coordinates, we need to reverse the positions
|
|
31
|
+
if (type !== 'normal') {
|
|
32
|
+
position = position.slice().reverse();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return [
|
|
36
|
+
Number(position[0]),
|
|
37
|
+
Number(position[1])
|
|
38
|
+
];
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const autobusMarker = new L.Icon({
|
|
42
|
+
iconUrl: markerIcon,
|
|
43
|
+
iconSize: [25, 41], // icon size
|
|
44
|
+
iconAnchor: [12, 41], // point of the icon which will correspond to marker's location
|
|
45
|
+
popupAnchor: [1, -34], // point from which the popup should open relative to the iconAnchor
|
|
46
|
+
shadowUrl: markerShadow,
|
|
47
|
+
shadowSize: [41, 41] // shadow size
|
|
48
|
+
});
|
package/Viewer/services.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { UseMutationResult, useMutation } from '@tanstack/react-query';
|
|
2
2
|
import { apiClient } from '@autobusal/providers';
|
|
3
|
-
import { UploadData } from '@autobusal/providers/types';
|
|
3
|
+
import { UploadData } from '@autobusal/providers/types/settings';
|
|
4
4
|
|
|
5
5
|
export const useFileUpload = (): UseMutationResult<UploadData, Error, any, unknown> => (
|
|
6
6
|
useMutation({
|
package/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import ChooseSeat from './Seats/ChooseSeat';
|
|
|
12
12
|
import CompanyItem from './CompanyItem/CompanyItem';
|
|
13
13
|
import ContactInfo from './ContactInfo/ContactInfo';
|
|
14
14
|
import CookieNotification from './CookieNotification/CookieNotification';
|
|
15
|
+
import Drive from './Drive/Drive';
|
|
15
16
|
import File from './File/File';
|
|
16
17
|
import Gender from './Gender';
|
|
17
18
|
import { General, Inline, Box, BoxMiddle, GeneralFull } from './Loading/Loading';
|
|
@@ -48,6 +49,7 @@ export {
|
|
|
48
49
|
CompanyItem,
|
|
49
50
|
ContactInfo,
|
|
50
51
|
CookieNotification,
|
|
52
|
+
Drive,
|
|
51
53
|
File,
|
|
52
54
|
Gender,
|
|
53
55
|
General,
|