SkateSpots/src/components/PaymentReadinessNote.tsx
shakespeare.diy a89fca8e28 Lab: payment-readiness prompt on every provider form + drop downhill/longboard from judge
- New PaymentReadinessNote component: checks the logged-in user's Nostr profile
  (kind 0) for a Lightning address / Silent Payment and either confirms "you can
  get paid" or links them to Edit Profile to add one. Wired into CraftProfileForm
  (coach, filmer, editor, photographer, builder, artist, graffiti, tattoo,
  trainer, musician, judge) and the standalone coach/filmer/editor/photographer/
  builder forms, alongside the existing CLINK (noffer) field. Lightning address
  stays a single source of truth on kind 0 — never duplicated/stale per event.
- become-judge: removed the "Downhill / Longboard" event format (not part of the
  skateboarding activities this app covers).

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-09-03 15:21:34 +07:00

69 lines
2.9 KiB
TypeScript

import { Link } from 'react-router-dom';
import { Zap, CheckCircle2, AlertCircle } from 'lucide-react';
import { useCurrentUser } from '@/hooks/useCurrentUser';
import { useAuthor } from '@/hooks/useAuthor';
import { isValidLightningAddress, isValidSilentPayment } from '@/lib/types';
/**
* Payment-readiness note for provider / Lab / crew forms.
*
* Lightning address (lud16) and Bitcoin Silent Payment live on the user's Nostr
* profile (kind 0), NOT on each individual Lab event — so a single source of
* truth never goes stale across a person's many profiles. This note simply
* tells a provider whether that source is set up, and links them to Edit Profile
* if it isn't, so they always have a clear path to "get paid".
*/
export function PaymentReadinessNote() {
const { user } = useCurrentUser();
const author = useAuthor(user?.pubkey || '');
const metadata = author.data?.metadata;
const lud16 = metadata?.lud16;
const hasLightning = isValidLightningAddress(lud16) || !!metadata?.lud06;
// Silent payment lives in a custom kind-0 field the app reads elsewhere.
const rawSp = (metadata as Record<string, unknown> | undefined)?.bitcoin_silent_payment;
const hasSilentPayment = typeof rawSp === 'string' && isValidSilentPayment(rawSp);
if (!user) return null;
const ready = hasLightning;
return (
<div
className={
ready
? 'space-y-1.5 rounded-lg border border-green-500/25 bg-green-500/5 p-4'
: 'space-y-1.5 rounded-lg border border-yellow-500/30 bg-yellow-500/5 p-4'
}
>
<div className="flex items-center gap-2">
<Zap className={ready ? 'h-4 w-4 text-green-400' : 'h-4 w-4 text-yellow-400'} />
<span className={ready ? 'text-sm font-bold text-green-300' : 'text-sm font-bold text-yellow-300'}>
{ready ? 'You can get paid' : 'Set up payments to get paid'}
</span>
</div>
{ready ? (
<p className="flex items-start gap-1.5 text-xs text-gray-400">
<CheckCircle2 className="mt-0.5 h-3.5 w-3.5 shrink-0 text-green-400" />
<span>
Your Lightning address{lud16 ? <> (<span className="font-mono">{lud16}</span>)</> : ''} is on your
profile — people can zap and pay you directly.
{hasSilentPayment && ' A Bitcoin Silent Payment address is set too.'}
</span>
</p>
) : (
<p className="flex items-start gap-1.5 text-xs text-gray-400">
<AlertCircle className="mt-0.5 h-3.5 w-3.5 shrink-0 text-yellow-400" />
<span>
Add a Lightning address (and optionally a Bitcoin Silent Payment address) to your{' '}
<Link to="/settings" className="text-yellow-400 underline hover:text-yellow-300">
Nostr profile
</Link>{' '}
so skaters can pay you. It's set once and works across every profile you have here.
</span>
</p>
)}
</div>
);
}