diff --git a/app/controllers/api/v1/countries/visited_cities_controller.rb b/app/controllers/api/v1/countries/visited_cities_controller.rb new file mode 100644 index 00000000..2b79ffd7 --- /dev/null +++ b/app/controllers/api/v1/countries/visited_cities_controller.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class Api::V1::Countries::VisitedCitiesController < ApiController + before_action :validate_params + + def index + start_at = DateTime.parse(params[:start_at]).to_i + end_at = DateTime.parse(params[:end_at]).to_i + + points = current_api_user + .tracked_points + .where(timestamp: start_at..end_at) + + render json: { data: CountriesAndCities.new(points).call } + end + + private + + def validate_params + missing_params = %i[start_at end_at].select { |param| params[param].blank? } + + if missing_params.any? + render json: { + error: "Missing required parameters: #{missing_params.join(', ')}" + }, status: :bad_request and return + end + + params.permit(:start_at, :end_at) + end +end diff --git a/app/helpers/api/v1/points/tracked_months_helper.rb b/app/helpers/api/v1/points/tracked_months_helper.rb deleted file mode 100644 index 7be4d70a..00000000 --- a/app/helpers/api/v1/points/tracked_months_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module Api::V1::Points::TrackedMonthsHelper -end diff --git a/app/javascript/controllers/maps_controller.js b/app/javascript/controllers/maps_controller.js index d4ed8c3a..9170f534 100644 --- a/app/javascript/controllers/maps_controller.js +++ b/app/javascript/controllers/maps_controller.js @@ -958,8 +958,9 @@ export default class extends Controller { } else { this.map.addControl(this.rightPanel); localStorage.setItem('mapPanelOpen', 'true'); + // Fetch visited cities when panel is opened + this.fetchAndDisplayVisitedCities(); } - return; } @@ -1008,6 +1009,7 @@ export default class extends Controller { `).join('')} + `; @@ -1141,6 +1143,24 @@ export default class extends Controller { L.DomEvent.disableClickPropagation(div); + // Add container for visited cities + div.innerHTML += ` +
+

Visited cities

+
+

Loading visited places...

+
+
+ `; + + // Prevent map zoom when scrolling the cities list + const citiesList = div.querySelector('#visited-cities-list'); + L.DomEvent.disableScrollPropagation(citiesList); + + // Fetch visited cities when panel is first created + this.fetchAndDisplayVisitedCities(); + return div; }; @@ -1187,5 +1207,71 @@ export default class extends Controller { const endDate = `${year}-12-31T23:59`; return `map?end_at=${encodeURIComponent(endDate)}&start_at=${encodeURIComponent(startDate)}`; } + + async fetchAndDisplayVisitedCities() { + const urlParams = new URLSearchParams(window.location.search); + const startAt = urlParams.get('start_at') || new Date().toISOString(); + const endAt = urlParams.get('end_at') || new Date().toISOString(); + + try { + const response = await fetch(`/api/v1/countries/visited_cities?api_key=${this.apiKey}&start_at=${startAt}&end_at=${endAt}`, { + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + } + }); + + if (!response.ok) { + throw new Error('Network response was not ok'); + } + + const data = await response.json(); + this.displayVisitedCities(data.data); + } catch (error) { + console.error('Error fetching visited cities:', error); + const container = document.getElementById('visited-cities-list'); + if (container) { + container.innerHTML = '

Error loading visited places

'; + } + } + } + + displayVisitedCities(citiesData) { + const container = document.getElementById('visited-cities-list'); + if (!container) return; + + if (!citiesData || citiesData.length === 0) { + container.innerHTML = '

No places visited during this period

'; + return; + } + + const html = citiesData.map(country => ` +
+

${country.country}

+ +
+ `).join(''); + + container.innerHTML = html; + } + + formatDuration(seconds) { + const days = Math.floor(seconds / (24 * 60 * 60)); + const hours = Math.floor((seconds % (24 * 60 * 60)) / (60 * 60)); + + if (days > 0) { + return `${days}d ${hours}h`; + } + return `${hours}h`; + } } diff --git a/config/routes.rb b/config/routes.rb index 8f179cfa..ebad44e5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -78,6 +78,7 @@ Rails.application.routes.draw do namespace :countries do resources :borders, only: :index + resources :visited_cities, only: :index end namespace :points do diff --git a/spec/requests/api/v1/countries/visited_cities_spec.rb b/spec/requests/api/v1/countries/visited_cities_spec.rb new file mode 100644 index 00000000..88441b3a --- /dev/null +++ b/spec/requests/api/v1/countries/visited_cities_spec.rb @@ -0,0 +1,7 @@ +require 'rails_helper' + +RSpec.describe "Api::V1::Countries::VisitedCities", type: :request do + describe "GET /index" do + pending "add some examples (or delete) #{__FILE__}" + end +end