{"id":13787392,"url":"https://github.com/busbud/coding-challenge-frontend-b","last_synced_at":"2025-04-16T01:26:22.661Z","repository":{"id":2555584,"uuid":"46835021","full_name":"busbud/coding-challenge-frontend-b","owner":"busbud","description":"A microsite that lists bus travel schedules for a given route and a given date ","archived":false,"fork":false,"pushed_at":"2023-06-23T14:21:56.000Z","size":144,"stargazers_count":24,"open_issues_count":0,"forks_count":123,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-15T17:54:39.682Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/busbud.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-11-25T03:29:14.000Z","updated_at":"2025-01-23T07:02:16.000Z","dependencies_parsed_at":"2024-08-03T20:02:10.277Z","dependency_job_id":"e022005e-b427-4ef9-96d6-44c230296192","html_url":"https://github.com/busbud/coding-challenge-frontend-b","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/busbud%2Fcoding-challenge-frontend-b","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/busbud%2Fcoding-challenge-frontend-b/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/busbud%2Fcoding-challenge-frontend-b/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/busbud%2Fcoding-challenge-frontend-b/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/busbud","download_url":"https://codeload.github.com/busbud/coding-challenge-frontend-b/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249181076,"owners_count":21225840,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T20:00:33.659Z","updated_at":"2025-04-16T01:26:22.640Z","avatar_url":"https://github.com/busbud.png","language":null,"funding_links":[],"categories":["React.js"],"sub_categories":[],"readme":"# Busbud Front-End Coding Challenge\n\n![osheaga](https://cloud.githubusercontent.com/assets/1574577/12971188/13471bd0-d066-11e5-8729-f0ca5375752e.png)\n\nIt will be hot this summer in Montreal with the [Osheaga festival](http://www.osheaga.com/)! \nYour challenge is to build a microsite that allows a traveler from Québec to find one-way departure schedules for the festival's opening weekend.\n\n## Functional requirements\n\n- Has a simple onboarding screen that will trigger the departure search\n- Lists all the departures for a given origin city (**Québec - geohash: f2m673**) and a given destination city (**Montréal - geohash: f25dvk**) for a given day (**the 2nd of August 2021**) for **1** adult.\n- For each departure, we want, at least, to see the **departure time**, the **arrival time**, the **location name** and the **price** (use `prices.total` of the `departure`).\n\n## Non-functional requirements\n\n- Challenge is submitted as pull request against this repo ([fork it](https://help.github.com/articles/fork-a-repo/) and [create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).\n- The microsite should be deployed to [Heroku](https://devcenter.heroku.com/articles/getting-started-with-nodejs).\n\n### Bonus\n\n* Localization: support for multiple languages (English, French, ...)\n* Responsive design\n\n### Remarks\n\n* You can setup your microsite any way you like; we're partial to NodeJS, ExpressJS and React\n* CSS can be written using SASS, LESS or similar higher-level language\n\n### Things that are important to us\n\n- Code quality, maintainability and readability\n- Attention to the User Experience\n\n### Things you'll not be evaluated on\n\n- Features we didn't list in this README\n- The quantity of code you write\n\n# Documentation\n\n## Supporting API\n\nThe following documentation describes the API you'll need to use to build out the challenge deliverable.\n\nThe API you'll be using is hosted at https://napi.busbud.com. This is the Busbud production API.\n\nTo interact with it from your code, you'll need to provide the following HTTP headers\n\nHTTP Header | Value\n------------|------\nAccept | `application/vnd.busbud+json; version=2; profile=https://schema.busbud.com/v2/`\nX-Busbud-Token | value provided in challenge invitation email (if not contact us)\n\n### Search overview\n\nSearch is performed in two steps\n\n1. A [search is initialized](#initialize-search), and may be `complete` if results are served from cache\n2. An initialized and incomplete [search is polled](#poll-search) until `complete`\n\n### Initialize search\n\nInitiating kicks off a search against the various supplier systems if one has yet to be started. It also includes a wealth of related models (cities, locations, operators, etc) in its response to ensure a client has all the context necessary to present a compelling experience to the user. If the cache already holds departures for the requested search, the departures will be returned as part of the response.\n\nTo get departures, search is initialized via the following endpoint:\n\n    https://napi.busbud.com/x-departures/:origin/:destination/:outbound_date\n\nPath parameters:  \n\n- `origin` : Origin's geohash\n- `destination` : Destination's geohash\n- `outbound_date` : ISO 8601 Outbound departure date\n\nQuerystring parameters:\n\n- `adult` : Number of adults\n- `child` : Number of children\n- `senior` : Number of seniors\n- `lang` :  ISO 639-1 (2 letter code) language code (supported values include `en`, `fr`, `es`, and a few others)\n- `currency` : ISO 4217 currency code (supported values include `CAD`, `USD`, `EUR`, and a few others)\n\nThe response looks like:\n```\n{\n  \"origin_city_id\": \"375dd5879001acbd84a4683dedf9eed1\",\n  \"destination_city_id\": \"375dd5879001acbd84a4683ded9c875b\",\n  \"cities\": [\n    { City },\n    { City }\n  ],\n  \"locations\": [\n    { Location }\n    { Location }\n  ],\n  \"operators\": [\n    { Operator },\n    { Operator }\n  ],\n  \"departures\": [\n    { XDeparture },\n    { XDeparture }\n  ],\n  \"complete\": false,    // \u003c!-- determines if all departures have been received from all relevant bus companies\n  \"ttl\": 900,\n  \"is_valid_route\": true\n}\n```\n\nWhere a City is like:\n```\n   {\n      \"id\": \"375dd5879001acbd84a4683deda84183\",\n      \"locale\": \"en\",\n      \"region_id\": 6417,\n      \"name\": \"New York\",\n      \"lat\": 40.71427,\n      \"lon\": -74.00597,\n      \"geohash\": \"dr5reg\",\n      \"timezone\": \"America/New_York\",\n      \"image_url\": \"/images/promos/city-blocks/new-york.jpg\",\n      \"legacy_url_form\": \"NewYork,NewYork,UnitedStates\",\n      \"full_name\": \"New York, New York, United States\",\n      \"region\": {\n        \"id\": 6417,\n        \"locale\": \"en\",\n        \"country_code2\": \"US\",\n        \"name\": \"New York\",\n        \"country\": {\n          \"code2\": \"US\",\n          \"locale\": \"en\",\n          \"code3\": \"USA\",\n          \"name\": \"United States\",\n          \"continent\": \"NA\",\n          \"default_locale\": \"en\",\n          \"default_currency\": \"USD\",\n          \"population\": 310232863\n        }\n      }\n    }\n```\n\nWhere a Location is like:\n```\n    {\n      \"id\": 3970,\n      \"city_id\": \"375dd5879001acbd84a4683dedfb933e\",\n      \"name\": \"Métro Bonaventure Bus Station\",\n      \"address\": [\n        \"997 Rue St-Antoine Ouest\",\n        \"Montreal, QC H3C 1A6\"\n      ],\n      \"type\": \"transit_station\",\n      \"lat\": 45.4988273060484,\n      \"lon\": -73.5644745826722,\n      \"geohash\": \"f25dvfzcz\"\n    }\n```\n\nWhere an Operator is like:\n```\n    {\n      \"id\": \"bfc27cd544ca49c18d000f2bc00c58c0\",\n      \"source_id\": 155,\n      \"profile_id\": 111,\n      \"name\": \"Greyhound\",\n      \"url\": null,\n      \"logo_url\": \"https://busbud.imgix.net/operator-logos/logo_greyhound-og.png.png?h={height}\u0026w={width}\u0026auto=format\u0026fit=fill\u0026bg=0FF\",\n      \"display_name\": \"Greyhound\",\n      \"sellable\": true,\n      \"fuzzy_prices\": false,\n      \"sell_tickets_cutoff\": {\n        \"hours\": 1\n      },\n      \"amenities\": {\n        \"classes\": {\n          \"Normal\": {\n            \"display_name\": \"Economy\",\n            \"wifi\": true,\n            \"toilet\": true,\n            \"ac\": true,\n            \"food\": false,\n            \"refreshment\": false,\n            \"power_outlets\": true,\n            \"tv\": false,\n            \"bus_attendant\": false,\n            \"leg_room\": false\n          },\n          \"Economy\": {\n            \"display_name\": \"Economy\",\n            \"wifi\": true,\n            \"toilet\": true,\n            \"ac\": true,\n            \"food\": false,\n            \"refreshment\": false,\n            \"power_outlets\": true,\n            \"tv\": false,\n            \"bus_attendant\": false,\n            \"leg_room\": false\n          }\n        }\n      },\n      \"source\": \"greyhound_us\",\n      \"referral_deal\": false,\n      \"display_url\": null,\n      \"fraud_check\": \"iovation\",\n      \"terms\": {\n        \"refund\": false,\n        \"exchange\": true,\n        \"bag_allowed\": true,\n        \"piece_of_id\": false,\n        \"boarding_requirement\": \"printed_tkt\",\n        \"extra_bag_policy\": true,\n        \"use_new_ticket\": false,\n        \"exchange_cutoff\": 24,\n        \"nb_checked_bags\": 1,\n        \"kg_by_bag\": 25,\n        \"nb_carry_on\": 1,\n        \"extra_bag_cost\": 1500\n      }\n    }\n```\n\nAnd an XDeparture is like:\n```\n    {\n      \"id\": \"7c5dd26a\",\n      \"source_id\": 155,\n      \"checkout_type\": \"new\",\n      \"operator_id\": \"bfc27cd544ca49c18d000f2bc00c58c0\",\n      \"origin_location_id\": 1942,\n      \"destination_location_id\": 1938,\n      \"class\": \"Economy\",\n      \"class_name\": \"Economy\",\n      \"amenities\": {\n        \"display_name\": \"Economy\",\n        \"wifi\": true,\n        \"toilet\": true,\n        \"ac\": true,\n        \"food\": false,\n        \"refreshment\": false,\n        \"power_outlets\": true,\n        \"tv\": false,\n        \"bus_attendant\": false,\n        \"leg_room\": false\n      },\n      \"available_seats\": 55,\n      \"prices\": {\n        \"total\": 5200,\n        \"breakdown\": {\n          \"base\": 5200\n        },\n        \"categories\": {},\n        \"discounted\": false\n      },\n      \"ticket_types\": [\n        \"print\"\n      ],\n      \"departure_timezone\": \"America/New_York\",\n      \"arrival_timezone\": \"America/Montreal\",\n      \"departure_time\": \"2016-01-14T00:01:00\",\n      \"arrival_time\": \"2016-01-14T07:55:00\"\n    }\n```\n\n### Poll search\n\nPolling provides incremental updates from the [initial search](#initialize-search) attempt. _Polling can only be performed after a successful fetch has been initiated_. The response contains a `complete` property which indicates if the system is done fetching departures from bus companies. The polling endpoints should be called every 2-5 seconds until `complete` is true.\n\nTo avoid getting the same departures data multiple times, Busbud supports pagination starting at arbitrary indices using the `index` querystring parameter. For example, if after the first polling request 10 departures are returned and `complete` is false, the second polling request should use `?index=10` to only get new departures.\n\n\u003e **Tip**\n\u003e\n\u003e Incremental updates are only available during the small period of time when Busbud is retrieving departures from bus companies. Once departures for a specific date and set of passengers are obtained, they are saved in a cache for a period of time.\n\u003e\n\u003e Although the cache cannot be bypassed, you can change the date or the number of passengers to trigger a new search and obtain incremental updates.\n\nWhile the `complete` property from the response is false, you need to call:\n\n    https://napi.busbud.com/x-departures/:origin/:destination/:outbound_date/poll\n\nwith ***all*** the same parameters as the previous endpoint, plus the following additional querystring parameter:\n\n- `index` : Index from which to return new departures, generally set to the total number of departures received since the initial search\n\nThe response is similar to:\n```\n{\n  \"departures\": [\n    { XDeparture },\n    { XDeparture }\n  ],\n  \"operators\": [\n    { Operator },\n    { Operator }\n  ],\n  \"complete\": true,\n  \"ttl\": 900\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbusbud%2Fcoding-challenge-frontend-b","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbusbud%2Fcoding-challenge-frontend-b","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbusbud%2Fcoding-challenge-frontend-b/lists"}