diff --git a/src/pages/NewsletterPage.tsx b/src/pages/NewsletterPage.tsx index d537f85..ae2bac9 100644 --- a/src/pages/NewsletterPage.tsx +++ b/src/pages/NewsletterPage.tsx @@ -5,15 +5,25 @@ import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Link } from 'react-router-dom'; import { Skeleton } from '@/components/ui/skeleton'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, +} from '@/components/ui/dialog'; import { Zap, MapPin, Shield, Layers, Crown, Radio, ArrowRight, Share2, CheckCircle2, Users, Store, Calendar, - GraduationCap, Route, + GraduationCap, Route, Eye, Send, } from 'lucide-react'; +import { useAuthor } from '@/hooks/useAuthor'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useNostrPublish } from '@/hooks/useNostrPublish'; import { useGrowthStats } from '@/hooks/useGrowthStats'; import { useToast } from '@/hooks/useToast'; +import { genUserName } from '@/lib/genUserName'; +import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'; // ─── Admin pubkeys allowed to publish newsletter as kind 1 ─────────────────── @@ -128,7 +138,7 @@ export const NEWSLETTER_ISSUES: NewsletterIssue[] = [ icon: 'feature', title: 'Trusted count on community stats', tag: 'Transparency', - body: "The stats page now shows spots from 'active accounts' — pubkeys that have published at least 2 items — alongside the raw total. Sponsors see the organic number.", + body: "The stats page now shows spots from 'active accounts' — pubkeys that have published at least 2 items — alongside the raw total. Users can now see both the raw number and the organic number side by side.", }, { icon: 'shield', @@ -156,16 +166,125 @@ https://skate-spots.org/newsletter }, ]; -// ─── Publish to Nostr button ────────────────────────────────────────────────── +// ─── Nostr post preview + publish ──────────────────────────────────────────── + +function NostrPreviewModal({ + issue, + open, + onClose, + onConfirm, + isPending, +}: { + issue: NewsletterIssue; + open: boolean; + onClose: () => void; + onConfirm: () => void; + isPending: boolean; +}) { + const { user } = useCurrentUser(); + const author = useAuthor(user?.pubkey ?? ''); + const metadata = author.data?.metadata; + const displayName = metadata?.name ?? genUserName(user?.pubkey ?? ''); + const avatar = metadata?.picture; + const now = new Date(); + const timeStr = now.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' }); + + // Render the nostrText with hashtags highlighted and URL as a link-style span + const renderPreviewText = (text: string) => { + return text.split('\n').map((line, i) => { + const parts = line.split(/(\s+)/).map((word, j) => { + if (word.startsWith('#')) { + return {word}; + } + if (word.startsWith('https://')) { + return {word}; + } + return {word}; + }); + return
{parts}
; + }); + }; + + return ( + + ); +} function PublishToNostrButton({ issue }: { issue: NewsletterIssue }) { const { user } = useCurrentUser(); const { mutateAsync: publishEvent, isPending } = useNostrPublish(); const { toast } = useToast(); const [published, setPublished] = useState(false); + const [showPreview, setShowPreview] = useState(false); const isAdmin = NEWSLETTER_ADMIN_PUBKEYS.includes(user?.pubkey ?? ''); if (!user || !isAdmin) return null; + if (published) { return (