Remove prediction API endpoint and integrate into stations search
Consolidate prediction functionality by merging /api/prediction endpoint into /api/stations response. Move prediction logic from PredictionController into StationController, returning prediction data alongside station results. Replace usePrediction composable with unified useStations that returns {stations, meta, prediction}. Remove PredictionRequest, related tests, and unused Vue components (FuelFinderTest, MapTest, RecommendationTest, StationListTest). Add PredictionFull component and UpsellBanner. Extend NationalFuelPredictionService to include weekly_summary (7-day series, yesterday/today averages, cheapest/priciest days) and oil signal from price_predictions table. Update Home.vue to consume prediction from stations response. Add Plan::resolveCadenceForUser helper and configure Cashier to use custom Subscription model.
This commit is contained in:
@@ -8,6 +8,9 @@ use App\Http\Requests\Api\NearbyStationsRequest;
|
||||
use App\Http\Resources\Api\StationResource;
|
||||
use App\Models\Search;
|
||||
use App\Models\Station;
|
||||
use App\Models\User;
|
||||
use App\Services\NationalFuelPredictionService;
|
||||
use App\Services\PlanFeatures;
|
||||
use App\Services\PostcodeService;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -16,7 +19,10 @@ use Illuminate\Validation\ValidationException;
|
||||
|
||||
class StationController extends Controller
|
||||
{
|
||||
public function __construct(private readonly PostcodeService $postcodeService) {}
|
||||
public function __construct(
|
||||
private readonly PostcodeService $postcodeService,
|
||||
private readonly NationalFuelPredictionService $predictionService,
|
||||
) {}
|
||||
|
||||
public function index(NearbyStationsRequest $request): JsonResponse
|
||||
{
|
||||
@@ -115,6 +121,31 @@ class StationController extends Controller
|
||||
'outdated' => (int) $reliabilityCounts->get(PriceReliability::Outdated->value, 0),
|
||||
],
|
||||
],
|
||||
'prediction' => $this->predictionFor($request->user(), $lat, $lng),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the prediction payload for embedding in the search response.
|
||||
* Free/guest users get a stripped teaser; users with the ai_predictions
|
||||
* feature get the full multi-signal payload.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function predictionFor(?User $user, float $lat, float $lng): array
|
||||
{
|
||||
$result = $this->predictionService->predict($lat, $lng);
|
||||
|
||||
$canSeeFull = $user !== null && PlanFeatures::for($user)->can('ai_predictions');
|
||||
|
||||
if (! $canSeeFull) {
|
||||
return [
|
||||
'fuel_type' => $result['fuel_type'],
|
||||
'predicted_direction' => $result['predicted_direction'],
|
||||
'tier_locked' => true,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user