From 70b1b36852e6b9c0fb0607176f5e405756aa290c Mon Sep 17 00:00:00 2001 From: Vencislav Atanasov Date: Mon, 23 Sep 2024 18:15:16 +0300 Subject: [PATCH] Normalize API responses before parsing/rendering --- src/Schedule/Schedule.jsx | 12 +++++------- src/hooks/useSchedule.js | 14 +++++++------- src/hooks/useScheduleTable.js | 8 ++++---- src/utils.js | 23 ++++++++++++++--------- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/Schedule/Schedule.jsx b/src/Schedule/Schedule.jsx index 8871f22..e2ce3ac 100644 --- a/src/Schedule/Schedule.jsx +++ b/src/Schedule/Schedule.jsx @@ -41,7 +41,7 @@ export default function Schedule({ return (<> {isComplete && } {isLoading && } @@ -69,9 +69,7 @@ export default function Schedule({
- {Object.values(tracks).filter(track => - !isTrackHidden(track) - ).map(track => + {tracks.filter(track => !isTrackHidden(track)).map(track => )} {Object.entries(langs).map(([langId, langName]) => @@ -80,7 +78,7 @@ export default function Schedule({
{track.name[lang]}
- {Object.values(events).map(event =>
+ {events.map(event =>

{event.title} {event.participant_users && !isTrackHidden(event.track) && <> @@ -99,13 +97,13 @@ export default function Schedule({

)} {<>
- {Object.values(speakers).map(speaker =>
+ {speakers.map(speaker => )}
- {Object.values(speakers).map(speaker => + {speakers.map(speaker =>
{getSpeakerName(speaker)}/

{getSpeakerName(speaker)}

diff --git a/src/hooks/useSchedule.js b/src/hooks/useSchedule.js index e83eb9f..24a2893 100644 --- a/src/hooks/useSchedule.js +++ b/src/hooks/useSchedule.js @@ -4,7 +4,7 @@ import useTracks from './useTracks.js'; import useEventTypes from './useEventTypes.js'; import useHalls from './useHalls.js'; import useSlots from './useSlots.js'; -import { addIdAndRelations, calculateProgress } from '../utils.js'; +import { calculateProgress, normalizeResponse } from '../utils.js'; import { useMemo } from 'react'; export default function useSchedule(conferenceId) { @@ -14,7 +14,7 @@ export default function useSchedule(conferenceId) { isValidating: speakersValidating, } = useSpeakers(conferenceId); - const speakers = useMemo(() => addIdAndRelations(speakersResponse || []), [speakersResponse]); + const speakers = useMemo(() => normalizeResponse(speakersResponse), [speakersResponse]); const { data: tracksResponse, @@ -22,7 +22,7 @@ export default function useSchedule(conferenceId) { isValidating: tracksValidating, } = useTracks(conferenceId); - const tracks = useMemo(() => addIdAndRelations(tracksResponse || []), [tracksResponse]); + const tracks = useMemo(() => normalizeResponse(tracksResponse), [tracksResponse]); const { data: eventTypesResponse, @@ -30,7 +30,7 @@ export default function useSchedule(conferenceId) { isValidating: eventTypesValidating, } = useEventTypes(conferenceId); - const eventTypes = useMemo(() => addIdAndRelations(eventTypesResponse || []), [eventTypesResponse]); + const eventTypes = useMemo(() => normalizeResponse(eventTypesResponse), [eventTypesResponse]); const { data: hallsResponse, @@ -38,7 +38,7 @@ export default function useSchedule(conferenceId) { isValidating: hallsValidating, } = useHalls(conferenceId); - const halls = useMemo(() => addIdAndRelations(hallsResponse || []), [hallsResponse]); + const halls = useMemo(() => normalizeResponse(hallsResponse), [hallsResponse]); const { data: eventsResponse, @@ -46,7 +46,7 @@ export default function useSchedule(conferenceId) { isValidating: eventsValidating, } = useEvents(conferenceId); - const events = useMemo(() => addIdAndRelations(eventsResponse || [], [ + const events = useMemo(() => normalizeResponse(eventsResponse, [ ['event_type', eventTypes, 'event_type_id'], ['track', tracks, 'track_id'], ['participant_users', speakers, 'participant_user_ids'], @@ -58,7 +58,7 @@ export default function useSchedule(conferenceId) { isValidating: slotsValidating, } = useSlots(conferenceId); - const slots = useMemo(() => addIdAndRelations(slotsResponse || [], [ + const slots = useMemo(() => normalizeResponse(slotsResponse, [ ['hall', halls, 'hall_id'], ['event', events, 'event_id'], ]), [slotsResponse, halls, events]); diff --git a/src/hooks/useScheduleTable.js b/src/hooks/useScheduleTable.js index 9b60b72..f5ecd0f 100644 --- a/src/hooks/useScheduleTable.js +++ b/src/hooks/useScheduleTable.js @@ -6,10 +6,10 @@ export default function useScheduleTable({ events = {}, slots = {}, }) { - const filteredEvents = useMemo(() => Object.values(events).filter(event => eventTypeId > 0 ? event.event_type_id === eventTypeId : true), [eventTypeId, events]); - const filteredEventIds = useMemo(() => new Set(filteredEvents.map(event => event.id)), [filteredEvents]); - const filteredHallIds = useMemo(() => new Set(Object.values(slots).filter(slot => filteredEventIds.has(slot.event_id)).map(slot => slot.hall_id)), [filteredEventIds, slots]); - const header = useMemo(() => Object.values(halls).filter(hall => filteredHallIds.has(hall.id)), [filteredHallIds, halls]); + const filteredEvents = useMemo(() => events.filter(event => eventTypeId > 0 ? event.event_type_id === eventTypeId : true), [eventTypeId, events]); + const filteredEventIds = useMemo(() => filteredEvents.map(event => event.id), [filteredEvents]); + const filteredHallIds = useMemo(() => new Set(slots.filter(slot => filteredEventIds.includes(slot.event_id)).map(slot => slot.hall_id)), [filteredEventIds, slots]); + const header = useMemo(() => halls.filter(hall => filteredHallIds.has(hall.id)), [filteredHallIds, halls]); const rows = filteredEvents.map(event => ({ id: event.id, diff --git a/src/utils.js b/src/utils.js index b7c313c..9d84a53 100644 --- a/src/utils.js +++ b/src/utils.js @@ -42,14 +42,19 @@ export function calculateProgress(...elements) { }; } -export const addIdAndRelations = (items, relations = []) => - Object.fromEntries(Object.entries(items).map(([id, item]) => - ([id, { +export const normalizeResponse = (items = [], relations = []) => + Object.entries(items).map(([id, item]) => + ({ id: parseInt(id, 10), ...item, - ...Object.fromEntries(relations.map(([field, collection, idField]) => ([ - field, - Array.isArray(item[idField]) ? item[idField].map(id => collection[id]) : collection[item[idField]], - ]))), - }]) - )); + ...Object.fromEntries(relations.map(([field, collection, idField]) => { + const key = item[idField]; + const fn = Array.isArray(key) ? 'filter' : 'find'; + + return [ + field, + collection[fn](item => item.id === key), + ]; + })), + }) + );