Files
fuel-price/resources/js/components/landing/VerdictCard.vue
Ovidiu U d822b77fb0
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
feat: redesign homepage with responsive hero, verdict card preview, and modular landing components
- Extract LandingNav, LiveTicker, StatsRow, VerdictCard, and HeroSearch into reusable landing components
- Implement responsive two-layout strategy: mobile stacked (hero search + verdict card + CTA) vs desktop inline pill input with verdict card sidebar
- Add serif/mono font tokens and live-dot pulse animation to CSS
- Move verdict card above search input on mobile, to right sidebar on desktop
- Replace hero "fill up now" mockup with dynamic VerdictCard showing top stations, pricing, and recommendation
- Simplify navigation with uppercase tracking, add Fleet anchor, and gate CTA by auth state
- Lazy-load LeafletMap with defineAsyncComponent to reduce initial bundle
- Relocate SearchBar below hero on search attempt for persistent filter UI
- Add meta description for SEO
2026-04-20 20:27:02 +01:00

74 lines
3.0 KiB
Vue

<template>
<div
:class="{ 'max-w-md mx-auto': variant === 'full' }"
class="bg-zinc-50 border border-zinc-300 rounded-3xl p-5 md:p-6 shadow-[0_20px_40px_-20px_rgba(74,63,59,0.25)]"
>
<!-- Header -->
<div class="flex items-center justify-between gap-3 mb-5">
<div class="min-w-0">
<p class="font-mono text-[10px] uppercase tracking-widest text-zinc-500 mb-1 truncate">
Today near {{ postcode }}
</p>
<h3
:class="variant === 'compact' ? 'text-3xl' : 'text-4xl'"
class="font-serif text-accent leading-none"
>
{{ verdict }}
</h3>
</div>
<span class="inline-flex items-center gap-1.5 shrink-0 font-mono text-[10px] uppercase tracking-widest text-zinc-600 bg-white border border-zinc-300 rounded-full px-2.5 py-1">
<span class="size-1.5 rounded-full bg-status-good live-dot"></span>
Live
</span>
</div>
<!-- Station rows -->
<ul class="space-y-2">
<li
v-for="(station, idx) in stations"
:key="station.name + idx"
class="flex items-center gap-3 bg-white border border-zinc-300 rounded-xl px-3 py-2.5"
>
<span class="font-mono text-xs text-zinc-500 tabular-nums">{{ String(idx + 1).padStart(2, '0') }}</span>
<div class="flex-1 min-w-0">
<p class="font-semibold text-sm text-zinc-800 truncate">{{ station.name }}</p>
<p class="font-mono text-[11px] text-zinc-500 mt-0.5">{{ station.distance }}</p>
</div>
<span
v-if="station.tag"
class="font-mono text-[9px] uppercase tracking-widest bg-accent text-white rounded-full px-2 py-0.5"
>
{{ station.tag }}
</span>
<span class="font-mono font-medium text-sm text-zinc-900 tabular-nums">{{ station.price }}</span>
</li>
</ul>
<!-- Footer -->
<p v-if="moreCount" class="font-mono text-[11px] text-zinc-500 mt-4 text-center">
+ {{ moreCount }} more stations within {{ radiusMiles }} miles
</p>
</div>
</template>
<script setup>
defineProps({
postcode: { type: String, default: 'SW1A 1AA' },
verdict: { type: String, default: 'Fill up today' },
stations: {
type: Array,
default: () => [
{ name: 'Tesco Victoria', distance: '0.4 mi', price: '142.9p', tag: 'Cheapest' },
{ name: "Sainsbury's Nine Elms", distance: '1.4 mi', price: '143.9p', tag: null },
],
},
moreCount: { type: Number, default: 21 },
radiusMiles: { type: Number, default: 5 },
variant: {
type: String,
default: 'full',
validator: (v) => ['full', 'compact'].includes(v),
},
})
</script>