🚚 Remove business logic from Component instances
This commit is contained in:
@@ -35,44 +35,59 @@ export function BusinessDataProvider(props: { children: JSX.Element }) {
|
|||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
const passages = () => {
|
|
||||||
return store.passages;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getLinePassages = (lineId: string) => {
|
const getLinePassages = (lineId: string) => {
|
||||||
return store.passages[lineId];
|
return store.passages[lineId];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const passages = () => {
|
||||||
|
return store.passages;
|
||||||
|
}
|
||||||
|
|
||||||
|
const refreshPassages = async (stopId: number) => {
|
||||||
|
const httpOptions = { headers: { "Content-Type": "application/json" } };
|
||||||
|
console.log(`Fetching data for ${stopId}`);
|
||||||
|
const data = await fetch(`${serverUrl()}/stop/nextPassages/${stopId}`, httpOptions);
|
||||||
|
const response = await data.json();
|
||||||
|
addPassages(response.passages);
|
||||||
|
}
|
||||||
|
|
||||||
const addPassages = (passages) => {
|
const addPassages = (passages) => {
|
||||||
setStore((s) => {
|
setStore((s) => {
|
||||||
// console.log("s=", s);
|
|
||||||
setStore('passages', passages);
|
setStore('passages', passages);
|
||||||
// console.log("s=", s);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearPassages = () => {
|
const clearPassages = () => {
|
||||||
setStore((s) => {
|
setStore((s) => {
|
||||||
// TODO: Really need to set to undefined to reset ?
|
|
||||||
console.log("s=", s);
|
|
||||||
console.log("s.passages=", s.passages);
|
|
||||||
// setStore('passages', undefined);
|
|
||||||
// setStore('passages', {});
|
|
||||||
console.log("Object.keys(s.passages)=", Object.keys(s.passages));
|
|
||||||
for (const lineId of Object.keys(s.passages)) {
|
for (const lineId of Object.keys(s.passages)) {
|
||||||
console.log("lineId=", lineId);
|
|
||||||
setStore('passages', lineId, undefined);
|
setStore('passages', lineId, undefined);
|
||||||
}
|
}
|
||||||
console.log("s=", s);
|
|
||||||
});
|
});
|
||||||
// setStore('passages', undefined);
|
}
|
||||||
// setStore('passages', {});
|
|
||||||
// }
|
const getStop = (stopId: int) => {
|
||||||
console.log("passages=", store.passages);
|
return store.stops[stopId];
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchStopByName = async (name: string) => {
|
||||||
|
const data = await fetch(`${serverUrl()}/stop/?name=${name}`, {
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
const stops = await data.json();
|
||||||
|
|
||||||
|
const byIdStops = {};
|
||||||
|
for (const stop of stops) {
|
||||||
|
byIdStops[stop.id] = stop;
|
||||||
|
setStore('stops', stop.id, stop);
|
||||||
|
}
|
||||||
|
return byIdStops;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BusinessDataContext.Provider value={{ getLine, passages, getLinePassages, addPassages, clearPassages, serverUrl }}>
|
<BusinessDataContext.Provider value={{
|
||||||
|
getLine, getLinePassages, passages, refreshPassages, clearPassages,
|
||||||
|
getStop, searchStopByName
|
||||||
|
}}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</BusinessDataContext.Provider>
|
</BusinessDataContext.Provider>
|
||||||
);
|
);
|
||||||
|
@@ -16,13 +16,13 @@ export const PassagesDisplay: Component = () => {
|
|||||||
const maxPassagePerPanel = 5;
|
const maxPassagePerPanel = 5;
|
||||||
const syncPeriodMsec = 20 * 1000;
|
const syncPeriodMsec = 20 * 1000;
|
||||||
|
|
||||||
const { passages, getLinePassages, addPassages, clearPassages, serverUrl } = useContext(BusinessDataContext);
|
const { passages, getLine, getLinePassages, refreshPassages, clearPassages } = useContext(BusinessDataContext);
|
||||||
const { getDisplayedStop } = useContext(SearchContext);
|
|
||||||
|
// TODO: Use props instead
|
||||||
|
const { getDisplayedStops } = useContext(SearchContext);
|
||||||
|
|
||||||
const [panels, setPanels] = createStore([]);
|
|
||||||
const [displayedPanelId, setDisplayedPanelId] = createSignal<number>(0);
|
const [displayedPanelId, setDisplayedPanelId] = createSignal<number>(0);
|
||||||
|
const [panels, setPanels] = createStore([]);
|
||||||
let _lines = new Map();
|
|
||||||
|
|
||||||
const [dateNow] = createDateNow(1000);
|
const [dateNow] = createDateNow(1000);
|
||||||
|
|
||||||
@@ -37,61 +37,24 @@ export const PassagesDisplay: Component = () => {
|
|||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
console.log("######### onStopIdUpdate #########");
|
console.log("######### onStopIdUpdate #########");
|
||||||
// Track local.stopIp to force dependency.
|
// Track local.stopIp to force dependency.
|
||||||
console.log("getDisplayedStop=", getDisplayedStop());
|
console.log("getDisplayedStop=", getDisplayedStops());
|
||||||
clearPassages();
|
clearPassages();
|
||||||
});
|
});
|
||||||
|
|
||||||
createEffect(async () => {
|
createEffect(async () => {
|
||||||
console.log(`## OnPassageUpdate ${passages()} ##`);
|
console.log(`## OnPassageUpdate ${passages()} ##`);
|
||||||
/* console.log(passages()); */
|
const stops = getDisplayedStops();
|
||||||
await requestPassages();
|
if (stops.length > 0) {
|
||||||
|
refreshPassages(stops[0].id);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async function _fetchLine(lineId: string) {
|
|
||||||
if (!_lines.has(lineId)) {
|
|
||||||
const data = await fetch(`${serverUrl()}/line/${lineId}`, {
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
});
|
|
||||||
const line = await data.json();
|
|
||||||
_lines.set(line.id, line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function requestPassages() {
|
|
||||||
console.log("### requestPassages ###");
|
|
||||||
/* TODO: Manage several displays (one by stop) */
|
|
||||||
const stops = getDisplayedStop();
|
|
||||||
if (stops.length == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const stop = stops[0];
|
|
||||||
|
|
||||||
const httpOptions = { headers: { "Content-Type": "application/json" } };
|
|
||||||
if (stop !== undefined) {
|
|
||||||
const stopId = stop.id;
|
|
||||||
console.log(`Fetching data for ${stopId}`);
|
|
||||||
const url = `${serverUrl()}/stop/nextPassages/${stopId}`;
|
|
||||||
/* console.log(`url=${url}`); */
|
|
||||||
const data = await fetch(url, httpOptions);
|
|
||||||
const response = await data.json();
|
|
||||||
/* console.log(response); */
|
|
||||||
const byLineByDstPassages = response.passages;
|
|
||||||
/* console.log(byLineByDstPassages); */
|
|
||||||
const linePromises = [];
|
|
||||||
for (const lineId of Object.keys(byLineByDstPassages)) {
|
|
||||||
linePromises.push(_fetchLine(lineId));
|
|
||||||
}
|
|
||||||
await Promise.all(linePromises);
|
|
||||||
console.log("byLineByDstPassages=", byLineByDstPassages);
|
|
||||||
// console.log("before addPassages passages=", passages());
|
|
||||||
addPassages(byLineByDstPassages);
|
|
||||||
console.log("AFTER passages=", passages());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setInterval(
|
setInterval(
|
||||||
async () => {
|
async () => {
|
||||||
await requestPassages();
|
const stops = getDisplayedStops();
|
||||||
|
if (stops.length > 0) {
|
||||||
|
refreshPassages(stops[0].id);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
syncPeriodMsec
|
syncPeriodMsec
|
||||||
);
|
);
|
||||||
|
@@ -21,55 +21,42 @@ export const SearchContext = createContext<Store>();
|
|||||||
|
|
||||||
export function SearchProvider(props: { children: JSX.Element }) {
|
export function SearchProvider(props: { children: JSX.Element }) {
|
||||||
|
|
||||||
const [store, setStore] = createStore({stops: {}, markers: {}, displayedStop: []});
|
const [store, setStore] = createStore({ stops: {}, markers: {}, displayedStops: [] });
|
||||||
|
|
||||||
const getStops = () => {
|
const getDisplayedStops = () => {
|
||||||
return store.stops;
|
return store.displayedStops;
|
||||||
};
|
}
|
||||||
|
|
||||||
const setStops = (stops) => {
|
const setDisplayedStops = (stops: Array<Stop>) => {
|
||||||
setStore((s) => {
|
setStore((s) => {
|
||||||
setStore('stops', stops);
|
setStore('displayedStops', stops);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
const removeStops = (stopIds) => {
|
const removeStops = (stopIds: Array<number>) => {
|
||||||
batch(() => {
|
batch(() => {
|
||||||
for(const stopId of stopIds) {
|
for (const stopId of stopIds) {
|
||||||
setStore('stops', stopId, undefined);
|
setStore('stops', stopId, undefined);
|
||||||
setStore('markers', stopId, undefined);
|
setStore('markers', stopId, undefined);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
const getMarkers = () => {
|
const getMarkers = () => {
|
||||||
return store.markers;
|
return store.markers;
|
||||||
};
|
}
|
||||||
|
|
||||||
const addMarkers = (stopId, markers) => {
|
const addMarkers = (stopId: number, markers) => {
|
||||||
setStore('markers', stopId, markers);
|
setStore('markers', stopId, markers);
|
||||||
};
|
}
|
||||||
|
|
||||||
const setMarkers = (markers) => {
|
const setMarkers = (markers) => {
|
||||||
setStore('markers', markers);
|
setStore('markers', markers);
|
||||||
};
|
}
|
||||||
|
|
||||||
const getDisplayedStop = () => {
|
return (
|
||||||
/* console.log(store.displayedStop); */
|
<SearchContext.Provider value={{ getDisplayedStops, setDisplayedStops, removeStops, getMarkers, addMarkers, setMarkers }}>
|
||||||
return store.displayedStop;
|
{props.children}
|
||||||
};
|
</SearchContext.Provider>
|
||||||
const setDisplayedStop = (stop: Stop) => {
|
);
|
||||||
/* console.log(stop); */
|
|
||||||
setStore((s) => {
|
|
||||||
console.log("s.displayedStop=", s.displayedStop);
|
|
||||||
setStore('displayedStop', [stop]);
|
|
||||||
});
|
|
||||||
/* console.log(store.displayedStop); */
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SearchContext.Provider value={{addMarkers, getMarkers, setMarkers, getStops, removeStops, setStops, getDisplayedStop, setDisplayedStop}}>
|
|
||||||
{props.children}
|
|
||||||
</SearchContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@@ -94,7 +94,7 @@ const Map: Component = (props) => {
|
|||||||
|
|
||||||
const mapCenter = [48.853, 2.35];
|
const mapCenter = [48.853, 2.35];
|
||||||
|
|
||||||
const { addMarkers, getStops } = useContext(SearchContext);
|
const { addMarkers } = useContext(SearchContext);
|
||||||
|
|
||||||
let mapDiv: any;
|
let mapDiv: any;
|
||||||
let map = null;
|
let map = null;
|
||||||
@@ -147,40 +147,24 @@ const Map: Component = (props) => {
|
|||||||
|
|
||||||
export const StopsManager: Component = (props) => {
|
export const StopsManager: Component = (props) => {
|
||||||
|
|
||||||
const [minCharactersNb, setMinCharactersNb] = createSignal<int>(4);
|
export const StopsManager: Component = () => {
|
||||||
const [_inProgress, _setInProgress] = createSignal<bool>(false);
|
|
||||||
|
|
||||||
const { serverUrl } = useContext(BusinessDataContext);
|
const [minCharactersNb, setMinCharactersNb] = createSignal<number>(4);
|
||||||
const { getStops, removeStops, setStops, setDisplayedStop } = useContext(SearchContext);
|
const [inProgress, setInProgress] = createSignal<boolean>(false);
|
||||||
|
const [foundStops, setFoundStops] = createSignal<Array<number>>([]);
|
||||||
|
|
||||||
async function _fetchStopByName(name) {
|
const { getStop, searchStopByName } = useContext(BusinessDataContext);
|
||||||
const data = await fetch(`${serverUrl()}/stop/?name=${name}`, {
|
const { setDisplayedStops } = useContext(SearchContext);
|
||||||
headers: { 'Content-Type': 'application/json' }
|
|
||||||
});
|
|
||||||
const stops = await data.json();
|
|
||||||
const stopIds = stops.map((stop) => stop.id);
|
|
||||||
|
|
||||||
const stopIdsToRemove = Object.keys(getStops()).filter(stopId => !(stopId in stopIds));
|
const onStopNameInput = async (event) => {
|
||||||
|
|
||||||
const byIdStops = {};
|
|
||||||
for (const stop of stops) {
|
|
||||||
byIdStops[stop.id] = stop;
|
|
||||||
}
|
|
||||||
|
|
||||||
batch(() => {
|
|
||||||
removeStops(stopIdsToRemove);
|
|
||||||
setStops(byIdStops);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function _onStopNameInput(event) {
|
|
||||||
/* TODO: Add a tempo before fetching stop for giving time to user to finish his request */
|
/* TODO: Add a tempo before fetching stop for giving time to user to finish his request */
|
||||||
const stopName = event.target.value;
|
const stopName = event.target.value;
|
||||||
if (stopName.length >= minCharactersNb()) {
|
if (stopName.length >= minCharactersNb()) {
|
||||||
console.log(`Fetching data for ${stopName}`);
|
console.log(`Fetching data for ${stopName}`);
|
||||||
_setInProgress(true);
|
setInProgress(true);
|
||||||
await _fetchStopByName(stopName);
|
const stopsById = await searchStopByName(stopName);
|
||||||
_setInProgress(false);
|
setFoundStops(Object.values(stopsById));
|
||||||
|
setInProgress(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user