diff --git a/biome.json b/biome.json index 74eadfcb..4f8e6c85 100644 --- a/biome.json +++ b/biome.json @@ -42,6 +42,26 @@ } } } + }, + { + "includes": ["packages/ui/src/lacowiki/**"], + "linter": { + "rules": { + "a11y": { + "noSvgWithoutTitle": "off", + "useKeyWithClickEvents": "off", + "useSemanticElements": "off", + "noStaticElementInteractions": "off", + "useValidAnchor": "off" + }, + "correctness": { + "useJsxKeyInIterable": "off" + }, + "suspicious": { + "noArrayIndexKey": "off" + } + } + } } ], "javascript": { diff --git a/host/client_app/pages/Landing.tsx b/host/client_app/pages/Landing.tsx index bbbfcd6f..c9091d8d 100644 --- a/host/client_app/pages/Landing.tsx +++ b/host/client_app/pages/Landing.tsx @@ -1,213 +1,156 @@ -import { usePage } from '@inertiajs/react'; +import { Link, usePage } from '@inertiajs/react'; import { keys, useT } from '@simple-module-py/i18n'; -import { Badge } from '@simple-module-py/ui/components/ui/badge'; -import { Button } from '@simple-module-py/ui/components/ui/button'; -import { Card, CardContent } from '@simple-module-py/ui/components/ui/card'; -import { Separator } from '@simple-module-py/ui/components/ui/separator'; -import { PublicLayout } from '@simple-module-py/ui/layouts/PublicLayout'; interface Props { isAuthenticated: boolean; } +const STATS = ['14k+ datasets', '·', '2.4M validated points', '·', 'open source']; +const FEATURE_GRID: [string, string][] = [ + ['Datasets', 'Upload COG/PMTiles'], + ['Sampling', '7 strategies'], + ['Validation', 'Map-side classify'], + ['Reports', 'Confusion matrix'], +]; + +const SAMPLE_DOTS: [number, number][] = [ + [30, 40], + [60, 55], + [75, 30], + [45, 70], + [20, 55], +]; + +const MAP_BG = `radial-gradient(ellipse at 30% 40%, oklch(0.92 0.03 155) 0%, transparent 35%), + radial-gradient(ellipse at 70% 60%, oklch(0.88 0.04 200) 0%, transparent 40%), + repeating-linear-gradient(45deg, transparent 0 14px, rgba(0,0,0,0.025) 14px 15px), + repeating-linear-gradient(-45deg, transparent 0 14px, rgba(0,0,0,0.025) 14px 15px), + oklch(0.93 0.005 250)`; + function Landing() { const { isAuthenticated } = usePage<{ props: Props }>().props as unknown as Props; const { t } = useT(); - const features = [ - { - icon: ( - - ), - title: t(keys.host.landing.features.module_system_title), - description: t(keys.host.landing.features.module_system_description), - }, - { - icon: ( - - ), - title: t(keys.host.landing.features.auth_title), - description: t(keys.host.landing.features.auth_description), - }, - { - icon: ( - - ), - title: t(keys.host.landing.features.schema_title), - description: t(keys.host.landing.features.schema_description), - }, - { - icon: ( - - ), - title: t(keys.host.landing.features.inertia_title), - description: t(keys.host.landing.features.inertia_description), - }, - { - icon: ( - - ), - title: t(keys.host.landing.features.diagnostics_title), - description: t(keys.host.landing.features.diagnostics_description), - }, - { - icon: ( - - ), - title: t(keys.host.landing.features.devtools_title), - description: t(keys.host.landing.features.devtools_description), - }, - ]; + const ctaHref = isAuthenticated ? '/dashboard/' : '/auth/login'; + const ctaLabel = isAuthenticated + ? t(keys.host.landing.cta_dashboard) + : t(keys.host.landing.cta_get_started); return ( - <> - {/* Hero */} -
- - - {t(keys.host.landing.badge)} - - -

- {t(keys.host.landing.hero_title_line1)} -
- - {t(keys.host.landing.hero_title_line2)} - -

- -

- {t(keys.host.landing.hero_subtitle)} -

- -
- - + + Request access + +
-
+ - + {/* Hero */} +
+
+
+ + {t(keys.host.landing.badge)} + +

+ {t(keys.host.landing.hero_title_line1)} +
+ {t(keys.host.landing.hero_title_line2)} +

+

+ {t(keys.host.landing.hero_subtitle)} +

+
+ + {ctaLabel} + + + {t(keys.host.landing.cta_docs)} + +
+
+ {STATS.map((s) => ( + {s} + ))} +
+
- {/* Features */} -
-
- {features.map((feature) => ( - +
- -
- {feature.icon} -
-

- {feature.title} -

-

- {feature.description} -

-
- + {SAMPLE_DOTS.map(([x, y]) => ( + + ))} +
+
+
+ Overall accuracy +
+
87.3%
+
±2.1% at 95% CI
+
+
+
+
+ + {/* Feature row */} +
+
+ {FEATURE_GRID.map(([title, sub]) => ( +
+
{title}
+
{sub}
+
))}
- + + + ); } -Landing.layout = (page: React.ReactNode) => {page}; +Landing.layout = (page: React.ReactNode) => page; export default Landing; diff --git a/host/templates/index.html b/host/templates/index.html index ea8da7ea..41acee4b 100644 --- a/host/templates/index.html +++ b/host/templates/index.html @@ -6,7 +6,7 @@ SimpleModule - + {% inertia_head %} {% if request.app.state.sm.inertia_config.environment == "development" %}