The guide's action buttons used window.location.href = '/onboarding', a hard full-page navigation. In the SPA/native (Capacitor) context this reboots the app at its entry point (home) rather than resolving the client-side route, so tapping "Learn More" dumped users back on the home page. Switched all Sasquatch guide navigation (Learn More, Login to begin, Login to Offer Services / Create a Crew, Start exploring) to React Router's navigate(), which performs proper in-app client-side routing and reliably renders the target page. Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
165 lines
5.8 KiB
TypeScript
165 lines
5.8 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { useLocation, useNavigate } from 'react-router-dom';
|
|
import { useCurrentUser } from '@/hooks/useCurrentUser';
|
|
import type { GuideMessage } from '@/components/SasquatchGuide';
|
|
|
|
/**
|
|
* Sasquatch Guide - Context-aware helper for onboarding and tips
|
|
* Always visible on home and onboarding pages, can be minimized/expanded at will
|
|
*/
|
|
export function useSasquatchGuide() {
|
|
const location = useLocation();
|
|
const navigate = useNavigate();
|
|
const { user } = useCurrentUser();
|
|
const [currentMessage, setCurrentMessage] = useState<GuideMessage | undefined>();
|
|
|
|
useEffect(() => {
|
|
let message: GuideMessage | undefined;
|
|
|
|
// Show on home page
|
|
if (location.pathname === '/') {
|
|
message = {
|
|
id: 'welcome',
|
|
title: 'Welcome to SkateSpots! 🦧',
|
|
message: "Yo, I'm The Sasquatch. Keeper of boards, trails, and wild rides. Welcome to the untamed skate world on Nostr—no suits, no ads, just skaters carving their own path. Here, you own your tricks, your data, and even earn Bitcoin for leaving your mark. Connect with skaters in your hood or across the globe. No rules but shredding, no footprints but your own.",
|
|
context: 'home',
|
|
suggestedQuestions: [
|
|
'Plan me 3 days in Barcelona',
|
|
'Find beginner spots',
|
|
'Any upcoming events?',
|
|
'Community stats',
|
|
'Find coaches near me',
|
|
'Gear for sale?',
|
|
'What is Nostr?',
|
|
'Is this free?',
|
|
],
|
|
action: {
|
|
label: 'Learn More',
|
|
onClick: () => {
|
|
navigate('/onboarding');
|
|
},
|
|
},
|
|
enableChat: true,
|
|
// Map homepage: don't auto-open the panel — the bubble stays minimized
|
|
// until the user taps it.
|
|
autoShow: false,
|
|
};
|
|
}
|
|
|
|
// Show on onboarding page
|
|
else if (location.pathname === '/onboarding') {
|
|
message = {
|
|
id: 'onboarding',
|
|
title: 'Getting Started 🚀',
|
|
message: "Let me help you understand the basics! Nostr is your identity, Bitcoin Lightning lets you earn sats for contributions, and zaps are instant tips. Ask me anything about getting started!",
|
|
context: 'onboarding',
|
|
suggestedQuestions: [
|
|
'How to login?',
|
|
'What is Nostr?',
|
|
'How does Nostr work?',
|
|
'What is Cashu?',
|
|
'How to use Cashu wallet?',
|
|
'What are mints?',
|
|
'What are zaps?',
|
|
'What is NWC?',
|
|
],
|
|
action: {
|
|
label: user ? 'Start exploring' : 'Login to begin',
|
|
onClick: () => {
|
|
if (user) {
|
|
navigate('/map');
|
|
} else {
|
|
// Scroll to login section
|
|
const loginSection = document.getElementById('login-section');
|
|
if (loginSection) {
|
|
loginSection.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
// Highlight the section briefly
|
|
loginSection.classList.add('ring-4', 'ring-red-500/50');
|
|
setTimeout(() => {
|
|
loginSection.classList.remove('ring-4', 'ring-red-500/50');
|
|
}, 2000);
|
|
} else {
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
}
|
|
}
|
|
},
|
|
},
|
|
enableChat: true,
|
|
// Dedicated onboarding page — auto-open is helpful here.
|
|
autoShow: true,
|
|
};
|
|
}
|
|
|
|
// Show on The Lab page
|
|
else if (location.pathname === '/lab') {
|
|
message = {
|
|
id: 'lab-guide',
|
|
title: 'Welcome to The Lab! 🎓',
|
|
message: `This is where the magic happens! Find coaches who can teach you anything from kickflips to darkslides, or connect with filmers to capture your best sessions. Filter by skills, check their experience, and book a session. Remember - everyone started somewhere!`,
|
|
context: 'lab',
|
|
suggestedQuestions: [
|
|
'Find coaches',
|
|
'Find filmers',
|
|
'Find photographers',
|
|
'Find video editors',
|
|
'Find a ramp builder',
|
|
'What is The Lab?',
|
|
'What is a builder?',
|
|
'How to offer coaching?',
|
|
],
|
|
action: user ? undefined : {
|
|
label: 'Login to Offer Services',
|
|
onClick: () => {
|
|
navigate('/onboarding');
|
|
},
|
|
},
|
|
enableChat: true,
|
|
// The Lab: don't auto-open — the bubble stays minimized until tapped.
|
|
autoShow: false,
|
|
};
|
|
}
|
|
|
|
// Show on the Crews page
|
|
else if (location.pathname === '/crews') {
|
|
message = {
|
|
id: 'crews-guide',
|
|
title: 'Crews 🤘',
|
|
message: `Crews are your map-anchored skate family — the people you skate WITH, not who you hire. Every crew has home turf on the map, home spots, members and a manifesto. Members confirm from their own keys, so the roster's legit. Start your own or find your people!`,
|
|
context: undefined,
|
|
suggestedQuestions: [
|
|
'What are crews?',
|
|
'How to start a crew?',
|
|
'How is a crew different from The Lab?',
|
|
'How do members confirm?',
|
|
'What is Nostr?',
|
|
'How do zaps work?',
|
|
],
|
|
action: user ? undefined : {
|
|
label: 'Login to Create a Crew',
|
|
onClick: () => {
|
|
navigate('/onboarding');
|
|
},
|
|
},
|
|
enableChat: true,
|
|
autoShow: false,
|
|
};
|
|
}
|
|
|
|
// /map: never auto-show — user opens Sasquatch by tapping the floating bubble
|
|
// The map guide context is still available in the generic fallback inside SasquatchGuide
|
|
else if (location.pathname === '/map') {
|
|
message = undefined;
|
|
}
|
|
|
|
setCurrentMessage(message);
|
|
}, [location.pathname, user, navigate]);
|
|
|
|
const dismissCurrentMessage = () => {
|
|
setCurrentMessage(undefined);
|
|
};
|
|
|
|
return {
|
|
currentMessage,
|
|
dismissCurrentMessage,
|
|
};
|
|
}
|