diff --git a/src/modules/api/yelp.cr b/src/modules/api/yelp.cr index 494ce58..d6baa87 100644 --- a/src/modules/api/yelp.cr +++ b/src/modules/api/yelp.cr @@ -1,9 +1,73 @@ require "http/client" require "io" +require "json" module Wince::Yelp extend self + class SearchResponse + include JSON::Serializable + property businesses : Array(Business)? + property error : Error? + end + + class Error + include JSON::Serializable + property code : String + property description : String + end + + class Business + include JSON::Serializable + property id : String + property name : String + property rating : Float32 + property distance : Float32 + end + + class DetailsResponse + include JSON::Serializable + property error : Error? + property name : String + property price : String? + property display_phone : String? + property location : Location + property coordinates : Coordinates + property url : String + property hours : Array(Hours) + + def is_open + hours[0].is_open_now + end + end + + class Coordinates + include JSON::Serializable + property latitude : Float32 + property longitude : Float32 + end + + class Location + include JSON::Serializable + property display_address : Array(String) + end + + class Hours + include JSON::Serializable + property open : Array(Open) + property is_open_now : Bool + end + + class Open + include JSON::Serializable + property is_overnight : Bool + @[JSON::Field(key: "start")] + property open : String + @[JSON::Field(key: "end")] + property close : String + property day : Int32 + end + @@token : String = {{ read_file("./api_key") }} def search_businesses(search : String, location : String) @@ -21,6 +85,8 @@ module Wince::Yelp ) headers = HTTP::Headers{ "Authorization" => "Bearer " + @@token } response = HTTP::Client.get(uri, headers) + + {response.status_code, SearchResponse.from_json(response.body)} end def get_business_info(id : String) @@ -32,6 +98,8 @@ module Wince::Yelp ) headers = HTTP::Headers{ "Authorization" => "Bearer " + @@token } response = HTTP::Client.get(uri, headers) + + {response.status_code, DetailsResponse.from_json(response.body)} end end diff --git a/src/modules/utils/utils.cr b/src/modules/utils/utils.cr index 20cd7ac..069eeea 100644 --- a/src/modules/utils/utils.cr +++ b/src/modules/utils/utils.cr @@ -3,13 +3,12 @@ require "time" # yeah me too module Wince::Utils extend self - def hours_for_day(hours_json : JSON::Any, day : Time::DayOfWeek, seperator : String) - open = hours_json[0]["open"].as_a + def hours_for_day(hours : Yelp::Hours, day : Time::DayOfWeek, seperator : String) day_number = day_of_week_to_int(day) - formatted_hours = open.select { |hour| hour["day"].as_i == day_number }.map { |hour| - start_hour = hour["start"].as_s - end_hour = hour["end"].as_s + formatted_hours = hours.open.select { |hour| hour.day == day_number }.map { |hour| + start_hour = hour.open + end_hour = hour.close "#{start_hour.insert(2, ":")}-#{end_hour.insert(2, ":")}" }.join(seperator) @@ -34,11 +33,7 @@ module Wince::Utils end end - def format_address(display_address_json : JSON::Any) - display_address_json.as_a.map { |line| line.as_s? || "" }.join("\n") + def format_address(display_address : Array(String)) + display_address.join("\n") end - - def load_url_to_image(url : String, image : Gtk::Image) - - end -end \ No newline at end of file +end diff --git a/src/modules/views/main.cr b/src/modules/views/main.cr index 15ab635..1385834 100644 --- a/src/modules/views/main.cr +++ b/src/modules/views/main.cr @@ -1,4 +1,3 @@ -require "json" require "time" require "../templates/businessrow.cr" @@ -71,17 +70,13 @@ module Wince end end - def yelp_response_to_business_ids(response : JSON::Any) - response["businesses"].as_a.map { |b| b["id"].as_s } + def yelp_response_to_business_ids(businesses : Array(Yelp::Business)) + businesses.map { |b| b.id } end - def yelp_response_to_business_rows(response : JSON::Any) - response["businesses"].as_a.map do |business| - name = business["name"].as_s? || "" - rating = business["rating"].as_f32 - distance = business["distance"].as_f32 - - BusinessRow.new(name, rating, distance) + def yelp_response_to_business_rows(businesses : Array(Yelp::Business)) + businesses.map do |business| + BusinessRow.new(business.name, business.rating, business.distance) end end @@ -106,19 +101,23 @@ module Wince LEAFLET.visible = true POWERD_BY_TEXT.visible = false - response = Yelp.search_businesses(search, location) + status_code, response = Yelp.search_businesses(search, location) - if response.status_code != 200 + if status_code != 200 puts "api call error" - puts response.body + if response.error.is_a? Yelp::Error + puts response.error.as(Yelp::Error).description + end return #TODO: show a toast here end - response_json = JSON.parse(response.body) + # this can technically fail if we get a weird case of a 200 response + # but a malformed response, but it's probably fine + businesses = response.businesses.as(Array(Yelp::Business)) clear_business_rows() - @@business_ids = yelp_response_to_business_ids(response_json) - @@business_rows = yelp_response_to_business_rows(response_json) + @@business_ids = yelp_response_to_business_ids(businesses) + @@business_rows = yelp_response_to_business_rows(businesses) @@business_rows.each do |row| BUSINESS_LIST.append(row) end @@ -128,37 +127,36 @@ module Wince index = @@business_rows.index(BUSINESS_LIST.selected_row) || 0 id = @@business_ids[index] - response = Yelp.get_business_info(id) + status_code, response = Yelp.get_business_info(id) - if response.status_code != 200 + if status_code != 200 puts "api call error" - puts response.body + if response.error.is_a? Yelp::Error + puts response.error.as(Yelp::Error).description + end return #TODO: show a toast here end - response_json = JSON.parse(response.body) - DETAILS_TITLE.text = response_json["name"].as_s? || "" + DETAILS_TITLE.text = response.name || "" - is_open = response_json["hours"][0]["is_open_now"].as_bool? || false - - if is_open + if response.is_open DETAILS_IS_OPEN.markup = "open" else DETAILS_IS_OPEN.markup = "closed" end - DETAILS_CURRENT_HOURS.text = Utils.hours_for_day(response_json["hours"], Time.local.day_of_week, ", ") - DETAILS_PRICING.text = response_json["price"].as_s? || "" - DETAILS_ADDRESS.markup = Utils.format_address(response_json["location"]["display_address"]) - DETAILS_PHONE.text = response_json["display_phone"].as_s? || "no phone number" - DETAILS_URL.uri = response_json["url"].as_s? || "" + DETAILS_CURRENT_HOURS.text = Utils.hours_for_day(response.hours[0], Time.local.day_of_week, ", ") + DETAILS_PRICING.text = response.price || "" + DETAILS_ADDRESS.markup = Utils.format_address(response.location.display_address) + DETAILS_PHONE.text = response.display_phone || "no phone number" + DETAILS_URL.uri = response.url || "" clear_hour_rows() - @@hour_rows = format_hours(response_json["hours"]) + @@hour_rows = format_hours(response.hours[0]) @@hour_rows.each { |hour_row| DETAILS_HOURS_BOX.append(hour_row) } - set_map_location(response_json["coordinates"]) + set_map_location(response.coordinates) # If we're in the small layout we want to show the back button if LEAFLET.folded @@ -171,21 +169,18 @@ module Wince LEAFLET.visible_child = DETAILS_SCROLL end - def set_map_location(coordinates : JSON::Any) - latitude = coordinates["latitude"].as_f - longitude = coordinates["longitude"].as_f - + def set_map_location(coordinates : Yelp::Coordinates) viewport = DETAILS_MAP.viewport - viewport.set_location(latitude, longitude) + viewport.set_location(coordinates.latitude, coordinates.longitude) viewport.zoom_level = 16 - @@marker.try {|m| m.set_location(latitude, longitude) } + @@marker.try {|m| m.set_location(coordinates.latitude, coordinates.longitude) } end - def format_hours(hours_json : JSON::Any) + def format_hours(hours : Yelp::Hours) Time::DayOfWeek.values.map do |day| - hours = Utils.hours_for_day(hours_json, day, "\n") - HourRow.new(day, hours) + hours_for_day = Utils.hours_for_day(hours, day, "\n") + HourRow.new(day, hours_for_day) end end