125 lines
3.5 KiB
Svelte
Executable File
125 lines
3.5 KiB
Svelte
Executable File
<!-- src/routes/+page.svelte -->
|
|
<script lang="ts">
|
|
import { newEnglandStates, mapViewBox, user } from '$lib/states';
|
|
import { goto } from '$app/navigation';
|
|
import { browser } from '$app/environment'; // To ensure SVG interactions only run client-side
|
|
import { onMount } from 'svelte';
|
|
import {
|
|
Scissors,
|
|
Snowflake,
|
|
Hammer,
|
|
Wrench,
|
|
Zap,
|
|
Bug,
|
|
Home,
|
|
Sparkles,
|
|
Eye,
|
|
Trash2,
|
|
Palette,
|
|
TreePine,
|
|
Fence,
|
|
Waves,
|
|
Camera,
|
|
Lock,
|
|
Refrigerator,
|
|
DoorOpen,
|
|
Eye as InspectionIcon,
|
|
GlassWater,
|
|
Shield,
|
|
Flame,
|
|
Square,
|
|
Grid,
|
|
Fan,
|
|
Clock,
|
|
Construction,
|
|
ExternalLink
|
|
} from 'lucide-svelte';
|
|
|
|
interface ServiceCategory {
|
|
id: number;
|
|
name: string;
|
|
description: string;
|
|
clicks_total: number;
|
|
total_companies: number;
|
|
}
|
|
|
|
let hoveredState: string | null = null;
|
|
|
|
function handleStateClick(id: string) {
|
|
goto(`/${id}`);
|
|
}
|
|
|
|
function handleMouseEnter(stateId: string) {
|
|
if (browser) {
|
|
hoveredState = stateId;
|
|
}
|
|
}
|
|
|
|
function handleMouseLeave() {
|
|
if (browser) {
|
|
hoveredState = null;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
|
|
|
|
<div class="text-center mb-8">
|
|
<p class="text-lg mb-4">Welcome to TradeWar, your go-to source for fuel prices across New England. Compare prices by state and county to find the best deals.</p>
|
|
<p class="text-sm">Click your state to find prices.</p>
|
|
</div>
|
|
|
|
<div class="flex justify-center items-center">
|
|
{#if browser}
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
viewBox={mapViewBox}
|
|
class="w-full max-w-md h-auto border border-gray-300 rounded-lg shadow-md"
|
|
aria-labelledby="mapTitle"
|
|
role="img"
|
|
>
|
|
<title id="mapTitle">Interactive Map of New England States</title>
|
|
{#each newEnglandStates as state}
|
|
<path
|
|
d={state.pathD}
|
|
class={`stroke-black stroke-1 cursor-pointer transition-all duration-150 ease-in-out
|
|
${hoveredState === state.id ? state.hoverFill : state.fill}`}
|
|
on:click={() => handleStateClick(state.id)}
|
|
on:mouseenter={() => handleMouseEnter(state.id)}
|
|
on:mouseleave={handleMouseLeave}
|
|
aria-label={state.id}
|
|
tabindex="0"
|
|
role="link"
|
|
on:keydown={(e) => { if (e.key === 'Enter' || e.key === ' ') handleStateClick(state.id)}}
|
|
>
|
|
<title>{state.name}</title> <!-- Tooltip on hover -->
|
|
</path>
|
|
{/each}
|
|
</svg>
|
|
{:else}
|
|
<div class="w-full max-w-2xl h-[500px] bg-gray-200 animate-pulse rounded-lg flex justify-center items-center">
|
|
<p>Loading map...</p>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
|
|
<div class="mt-8 text-center">
|
|
<h2 class="text-2xl font-semibold mb-4">States:</h2>
|
|
<ul class="flex flex-wrap justify-center gap-4">
|
|
{#each newEnglandStates as state}
|
|
<li>
|
|
<a href="/{state.id}" class="text-blue-600 hover:text-blue-800 underline flex items-center gap-1">
|
|
<span>{state.name}</span>
|
|
<ExternalLink size={12} />
|
|
</a>
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
</div>
|
|
|
|
{#if !$user}
|
|
<div class="mt-8 text-center">
|
|
<a href="/login" class="btn btn-primary">Dealer Login</a>
|
|
</div>
|
|
{/if}
|