Files
Travel-tracker/src/contexts/CitiesContext.jsx
Bram Prieshof e88269224c Added backend and refactored frond-end to support it.
* Removed unecesery home page
* Added PHP Api that provides auth and replaces the json-server for data storage
* Added support for alternate geocode-api
* Added registration  page
2025-05-27 00:42:00 +02:00

149 lines
3.3 KiB
JavaScript

import {
useEffect,
createContext,
useState,
useContext,
useReducer,
} from "react";
import axios from 'axios';
const CitiesContext = createContext();
const API_URL = import.meta.env.VITE_API_URL;
const initialState = {
cities: [],
isLoading: false,
currentCity: {},
error: "",
};
function reducer(state, action) {
switch (action.type) {
case "loading":
return { ...state, isLoading: true };
case "cities/loaded":
return { ...state, isLoading: false,cities: action.payload };
case "city/loaded":
return { ...state, currentCity: action.payload, isLoading: false };
case "cities/created":
return {
...state,
cities: [...state.cities, action.payload],
isLoading: false,
currentCity:action.payload
};
case "cities/deleted":
return {
...state,
isLoading: false,
cities: state.cities.filter((city) => city.id !== action.payload),
currentCity:{}
};
case "rejected":
return { ...state, isLoading: false, error: action.payload };
default:
throw new Error(`Action not supported`);
}
}
function CitiesProvider({ children }) {
const [state, dispatch] = useReducer(reducer,initialState);
const { cities, isLoading, currentCity } = state;
useEffect(function () {
async function fetchData() {
dispatch({ type: "loading" });
try {
const response = await axios.get(`${API_URL}/get_items`);
const res = await response.data;
dispatch({ type:"cities/loaded", payload: res });
} catch {
dispatch({
type: "rejected",
payload: "There was an error loading the cities",
});
}
}
fetchData();
}, []);
async function getCity(id) {
if(Number(id)===currentCity.id) return;
dispatch({ type: "loading" });
try {
const response = await axios.get(`${API_URL}/get_item?id=${id}`);
const res = await response.data.json();
dispatch({ type: "city/loaded", payload: res });
} catch {
dispatch({
type: "rejected",
payload: "There was an error loading the city",
});
}
}
async function createCity(newCity) {
dispatch({ type: "loading" });
try {
const response = await axios.post(
`${API_URL}/create_item`,
newCity,
{
headers: {
'Content-Type': 'application/json',
},
}
);
dispatch({ type: "cities/created", payload: response.data });
} catch (error) {
dispatch({
type: "rejected",
payload: error.response?.data?.message || 'There was an error loading the city',
});
}
}
async function deleteCity(id) {
dispatch({ type: "loading" });
try {
const response = await axios.delete(`${API_URL}/delete_item?id=${id}`, {
method: "DELETE",
});
dispatch({ type: "cities/deleted", payload: id });
} catch {
dispatch({
type: "rejected",
payload: "There was an error deleting the city",
});
}
}
return (
<CitiesContext.Provider
value={{
cities,
isLoading,
currentCity,
getCity,
createCity,
deleteCity,
}}
>
{children}
</CitiesContext.Provider>
);
}
function useCities() {
const context = useContext(CitiesContext);
return context;
}
export { CitiesProvider, useCities };