Commit graph

7 commits

Author SHA1 Message Date
SkateSpots
f7c9f9ef4c i18n: sweep hardcoded English (deckCost, becomeRoles, weather, skaterLabels, notify, misc) into 4 locales 2026-10-07 18:09:57 +07:00
SkateSpots
681eab9592 Add craft-specific detail fields with matching display sections
Per-craft freeform fields, each wired end-to-end (form + detail display) so
none are stored invisibly:

- Artist: deliverables, turnaround
- Graffiti: surfaces, max_size
- Musician: set_length, tech_rider
- Judge: travel, certifications
- Organizer: insurance, permits
- Tattoo: deposit, minimum
- Trainer: modalities
- Barber: duration
- Filmer/Editor/Photographer: turnaround, deliverables (filmer adds drone)
- Builder: lead_time, warranty

Data-driven crafts declare them via CraftProfileForm's extraFields (now with
labelKey); the bespoke pages add matching state/inputs/prefill/save.
src/lib/craftFields.ts (CRAFT_DETAIL_FIELDS) maps each tag to a display label,
rendered on the shared detail page; toggle tags render as a localized Yes.
Labels are translated (EN/ES); placeholders stay as examples.
2026-10-04 10:53:57 +07:00
SkateSpots
88a3e4d1b4 Generalize the coach profile enrichment to every Lab craft
The coach portfolio/experience/payments treatment is now a shared layer instead
of 12 copies:

- src/lib/labExtras.ts: parseLabExtras + shared option sets (languages,
  availability, structured rate, payment methods, booking fee, gallery/reel).
- components/LabExtrasFields.tsx: the self-contained form block — prefills from
  the existing event, owns its state, and reports the managed tags via onChange.
- components/LabExtrasSection.tsx: the detail block (all crafts).

Wired into CraftProfileForm (the 8 data-driven crafts) and the four bespoke
pages (filmer/editor/photographer/builder); CoachDetailPage renders the shared
section for every craft. Per-craft buying units (rateUnits) are set per craft in
becomeRoles.tsx (e.g. barber 'per cut', musician 'per gig', photographer 'per
shoot'). /lab facet filters now read parseLabExtras, so availability/languages
filter across crafts.

Coach-specific formats/levels/ages/credentials remain coach-only. Money stays
custody-free: declared methods + a booking fee paid directly to the provider.
2026-10-04 10:49:48 +07:00
SkateSpots
7347f874ad i18n(es): batch 4 — Lab option labels, Sasquatch static FAQ, fee tiers
- labOptions.* (430 keys): all ~50 role LABELS/DESCRIPTIONS maps in types.ts
  (coach/filmer/editor/photo/builder/artist/graffiti/tattoo/trainer/musician/
  judge/organizer/barber) + TOUR_SKILL_LEVELS; 51 shared key maps in
  labelKeys.ts; consumers in becomeRoles/CraftProfileForm, LabPage,
  CoachDetailPage, the /become/* pages, TourCard/TourDetailPage/CreateTourPage/
  EventsPage. Trick names + tool/brand nouns stay English.
- sasquatchChat.* (83 keys): the free-tier STATIC_FAQ and local-result/fallback
  chat bodies (live AI already replies in-language; prompts stay English).
- feesUi.* (57 keys): usePurchasePro receipt prose + errors, PlatformFeePayment
  fee/duration tiers (LabProUpgrade/FeaturedEventUpgrade were already done).
- New src/i18n/batch4/ fragments spread into en/es.
2026-10-02 15:57:44 +07:00
SkateSpots
a881a87f4d feat(lab): add Barber / Hairstylist profile (kind 35014)
A full Lab role, mirroring how Event Organizer was added:
- kinds: SKATE_BARBER_KIND 35014, self-tag 'skatebarber', BARBER_*_LABELS,
  SkateBarber + parseSkateBarber (studio, books_open).
- craft config at /become/barber (cyan accent, Sparkles icon), Lab tab
  'Barbers', filter sections (services/styles/setting), empty state, FAB item.
- Lab pipeline: useLabProfiles kind/tag/parser, LabPage ServiceType
  'barbering' + ACCENT/maps/counts, CoachDetailPage per-role maps + studio &
  books-open block, LabLinkField label, growth stats + Community Stats card.
- No crew-scene strip for barbers (LabCrewsStrip returns null).
- Documented in NIP.md; smoke test now boots /become/barber.
2026-09-27 10:15:30 +07:00
SkateSpots
b60b13dc18 feat(lab): add Event Organizer craft profile (kind 35013)
New data-driven Lab role 'Event Organizer / Host' — skaters who put on jams,
comps, meetups, demos and tour stops.
- types.ts: SKATE_ORGANIZER_KIND=35013, ORGANIZER_EVENT/SERVICE/SCALE label
  maps, SkateOrganizer + parseSkateOrganizer (events_hosted extra tag)
- becomeRoles: craft config (teal accent, Tent icon, 3 skill sections)
- useLabProfiles: registered kind/self-tag/parser
- LabPage: Organizers tab, accent, filter drawer section, empty state, Offer
  link, counts
- CoachDetailPage (generic Lab detail): accent/icon/kind/labels/noun
- LabCrewsStrip: union updated
- NIP.md documents kind 35013; smoke covers /lab and /become/organizer

Gate: 101 tests, 0 errors/warnings, boot smoke green.
2026-09-27 00:02:39 +07:00
shakespeare.diy
16e943d4ef refactor: consolidate become-* routes + migrate empty states to shared component
Empty states (P4 follow-up):
- CrewsPage and EventsPage now render the shared <EmptyState> instead of
  their own local copies, keeping spacing/actions/footer consistent.

Become-role routes (P1):
- Add src/lib/becomeRoles.tsx: single registry mapping each role slug to
  either a CraftProfileForm config (artist/graffiti/musician/judge/tattoo/
  trainer) or a lazy bespoke page (coach/filmer/editor/photographer/
  builder/skater). The 6 craft roles were already thin config wrappers, so
  their configs move into the registry and the wrapper files are deleted.
- Replace 12 hardcoded /become-* routes + 12 imports with one
  /become/:role route (BecomeRolePage) that renders from the registry.
- Legacy /become-<slug> URLs now redirect to /become/<slug> so shared/
  bookmarked links keep working.
- Update all internal links (LabPage, Index, SkatersPage, SpotDetailPage,
  NIP19Page, SkaterDirectoryCard) to the canonical /become/<slug> paths.

Note: the 5 large bespoke forms were intentionally NOT merged into one
config — they carry distinct machinery (SpotPicker, wallet/Pro, geohashing)
and forcing them together would increase complexity, not reduce it.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-09-24 18:44:53 +07:00