at main 2.9 kB view raw
1/// <reference path="../../guestbook.d.ts" /> 2import { useEffect, useRef } from "react" 3import { configureGuestbook } from "cutebook/register" 4import { GuestbookEntries } from "../GuestbookEntries" 5 6// Configure guestbook once 7let configured = false 8if (!configured) { 9 const isDev = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1' 10 const port = window.location.port || '3000' 11 12 // For dev, use loopback client format matching the demo 13 // Client ID uses http://localhost, redirect_uri uses 127.0.0.1 14 const scope = 'atproto transition:generic' 15 const redirectUri = isDev ? `http://127.0.0.1:${port}/guestbook` : 'https://nekomimi.pet/guestbook' 16 const clientId = isDev 17 ? `http://localhost?redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scope)}` 18 : 'https://nekomimi.pet/client-metadata.json' 19 20 configureGuestbook({ 21 oauth: { 22 clientId, 23 redirectUri, 24 scope, 25 }, 26 }) 27 configured = true 28} 29 30export function GuestbookPage() { 31 const refreshRef = useRef<(() => void) | null>(null) 32 33 const handleSignCreated = () => { 34 refreshRef.current?.() 35 } 36 37 useEffect(() => { 38 const signElement = document.querySelector('guestbook-sign') 39 if (signElement) { 40 signElement.addEventListener('sign-created', handleSignCreated) 41 return () => signElement.removeEventListener('sign-created', handleSignCreated) 42 } 43 }, []) 44 45 return ( 46 <div className="min-h-screen bg-gradient-to-b from-gray-50 to-gray-100 py-12 px-6"> 47 <div className="max-w-xl mx-auto"> 48 {/* Header */} 49 <header className="mb-12 text-center"> 50 <div className="inline-block mb-4"> 51 <span className="text-5xl">📖</span> 52 </div> 53 <h1 className="text-3xl font-light tracking-tight text-gray-900 mb-3"> 54 Ana's Guestbook 55 </h1> 56 <p className="text-gray-500 font-mono text-sm"> 57 Leave a message, say hello 58 </p> 59 </header> 60 61 {/* Sign Form */} 62 <div className="mb-12 bg-white rounded-2xl shadow-sm border border-gray-200/50 p-6"> 63 <guestbook-sign did="did:plc:ttdrpj45ibqunmfhdsb4zdwq"></guestbook-sign> 64 </div> 65 66 {/* Entries Header */} 67 <div className="flex items-center gap-3 mb-6"> 68 <div className="h-px flex-1 bg-gradient-to-r from-transparent via-gray-300 to-transparent"></div> 69 <span className="text-xs font-mono text-gray-400 uppercase tracking-widest"> 70 Messages 71 </span> 72 <div className="h-px flex-1 bg-gradient-to-r from-transparent via-gray-300 to-transparent"></div> 73 </div> 74 75 <GuestbookEntries 76 did="did:plc:ttdrpj45ibqunmfhdsb4zdwq" 77 limit={50} 78 onRefresh={(refresh) => { refreshRef.current = refresh }} 79 /> 80 </div> 81 </div> 82 ) 83} 84