import { PlaceMapper } from "../resources/place/mapper"; import { IJsonApiRelationship, IJsonApiResource } from "../interfaces"; import { placeType, IPlaceResource } from "../resources/place"; import Lodging from "../resources/lodging"; import Poi from "../resources/poi"; const placeMapper = new PlaceMapper(); const ancestryList = (ancestry) => Array.isArray(ancestry) ? ancestry : [ancestry]; export function assignContainingPlaces(included: IJsonApiResource[], ancestry: IPlaceResource[], model: Lodging | Poi) { model.containingPlaces = ancestry.reduce((acc, curr) => { const ancestor = included.find((i) => i.id === curr.id); if (ancestor) { acc.push(placeMapper.toModel(ancestor)); } return acc; }, []); } const capitalize = string => `${string[0].toUpperCase()}${string.slice(1)}`; const getPlaces = (included: IJsonApiResource[], ancestry: IPlaceResource[]): IPlaceResource[] => included.filter((resource) => resource.type === placeType && ancestryList(ancestry).some(p => p.id === resource.id)); const createPlaceTypeAssigner = ( type: "city" | "continent" | "country" | "neighborhood", // any place type that a given POI will possess one of (see "assignRegions" below) assignments: string[] = ["id", "name"], // will check for these keys on both `result` and `result.attributes` & assign value if found. ifFound: (result, model) => void = () => null, // for anything that doesn't fit into the above pattern. ) => (included: IJsonApiResource[], ancestry: IPlaceResource[], place: IPlaceResource, model: Lodging | Poi) => { const places = getPlaces(included, ancestry); const result = place.attributes.place_type === type ? place : places.find((p: IPlaceResource) => p.attributes.place_type === type); if (result) { Object.assign( model, assignments.reduce((acc, assignment) => { const assignmentKey = `containing${capitalize(type)}${capitalize(assignment)}`; // e.g. "containingCityName", "containingNeighborhoodId". const assignmentValue = result[assignment] || result.attributes && result.attributes[assignment]; return { ...acc, [assignmentKey]: assignmentValue, }; }, {}), ); ifFound(result, model); } }; export const assignRegions = (included: IJsonApiResource[], ancestry: IPlaceResource[], place: IPlaceResource, model: Lodging | Poi) => { /** * Special case for regions, as there seem to be multiple for a given POI. */ const places = getPlaces(included, ancestry); const regions = place.attributes.place_type === "region" ? [place] : places.filter((p: IPlaceResource) => p.attributes.place_type === "region"); const regionNames = regions.map(({ attributes }) => attributes.name); if (regionNames.length > 0) { model.containingRegionNames = regionNames; } }; export const assignCity = createPlaceTypeAssigner("city"); export const assignContinent = createPlaceTypeAssigner("continent"); export const assignCountry = createPlaceTypeAssigner("country", ["name"], (result, model) => { if (model.telephone) { model.telephone.callingCode = `+${result.attributes.calling_code}`; } if (model.poi && model.poi.telephone) { model.poi.telephone.callingCode = `+${result.attributes.calling_code}`; } }); export const assignNeighborhood = createPlaceTypeAssigner("neighborhood");