From 9265a4a4609b54c3dcfc69185f19bf349c45b3cc Mon Sep 17 00:00:00 2001 From: Dlurak <84224239+Dlurak@users.noreply.github.com> Date: Sun, 27 Aug 2023 16:26:50 +0200 Subject: [PATCH 1/9] added a renderer for the fhrs --- src/components/FeaturePanel/FeaturePanel.tsx | 1 + src/components/FeaturePanel/FeaturedTag.tsx | 6 +++++- .../FeaturePanel/renderers/FoodHygieneRatingScheme.tsx | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx diff --git a/src/components/FeaturePanel/FeaturePanel.tsx b/src/components/FeaturePanel/FeaturePanel.tsx index e1a9c3a39..2071f0b19 100644 --- a/src/components/FeaturePanel/FeaturePanel.tsx +++ b/src/components/FeaturePanel/FeaturePanel.tsx @@ -33,6 +33,7 @@ const featuredKeys = [ 'contact:mobile', 'opening_hours', 'description', + 'fhrs:id', ]; const FeaturePanel = () => { diff --git a/src/components/FeaturePanel/FeaturedTag.tsx b/src/components/FeaturePanel/FeaturedTag.tsx index f68d327ee..c6b28f55b 100644 --- a/src/components/FeaturePanel/FeaturedTag.tsx +++ b/src/components/FeaturePanel/FeaturedTag.tsx @@ -5,6 +5,7 @@ import WebsiteRenderer from './renderers/WebsiteRenderer'; import OpeningHoursRenderer from './renderers/OpeningHoursRenderer'; import PhoneRenderer from './renderers/PhoneRenderer'; import { EditIconButton } from './helpers/EditIconButton'; +import { FoodHygieneRatingSchemeRenderer } from './renderers/FoodHygieneRatingScheme'; const Wrapper = styled.div` position: relative; @@ -29,13 +30,16 @@ const Value = styled.div` `; const DefaultRenderer = ({ v }) => v; -const renderers = { +const renderers: { + [key: string]: React.FC<{ v: string }>; +} = { website: WebsiteRenderer, 'contact:website': WebsiteRenderer, phone: PhoneRenderer, 'contact:phone': PhoneRenderer, 'contact:mobile': PhoneRenderer, opening_hours: OpeningHoursRenderer, + 'fhrs:id': FoodHygieneRatingSchemeRenderer, }; export const FeaturedTag = ({ k, v, onEdit }) => { diff --git a/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx b/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx new file mode 100644 index 000000000..a9e9116da --- /dev/null +++ b/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx @@ -0,0 +1,3 @@ +import React from 'react'; + +export const FoodHygieneRatingSchemeRenderer = ({ v }) =>

{v}

; From 932cd06004e60a470d69180af6ac55b5c1fd0eb7 Mon Sep 17 00:00:00 2001 From: Dlurak <84224239+Dlurak@users.noreply.github.com> Date: Sun, 27 Aug 2023 23:27:52 +0200 Subject: [PATCH 2/9] added a function to load the data from the api --- .../renderers/FoodHygieneRatingScheme.tsx | 71 ++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx b/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx index a9e9116da..8db2eda3d 100644 --- a/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx +++ b/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx @@ -1,3 +1,70 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; +import { Typography } from '@material-ui/core'; +import { getEstablishmentRatingValue } from '../../../services/fhrsApi'; -export const FoodHygieneRatingSchemeRenderer = ({ v }) =>

{v}

; +const useLoadingState = () => { + const [rating, setRating] = useState(); + const [error, setError] = useState(); + const [loading, setLoading] = useState(true); + + const finishRating = (payload) => { + setLoading(false); + setRating(payload); + }; + + const startRating = () => { + setLoading(true); + setRating(undefined); + setError(undefined); + }; + + const failRating = () => { + setError('Could not load rating'); + setLoading(false); + }; + + return { rating, error, loading, startRating, finishRating, failRating }; +}; + +export const FoodHygieneRatingSchemeRenderer = ({ v }) => { + const { rating, error, loading, startRating, finishRating, failRating } = + useLoadingState(); + + useEffect(() => { + const loadData = async () => { + startRating(); + const ratingValue = await getEstablishmentRatingValue(v); + if (Number.isNaN(rating)) { + failRating(); + } + finishRating(ratingValue); + }; + + loadData(); + console.log('rating', error); + }, []); + + return ( + <> + {loading ? ( + <> + + + + + ) : ( + <> + {Number.isNaN(rating) || error ? ( + <> + No rating available + + ) : ( + <> +

Rating: {rating}

+ + )} + + )} + + ); +}; From edb8c8708b66db97d03f7c700383428f9ae1732c Mon Sep 17 00:00:00 2001 From: Dlurak <84224239+Dlurak@users.noreply.github.com> Date: Mon, 28 Aug 2023 00:11:14 +0200 Subject: [PATCH 3/9] implemented a component for the stars and added a icon --- .../renderers/FoodHygieneRatingScheme.tsx | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx b/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx index 8db2eda3d..544df96c1 100644 --- a/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx +++ b/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx @@ -1,7 +1,24 @@ import React, { useEffect, useState } from 'react'; import { Typography } from '@material-ui/core'; +import { Restaurant } from '@material-ui/icons'; import { getEstablishmentRatingValue } from '../../../services/fhrsApi'; +interface StarRatingProps { + stars: number; + maxStars: number; +} + +const StarRating = ({ stars, maxStars }: StarRatingProps) => { + const starArray = new Array(maxStars).fill(0); + return ( +
+ {starArray.map((_, i) => ( + {i < stars ? '★' : '☆'} + ))} +
+ ); +}; + const useLoadingState = () => { const [rating, setRating] = useState(); const [error, setError] = useState(); @@ -41,7 +58,6 @@ export const FoodHygieneRatingSchemeRenderer = ({ v }) => { }; loadData(); - console.log('rating', error); }, []); return ( @@ -54,13 +70,12 @@ export const FoodHygieneRatingSchemeRenderer = ({ v }) => { ) : ( <> + {Number.isNaN(rating) || error ? ( - <> - No rating available - + No rating available ) : ( <> -

Rating: {rating}

+ )} From f3db428788afa03809464f8965eae803fad8170d Mon Sep 17 00:00:00 2001 From: Dlurak <84224239+Dlurak@users.noreply.github.com> Date: Mon, 28 Aug 2023 02:02:59 +0200 Subject: [PATCH 4/9] added previously forgotten files --- src/services/__tests__/fhrsApi.test.ts | 13 +++++++++++++ src/services/fhrsApi.ts | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/services/__tests__/fhrsApi.test.ts create mode 100644 src/services/fhrsApi.ts diff --git a/src/services/__tests__/fhrsApi.test.ts b/src/services/__tests__/fhrsApi.test.ts new file mode 100644 index 000000000..3c16db9e7 --- /dev/null +++ b/src/services/__tests__/fhrsApi.test.ts @@ -0,0 +1,13 @@ +import { getEstablishmentRatingValue } from '../fhrsApi'; + +describe('fetchRating', () => { + it('should return a rating between 0 and 5', () => { + const fhrsIds = ['988122', '269229', '268672', '268669']; + + fhrsIds.forEach(async (id) => { + const rating = await getEstablishmentRatingValue(parseInt(id, 10)); + expect(rating).toBeGreaterThanOrEqual(0); + expect(rating).toBeLessThanOrEqual(5); + }); + }); +}); diff --git a/src/services/fhrsApi.ts b/src/services/fhrsApi.ts new file mode 100644 index 000000000..787bb2ef8 --- /dev/null +++ b/src/services/fhrsApi.ts @@ -0,0 +1,16 @@ +import { fetchJson } from './fetch'; + +function fetchEstablishmentData(id: number) { + return fetchJson(`https://api.ratings.food.gov.uk/Establishments/${id}`, { + headers: { + 'x-api-version': '2', + }, + }); +} + +export async function getEstablishmentRatingValue(id: number) { + const allData = await fetchEstablishmentData(id).catch(() => null); + const ratingString = allData?.RatingValue; + const ratingValue = parseInt(ratingString, 10); + return ratingValue; +} From 50dba6c455edf54bb5e79aa232c91d3d1d528cf0 Mon Sep 17 00:00:00 2001 From: Dlurak <84224239+Dlurak@users.noreply.github.com> Date: Mon, 28 Aug 2023 02:14:11 +0200 Subject: [PATCH 5/9] fixed the test --- src/services/__tests__/fhrsApi.test.ts | 150 ++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) diff --git a/src/services/__tests__/fhrsApi.test.ts b/src/services/__tests__/fhrsApi.test.ts index 3c16db9e7..e332530c1 100644 --- a/src/services/__tests__/fhrsApi.test.ts +++ b/src/services/__tests__/fhrsApi.test.ts @@ -2,10 +2,158 @@ import { getEstablishmentRatingValue } from '../fhrsApi'; describe('fetchRating', () => { it('should return a rating between 0 and 5', () => { - const fhrsIds = ['988122', '269229', '268672', '268669']; + const fhrsIds = [ + '268458', + '269382', + '268811', + '268903', + '269258', + '269026', + '269099', + '269095', + '809473', + '268631', + '269312', + '269253', + '988122', + '723651', + '269229', + '268672', + '268669', + '269078', + '854391', + '708562', + '268508', + '989695', + '268628', + '268629', + '269386', + '268937', + '269058', + '268487', + '1065520', + '268323', + '268324', + '268322', + '842962', + '268874', + '269309', + '269148', + '269171', + '268488', + '777803', + '268630', + '269224', + '268617', + '268615', + '268618', + '269431', + '269384', + '269383', + '999835', + '268752', + '269248', + '269495', + '269497', + '268490', + '977892', + '268807', + '729281', + '269464', + '269158', + '848733', + '268780', + '952041', + '268481', + '269028', + '949726', + '269039', + '542347', + '1015463', + '268624', + '269252', + '268982', + '679551', + '949727', + '989697', + '406128', + '997133', + '836583', + '997140', + '743833', + '988109', + '268454', + '964599', + '1011214', + '269163', + '841948', + '889450', + '268806', + '1015461', + '268453', + '929914', + '269262', + '268351', + '269202', + '268849', + '777807', + '268441', + '997130', + '1031734', + '661417', + '269447', + '269434', + '269449', + '268866', + '269448', + '269442', + '269441', + '269436', + '269437', + '269446', + '269438', + '269452', + '269433', + '955351', + '269493', + '268355', + '269260', + '269361', + '268548', + '268352', + '269402', + '681923', + '269142', + '268353', + '269391', + '661418', + '904891', + '268433', + '268667', + '1401890', + '268356', + '268993', + '268935', + '268934', + '268933', + '268435', + '269201', + '848730', + '268461', + '268410', + '668853', + '268447', + '269155', + '268450', + '1292333', + ]; fhrsIds.forEach(async (id) => { const rating = await getEstablishmentRatingValue(parseInt(id, 10)); + if (Number.isNaN(rating)) { + expect(rating).toBeNaN(); + return; + } expect(rating).toBeGreaterThanOrEqual(0); expect(rating).toBeLessThanOrEqual(5); }); From 0f92d29b7b74b377a05a7dc135df83365739c869 Mon Sep 17 00:00:00 2001 From: Dlurak <84224239+Dlurak@users.noreply.github.com> Date: Tue, 29 Aug 2023 13:23:05 +0200 Subject: [PATCH 6/9] updated the test --- src/services/__tests__/fhrsApi.test.ts | 203 ++++++------------------- 1 file changed, 48 insertions(+), 155 deletions(-) diff --git a/src/services/__tests__/fhrsApi.test.ts b/src/services/__tests__/fhrsApi.test.ts index e332530c1..526f502ca 100644 --- a/src/services/__tests__/fhrsApi.test.ts +++ b/src/services/__tests__/fhrsApi.test.ts @@ -1,161 +1,54 @@ +import * as fetchModule from '../fetch'; import { getEstablishmentRatingValue } from '../fhrsApi'; describe('fetchRating', () => { - it('should return a rating between 0 and 5', () => { - const fhrsIds = [ - '268458', - '269382', - '268811', - '268903', - '269258', - '269026', - '269099', - '269095', - '809473', - '268631', - '269312', - '269253', - '988122', - '723651', - '269229', - '268672', - '268669', - '269078', - '854391', - '708562', - '268508', - '989695', - '268628', - '268629', - '269386', - '268937', - '269058', - '268487', - '1065520', - '268323', - '268324', - '268322', - '842962', - '268874', - '269309', - '269148', - '269171', - '268488', - '777803', - '268630', - '269224', - '268617', - '268615', - '268618', - '269431', - '269384', - '269383', - '999835', - '268752', - '269248', - '269495', - '269497', - '268490', - '977892', - '268807', - '729281', - '269464', - '269158', - '848733', - '268780', - '952041', - '268481', - '269028', - '949726', - '269039', - '542347', - '1015463', - '268624', - '269252', - '268982', - '679551', - '949727', - '989697', - '406128', - '997133', - '836583', - '997140', - '743833', - '988109', - '268454', - '964599', - '1011214', - '269163', - '841948', - '889450', - '268806', - '1015461', - '268453', - '929914', - '269262', - '268351', - '269202', - '268849', - '777807', - '268441', - '997130', - '1031734', - '661417', - '269447', - '269434', - '269449', - '268866', - '269448', - '269442', - '269441', - '269436', - '269437', - '269446', - '269438', - '269452', - '269433', - '955351', - '269493', - '268355', - '269260', - '269361', - '268548', - '268352', - '269402', - '681923', - '269142', - '268353', - '269391', - '661418', - '904891', - '268433', - '268667', - '1401890', - '268356', - '268993', - '268935', - '268934', - '268933', - '268435', - '269201', - '848730', - '268461', - '268410', - '668853', - '268447', - '269155', - '268450', - '1292333', - ]; + it('should return a rating between 0 and 5', async () => { + const fetchJsonMock = jest + .spyOn(fetchModule, 'fetchJson') + .mockResolvedValue({ + FHRSID: 423824, + ChangesByServerID: 0, + LocalAuthorityBusinessID: '13359', + BusinessName: 'Caffe Nero', + BusinessType: 'Restaurant/Cafe/Canteen', + BusinessTypeID: 1, + AddressLine1: '', + AddressLine2: '30 Monmouth Street', + AddressLine3: '', + AddressLine4: 'London', + PostCode: 'WC2H 9HA', + Phone: '', + RatingValue: '5', + RatingKey: 'fhrs_5_en-gb', + RatingDate: '2019-09-11T00:00:00', + LocalAuthorityCode: '506', + LocalAuthorityName: 'Camden', + LocalAuthorityWebSite: 'http://www.camden.gov.uk', + LocalAuthorityEmailAddress: 'foodsafety@camden.gov.uk', + scores: { + Hygiene: 0, + Structural: 0, + ConfidenceInManagement: 0, + }, + SchemeType: 'FHRS', + geocode: { + longitude: '-0.1272279', + latitude: '51.5136148', + }, + RightToReply: '', + Distance: null, + NewRatingPending: false, + }); - fhrsIds.forEach(async (id) => { - const rating = await getEstablishmentRatingValue(parseInt(id, 10)); - if (Number.isNaN(rating)) { - expect(rating).toBeNaN(); - return; - } - expect(rating).toBeGreaterThanOrEqual(0); - expect(rating).toBeLessThanOrEqual(5); - }); + const fhrsId = '269382'; + const rating = await getEstablishmentRatingValue(parseInt(fhrsId, 10)); + + if (Number.isNaN(rating)) { + expect(rating).toBeNaN(); + return; + } + expect(rating).toBeGreaterThanOrEqual(0); + expect(rating).toBeLessThanOrEqual(5); + fetchJsonMock.mockRestore(); }); }); From 7fa408b8c13bfbd7a7110b5a0aea8c33cdc560bb Mon Sep 17 00:00:00 2001 From: Dlurak <84224239+Dlurak@users.noreply.github.com> Date: Tue, 29 Aug 2023 13:41:48 +0200 Subject: [PATCH 7/9] optimized the renderer --- .../renderers/FoodHygieneRatingScheme.tsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx b/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx index 544df96c1..8d2ef1f30 100644 --- a/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx +++ b/src/components/FeaturePanel/renderers/FoodHygieneRatingScheme.tsx @@ -60,6 +60,15 @@ export const FoodHygieneRatingSchemeRenderer = ({ v }) => { loadData(); }, []); + const linkStyle: React.CSSProperties = { + display: 'flex', + alignItems: 'center', + gap: '0.5rem', + }; + const pStyle: React.CSSProperties = { + marginBlock: '0', + }; + return ( <> {loading ? ( @@ -75,7 +84,14 @@ export const FoodHygieneRatingSchemeRenderer = ({ v }) => { No rating available ) : ( <> - + +

FHRS

+ +
)} From 326b61bd2a40e3835554e0fea22bfd9bc5647bc0 Mon Sep 17 00:00:00 2001 From: Dlurak <84224239+Dlurak@users.noreply.github.com> Date: Tue, 29 Aug 2023 14:16:14 +0200 Subject: [PATCH 8/9] optimized the test again --- src/services/__tests__/fhrsApi.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/services/__tests__/fhrsApi.test.ts b/src/services/__tests__/fhrsApi.test.ts index 526f502ca..fb69773d7 100644 --- a/src/services/__tests__/fhrsApi.test.ts +++ b/src/services/__tests__/fhrsApi.test.ts @@ -40,8 +40,7 @@ describe('fetchRating', () => { NewRatingPending: false, }); - const fhrsId = '269382'; - const rating = await getEstablishmentRatingValue(parseInt(fhrsId, 10)); + const rating = await getEstablishmentRatingValue(269382); if (Number.isNaN(rating)) { expect(rating).toBeNaN(); From c965779e90c6f7d91476d1c707b312bfada88037 Mon Sep 17 00:00:00 2001 From: Dlurak <84224239+Dlurak@users.noreply.github.com> Date: Tue, 29 Aug 2023 14:17:46 +0200 Subject: [PATCH 9/9] optimized the test yet again --- src/services/__tests__/fhrsApi.test.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/services/__tests__/fhrsApi.test.ts b/src/services/__tests__/fhrsApi.test.ts index fb69773d7..57294d66a 100644 --- a/src/services/__tests__/fhrsApi.test.ts +++ b/src/services/__tests__/fhrsApi.test.ts @@ -41,12 +41,6 @@ describe('fetchRating', () => { }); const rating = await getEstablishmentRatingValue(269382); - - if (Number.isNaN(rating)) { - expect(rating).toBeNaN(); - return; - } - expect(rating).toBeGreaterThanOrEqual(0); expect(rating).toBeLessThanOrEqual(5); fetchJsonMock.mockRestore(); });