Skip to content

Commit 66edac3

Browse files
committed
feat: add http service
1 parent 211de0d commit 66edac3

File tree

5 files changed

+253
-200
lines changed

5 files changed

+253
-200
lines changed

frontend/src/components/Chart.tsx

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,7 @@ import FormControlLabel from '@mui/material/FormControlLabel';
1818
import FormControl from '@mui/material/FormControl';
1919
import GlobalState, { FuelType } from '../GlobalState';
2020
import { useRecoilState } from 'recoil';
21-
22-
export interface GsPoint {
23-
timestamp: string;
24-
price: number;
25-
}
26-
27-
export interface TimeSlot {
28-
x: string;
29-
e5: number;
30-
e10: number;
31-
diesel: number;
32-
}
21+
import { GsPoint, TimeSlot } from '../service/dtos';
3322

3423
export interface ChartProps {
3524
timeSlots: TimeSlot[];

frontend/src/components/GsMap.tsx

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,7 @@ import myStyle from './gsmap.module.scss';
2323
import { Icon, Style } from 'ol/style.js';
2424
import { useEffect } from 'react';
2525
import { nanoid } from 'nanoid';
26-
27-
export interface GsValue {
28-
location: string;
29-
e5: number;
30-
e10: number;
31-
diesel: number;
32-
date: Date;
33-
longitude: number;
34-
latitude: number;
35-
}
36-
37-
export interface CenterLocation {
38-
Longitude: number;
39-
Latitude: number;
40-
}
26+
import { CenterLocation, GsValue } from '../service/dtos';
4127

4228
interface InputProps {
4329
center: CenterLocation;

frontend/src/components/Main.tsx

Lines changed: 85 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -13,90 +13,17 @@
1313
import { Box, Tab, Tabs } from '@mui/material';
1414
import { useEffect, useState, SyntheticEvent } from 'react';
1515
import DataTable, { TableDataRow } from './DataTable';
16-
import GsMap, { GsValue } from './GsMap';
16+
import GsMap from './GsMap';
1717
import { useRecoilRefresher_UNSTABLE, useRecoilValue } from 'recoil';
18-
import GlobalState from '../GlobalState';
18+
import GlobalState, { UserDataState } from '../GlobalState';
1919
//import styles from './main.module.scss';
20-
import Chart, {TimeSlot} from './Chart';
20+
import Chart from './Chart';
2121
import { useNavigate } from 'react-router';
22+
import { GasPriceAvgs, GasStation, Notification, MyDataJson, TimeSlotResponse, GsValue, TimeSlot } from '../service/dtos';
23+
import { fetchGasStations, fetchPriceAvgs, fetchTimeSlots, fetchUserNotifications } from '../service/http-client';
2224

2325

24-
25-
interface GasPriceAvgs {
26-
Postcode: string
27-
County: string
28-
State: string
29-
CountyAvgDiesel: number
30-
CountyAvgE10: number
31-
CountyAvgE5: number
32-
StateAvgDiesel: number
33-
StateAvgE10: number
34-
StateAvgE5: number
35-
}
36-
37-
interface GasStation {
38-
StationName: string;
39-
Brand: string;
40-
Street: string;
41-
Place: string;
42-
HouseNumber: string;
43-
PostCode: string;
44-
Latitude: number;
45-
Longitude: number;
46-
PublicHolidayIdentifier: string;
47-
OtJson: string;
48-
FirstActive: Date;
49-
GasPrices: GasPrice[];
50-
}
51-
52-
interface GasPrice {
53-
E5: number;
54-
E10: number;
55-
Diesel: number;
56-
Date: string;
57-
Changed: number;
58-
}
59-
60-
interface Notification {
61-
Timestamp: Date;
62-
UserUuid: string;
63-
Title: string;
64-
Message: string;
65-
DataJson: string;
66-
}
67-
68-
interface MyDataJson {
69-
StationName: string;
70-
Brand: string;
71-
Street: string;
72-
Place: string;
73-
HouseNumber: string;
74-
PostCode: string;
75-
Latitude: number;
76-
Longitude: number;
77-
E5: number;
78-
E10: number;
79-
Diesel: number;
80-
Timestamp: string;
81-
}
82-
83-
interface TimeSlotResponse {
84-
ID: number;
85-
CreatedAt: Date;
86-
UpdatedAt: Date;
87-
DeletedAt: Date;
88-
GasStationNum: number;
89-
AvgE5: number;
90-
AvgE10: number;
91-
AvgDiesel: number;
92-
GsNumE5: number;
93-
GsNumE10: number;
94-
GsNumDiesel: number;
95-
StartDate: Date;
96-
CountyDataID: number;
97-
}
98-
99-
export default function Main() {
26+
export default function Main() {
10027
const navigate = useNavigate();
10128
const [controller, setController] = useState(null as AbortController | null);
10229
const [timer, setTimer] = useState(undefined as undefined | NodeJS.Timer);
@@ -107,8 +34,8 @@ export default function Main() {
10734
const [gsValues, setGsValues] = useState([] as GsValue[]);
10835
const globalJwtTokenState = useRecoilValue(GlobalState.jwtTokenState);
10936
const globalUserUuidState = useRecoilValue(GlobalState.userUuidState);
110-
const globalUserDataState = useRecoilValue(GlobalState.userDataState);
111-
const refreshJwtTokenState = useRecoilRefresher_UNSTABLE(GlobalState.jwtTokenState);
37+
const globalUserDataState = useRecoilValue(GlobalState.userDataState);
38+
const refreshJwtTokenState = useRecoilRefresher_UNSTABLE(GlobalState.jwtTokenState);
11239

11340
const handleTabChange = (event: SyntheticEvent, newValue: number) => {
11441
setValue(newValue);
@@ -117,129 +44,114 @@ export default function Main() {
11744
setTimer(setInterval(() => getData(newValue), 10000));
11845
}
11946

120-
const formatPostCode = (myPlz: number) => {
47+
const formatPostCode = (myPlz: number) => {
12148
return '00000'.substring(0, 5 - myPlz?.toString()?.length > 0 ? myPlz?.toString()?.length : 0) + myPlz.toString();
12249
}
12350

12451
const getData = (newValue: number) => {
125-
if (globalJwtTokenState?.length < 10 || globalUserUuidState?.length < 10) {
52+
if (globalJwtTokenState?.length < 10 || globalUserUuidState?.length < 10) {
12653
navigate('/');
12754
return;
128-
}
55+
}
12956
//console.log(newValue);
130-
if(!!controller) {
57+
if (!!controller) {
13158
controller.abort();
13259
}
133-
setController(new AbortController());
134-
refreshJwtTokenState();
60+
setController(new AbortController());
61+
refreshJwtTokenState();
13562
// jwtToken = globalJwtTokenState; //When recoil makes refresh work.
136-
const jwtToken = !!GlobalState.jwtToken ? GlobalState.jwtToken : globalJwtTokenState;
137-
if (newValue === 0 || newValue === 2) {
63+
const jwtToken = !!GlobalState.jwtToken ? GlobalState.jwtToken : globalJwtTokenState;
64+
if (newValue === 0 || newValue === 2) {
13865
fetchSearchLocation(jwtToken);
139-
} else {
66+
} else {
14067
fetchLastMatches(jwtToken);
14168
};
14269
}
14370

144-
const fetchSearchLocation = (jwtToken: string) => {
145-
const requestOptions2 = {
146-
method: 'POST',
147-
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${jwtToken}` },
148-
body: JSON.stringify({ Longitude: globalUserDataState.Longitude, Latitude: globalUserDataState.Latitude, Radius: globalUserDataState.SearchRadius }),
149-
signal: controller?.signal
150-
}
151-
fetch('/gasstation/search/location', requestOptions2).then(myResult => myResult.json() as Promise<GasStation[]>).then(myJson => {
152-
const myResult = myJson.filter(value => value?.GasPrices?.length > 0).map(value => {
153-
return value;
154-
}).map(value => ({
155-
location: value.Place + ' ' + value.Brand + ' ' + value.Street + ' ' + value.HouseNumber, e5: value.GasPrices[0].E5,
156-
e10: value.GasPrices[0].E10, diesel: value.GasPrices[0].Diesel, date: new Date(Date.parse(value.GasPrices[0].Date)), longitude: value.Longitude, latitude: value.Latitude
157-
} as TableDataRow));
158-
const requestOptions3 = {
159-
method: 'GET',
160-
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${jwtToken}` },
161-
signal: controller?.signal
162-
}
163-
const myPostcode = formatPostCode(globalUserDataState.PostCode);
164-
fetch(`/gasprice/avgs/${myPostcode}`, requestOptions3).then(myResult => myResult.json() as Promise<GasPriceAvgs>).then(myJson => {
165-
const rowCounty = ({
166-
location: myJson.County, e5: Math.round(myJson.CountyAvgE5), e10: Math.round(myJson.CountyAvgE10), diesel: Math.round(myJson.CountyAvgDiesel), date: new Date(), longitude: 0, latitude: 0
167-
} as TableDataRow);
168-
const rowState = ({
169-
location: myJson.State, e5: Math.round(myJson.StateAvgE5), e10: Math.round(myJson.StateAvgE10), diesel: Math.round(myJson.StateAvgDiesel), date: new Date(), longitude: 0, latitude: 0
170-
} as TableDataRow);
171-
const resultRows = [rowCounty, rowState, ...myResult]
172-
setRows(resultRows);
173-
});
174-
setGsValues(myResult);
175-
}).then(() => setController(null));
71+
const fetchSearchLocation = async (jwtToken: string) => {
72+
const result = await fetchGasStations(jwtToken, controller, globalUserDataState);
73+
const myResult = result.filter(value => value?.GasPrices?.length > 0).map(value => {
74+
return value;
75+
}).map(value => ({
76+
location: value.Place + ' ' + value.Brand + ' ' + value.Street + ' ' + value.HouseNumber, e5: value.GasPrices[0].E5,
77+
e10: value.GasPrices[0].E10, diesel: value.GasPrices[0].Diesel, date: new Date(Date.parse(value.GasPrices[0].Date)), longitude: value.Longitude, latitude: value.Latitude
78+
} as TableDataRow));
79+
const myPostcode = formatPostCode(globalUserDataState.PostCode);
80+
const myJson = await fetchPriceAvgs(jwtToken, controller, myPostcode);
81+
const rowCounty = ({
82+
location: myJson.County, e5: Math.round(myJson.CountyAvgE5), e10: Math.round(myJson.CountyAvgE10), diesel: Math.round(myJson.CountyAvgDiesel), date: new Date(), longitude: 0, latitude: 0
83+
} as TableDataRow);
84+
const rowState = ({
85+
location: myJson.State, e5: Math.round(myJson.StateAvgE5), e10: Math.round(myJson.StateAvgE10), diesel: Math.round(myJson.StateAvgDiesel), date: new Date(), longitude: 0, latitude: 0
86+
} as TableDataRow);
87+
const resultRows = [rowCounty, rowState, ...myResult]
88+
setRows(resultRows);
89+
setGsValues(myResult);
90+
setController(null);
17691
}
17792

178-
const fetchLastMatches = (jwtToken: string) => {
179-
const requestOptions1 = {
93+
const fetchLastMatches = async (jwtToken: string) => {
94+
const result = await fetchUserNotifications(jwtToken, controller, globalUserUuidState);
95+
const myResult = result.map(value => {
96+
return JSON.parse(value?.DataJson);
97+
});
98+
//console.log(myJson);
99+
const result2 = myResult?.map(value => {
100+
//console.log(JSON.parse(value?.DataJson));
101+
return (JSON.parse(value?.DataJson) as MyDataJson[])?.map(value2 => {
102+
//console.log(value2);
103+
return {
104+
location: value2.Place + ' ' + value2.Brand + ' ' + value2.Street + ' ' + value2.HouseNumber,
105+
e5: value2.E5, e10: value2.E10, diesel: value2.Diesel, date: new Date(Date.parse(value2.Timestamp)), longitude: 0, latitude: 0
106+
} as TableDataRow;
107+
});
108+
})?.flat() || [];
109+
setRows(result2);
110+
//const result
111+
const requestOptions2 = {
180112
method: 'GET',
181113
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${jwtToken}` },
182114
signal: controller?.signal
183115
}
184-
fetch(`/usernotification/current/${globalUserUuidState}`, requestOptions1).then(myResult => myResult?.json() as Promise<Notification[]>).then(myJson => {
185-
//console.log(myJson);
186-
const result = myJson?.map(value => {
187-
//console.log(JSON.parse(value?.DataJson));
188-
return (JSON.parse(value?.DataJson) as MyDataJson[])?.map(value2 => {
189-
//console.log(value2);
190-
return {
191-
location: value2.Place + ' ' + value2.Brand + ' ' + value2.Street + ' ' + value2.HouseNumber,
192-
e5: value2.E5, e10: value2.E10, diesel: value2.Diesel, date: new Date(Date.parse(value2.Timestamp)), longitude: 0, latitude: 0
193-
} as TableDataRow;
194-
});
195-
})?.flat() || [];
196-
setRows(result);
197-
//const result
198-
const requestOptions2 = {
199-
method: 'GET',
200-
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${jwtToken}` },
201-
signal: controller?.signal
202-
}
203-
const myPostcode = formatPostCode(globalUserDataState.PostCode);
204-
fetch(`/postcode/countytimeslots/${myPostcode}`, requestOptions2).then(myResult1 => myResult1.json() as Promise<TimeSlotResponse[]>).then(myJson1 => {
205-
const timeSlots = [] as TimeSlot[];
206-
timeSlots.push(...myJson1.filter(myValue => myValue.AvgDiesel > 10).map(myValue => {
207-
const dieselTimeSlot = {x: '00.00', diesel: 0, e10: 0, e5: 0} as TimeSlot;
208-
const myDate = new Date(myValue.StartDate);
209-
dieselTimeSlot.x = ''+myDate.getHours()+':'+(myDate.getMinutes().toString().length < 2 ? myDate.getMinutes().toString().length +'0': myDate.getMinutes());
210-
dieselTimeSlot.diesel = myValue.AvgDiesel/1000;
211-
dieselTimeSlot.e10 = myValue.AvgE10/1000;
212-
dieselTimeSlot.e5 = myValue.AvgE5/1000;
213-
return dieselTimeSlot;
214-
}));
215-
setAvgTimeSlots(timeSlots);
216-
//console.log(myJson1);
217-
});
218-
})
219-
.then(() => setController(null));
116+
const myPostcode = formatPostCode(globalUserDataState.PostCode);
117+
const myJson1 = await fetchTimeSlots(jwtToken, controller, myPostcode);
118+
const timeSlots = [] as TimeSlot[];
119+
timeSlots.push(...myJson1.filter(myValue => myValue.AvgDiesel > 10).map(myValue => {
120+
const dieselTimeSlot = { x: '00.00', diesel: 0, e10: 0, e5: 0 } as TimeSlot;
121+
const myDate = new Date(myValue.StartDate);
122+
dieselTimeSlot.x = '' + myDate.getHours() + ':' + (myDate.getMinutes().toString().length < 2 ? myDate.getMinutes().toString().length + '0' : myDate.getMinutes());
123+
dieselTimeSlot.diesel = myValue.AvgDiesel / 1000;
124+
dieselTimeSlot.e10 = myValue.AvgE10 / 1000;
125+
dieselTimeSlot.e5 = myValue.AvgE5 / 1000;
126+
return dieselTimeSlot;
127+
}));
128+
setAvgTimeSlots(timeSlots);
129+
//console.log(myJson1);
130+
setController(null);
220131
}
221132

222133
// eslint-disable-next-line
223134
useEffect(() => {
224135
if (globalJwtTokenState?.length > 10 && globalUserUuidState?.length > 10 && first) {
225-
setTimeout(() => handleTabChange({} as unknown as SyntheticEvent, value), 3000);
136+
setTimeout(() => handleTabChange({} as unknown as SyntheticEvent, value), 3000);
226137
setFirst(false);
227-
}
138+
}
228139
});
229140

230141
return (<Box sx={{ width: '100%' }}>
231142
<Tabs value={value} onChange={handleTabChange} centered={true}>
232-
<Tab label="Current Prices"/>
233-
<Tab label="Last Price matches"/>
234-
<Tab label="Current Prices Map"/>
143+
<Tab label="Current Prices" />
144+
<Tab label="Last Price matches" />
145+
<Tab label="Current Prices Map" />
235146
</Tabs>
236-
{ value === 0 &&
237-
<DataTable diesel='Diesel' e10='E10' e5='E5' location='Location' showAverages={true} time='Time' rows={rows}></DataTable>}
238-
{ value === 1 &&
147+
{value === 0 &&
148+
<DataTable diesel='Diesel' e10='E10' e5='E5' location='Location' showAverages={true} time='Time' rows={rows}></DataTable>}
149+
{value === 1 &&
239150
<Chart timeSlots={avgTimeSlots}></Chart>}
240-
{ value === 1 &&
241-
<DataTable diesel='Diesel' e10='E10' e5='E5' location='Location' showAverages={true} time='Time' rows={rows}></DataTable>}
242-
{ value === 2 &&
243-
<GsMap gsValues={gsValues} center={globalUserDataState}></GsMap>}
151+
{value === 1 &&
152+
<DataTable diesel='Diesel' e10='E10' e5='E5' location='Location' showAverages={true} time='Time' rows={rows}></DataTable>}
153+
{value === 2 &&
154+
<GsMap gsValues={gsValues} center={globalUserDataState}></GsMap>}
244155
</Box>);
245-
}
156+
}
157+

0 commit comments

Comments
 (0)