Commit graph

146 commits

Author SHA1 Message Date
SkateSpots
5f8975d631 fix(ux): URL-addressable marketplace tabs, offers error state, nav reset
Next P1 slice from UX_AUDIT_2026-10-09.md:
- Marketplace hub tabs now live in the URL (?tab=...) so refresh, share and
  back/forward keep the tab; unknown values fall back to Browse.
- ListingOffersPanel shows an error state on a relay outage instead of
  returning null (a failure no longer reads as no offers).
- Nav customizer Reset reseeds from DEFAULT_TAB_IDS (4) instead of a
  hardcoded 3, matching MIDDLE_SLOTS.
New marketUi.offers.loadFailed (en/es).
2026-10-09 21:04:52 +07:00
SkateSpots
0d15a7ce3d fix(marketplace): close the P0 audit gaps + borrow the guidelines page
P0 fixes from UX_AUDIT_2026-10-09.md:
- useMarketplaceItem now filters admin-hidden listings and skips
  showcase-only (not-for-sale) items, so a direct /listing/... URL cannot
  surface removed or non-sale content.
- Listing detail hides Make an offer for logged-out users and for
  fixed-price listings (Buy is the single primary CTA there).

Borrowed from the Plebeian market review: a /marketplace-guidelines page
(peer-to-peer, buyer-beware, no checkout, prohibited items, soft
moderation), linked from the marketplace hub; new marketTerms en/es keys.
Records the remaining borrowables in the audit doc.
2026-10-09 20:21:04 +07:00
SkateSpots
18a9e28f0b feat(trust): network alerts for reported accounts you follow
Fifth slice of TRUST_SCORE.md. useNetworkAlerts reads the viewer's NIP-85
assertions for the accounts they follow and surfaces those trusted people
reported or muted. New /alerts page lists them with Ignore / Unfollow /
Mute / Report (reusing useFollowActions, useMuteUser, ReportDialog) —
inform, never auto-act. Settings -> Trust links to it with a live count;
ignored accounts are device-local. /alerts added to the smoke list.
2026-10-09 18:32:47 +07:00
SkateSpots
e66888128f feat(trust): a real mute (NIP-51 kind 10000) that hides content
Completes the safety loop. useMuteList reads the viewer's kind-10000 mute
list plus optimistic local mutes (lib/localMutes.ts); useMuteUser
republishes the list with the target added, records it locally and
invalidates content queries. useAdminModeration carries a new
mutedPubkeys set, and the shared filterAdminHidden/filterAdminHiddenMixed
drop muted authors — so every list hook filters them with no per-hook
changes (admin tooling with includeHidden still sees them). The flagged
notice gains a Mute action.
2026-10-09 18:23:04 +07:00
SkateSpots
3b06e90d15 feat(trust): let the viewer choose the trust provider (NIP-85 kind 10040)
Settings -> Trust is now functional, not read-only. useSetTrustProvider
publishes a kind-10040 designation for a custom provider (npub or 64-hex +
wss relay, the five 30382:<type> rows) and can clear it to fall back to the
community provider. The card validates input, prompts the signer, and
invalidates the provider + assertion queries so scores refresh. Docs
updated.
2026-10-09 17:55:00 +07:00
SkateSpots
fd9316331b feat(trust): Settings -> Trust and name AGPL on the License page
- Settings -> Trust section (?section=trust, TrustSettingsCard): a
  show/hide-marks toggle (useTrustDisplay; Flagged is never hidden) and the
  active provider + relay (useTrustProvider), linked to /trust.
- TrustBadge respects the display preference.
- Name AGPL-3.0 on the License page by updating its existing copy
  (licenseLabel + body) in en/es.
- Settings + card i18n keys; /settings?section=trust added to the smoke
  list. Docs updated.
2026-10-09 17:45:56 +07:00
SkateSpots
d1fae2688c feat(trust): attribute the badge and add a /trust explainer
Legibility pass: a trust verdict has to be explainable and sourced.

- TrustBadge tooltips now attribute the claim (from your network / the
  community provider / the provider you chose) and link to /trust.
- New /trust page: the three states, why absence is not distrust, who
  computes it, presence-is-not-endorsement, and point-of-view. Public,
  linked from the badge; added to the smoke-test route list.
- New trustUi.* keys and four walletUi.trust attribution keys (en/es).
2026-10-09 17:30:00 +07:00
SkateSpots
2d1144bb7e feat(trust): batch provider reads, neutral direct follows, flagged notice
Second pass of TRUST_SCORE.md.

- useTrustAssertions now batches: every TrustBadge registers its subject into
  a shared per-viewer union and ONE query fetches the union (no per-card
  query), with a debounced refetch when a list grows. Same hook API.
- A direct follow (or self) is no longer shown as Verified - only a
  friend-of-friend or a provider assertion counts; Flagged is never
  suppressed.
- useUserReports reads public NIP-56 reports for an account, and
  TrustFlaggedNotice shows a flagged counterparty with the reporters grouped
  by the viewer's network plus Report / Dismiss. Wired into the listing
  seller card and the coach detail page.
- New walletUi.trust.* keys (en/es).
2026-10-09 17:17:11 +07:00
SkateSpots
fead9ca781 feat(trust): spec-correct NIP-85 consumer + Verified/Unknown/Flagged badge
First slice of TRUST_SCORE.md.

- lib/nip85.ts: parse kind-10040 provider designations, resolve a provider
  with a house fallback, parse kind-30382 assertions (rank/followers/
  reporters/muters/hops; absent hops means no path, absence is not
  distrust), and author-check the provider.
- hooks/useTrustAssertions.ts: batch read from the resolved provider,
  signature-verified via onlyVerified + the author check.
- lib/trustLadder.ts: three buckets and thresholds (flagged = trusted
  reporters >= 2; verified rank >= 2).
- hooks/useTrustBucket.ts: prefers a NIP-85 assertion (verify + flag),
  falls back to the local WoT ladder (verify only).
- TrustBadge.tsx: now renders Verified / Unknown / Flagged with glyph,
  colour and tooltip; Unknown hidden by default, Flagged always shown.
  Reaches the map/tour/event cards, marketplace card, listing detail and
  coach detail through the shared component.

Open follow-ups (in TRUST_SCORE.md): batch the bucket at list level, a
'who reported' breakdown, a provider-choice setting, alerts, confidence
scoring.
2026-10-09 17:07:34 +07:00
SkateSpots
486ffdb000 feat(map): add autocomplete suggestions to the search bar
Typing in the map search pill now opens a suggestions dropdown built
from the items that already match the active filters:
- Spots: title matches; selecting one flies to it and opens its sheet.
- Places: distinct city/region/country tokens split out of each item's
  location; selecting one sets the query to that token (e.g. spain ->
  Spain).

buildSearchSuggestions lives in lib (pure, testable) and
MapSearchSuggestions.tsx is presentational; MapPage owns the list and
keyboard nav (ArrowUp/Down, Enter, Escape). Adds mapPage.searchSuggestPlaces
(en/es only; other locales fall back to English).
2026-10-09 16:31:31 +07:00
SkateSpots
281a4c6ba5 feat(i18n): add search/filter to the language picker
The language list now has a search input in both the header dropdown
(pinned above the scrolling list) and the inline list used in the mobile
nav sheet. Filtering matches the English name, native name, or locale
code, and shows a localized empty state. Adds nav.searchLanguages and
nav.noLanguages to en/es (other locales fall back to English).
2026-10-08 18:16:13 +07:00
SkateSpots
d0e6fd5274 i18n(sv): finalize batch2 2026-10-08 17:21:49 +07:00
SkateSpots
d7a836e558 i18n(uk): complete Ukrainian (100%) + add to picker 2026-10-08 17:21:03 +07:00
SkateSpots
2e1167f8bd i18n(id): complete Indonesian (100%) + add to picker 2026-10-08 17:19:24 +07:00
SkateSpots
86427a0fb0 i18n(cs): complete Czech (100%) + add to picker 2026-10-08 17:18:34 +07:00
SkateSpots
2d656e5269 i18n(ro): complete Romanian (100%) + add to picker 2026-10-08 17:18:03 +07:00
SkateSpots
4acfa59e56 i18n(sv): complete Swedish (100%) + add to picker 2026-10-08 17:17:54 +07:00
SkateSpots
9998e7b8f6 i18n(el): complete Greek (100%) + add to picker 2026-10-08 17:17:43 +07:00
SkateSpots
09859bb7da i18n(vi): complete Vietnamese (100%) + add to picker 2026-10-08 17:17:35 +07:00
SkateSpots
69d04469f5 i18n(tr): complete Turkish (100%) + add to picker 2026-10-08 17:17:34 +07:00
SkateSpots
8e98a43949 i18n(zh-TW): complete Traditional Chinese (100%) + add to picker 2026-10-08 17:15:51 +07:00
SkateSpots
1c670d314b i18n(zh-CN): complete Simplified Chinese (100%) + add to picker 2026-10-08 16:00:33 +07:00
SkateSpots
feac9f764b i18n: register 10 locales (framework + scaffold); ro/el partial 2026-10-08 14:59:27 +07:00
SkateSpots
361f03c988 i18n(ru,ko): complete Russian + Korean translations; use North Korean flag for Korean 2026-10-07 23:56:20 +07:00
SkateSpots
78660580fa i18n(nl,pl): complete Dutch + Polish translations (100% — 8450 keys each) 2026-10-07 23:51:30 +07:00
SkateSpots
e73c678199 i18n(it): complete Italian translation (100% — 8450 keys) 2026-10-07 23:04:59 +07:00
SkateSpots
7635e1eaa9 i18n(de): complete German translation (100% — 8450 keys) 2026-10-07 22:35:32 +07:00
SkateSpots
1954adfdc2 i18n(fr): complete French translation (100% — 8450 keys) 2026-10-07 22:20:07 +07:00
SkateSpots
845733de24 i18n(pt): complete Brazilian Portuguese translation (100% — 8450 keys) 2026-10-07 21:57:07 +07:00
SkateSpots
90c06eeb91 i18n: scaffold fragment slots for the 8 new locales 2026-10-07 21:24:09 +07:00
SkateSpots
1460b06277 i18n: lazy-load locales + register 8 new (pt fr de it nl pl ru ko) with fonts 2026-10-07 21:23:39 +07:00
SkateSpots
a3b7f311ce i18n: translate image alt/aria + generated export documents (last English literals) 2026-10-07 18:30:52 +07:00
SkateSpots
0339395036 i18n: translate the moderation help line (last hardcoded JSX prose) 2026-10-07 18:11:57 +07:00
SkateSpots
f7c9f9ef4c i18n: sweep hardcoded English (deckCost, becomeRoles, weather, skaterLabels, notify, misc) into 4 locales 2026-10-07 18:09:57 +07:00
SkateSpots
8d1598d6c4 i18n: complete Japanese + Thai translation (both 100% — 7,889/7,889 keys) 2026-10-07 17:48:18 +07:00
SkateSpots
ba4beba09d i18n(th): add missing common.hide/undo keys 2026-10-07 17:45:52 +07:00
SkateSpots
312ee3a21c i18n: ja batches 9-11 (social, labOptions, small ns) + th batches 10-13 (lab, social, labOptions, small ns) 2026-10-07 17:45:12 +07:00
SkateSpots
c4c540826a i18n(ja): batch 6 — settingsUi 2026-10-07 17:41:51 +07:00
SkateSpots
83cc11f2dc i18n(th): batch 8 — settingsUi 2026-10-07 17:40:49 +07:00
SkateSpots
f1043c8881 i18n(th): batch 9 — walletUi 2026-10-07 17:39:44 +07:00
SkateSpots
2392b0ee2f i18n(ja): batch 7 — walletUi 2026-10-07 17:39:01 +07:00
SkateSpots
4ba13675cf i18n(ja): batch 8 — labUi 2026-10-07 17:38:05 +07:00
SkateSpots
91cd916b3f i18n: ja batches 4-5 (labels/fees/card, route/sasquatch) + th batches 6-7 (marketUi, placesUi) 2026-10-07 17:35:04 +07:00
SkateSpots
f41cb4a920 i18n(ja): batches 2-3 — map + spot/diy 2026-10-07 17:31:05 +07:00
SkateSpots
ab05973ff0 i18n(ja): add Japanese as fourth locale (plumbing + font + batch 1 shell) 2026-10-07 17:21:18 +07:00
SkateSpots
ae02f51d20 i18n(es): translate SEO titles & descriptions across 40 pages (seoUi) 2026-10-07 17:17:26 +07:00
SkateSpots
94a6628faa i18n(es): translate page/component toasts (follow, delete, reports, sync, review queue) 2026-10-07 17:14:18 +07:00
SkateSpots
2e9cbfba2b i18n(es): use "peña" instead of "cuadrilla" for crew (158 occurrences) 2026-10-07 17:09:39 +07:00
SkateSpots
dd2062dc74 i18n(es): translate status presets, SetStatusDialog, nutzap + wallet toasts 2026-10-07 17:04:04 +07:00
SkateSpots
69458e1ae6 i18n(es): translate the Sasquatch onboarding guide script 2026-10-07 16:58:43 +07:00