- New SkateCrew kind 35006 + type/parser + useCrews/useCrew hooks - /crews directory, /create-crew, /edit-crew, /crew/:pubkey/:identifier pages - Reuses the collective engine: NIP-32 membership attestation (confirmed/pending), CollectiveMembers + ConfirmMembershipCard, ClinkPayButton, SpotPicker - Activity v1: home spots + crew member feed (no events, per plan) - Map: teal/cyan Crews layer at home turf with crew markers + popups; wired through SpotMap props, layer toggles (mobile popover + filters sheet), and mobileLayerCount badge - Nav: Crews added to navItemKeys (desktop header, mobile bottom bar, sidebar) with en/es i18n keys - NIP.md: documents kind 35006, tag taxonomy, and shared membership mechanism Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
146 lines
8.3 KiB
TypeScript
146 lines
8.3 KiB
TypeScript
import { lazy, Suspense } from "react";
|
|
import { HashRouter, Route, Routes } from "react-router-dom";
|
|
import { ScrollToTop } from "./components/ScrollToTop";
|
|
import { DeepLinkHandler } from "./components/DeepLinkHandler";
|
|
|
|
// Eagerly load the map — it's now the homepage
|
|
import MapPage from "./pages/MapPage";
|
|
|
|
// Lazy load everything else — each page becomes its own JS chunk
|
|
const Index = lazy(() => import("./pages/Index"));
|
|
const EventsPage = lazy(() => import("./pages/EventsPage"));
|
|
const LabPage = lazy(() => import("./pages/LabPage"));
|
|
const WalletPage = lazy(() => import("./pages/WalletPage"));
|
|
const SettingsPage = lazy(() => import("./pages/SettingsPage"));
|
|
const CreateSpotPage = lazy(() => import("./pages/CreateSpotPage"));
|
|
const CreateShopPage = lazy(() => import("./pages/CreateShopPage"));
|
|
const CreateEventPage = lazy(() => import("./pages/CreateEventPage"));
|
|
const CreateListingPage = lazy(() => import("./pages/CreateListingPage"));
|
|
const CreateTourPage = lazy(() => import("./pages/CreateTourPage"));
|
|
const EditSpotPage = lazy(() => import("./pages/EditSpotPage"));
|
|
const EditShopPage = lazy(() => import("./pages/EditShopPage"));
|
|
const EditEventPage = lazy(() => import("./pages/EditEventPage"));
|
|
const GearSwapPage = lazy(() => import("./pages/GearSwapPage"));
|
|
const SpotDetailPage = lazy(() => import("./pages/SpotDetailPage"));
|
|
const ShopDetailPage = lazy(() => import("./pages/ShopDetailPage"));
|
|
const EventDetailPage = lazy(() => import("./pages/EventDetailPage"));
|
|
const OnboardingPage = lazy(() => import("./pages/OnboardingPage"));
|
|
const PyramidPage = lazy(() => import("./pages/PyramidPage"));
|
|
const BecomeCoachPage = lazy(() => import("./pages/BecomeCoachPage"));
|
|
const BecomeFilmerPage = lazy(() => import("./pages/BecomeFilmerPage"));
|
|
const BecomeEditorPage = lazy(() => import("./pages/BecomeEditorPage"));
|
|
const BecomePhotographerPage = lazy(() => import("./pages/BecomePhotographerPage"));
|
|
const BecomeBuilderPage = lazy(() => import("./pages/BecomeBuilderPage"));
|
|
const CrewsPage = lazy(() => import("./pages/CrewsPage"));
|
|
const CreateCrewPage = lazy(() => import("./pages/CreateCrewPage"));
|
|
const EditCrewPage = lazy(() => import("./pages/EditCrewPage"));
|
|
const CrewDetailPage = lazy(() => import("./pages/CrewDetailPage"));
|
|
const CoachDetailPage = lazy(() => import("./pages/CoachDetailPage"));
|
|
const TourDetailPage = lazy(() => import("./pages/TourDetailPage"));
|
|
const AboutPage = lazy(() => import("./pages/AboutPage"));
|
|
const FAQPage = lazy(() => import("./pages/FAQPage"));
|
|
const FoodPage = lazy(() => import("./pages/FoodPage"));
|
|
const CommunityStatsPage = lazy(() => import("./pages/CommunityStatsPage"));
|
|
const SpotCollectionsPage = lazy(() => import("./pages/SpotCollectionsPage"));
|
|
const CollectionDetailPage = lazy(() => import("./pages/CollectionDetailPage"));
|
|
const DirectMessagesPage = lazy(() => import("./pages/DirectMessagesPage"));
|
|
const ConversationPage = lazy(() => import("./pages/ConversationPage"));
|
|
const BountyLeaderboardPage = lazy(() => import("./pages/BountyLeaderboardPage"));
|
|
const SignersPage = lazy(() => import("./pages/SignersPage"));
|
|
const StashPage = lazy(() => import("./pages/StashPage"));
|
|
const NIP19Page = lazy(() => import("./pages/NIP19Page").then(m => ({ default: m.NIP19Page })));
|
|
const LicensePage = lazy(() => import("./pages/LicensePage"));
|
|
const SupportersPage = lazy(() => import("./pages/SupportersPage"));
|
|
const RiderCardPage = lazy(() => import("./pages/RiderCardPage"));
|
|
const AmberCallbackPage = lazy(() => import("./pages/AmberCallbackPage"));
|
|
const MarketplacePage = lazy(() => import("./pages/MarketplacePage"));
|
|
const NewsletterPage = lazy(() => import("./pages/NewsletterPage"));
|
|
const NotFound = lazy(() => import("./pages/NotFound"));
|
|
|
|
// Minimal inline fallback — no extra component needed
|
|
function PageLoader() {
|
|
return (
|
|
<div className="min-h-screen bg-black flex items-center justify-center">
|
|
<div className="w-8 h-8 border-2 border-[#ff0040] border-t-transparent rounded-full animate-spin" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function AppRouter() {
|
|
return (
|
|
<HashRouter>
|
|
<DeepLinkHandler />
|
|
<ScrollToTop />
|
|
<Suspense fallback={<PageLoader />}>
|
|
<Routes>
|
|
{/* Map is the homepage */}
|
|
<Route path="/" element={<MapPage />} />
|
|
{/* /map redirects to / */}
|
|
<Route path="/map" element={<MapPage />} />
|
|
{/* Legacy home page still accessible */}
|
|
<Route path="/home" element={<Index />} />
|
|
<Route path="/events" element={<EventsPage />} />
|
|
<Route path="/lab" element={<LabPage />} />
|
|
{/* Legacy route redirect */}
|
|
<Route path="/coaches" element={<LabPage />} />
|
|
<Route path="/become-coach" element={<BecomeCoachPage />} />
|
|
<Route path="/become-filmer" element={<BecomeFilmerPage />} />
|
|
<Route path="/become-editor" element={<BecomeEditorPage />} />
|
|
<Route path="/become-photographer" element={<BecomePhotographerPage />} />
|
|
<Route path="/become-builder" element={<BecomeBuilderPage />} />
|
|
<Route path="/crews" element={<CrewsPage />} />
|
|
<Route path="/create-crew" element={<CreateCrewPage />} />
|
|
<Route path="/edit-crew/:pubkey/:identifier" element={<EditCrewPage />} />
|
|
<Route path="/crew/:pubkey/:identifier" element={<CrewDetailPage />} />
|
|
<Route path="/coach/:pubkey/:identifier" element={<CoachDetailPage />} />
|
|
<Route path="/onboarding" element={<OnboardingPage />} />
|
|
<Route path="/pyramid" element={<PyramidPage />} />
|
|
<Route path="/marketplace" element={<GearSwapPage />} />
|
|
<Route path="/stats" element={<CommunityStatsPage />} />
|
|
<Route path="/about" element={<AboutPage />} />
|
|
<Route path="/faq" element={<FAQPage />} />
|
|
<Route path="/food" element={<FoodPage />} />
|
|
<Route path="/wallet" element={<WalletPage />} />
|
|
<Route path="/settings" element={<SettingsPage />} />
|
|
<Route path="/create-spot" element={<CreateSpotPage />} />
|
|
<Route path="/create-shop" element={<CreateShopPage />} />
|
|
<Route path="/create-event" element={<CreateEventPage />} />
|
|
<Route path="/create-listing" element={<CreateListingPage />} />
|
|
<Route path="/create-tour" element={<CreateTourPage />} />
|
|
<Route path="/edit-spot/:pubkey/:identifier" element={<EditSpotPage />} />
|
|
<Route path="/edit-shop/:pubkey/:identifier" element={<EditShopPage />} />
|
|
<Route path="/edit-event/:pubkey/:identifier" element={<EditEventPage />} />
|
|
<Route path="/spot/:pubkey/:identifier" element={<SpotDetailPage />} />
|
|
<Route path="/shop/:pubkey/:identifier" element={<ShopDetailPage />} />
|
|
<Route path="/event/:pubkey/:identifier" element={<EventDetailPage />} />
|
|
<Route path="/tour/:pubkey/:identifier" element={<TourDetailPage />} />
|
|
<Route path="/collections" element={<SpotCollectionsPage />} />
|
|
<Route path="/collections/:pubkey/:identifier" element={<CollectionDetailPage />} />
|
|
<Route path="/messages" element={<DirectMessagesPage />} />
|
|
<Route path="/messages/:npub" element={<ConversationPage />} />
|
|
{/* Bounty System */}
|
|
<Route path="/bounties" element={<BountyLeaderboardPage />} />
|
|
{/* Security & Signers */}
|
|
<Route path="/signers" element={<SignersPage />} />
|
|
{/* Stash - Private Inventory */}
|
|
<Route path="/stash" element={<StashPage />} />
|
|
{/* Info pages */}
|
|
<Route path="/card" element={<RiderCardPage />} />
|
|
<Route path="/license" element={<LicensePage />} />
|
|
<Route path="/supporters" element={<SupportersPage />} />
|
|
{/* Amber NIP-55 callback — Amber redirects here after signing/login */}
|
|
<Route path="/amber-callback" element={<AmberCallbackPage />} />
|
|
{/* Marketplace */}
|
|
<Route path="/marketplace-listings" element={<MarketplacePage />} />
|
|
{/* Newsletter */}
|
|
<Route path="/newsletter" element={<NewsletterPage />} />
|
|
{/* NIP-19 route for npub1, note1, naddr1, nevent1, nprofile1 */}
|
|
<Route path="/:nip19" element={<NIP19Page />} />
|
|
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
|
|
<Route path="*" element={<NotFound />} />
|
|
</Routes>
|
|
</Suspense>
|
|
</HashRouter>
|
|
);
|
|
}
|
|
export default AppRouter;
|