Files
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

46 lines
1.5 KiB
Vue

<template>
<div class="inline-flex items-center gap-2 font-mono text-[11px] uppercase tracking-[0.15em] text-zinc-600">
<span class="size-1.5 rounded-full bg-status-good live-dot"></span>
<span class="font-medium">Live</span>
<span v-if="stationCount" aria-hidden="true">·</span>
<span v-if="stationCount">{{ formattedStationCount }} UK stations</span>
<span aria-hidden="true">·</span>
<span>updated {{ updatedAgo || '…' }}</span>
</div>
</template>
<script setup>
import { computed, onMounted, onUnmounted, ref } from 'vue'
const props = defineProps({
stationCount: { type: Number, default: null },
latestPriceAt: { type: String, default: null },
})
const now = ref(Date.now())
let ticker = null
const formattedStationCount = computed(() => {
return props.stationCount == null ? '' : props.stationCount.toLocaleString('en-GB')
})
const updatedAgo = computed(() => {
if (!props.latestPriceAt) return ''
const diffMin = Math.floor((now.value - new Date(props.latestPriceAt).getTime()) / 60000)
if (diffMin < 1) return 'just now'
if (diffMin < 60) return `${diffMin} min ago`
const hours = Math.floor(diffMin / 60)
if (hours < 24) return `${hours} hr ago`
const days = Math.floor(hours / 24)
return `${days} day${days === 1 ? '' : 's'} ago`
})
onMounted(() => {
ticker = setInterval(() => { now.value = Date.now() }, 60000)
})
onUnmounted(() => {
if (ticker) clearInterval(ticker)
})
</script>