Crews page
- "Near me" geolocation toggle with haversine distance sort + distance chips
- Crew count + cities social-proof stat header
- Deterministic per-crew vibe-colour accents (no more wall of teal)
- Activity pulse ("🔥 active this week") + OG/Verified/Established rep badges
- Rich empty state ("Claim your local scene") instead of dead "No crews yet"
Crew synergies
- Crew treasury: transparent, non-custodial NIP-75 zap goal (kind 9041) with
live progress bar tallied from zap receipts; funds settle to founder's own
Lightning wallet — no shared wallet or new wallet settings needed
- Crew-hosted events: host a jam/comp as the crew (event a-tag → crew coord),
"Hosted by [crew]" on event pages, Crew Events list on the crew page
- Crew ↔ Lab hiring pipeline: "Open Call / looking-for" flags (filmer, editor,
coach, builder, members) surfaced on the crew page
- Request to join: encrypted NIP-17 DM to founder + admins (no founder-push
bottleneck, no public join event)
- Reverse links: "Crews that skate here" on spot pages
Contacts (0xchat-style + Armada-style privacy)
- New /contacts page with Crew-mates / Follows / Recent DMs / Saved tabs
- Per-contact quick actions: message, zap, view profile, star
- Private encrypted contacts list (NIP-51 kind 30000, NIP-44 encrypted to self)
- Added to burger menu + desktop More menu (gated to logged-in users)
Docs: NIP.md updated with crew treasury, crew-hosted events, looking-for tags,
and the private encrypted contacts list.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
39 lines
1.5 KiB
TypeScript
39 lines
1.5 KiB
TypeScript
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { CREW_LOOKING_FOR_LABELS } from '@/lib/types';
|
|
import { Megaphone } from 'lucide-react';
|
|
|
|
/**
|
|
* Display a crew's open calls ("looking for a filmer / editor / new members").
|
|
* This is the crew ↔ Lab hiring pipeline: crews broadcast what they need, and
|
|
* matching Lab providers can reach out. Slugs map to Lab scenes.
|
|
*/
|
|
export function CrewLookingForCard({ lookingFor }: { lookingFor: string[] }) {
|
|
if (!lookingFor || lookingFor.length === 0) return null;
|
|
|
|
return (
|
|
<Card className="border-2 border-fuchsia-500/30 bg-black/90">
|
|
<CardHeader className="pb-3">
|
|
<CardTitle className="flex items-center gap-2 text-lg font-black uppercase text-white">
|
|
<Megaphone className="h-5 w-5 text-fuchsia-400" /> Open Call
|
|
</CardTitle>
|
|
<p className="text-xs text-gray-400">This crew is looking for:</p>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="flex flex-wrap gap-2">
|
|
{lookingFor.map((slug) => {
|
|
const meta = CREW_LOOKING_FOR_LABELS[slug];
|
|
return (
|
|
<span
|
|
key={slug}
|
|
className="inline-flex items-center gap-1.5 rounded-xl border border-fuchsia-500/40 bg-fuchsia-500/10 px-3 py-1.5 text-sm font-bold text-fuchsia-200"
|
|
>
|
|
<span>{meta?.emoji ?? '🛹'}</span>
|
|
{meta?.label ?? slug}
|
|
</span>
|
|
);
|
|
})}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|