profileShare

rasmusjy / tasteprint

Read-only snapshot

No repository description.

main default branch 169 files Expires Sep 13, 2026, 9:06 AM
LandingPage.tsx 3,725 bytes
1 import { useQuery } from "@tanstack/react-query";
2 import { ArrowRight, Camera, Check, MapPinned, Plane } from "lucide-react";
3 import { Link, Navigate } from "react-router-dom";
4 import { Logo } from "../components/Logo";
5 import { WorldMap } from "../components/WorldMap";
6 import { useAuth } from "../lib/auth";
7 import { api } from "../lib/api";
8 import type { Destination, DestinationProgress } from "../types";
9
10 const sampleCoverage: Record<string, number> = {
11 EE: 82, JP: 44, MX: 35, PT: 68, GE: 19, VN: 52
12 };
13
14 export function LandingPage() {
15 const { user, loading } = useAuth();
16 const destinations = useQuery({
17 queryKey: ["destinations"],
18 queryFn: () => api<Destination[]>("/api/v1/catalog/destinations")
19 });
20
21 if (!loading && user) {
22 return <Navigate to="/app" replace />;
23 }
24
25 const mapData: DestinationProgress[] = (destinations.data ?? []).map(destination => ({
26 destination,
27 coverage: sampleCoverage[destination.code] ?? 0,
28 triedDishes: 0,
29 totalDishes: destination.dishCount
30 }));
31
32 return (
33 <div className="landing-page">
34 <header className="landing-nav">
35 <Logo />
36 <div>
37 <Link className="button button-ghost" to="/login">Sign in</Link>
38 <Link className="button button-primary" to="/register">Start your map</Link>
39 </div>
40 </header>
41
42 <main>
43 <section className="landing-hero">
44 <div className="hero-copy">
45 <span className="eyebrow">A food passport for actual trips</span>
46 <h1>You visited it.<br /><em>Did you taste it?</em></h1>
47 <p>
48 Tasteprint remembers the dishes behind every journey, shows the important experiences you missed,
49 and turns your next destination into a five-bite mission.
50 </p>
51 <div className="hero-actions">
52 <Link className="button button-primary button-large" to="/register">
53 Make your Tasteprint <ArrowRight size={18} />
54 </Link>
55 <Link className="text-link" to="/login?demo=true">Open the demo passport</Link>
56 </div>
57 </div>
58
59 <div className="hero-ticket" aria-label="Example culinary passport">
60 <div className="ticket-route">
61 <span>TLL</span>
62 <i />
63 <Plane size={17} />
64 <i />
65 <span>WORLD</span>
66 </div>
67 <div className="ticket-score">
68 <span>Culinary coverage</span>
69 <strong>41%</strong>
70 <small>6 food cultures started</small>
71 </div>
72 <WorldMap destinations={mapData} interactive={false} className="hero-world-map" />
73 <div className="ticket-stamp">TASTED<br />06</div>
74 </div>
75 </section>
76
77 <section className="landing-proof" aria-label="How Tasteprint works">
78 <article>
79 <Camera size={22} />
80 <span>At the table</span>
81 <h2>Log the dish, not only the restaurant.</h2>
82 <p>A photo, place, date, and one note are enough.</p>
83 </article>
84 <article>
85 <MapPinned size={22} />
86 <span>Before the trip</span>
87 <h2>Get five bites that cover more than the obvious.</h2>
88 <p>Every mission mixes daily food, street bites, mornings, sweets, drinks, and a defining dish.</p>
89 </article>
90 <article>
91 <Check size={22} />
92 <span>After the trip</span>
93 <h2>See what the destination added to your map.</h2>
94 <p>Share a clear Tasteprint instead of another photo dump.</p>
95 </article>
96 </section>
97 </main>
98 </div>
99 );
100 }
101