From 7a797c0fc60140076786b918c0b04eda1b3f2a59 Mon Sep 17 00:00:00 2001 From: SkateSpots Date: Thu, 29 Oct 2026 10:09:50 +0700 Subject: [PATCH] feat: frictionless first-run tip and inline mute actions --- src/components/EventCard.tsx | 2 + src/components/FirstRunChecklist.tsx | 70 +++++++++++--------------- src/components/MarketplaceItemCard.tsx | 2 + src/components/MuteMenuItem.tsx | 37 ++++++++++++++ src/components/SpotCard.tsx | 2 + src/components/TourCard.tsx | 2 + src/i18n/ca/batch1.ts | 1 + src/i18n/cs/drift.ts | 1 + src/i18n/de/drift.ts | 1 + src/i18n/el/drift.ts | 1 + src/i18n/en.ts | 1 + src/i18n/es.ts | 1 + src/i18n/eu/batch1.ts | 1 + src/i18n/fr/drift.ts | 1 + src/i18n/gl/batch1.ts | 1 + src/i18n/hi/batch1.ts | 1 + src/i18n/id/drift.ts | 1 + src/i18n/it/drift.ts | 1 + src/i18n/ja/drift.ts | 1 + src/i18n/ko/drift.ts | 1 + src/i18n/nl/drift.ts | 1 + src/i18n/pl/drift.ts | 1 + src/i18n/pt/drift.ts | 1 + src/i18n/ro/drift.ts | 1 + src/i18n/ru/drift.ts | 1 + src/i18n/sv/drift.ts | 1 + src/i18n/th/drift.ts | 1 + src/i18n/tr/drift.ts | 1 + src/i18n/uk/drift.ts | 1 + src/i18n/vi/drift.ts | 1 + src/i18n/zh-CN/drift.ts | 1 + src/i18n/zh-TW/drift.ts | 1 + src/pages/MapPage.tsx | 2 +- 33 files changed, 100 insertions(+), 43 deletions(-) create mode 100644 src/components/MuteMenuItem.tsx diff --git a/src/components/EventCard.tsx b/src/components/EventCard.tsx index cb1f124..505f298 100644 --- a/src/components/EventCard.tsx +++ b/src/components/EventCard.tsx @@ -23,6 +23,7 @@ import { TrustBadge } from '@/components/TrustBadge'; import { OfficialBadge } from '@/components/OfficialBadge'; import { ProBadge } from '@/components/ProBadge'; import { ReportDialog } from '@/components/ReportDialog'; +import { MuteMenuItem } from '@/components/MuteMenuItem'; import { useTranslation } from '@/contexts/language'; import type { SkateEvent } from '@/lib/types'; import { EVENT_TYPE_LABELS } from '@/lib/types'; @@ -291,6 +292,7 @@ export function EventCard({ event, compact = false, goingCount: goingCountProp } {t('placesUi.eventCard.report')} )} + diff --git a/src/components/FirstRunChecklist.tsx b/src/components/FirstRunChecklist.tsx index f4bf170..fe0fa0d 100644 --- a/src/components/FirstRunChecklist.tsx +++ b/src/components/FirstRunChecklist.tsx @@ -1,41 +1,31 @@ import { useEffect, useRef, useState } from 'react'; import { X } from 'lucide-react'; -import { Link } from 'react-router-dom'; import { Button } from '@/components/ui/button'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useLocalStorage } from '@/hooks/useLocalStorage'; -import { useCrews } from '@/hooks/useCrews'; import { useTranslation } from '@/contexts/language'; const DISMISS_KEY = 'skatespots:first-run-dismissed'; -/** Set once, the first time the checklist has actually been shown. */ +/** Set once, the first time the tip has actually been shown. */ const SEEN_KEY = 'skatespots:first-run-seen'; /** The signup flow stamps this (ms). Only a *recent* signup counts as "first run". */ const SIGNUP_KEY = 'signup_completed'; const FRESH_WINDOW_MS = 2 * 24 * 60 * 60 * 1000; // 2 days /** - * One-shot "get started" nudge shown on the map for freshly signed-up users. + * One-shot, frictionless first-run tip. * - * The crew step is dynamic: when the community already has crews the CTA is - * "Join a crew" (→ /crews); when there are none it's "Start your crew" - * (→ /create-crew). Logged-out visitors see the welcome banner instead. - * - * ⚠️ Gating (fixed 2026-10-12): this used to show to ANY logged-in user until - * they tapped ✕, so returning skaters saw it forever. It now shows only when - * (a) the account has a **recent `signup_completed` stamp** (set by the signup - * flow — an imported key or an older account never matches) and (b) it has not - * been shown before (`first-run-seen`). It stays visible for that one session - * and never returns. + * It deliberately does NOT ask a new skater to create a spot, crew or wallet. + * The map is already populated; the only action is an optional "Near Me" (one + * location prompt) and a dismiss. Any content creation is left to the user's + * own intent, not onboarding. */ -export function FirstRunChecklist() { +export function FirstRunChecklist({ onFindNearby }: { onFindNearby?: () => void }) { const { t } = useTranslation(); const { user } = useCurrentUser(); const [dismissed, setDismissed] = useLocalStorage(DISMISS_KEY, false); const [seen, setSeen] = useLocalStorage(SEEN_KEY, false); - const crews = useCrews(1); - // Was this a fresh in-app signup? Read once (a stable local fact). const [fresh] = useState(() => { try { const at = Number(localStorage.getItem(SIGNUP_KEY) ?? 0); @@ -45,8 +35,7 @@ export function FirstRunChecklist() { } }); - // Capture `seen` at mount so marking it doesn't hide the checklist in the same - // session — only the next one. + // Capture at mount so marking it seen doesn't hide the tip in this session. const seenAtMount = useRef(seen); useEffect(() => { if (user && fresh && !dismissed && !seenAtMount.current) setSeen(true); @@ -54,10 +43,6 @@ export function FirstRunChecklist() { if (!user || dismissed || !fresh || seenAtMount.current) return null; - const hasCrews = (crews.data?.length ?? 0) > 0; - const crewTo = hasCrews ? '/crews' : '/create-crew'; - const crewLabel = hasCrews ? t('mapUi.firstRunJoinCrew') : t('mapUi.firstRunStartCrew'); - return (
@@ -71,27 +56,28 @@ export function FirstRunChecklist() {
+

{t('mapUi.firstRunTip')}

- - - - - - - - - - - - + )} +
); diff --git a/src/components/MarketplaceItemCard.tsx b/src/components/MarketplaceItemCard.tsx index 8b74458..60ae2f6 100644 --- a/src/components/MarketplaceItemCard.tsx +++ b/src/components/MarketplaceItemCard.tsx @@ -27,6 +27,7 @@ import { genUserName } from '@/lib/genUserName'; import { getLastLocation } from '@/lib/lastLocation'; import { itemDistanceKm } from '@/lib/sortOptions'; import { TrustBadge } from '@/components/TrustBadge'; +import { MuteMenuItem } from '@/components/MuteMenuItem'; import { Clock, Search, Tag, Flag, MoreVertical, ShieldCheck, Calendar, Package, AlertTriangle, CheckCircle, RotateCcw, Trash2, Loader2 } from 'lucide-react'; import { formatDistanceToNow } from '@/lib/dateFnsI18n'; import type { MarketplaceItem } from '@/lib/types'; @@ -288,6 +289,7 @@ export function MarketplaceItemCard({ item, compact = false }: MarketplaceItemCa {t('marketUi.card.reportListing')} + )} diff --git a/src/components/MuteMenuItem.tsx b/src/components/MuteMenuItem.tsx new file mode 100644 index 0000000..ced3169 --- /dev/null +++ b/src/components/MuteMenuItem.tsx @@ -0,0 +1,37 @@ +import { VolumeX } from 'lucide-react'; +import { DropdownMenuItem } from '@/components/ui/dropdown-menu'; +import { useCurrentUser } from '@/hooks/useCurrentUser'; +import { useMuteList } from '@/hooks/useMuteList'; +import { useMuteUser } from '@/hooks/useMuteUser'; +import { useTranslation } from '@/contexts/language'; + +/** Inline mute action for content cards. Renders nothing when logged out. */ +export function MuteMenuItem({ + pubkey, + className, +}: { + pubkey: string; + className?: string; +}) { + const { t } = useTranslation(); + const { user } = useCurrentUser(); + const { data: muted } = useMuteList(); + const mute = useMuteUser(); + if (!user || user.pubkey === pubkey) return null; + + const isMuted = !!muted?.has(pubkey); + return ( + { + event.preventDefault(); + event.stopPropagation(); + if (!isMuted) mute.mutate(pubkey); + }} + className={className} + > + + {isMuted ? t('walletUi.trust.muted') : t('walletUi.trust.mute')} + + ); +} diff --git a/src/components/SpotCard.tsx b/src/components/SpotCard.tsx index 0e5e6a3..26bd617 100644 --- a/src/components/SpotCard.tsx +++ b/src/components/SpotCard.tsx @@ -22,6 +22,7 @@ import { TrustBadge } from '@/components/TrustBadge'; import { OfficialBadge } from '@/components/OfficialBadge'; import { AddToCollectionDialog } from '@/components/AddToCollectionDialog'; import { ReportDialog } from '@/components/ReportDialog'; +import { MuteMenuItem } from '@/components/MuteMenuItem'; import { SpotStatusBadge } from '@/components/SpotStatusBadge'; import type { SkateSpot } from '@/lib/types'; import { ACCESS_TYPE_INFO, SHELTER_INFO, SKATE_SHOP_KIND } from '@/lib/types'; @@ -258,6 +259,7 @@ export function SpotCard({ spot, status, community }: SpotCardProps) { {t('mapUi.report')} )} + diff --git a/src/components/TourCard.tsx b/src/components/TourCard.tsx index 69483fd..5d53ca0 100644 --- a/src/components/TourCard.tsx +++ b/src/components/TourCard.tsx @@ -15,6 +15,7 @@ import { ZapButton } from '@/components/ZapButton'; import { TrustBadge } from '@/components/TrustBadge'; import { ProBadge } from '@/components/ProBadge'; import { ReportDialog } from '@/components/ReportDialog'; +import { MuteMenuItem } from '@/components/MuteMenuItem'; import type { SkateTour, TourCategory } from '@/lib/types'; import { TOUR_CATEGORIES, TOUR_SKILL_LEVELS } from '@/lib/types'; @@ -474,6 +475,7 @@ export function TourCard({ tour, compact = false }: TourCardProps) { {t('placesUi.eventCard.report')} )} + diff --git a/src/i18n/ca/batch1.ts b/src/i18n/ca/batch1.ts index a38222b..2fecd86 100644 --- a/src/i18n/ca/batch1.ts +++ b/src/i18n/ca/batch1.ts @@ -321,6 +321,7 @@ const batch1 = { "newHere": "Ets nou aquí?", "welcomeDesc": "Descobreix spots de skate, esdeveniments i la comunitat.", "firstRunTitle": "Comença", + "firstRunTip": "Toca qualsevol marcador per explorar. No cal configurar res — els spots a prop són a un toc.", "firstRunAddSpot": "Afegeix el teu primer spot", "firstRunJoinCrew": "Uneix-te a una colla", "firstRunStartCrew": "Crea la teva colla", diff --git a/src/i18n/cs/drift.ts b/src/i18n/cs/drift.ts index dbb5bd9..b73279b 100644 --- a/src/i18n/cs/drift.ts +++ b/src/i18n/cs/drift.ts @@ -12,6 +12,7 @@ const drift = { }, "mapUi": { "firstRunTitle": "Začít", + "firstRunTip": "Klepni na jakýkoli pin a objevuj. Nic není třeba nastavovat — okolní spoty máš na jeden dotek.", "firstRunAddSpot": "Přidej svůj první spot", "firstRunJoinCrew": "Přidej se k crew", "firstRunStartCrew": "Založ si crew", diff --git a/src/i18n/de/drift.ts b/src/i18n/de/drift.ts index b6b401e..64430da 100644 --- a/src/i18n/de/drift.ts +++ b/src/i18n/de/drift.ts @@ -14,6 +14,7 @@ const drift = { }, mapUi: { firstRunTitle: "Loslegen", + firstRunTip: "Tippe auf eine Markierung und leg los. Nichts einzurichten — Spots in der Nähe sind nur einen Tipp entfernt.", firstRunAddSpot: "Füge deinen ersten Spot hinzu", firstRunJoinCrew: "Einer Crew beitreten", firstRunStartCrew: "Starte deine Crew", diff --git a/src/i18n/el/drift.ts b/src/i18n/el/drift.ts index 30dd0d0..67c90a5 100644 --- a/src/i18n/el/drift.ts +++ b/src/i18n/el/drift.ts @@ -16,6 +16,7 @@ const drift = { }, mapUi: { firstRunTitle: "Ξεκίνα", + firstRunTip: "Πάτησε οποιαδήποτε πινέζα για εξερεύνηση. Δεν χρειάζεται καμία ρύθμιση — τα κοντινά spot είναι ένα άγγιγμα μακριά.", firstRunAddSpot: "Πρόσθεσε το πρώτο spot", firstRunJoinCrew: "Μπες σε ένα crew", firstRunStartCrew: "Ξεκίνα το δικό σου crew", diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 62c9f42..6ebf4b1 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -918,6 +918,7 @@ mapUi: { newHere: 'New here?', welcomeDesc: 'Discover skate spots, events & the community.', firstRunTitle: 'Get started', + firstRunTip: 'Tap any pin to explore. Nothing to set up — nearby spots are one tap away.', firstRunAddSpot: 'Add your first spot', firstRunJoinCrew: 'Join a crew', firstRunStartCrew: 'Start your crew', diff --git a/src/i18n/es.ts b/src/i18n/es.ts index e6e929a..81bfd40 100644 --- a/src/i18n/es.ts +++ b/src/i18n/es.ts @@ -918,6 +918,7 @@ mapUi: { newHere: '¿Nuevo por aquí?', welcomeDesc: 'Descubre spots, eventos y la comunidad.', firstRunTitle: 'Empieza aquí', + firstRunTip: 'Toca cualquier chincheta para explorar. No hay que configurar nada: los spots cercanos están a un toque.', firstRunAddSpot: 'Añade tu primer spot', firstRunJoinCrew: 'Únete a una peña', firstRunStartCrew: 'Crea tu peña', diff --git a/src/i18n/eu/batch1.ts b/src/i18n/eu/batch1.ts index 6ffa975..6a7675b 100644 --- a/src/i18n/eu/batch1.ts +++ b/src/i18n/eu/batch1.ts @@ -321,6 +321,7 @@ const batch1 = { newHere: "Berria zara hemen?", welcomeDesc: "Aurkitu skate tokiak, ekitaldiak eta komunitatea.", firstRunTitle: "Hasi", + firstRunTip: "Sakatu edozein markagailu esploratzeko. Ez dago ezer konfiguratu beharrik — inguruko tokiak ukitze bakarrera daude.", firstRunAddSpot: "Gehitu zure lehen tokia", firstRunJoinCrew: "Batu talde batera", firstRunStartCrew: "Sortu zure taldea", diff --git a/src/i18n/fr/drift.ts b/src/i18n/fr/drift.ts index 67ef7a2..5697a07 100644 --- a/src/i18n/fr/drift.ts +++ b/src/i18n/fr/drift.ts @@ -14,6 +14,7 @@ const drift = { }, mapUi: { firstRunTitle: "Pour commencer", + firstRunTip: "Touchez n'importe quel repère pour explorer. Rien à configurer — les spots à proximité sont à un toucher.", firstRunAddSpot: "Ajoutez votre premier spot", firstRunJoinCrew: "Rejoindre une Crew", firstRunStartCrew: "Lancer votre Crew", diff --git a/src/i18n/gl/batch1.ts b/src/i18n/gl/batch1.ts index 9aefe68..9660eb3 100644 --- a/src/i18n/gl/batch1.ts +++ b/src/i18n/gl/batch1.ts @@ -321,6 +321,7 @@ const batch1 = { newHere: "Es novo por aquí?", welcomeDesc: "Descubre spots de skate, eventos e a comunidade.", firstRunTitle: "Comeza", + firstRunTip: "Toca calquera marcador para explorar. Non hai nada que configurar — os spots preto están a un toque.", firstRunAddSpot: "Engade o teu primeiro spot", firstRunJoinCrew: "Únete a unha crew", firstRunStartCrew: "Crea a túa crew", diff --git a/src/i18n/hi/batch1.ts b/src/i18n/hi/batch1.ts index ca61344..a9a1988 100644 --- a/src/i18n/hi/batch1.ts +++ b/src/i18n/hi/batch1.ts @@ -321,6 +321,7 @@ const batch1 = { "newHere": "नए हैं?", "welcomeDesc": "स्केट स्पॉट, इवेंट और समुदाय खोजें।", "firstRunTitle": "शुरू करें", + "firstRunTip": "किसी भी पिन पर टैप करके एक्सप्लोर करें। कुछ सेट करने की ज़रूरत नहीं — आस-पास के स्पॉट बस एक टैप दूर हैं।", "firstRunAddSpot": "अपना पहला स्पॉट जोड़ें", "firstRunJoinCrew": "क्रू से जुड़ें", "firstRunStartCrew": "अपना क्रू शुरू करें", diff --git a/src/i18n/id/drift.ts b/src/i18n/id/drift.ts index 6a2510b..ecc4f7a 100644 --- a/src/i18n/id/drift.ts +++ b/src/i18n/id/drift.ts @@ -8,6 +8,7 @@ const driftStrings = { }, mapUi: { firstRunTitle: 'Mulai', + firstRunTip: 'Ketuk pin mana saja untuk menjelajah. Tanpa pengaturan — spot di sekitar tinggal sekali ketuk.', firstRunAddSpot: 'Tambahkan spot pertamamu', firstRunJoinCrew: 'Gabung crew', firstRunStartCrew: 'Mulai crew-mu', diff --git a/src/i18n/it/drift.ts b/src/i18n/it/drift.ts index 72730a0..54b6288 100644 --- a/src/i18n/it/drift.ts +++ b/src/i18n/it/drift.ts @@ -14,6 +14,7 @@ const drift = { }, mapUi: { firstRunTitle: "Inizia", + firstRunTip: "Tocca qualsiasi segnaposto per esplorare. Niente da configurare — gli spot vicini sono a un tocco.", firstRunAddSpot: "Aggiungi il tuo primo spot", firstRunJoinCrew: "Unisciti a una crew", firstRunStartCrew: "Avvia la tua crew", diff --git a/src/i18n/ja/drift.ts b/src/i18n/ja/drift.ts index dad9829..2028255 100644 --- a/src/i18n/ja/drift.ts +++ b/src/i18n/ja/drift.ts @@ -24,6 +24,7 @@ const drift: Dict = { }, mapUi: { firstRunTitle: 'はじめかた', + firstRunTip: 'ピンをタップして探索。設定は不要 — 近くのスポットはすぐそこ。', firstRunAddSpot: '最初のスポットを追加', firstRunJoinCrew: 'クルーに参加', firstRunStartCrew: 'クルーを始める', diff --git a/src/i18n/ko/drift.ts b/src/i18n/ko/drift.ts index b7373ee..f77b7cc 100644 --- a/src/i18n/ko/drift.ts +++ b/src/i18n/ko/drift.ts @@ -24,6 +24,7 @@ const drift: Dict = { }, mapUi: { firstRunTitle: '시작하기', + firstRunTip: '핀을 탭해 둘러보세요. 설정은 필요 없어요 — 근처 스팟은 한 번의 탭이면 됩니다.', firstRunAddSpot: '첫 스팟 추가', firstRunJoinCrew: '크루 참여', firstRunStartCrew: '크루 시작', diff --git a/src/i18n/nl/drift.ts b/src/i18n/nl/drift.ts index 1178c47..9e44bbb 100644 --- a/src/i18n/nl/drift.ts +++ b/src/i18n/nl/drift.ts @@ -12,6 +12,7 @@ const drift = { }, "mapUi": { "firstRunTitle": "Aan de slag", + "firstRunTip": "Tik op een pin om te verkennen. Niets in te stellen — spots in de buurt zijn één tik weg.", "firstRunAddSpot": "Voeg je eerste spot toe", "firstRunJoinCrew": "Sluit je aan bij een crew", "firstRunStartCrew": "Start je crew", diff --git a/src/i18n/pl/drift.ts b/src/i18n/pl/drift.ts index 5dc78d5..16be67a 100644 --- a/src/i18n/pl/drift.ts +++ b/src/i18n/pl/drift.ts @@ -12,6 +12,7 @@ const drift = { }, "mapUi": { "firstRunTitle": "Zacznij", + "firstRunTip": "Dotknij dowolnej pinezki, aby eksplorować. Niczego nie trzeba konfigurować — pobliskie spoty są o jedno dotknięcie.", "firstRunAddSpot": "Dodaj swój pierwszy spot", "firstRunJoinCrew": "Dołącz do crew", "firstRunStartCrew": "Załóż swoje crew", diff --git a/src/i18n/pt/drift.ts b/src/i18n/pt/drift.ts index c2df836..5505fb0 100644 --- a/src/i18n/pt/drift.ts +++ b/src/i18n/pt/drift.ts @@ -14,6 +14,7 @@ const drift = { }, mapUi: { firstRunTitle: "Comece agora", + firstRunTip: "Toque em qualquer pino para explorar. Nada para configurar — os spots por perto estão a um toque.", firstRunAddSpot: "Adicione seu primeiro spot", firstRunJoinCrew: "Entrar em uma crew", firstRunStartCrew: "Comece sua crew", diff --git a/src/i18n/ro/drift.ts b/src/i18n/ro/drift.ts index 3a9dcb8..e358391 100644 --- a/src/i18n/ro/drift.ts +++ b/src/i18n/ro/drift.ts @@ -12,6 +12,7 @@ const drift = { }, "mapUi": { "firstRunTitle": "Începe", + "firstRunTip": "Atinge orice pin pentru a explora. Nimic de configurat — spoturile din apropiere sunt la un tap.", "firstRunAddSpot": "Adaugă primul tău spot", "firstRunJoinCrew": "Alătură-te unui crew", "firstRunStartCrew": "Începe-ți crew-ul", diff --git a/src/i18n/ru/drift.ts b/src/i18n/ru/drift.ts index 8e947dc..9b5756a 100644 --- a/src/i18n/ru/drift.ts +++ b/src/i18n/ru/drift.ts @@ -16,6 +16,7 @@ const drift = { }, mapUi: { firstRunTitle: "Начните", + firstRunTip: "Нажмите на любую метку, чтобы осмотреться. Ничего настраивать не нужно — ближайшие Spot в одном касании.", firstRunAddSpot: "Добавьте первый Spot", firstRunJoinCrew: "Присоединиться к Crew", firstRunStartCrew: "Создать свой Crew", diff --git a/src/i18n/sv/drift.ts b/src/i18n/sv/drift.ts index b6ab341..0ec15c0 100644 --- a/src/i18n/sv/drift.ts +++ b/src/i18n/sv/drift.ts @@ -16,6 +16,7 @@ const drift = { }, mapUi: { firstRunTitle: "Kom igång", + firstRunTip: "Tryck på valfri nål för att utforska. Inget att ställa in — spots i närheten är ett tryck bort.", firstRunAddSpot: "Lägg till din första spot", firstRunJoinCrew: "Gå med i ett crew", firstRunStartCrew: "Starta ditt crew", diff --git a/src/i18n/th/drift.ts b/src/i18n/th/drift.ts index 8d603d6..3b6ae5d 100644 --- a/src/i18n/th/drift.ts +++ b/src/i18n/th/drift.ts @@ -8,6 +8,7 @@ const driftStrings = { }, mapUi: { firstRunTitle: 'เริ่มต้น', + firstRunTip: 'แตะหมุดใดก็ได้เพื่อสำรวจ ไม่ต้องตั้งค่าอะไร — spot ใกล้ ๆ อยู่แค่ปลายนิ้ว', firstRunAddSpot: 'เพิ่ม spot แรกของคุณ', firstRunJoinCrew: 'เข้าร่วม crew', firstRunStartCrew: 'เริ่ม crew ของคุณ', diff --git a/src/i18n/tr/drift.ts b/src/i18n/tr/drift.ts index 60ed744..c6de72f 100644 --- a/src/i18n/tr/drift.ts +++ b/src/i18n/tr/drift.ts @@ -8,6 +8,7 @@ const driftStrings = { }, mapUi: { firstRunTitle: 'Başla', + firstRunTip: 'Keşfetmek için herhangi bir iğneye dokun. Kurulum yok — yakındaki spotlar bir dokunuş uzağında.', firstRunAddSpot: 'İlk spotunu ekle', firstRunJoinCrew: "Bir crew'e katıl", firstRunStartCrew: "Crew'ini kur", diff --git a/src/i18n/uk/drift.ts b/src/i18n/uk/drift.ts index 4a90298..0d67f7d 100644 --- a/src/i18n/uk/drift.ts +++ b/src/i18n/uk/drift.ts @@ -16,6 +16,7 @@ const drift = { }, mapUi: { firstRunTitle: "Почніть", + firstRunTip: "Торкніться будь-якої мітки, щоб дослідити. Нічого налаштовувати не потрібно — найближчі Spot за один дотик.", firstRunAddSpot: "Додайте перший Spot", firstRunJoinCrew: "Приєднатися до команди", firstRunStartCrew: "Створіть свою команду", diff --git a/src/i18n/vi/drift.ts b/src/i18n/vi/drift.ts index 5f67fcb..a5eda94 100644 --- a/src/i18n/vi/drift.ts +++ b/src/i18n/vi/drift.ts @@ -8,6 +8,7 @@ const driftStrings = { }, mapUi: { firstRunTitle: 'Bắt đầu', + firstRunTip: 'Chạm vào bất kỳ ghim nào để khám phá. Không cần thiết lập — spot gần đây chỉ cách một lần chạm.', firstRunAddSpot: 'Thêm spot đầu tiên của bạn', firstRunJoinCrew: 'Tham gia một crew', firstRunStartCrew: 'Bắt đầu crew của bạn', diff --git a/src/i18n/zh-CN/drift.ts b/src/i18n/zh-CN/drift.ts index 271258f..27a446a 100644 --- a/src/i18n/zh-CN/drift.ts +++ b/src/i18n/zh-CN/drift.ts @@ -24,6 +24,7 @@ const drift: Dict = { }, mapUi: { firstRunTitle: '开始使用', + firstRunTip: '点击任意标记即可探索。无需设置——附近滑板点一触即达。', firstRunAddSpot: '添加你的第一个滑板点', firstRunJoinCrew: '加入一个 Crew', firstRunStartCrew: '创建你的 Crew', diff --git a/src/i18n/zh-TW/drift.ts b/src/i18n/zh-TW/drift.ts index 1034811..03a97d3 100644 --- a/src/i18n/zh-TW/drift.ts +++ b/src/i18n/zh-TW/drift.ts @@ -24,6 +24,7 @@ const drift: Dict = { }, mapUi: { firstRunTitle: '開始使用', + firstRunTip: '點按任一標記即可探索。無需設定——附近滑板點一觸即達。', firstRunAddSpot: '新增你的第一個滑板點', firstRunJoinCrew: '加入一個 Crew', firstRunStartCrew: '建立你的 Crew', diff --git a/src/pages/MapPage.tsx b/src/pages/MapPage.tsx index f76faa7..119effe 100644 --- a/src/pages/MapPage.tsx +++ b/src/pages/MapPage.tsx @@ -1150,7 +1150,7 @@ export default function MapPage() { the floating toolbar would paint over it. */} {/* First-run "get started" nudge for freshly signed-up users (hidden for logged-out visitors, who get the welcome banner). */} - + void handleNearMe()} /> {showWelcomeBanner && (