fix(ux): Batch A part 2 — stash, crew invites, map marker
- Stash: remove the handler-less 'Share via DM' button; action overlay stays visible on touch (was hover-only, so edit/delete were unreachable on mobile) - Crew invite accept no longer claims membership is confirmed (only the founder ratifies the roster) — both the toast and the accepted state now say so - Crew invite share message no longer promises a one-click join - Map marker: don't bind the Leaflet popup when a host supplies onSpotClick (MapPage's bottom sheet) — both used to appear at once
This commit is contained in:
parent
f4192e2f3d
commit
cbd12f3e52
4 changed files with 21 additions and 23 deletions
|
|
@ -40,8 +40,8 @@ export function CrewInviteCard({
|
||||||
await accept({ invite });
|
await accept({ invite });
|
||||||
setDone('accepted');
|
setDone('accepted');
|
||||||
toast({
|
toast({
|
||||||
title: `Welcome to ${invite.crewName}! 🛹`,
|
title: 'Invite accepted 🛹',
|
||||||
description: 'Your membership is confirmed.',
|
description: `The crew founder confirms members on ${invite.crewName}. You'll appear on the roster once they approve.`,
|
||||||
});
|
});
|
||||||
onResolved?.();
|
onResolved?.();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -69,7 +69,7 @@ export function CrewInviteCard({
|
||||||
{done === 'accepted' ? (
|
{done === 'accepted' ? (
|
||||||
<>
|
<>
|
||||||
<Check className="h-4 w-4 text-teal-400" />
|
<Check className="h-4 w-4 text-teal-400" />
|
||||||
You joined <span className="font-bold text-white">{invite.crewName}</span>
|
Accepted — <span className="font-bold text-white">{invite.crewName}</span> confirms members
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ export function CrewInviteDialog({ crew, isFounder, triggerClassName }: CrewInvi
|
||||||
const crewUrl = `${window.location.origin}/crew/${crew.pubkey}/${crew.identifier}`;
|
const crewUrl = `${window.location.origin}/crew/${crew.pubkey}/${crew.identifier}`;
|
||||||
const inviteMessage =
|
const inviteMessage =
|
||||||
`Yo — join the ${crew.name} crew on SkateSpots 🛹\n${crewUrl}\n\n` +
|
`Yo — join the ${crew.name} crew on SkateSpots 🛹\n${crewUrl}\n\n` +
|
||||||
`Log in with your Nostr key, then confirm your membership on the crew page.`;
|
`Log in with your Nostr key, then request to join from the crew page.`;
|
||||||
|
|
||||||
const copy = async (text: string, which: 'link' | 'msg') => {
|
const copy = async (text: string, which: 'link' | 'msg') => {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1113,19 +1113,23 @@ export function SpotMap({
|
||||||
icon,
|
icon,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create popup
|
// When the host page supplies onSpotClick (MapPage's bottom sheet), let it
|
||||||
|
// own the detail UI — binding the Leaflet popup too made BOTH appear at
|
||||||
|
// once. Standalone map usages (no handler) keep the popup.
|
||||||
if (primarySpot) {
|
if (primarySpot) {
|
||||||
const spotWeather = weatherEnabled && weatherData ? weatherData.get(primarySpot.geohash) : undefined;
|
if (!onSpotClick) {
|
||||||
|
const spotWeather = weatherEnabled && weatherData ? weatherData.get(primarySpot.geohash) : undefined;
|
||||||
|
|
||||||
// Use enhanced popup if there are marketplace items, otherwise use standard
|
// Use enhanced popup if there are marketplace items, otherwise use standard
|
||||||
const popupContent = hasGear
|
const popupContent = hasGear
|
||||||
? createEnhancedPopupContent(primarySpot, group.marketplaceItems, () => handleViewDetails(primarySpot), spotWeather)
|
? createEnhancedPopupContent(primarySpot, group.marketplaceItems, () => handleViewDetails(primarySpot), spotWeather)
|
||||||
: createPopupContent(primarySpot, () => handleViewDetails(primarySpot), spotWeather);
|
: createPopupContent(primarySpot, () => handleViewDetails(primarySpot), spotWeather);
|
||||||
|
|
||||||
marker.bindPopup(popupContent, {
|
marker.bindPopup(popupContent, {
|
||||||
maxWidth: 350,
|
maxWidth: 350,
|
||||||
className: 'custom-popup',
|
className: 'custom-popup',
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
marker.on('click', () => {
|
marker.on('click', () => {
|
||||||
onSpotClick?.(primarySpot);
|
onSpotClick?.(primarySpot);
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ import {
|
||||||
Target,
|
Target,
|
||||||
Swords,
|
Swords,
|
||||||
Heart,
|
Heart,
|
||||||
Send,
|
|
||||||
Backpack,
|
Backpack,
|
||||||
Trophy,
|
Trophy,
|
||||||
Flame,
|
Flame,
|
||||||
|
|
@ -204,7 +203,7 @@ function StashItemCard({ item, onEdit, onDelete, onListOnMarketplace, isWTB = fa
|
||||||
<span className="text-[10px] uppercase tracking-wider text-muted-foreground">{category.label}</span>
|
<span className="text-[10px] uppercase tracking-wider text-muted-foreground">{category.label}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="absolute inset-0 bg-black/85 opacity-0 group-hover:opacity-100 transition-all duration-200 flex flex-col items-center justify-center gap-2 backdrop-blur-sm">
|
<div className="absolute inset-0 bg-black/85 transition-all duration-200 flex flex-col items-center justify-center gap-2 backdrop-blur-sm opacity-100 md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Button size="sm" variant="outline" className="h-8 border-white/30" onClick={(e) => { e.stopPropagation(); onEdit(); }}>
|
<Button size="sm" variant="outline" className="h-8 border-white/30" onClick={(e) => { e.stopPropagation(); onEdit(); }}>
|
||||||
<Edit3 className="h-3.5 w-3.5 mr-1" />Edit
|
<Edit3 className="h-3.5 w-3.5 mr-1" />Edit
|
||||||
|
|
@ -219,11 +218,6 @@ function StashItemCard({ item, onEdit, onDelete, onListOnMarketplace, isWTB = fa
|
||||||
<Store className="h-3 w-3 mr-1" />List on Marketplace
|
<Store className="h-3 w-3 mr-1" />List on Marketplace
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{item.visibility !== 'private' && (
|
|
||||||
<Button size="sm" variant="ghost" className="h-7 text-cyan-400 hover:text-cyan-300 hover:bg-cyan-500/10">
|
|
||||||
<Send className="h-3 w-3 mr-1" />Share via DM
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<CardContent className="p-3 space-y-2">
|
<CardContent className="p-3 space-y-2">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue