From 7c88f723d13c3c2f94ba7d33bc0c36d170d569bb Mon Sep 17 00:00:00 2001 From: Max Morgan Date: Tue, 28 May 2024 18:56:08 -0400 Subject: [PATCH] Fetch schedules dynamically in calendar --- src/components/App.js | 4 +- src/components/Cal.js | 203 +++++++++++++++++++----------------------- src/utils/WasteAPI.js | 16 +++- 3 files changed, 112 insertions(+), 111 deletions(-) diff --git a/src/components/App.js b/src/components/App.js index 6c8046f..ff122f0 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -18,6 +18,7 @@ export default class App { this.calendar = new Cal('calendar', this);; this.panel = new Panel(this); this.geocoder = new Geocoder('geocoder', this); + this.routeNum = null; this.initialLoad(this); } @@ -94,7 +95,8 @@ export default class App { } _app.map.flyTo(tempLocation, 15); _app.panel.currentProvider = featureCollection.features[0].properties.contractor; - const wasteAPIEndpoint = buildWasteAPI(featureCollection.features[0].properties.FID, _app.year, _app.month); + _app.routeNum = featureCollection.features[0].properties.FID; + const wasteAPIEndpoint = buildWasteAPI(_app.routeNum, _app.year, _app.month); fetch(wasteAPIEndpoint) .then((res) => { res.json().then(data => { diff --git a/src/components/Cal.js b/src/components/Cal.js index 2cc199d..1b6e46c 100644 --- a/src/components/Cal.js +++ b/src/components/Cal.js @@ -1,12 +1,12 @@ import { Calendar } from '@fullcalendar/core'; import dayGridPlugin from '@fullcalendar/daygrid'; import moment from 'moment'; +import { buildWasteAPI, PICKUP_TYPES, PICKUP_TYPES_PRINT } from '../utils/WasteAPI'; import './Cal.scss'; export default class Cal { constructor(container, _controller) { this.calendar = null; this.controller = _controller; - this.pickups = []; } createCalendar(_app){ @@ -30,131 +30,116 @@ export default class Cal { `; tempCal.appendChild(calContainer); tempCal.prepend(closeBtn); - _app.calendar.buildSchedule(_app); _app.calendar.calendar = new Calendar(calContainer, { plugins: [ dayGridPlugin ], - eventSources: _app.calendar.pickups + showNonCurrentDates: false, + eventSources: [ + { + events: this.fetchTrashPickups.bind(this), + color: '#cb4d4f', + textColor: 'white' + }, + { + events: this.fetchRecyclingPickups.bind(this), + color: '#9FD5B3', + textColor: '#004445' + }, + { + events: this.fetchBulkPickups.bind(this), + color: '#5f355a', + textColor: 'white' + }, + { + events: this.fetchYardPickups.bind(this), + color: '#feb70d', + textColor: 'black' + } + ], }); _app.calendar.calendar.render(); document.querySelector('#app .calendar').className = "calendar active"; } - buildSchedule(_app){ - _app.calendar.buildPickUps(_app); + fetchPickups(info, successCb, failureCb, pickupType, routeNum, eventBuilder) { + const month = info.start.getMonth() + 1; + const wasteAPIEndpoint = buildWasteAPI(routeNum, info.start.getFullYear(), month); + fetch(wasteAPIEndpoint) + .then((res) => { + res.json().then((data) => { + const events = eventBuilder(data, pickupType); + successCb(events); + }) + }) + .catch((error) => { + console.error(error); + failureCb(error); + }); } - buildPickUps(_app){ - let pastDate = _app.schedule.recycle; - let latestDate = _app.schedule.recycle; - let pastTrashDate = _app.schedule.garbage; - let trashDate = _app.schedule.garbage; + fetchTrashPickups(info, successCb, failureCb) { + this.fetchPickups( + info, + successCb, + failureCb, + PICKUP_TYPES.TRASH, + this.controller.routeNum, + this.buildPickUps + ); + } - let gList = { - events: [ - { - title : 'Trash', - start : moment(trashDate).format('YYYY-MM-DD'), - } - ], - color: '#cb4d4f', // an option! - textColor: 'white' // an option! - }; - let rList = { - events: [ - { - title : 'Recycle', - start : moment(latestDate).format('YYYY-MM-DD'), - } - ], - color: '#9FD5B3', // an option! - textColor: '#004445' // an option! - }; - let bList = { - events: [ - { - title : 'Bulk', - start : moment(latestDate).format('YYYY-MM-DD'), - } - ], - color: '#5f355a', // an option! - textColor: 'white' // an option! - }; - let yList = { - events: [], - color: '#feb70d', // an option! - textColor: 'black' // an option! - } - if(moment(latestDate).isBetween(_app.schedule.yard.start, _app.schedule.yard.end)){ - yList.events.push( - { - title : 'Yard', - start : moment(latestDate).format('YYYY-MM-DD'), - } - ); - } - for (let index = 0; index < 52; index++) { - let tempG = { - title : 'Trash', - start : moment(trashDate).add(7,'d').format('YYYY-MM-DD'), - }; - let pasttempG = { - title : 'Trash', - start : moment(pastTrashDate).subtract(7,'d').format('YYYY-MM-DD'), - }; - trashDate = moment(trashDate).add(7,'d'); - pastTrashDate = moment(pastTrashDate).subtract(7,'d'); - gList.events.push(tempG); - gList.events.push(pasttempG); - } + fetchRecyclingPickups(info, successCb, failureCb) { + this.fetchPickups( + info, + successCb, + failureCb, + PICKUP_TYPES.RECYCLING, + this.controller.routeNum, + this.buildPickUps + ); + } - for (let index = 0; index < 26; index++) { - let tempR = { - title : 'Recycle', - start : moment(latestDate).add(14,'d').format('YYYY-MM-DD'), - }; - let tempB = { - title : 'Bulk', - start : moment(latestDate).add(14,'d').format('YYYY-MM-DD'), - }; - if(moment(latestDate).add(14,'d').isBetween(_app.schedule.yard.start, _app.schedule.yard.end)){ - let tempY = { - title : 'Yard', - start : moment(latestDate).add(14,'d').format('YYYY-MM-DD'), - }; - yList.events.push(tempY); - } - let pasttempR = { - title : 'Recycle', - start : moment(pastDate).subtract(14,'d').format('YYYY-MM-DD'), - }; - let pasttempB = { - title : 'Bulk', - start : moment(pastDate).subtract(14,'d').format('YYYY-MM-DD'), - }; - if(moment(pastDate).subtract(14,'d').isBetween(_app.schedule.yard.start, _app.schedule.yard.end)){ - let pasttempY = { - title : 'Yard', - start : moment(pastDate).subtract(14,'d').format('YYYY-MM-DD'), - }; - yList.events.push(pasttempY); + fetchYardPickups(info, successCb, failureCb) { + this.fetchPickups( + info, + successCb, + failureCb, + PICKUP_TYPES.YARD_WASTE, + this.controller.routeNum, + this.buildPickUps + ); + } + + fetchBulkPickups(info, successCb, failureCb) { + this.fetchPickups( + info, + successCb, + failureCb, + PICKUP_TYPES.BULK, + this.controller.routeNum, + this.buildPickUps + ); + } + + buildPickUps(eventData, pickupType){ + let events = []; + eventData.schedule.forEach((pickupDateDetails) => { + for (const [pickupDate, pickupTypeDetails] of Object.entries(pickupDateDetails)) { + if (pickupType in pickupTypeDetails) { + events.push( + { + title : PICKUP_TYPES_PRINT[pickupType], + start : moment(pickupDate).format('YYYY-MM-DD'), + } + ); + } } - pastDate = moment(pastDate).subtract(14,'d'); - latestDate = moment(latestDate).add(14,'d'); - rList.events.push(tempR); - bList.events.push(tempB); - rList.events.push(pasttempR); - bList.events.push(pasttempB); - } - _app.calendar.pickups.push(gList); - _app.calendar.pickups.push(rList); - _app.calendar.pickups.push(bList); - _app.calendar.pickups.push(yList); + }); + return events; } closeCalendar(ev,_calendar){ _calendar.calendar.destroy(); _calendar.calendar = null; - _calendar.pickups.length = 0; let tempClass = ev.target.parentNode.parentNode.className; tempClass = tempClass.split(' '); ev.target.parentNode.parentNode.className = tempClass[0]; diff --git a/src/utils/WasteAPI.js b/src/utils/WasteAPI.js index 6b7dbcb..095c335 100644 --- a/src/utils/WasteAPI.js +++ b/src/utils/WasteAPI.js @@ -9,4 +9,18 @@ function buildWasteAPI(routeNum, year, month) { return `https://apis.detroitmi.gov/waste_schedule/details/${routeNum}/year/${year}/month/${month}/`; } -export {buildWasteAPI}; \ No newline at end of file +const PICKUP_TYPES = Object.freeze({ + TRASH: "trash", + RECYCLING: "recycling", + BULK: "bulk", + YARD_WASTE: "yard waste" +}); + +const PICKUP_TYPES_PRINT = Object.freeze({ + "trash": "Trash", + "recycling": "Recycling", + "bulk": "Bulk", + "yard waste": "Yard Waste" +}); + +export {buildWasteAPI, PICKUP_TYPES, PICKUP_TYPES_PRINT}; \ No newline at end of file