Files
fuel-price/resources/js/components/PredictionCard.vue
Ovidiu U 088fd11058
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.3) (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled
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.
2026-04-29 13:28:33 +01:00

66 lines
2.2 KiB
Vue

<template>
<div>
<!-- Loading state -->
<div
v-if="loading"
class="p-6 bg-white rounded-2xl border border-zinc-300 animate-pulse space-y-2"
>
<div class="h-4 bg-zinc-200 rounded w-1/3"></div>
<div class="h-6 bg-zinc-200 rounded w-2/3"></div>
</div>
<!-- Free / guest: compact one-liner -->
<div
v-else-if="!isPaidTier"
class="flex items-center gap-3 px-4 py-3 bg-white rounded-2xl border border-zinc-300"
>
<div :class="['shrink-0 w-10 h-10 rounded-full flex items-center justify-center', accentBg]">
<iconify-icon :icon="genericIcon" class="text-xl text-white"></iconify-icon>
</div>
<p class="flex-1 text-sm text-zinc-800 font-medium leading-snug">
{{ genericSentence }}
</p>
<a
class="hidden sm:inline-flex shrink-0 text-sm font-bold text-accent hover:text-accent-content whitespace-nowrap"
href="/pricing"
>
See full prediction
</a>
</div>
<!-- Paid: full prediction -->
<PredictionFull v-else :prediction="prediction" />
</div>
</template>
<script setup>
import { computed } from 'vue'
import PredictionFull from './PredictionFull.vue'
const props = defineProps({
prediction: { type: Object, default: null },
loading: { type: Boolean, default: false },
isPaidTier: { type: Boolean, default: false },
})
const direction = computed(() => props.prediction?.predicted_direction ?? 'stable')
const genericSentence = computed(() => ({
up: 'UK fuel prices are trending upward this week.',
down: 'UK fuel prices have been falling this week.',
stable: 'UK fuel prices have been steady this week.',
})[direction.value] ?? 'UK fuel prices have been steady this week.')
const genericIcon = computed(() => ({
up: 'lucide:trending-up',
down: 'lucide:trending-down',
stable: 'lucide:minus',
})[direction.value] ?? 'lucide:minus')
const accentBg = computed(() => ({
up: 'bg-mauve',
down: 'bg-teal',
stable: 'bg-tan',
})[direction.value] ?? 'bg-tan')
</script>