Files
Lovemap/app/hooks/useData.ts
T
2024-10-11 19:08:52 +02:00

154 lines
4.1 KiB
TypeScript

// ---------------------------------------------------------------------------------------------------------------------
//! Imports
// ---------------------------------------------------------------------------------------------------------------------
// -------------------------------------------------- React & Next -----------------------------------------------------
import { useEffect, useRef, useState } from 'react';
// ---------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------- Components ------------------------------------------------------
import { IconLayer, ScatterplotLayer } from 'deck.gl';
// ---------------------------------------------------------------------------------------------------------------------
// ------------------------------------------------- Assets & Styles ---------------------------------------------------
import { StringifiedPinIcon } from '@/assets/PinIcon';
import { getDataset } from '../request';
// ---------------------------------------------------------------------------------------------------------------------
export const useData = () => {
const deckRef = useRef(null);
const [canUseGeolocation, setCanUseGeolocation] = useState<boolean>(false);
const [geoError, setGeoError] = useState<string | null>(null);
const [userLocation, setUserLocation] = useState<{ [key: string]: number }>(
{}
);
const [source, setSource] = useState([]);
const [layers, setLayers] = useState([]);
const [isAddLoveOpened, setIsAddLoveOpened] = useState<boolean>(false);
const [isLoading, setIsLoading] = useState<boolean>(false);
const [addLoveMessage, setAddLoveMessage] = useState<string | null>(null);
const [viewState, setViewState] = useState<any>({
longitude: 2.209666999999996,
latitude: 46.232192999999995,
zoom: 5,
});
useEffect(() => {
if ('geolocation' in navigator == false) {
setCanUseGeolocation(false);
return;
}
setCanUseGeolocation(true);
navigator.geolocation.getCurrentPosition(
(position) => {
setViewState((prev) => ({
...prev,
latitude: position.coords.latitude,
longitude: position.coords.longitude,
zoom: 17,
}));
setUserLocation({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
});
},
(error) => {
console.warn(error.message);
if (error.PERMISSION_DENIED) {
setGeoError('permission_denied');
}
},
{
maximumAge: 0,
timeout: 5000,
enableHighAccuracy: true,
}
);
(async () => {
const dataset = await getDataset();
const formattedDataset = dataset.map((point) => {
const properties = { ...point };
delete properties.geopoint;
return {
type: 'Feature',
geometry: point.geopoint,
properties: properties,
};
});
setSource(formattedDataset);
})();
}, []);
useEffect(() => {
const newLayers = [];
if (userLocation) {
const userLayer = new ScatterplotLayer({
id: 'userLayer',
data: [userLocation],
stroked: true,
getPosition: (d) => [d.longitude, d.latitude],
getRadius: 10,
getFillColor: [217, 66, 83],
getLineColor: [217, 66, 83, 175],
getLineWidth: 5,
radiusUnits: 'pixels',
lineWidthUnits: 'pixels',
pickable: false,
});
newLayers.push(userLayer);
}
const datasetLayer = new IconLayer({
id: 'lovePoints',
data: source,
iconAtlas: `data:image/svg+xml;charset=utf-8,${encodeURIComponent(
StringifiedPinIcon()
)}`,
iconMapping: {
marker: {
x: 0,
y: 0,
width: 100,
height: 100,
anchorY: 100,
},
},
getIcon: (d) => 'marker',
getSize: (d) => 35,
getPosition: (d) => d.geometry.coordinates,
billboard: true,
pickable: true,
});
newLayers.push(datasetLayer);
setLayers(newLayers);
}, [userLocation, source, isAddLoveOpened]);
return {
deckRef,
viewState,
setViewState,
geoError,
layers,
canUseGeolocation,
isAddLoveOpened,
setIsAddLoveOpened,
isLoading,
setIsLoading,
addLoveMessage,
setAddLoveMessage,
};
};