From 40a7c041d19d2c61b93e8d100b68d1b8c94dc6a6 Mon Sep 17 00:00:00 2001 From: Brian Rogers Date: Fri, 9 Jan 2026 17:41:52 -0700 Subject: [PATCH] adding base of JSON API for others to consume --- .../Controllers/Api/WeatherController.php | 134 ++++++++++++++++++ bootstrap/app.php | 1 + routes/api.php | 6 + 3 files changed, 141 insertions(+) create mode 100644 app/Http/Controllers/Api/WeatherController.php create mode 100644 routes/api.php diff --git a/app/Http/Controllers/Api/WeatherController.php b/app/Http/Controllers/Api/WeatherController.php new file mode 100644 index 0000000..f6a1e99 --- /dev/null +++ b/app/Http/Controllers/Api/WeatherController.php @@ -0,0 +1,134 @@ + $this->getCurrentConditions(), + 'daily' => $this->getDailyForecast(), + 'weekly' => $this->getWeeklyForecast(), + }; + } + + private function getCurrentConditions(): JsonResponse + { + $latestHourly = WeatherReport::query() + ->where('type', 'hourly') + ->with('periods') + ->orderByDesc('reported_at') + ->first(); + + $currentPeriod = $latestHourly?->periods->first(); + + if (! $currentPeriod) { + return response()->json(['error' => 'No current conditions available'], 404); + } + + return response()->json([ + 'period' => 'now', + 'reportedAt' => $latestHourly->reported_at->toIso8601String(), + 'location' => [ + 'latitude' => $latestHourly->latitude, + 'longitude' => $latestHourly->longitude, + ], + 'conditions' => [ + 'temperature' => $currentPeriod->temperature, + 'temperatureUnit' => $currentPeriod->temperature_unit, + 'shortForecast' => $currentPeriod->short_forecast, + 'detailedForecast' => $currentPeriod->detailed_forecast, + 'windSpeed' => $currentPeriod->wind_speed, + 'windDirection' => $currentPeriod->wind_direction, + 'humidity' => $currentPeriod->relative_humidity, + 'dewpointCelsius' => $currentPeriod->dewpoint_celsius, + 'precipitationProbability' => $currentPeriod->precipitation_probability, + 'isDaytime' => $currentPeriod->is_daytime, + 'startTime' => $currentPeriod->start_time->toIso8601String(), + 'endTime' => $currentPeriod->end_time->toIso8601String(), + ], + ]); + } + + private function getDailyForecast(): JsonResponse + { + $latestHourly = WeatherReport::query() + ->where('type', 'hourly') + ->with('periods') + ->orderByDesc('reported_at') + ->first(); + + if (! $latestHourly || $latestHourly->periods->isEmpty()) { + return response()->json(['error' => 'No daily forecast available'], 404); + } + + $periods = $latestHourly->periods->map(fn ($period) => [ + 'periodNumber' => $period->period_number, + 'startTime' => $period->start_time->toIso8601String(), + 'endTime' => $period->end_time->toIso8601String(), + 'isDaytime' => $period->is_daytime, + 'temperature' => $period->temperature, + 'temperatureUnit' => $period->temperature_unit, + 'shortForecast' => $period->short_forecast, + 'windSpeed' => $period->wind_speed, + 'windDirection' => $period->wind_direction, + 'humidity' => $period->relative_humidity, + 'precipitationProbability' => $period->precipitation_probability, + ]); + + return response()->json([ + 'period' => 'daily', + 'reportedAt' => $latestHourly->reported_at->toIso8601String(), + 'location' => [ + 'latitude' => $latestHourly->latitude, + 'longitude' => $latestHourly->longitude, + ], + 'periods' => $periods, + ]); + } + + private function getWeeklyForecast(): JsonResponse + { + $latestWeekly = WeatherReport::query() + ->where('type', 'weekly') + ->with('periods') + ->orderByDesc('reported_at') + ->first(); + + if (! $latestWeekly || $latestWeekly->periods->isEmpty()) { + return response()->json(['error' => 'No weekly forecast available'], 404); + } + + $periods = $latestWeekly->periods->map(fn ($period) => [ + 'periodNumber' => $period->period_number, + 'name' => $period->name, + 'startTime' => $period->start_time->toIso8601String(), + 'endTime' => $period->end_time->toIso8601String(), + 'isDaytime' => $period->is_daytime, + 'temperature' => $period->temperature, + 'temperatureUnit' => $period->temperature_unit, + 'shortForecast' => $period->short_forecast, + 'detailedForecast' => $period->detailed_forecast, + 'windSpeed' => $period->wind_speed, + 'windDirection' => $period->wind_direction, + 'precipitationProbability' => $period->precipitation_probability, + ]); + + return response()->json([ + 'period' => 'weekly', + 'reportedAt' => $latestWeekly->reported_at->toIso8601String(), + 'location' => [ + 'latitude' => $latestWeekly->latitude, + 'longitude' => $latestWeekly->longitude, + ], + 'periods' => $periods, + ]); + } +} diff --git a/bootstrap/app.php b/bootstrap/app.php index bf216c2..f382dc6 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -9,6 +9,7 @@ use Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', + api: __DIR__.'/../routes/api.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) diff --git a/routes/api.php b/routes/api.php new file mode 100644 index 0000000..05c3c30 --- /dev/null +++ b/routes/api.php @@ -0,0 +1,6 @@ +name('api.weather');