import React, { useState } from 'react' import { env } from '../config/env.js' import AvatarTestPanel from './AvatarTestPanel.jsx' import AvatarTest from './AvatarTest.jsx' export default function TestUI() { const [activeTab, setActiveTab] = useState('putRecord') const [accessJwt, setAccessJwt] = useState('') const [handle, setHandle] = useState('') const [sessionDid, setSessionDid] = useState('') const [collection, setCollection] = useState('ai.syui.log') const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [success, setSuccess] = useState(null) const [showJson, setShowJson] = useState(false) const [lastRecord, setLastRecord] = useState(null) const collections = [ 'ai.syui.log', 'ai.syui.log.chat', 'ai.syui.log.chat.lang', 'ai.syui.log.chat.comment' ] const generateDummyData = (collectionType) => { const timestamp = new Date().toISOString() const url = 'https://syui.ai/test/dummy' const basePost = { url: url, date: timestamp, slug: 'dummy-test', tags: ['test', 'dummy'], title: 'Test Post', language: 'ja' } const baseAuthor = { did: sessionDid || null, // Use real session DID if available, otherwise null handle: handle || 'test.user', displayName: 'Test User', avatar: null } switch (collectionType) { case 'ai.syui.log': return { $type: collectionType, url: url, post: basePost, text: 'テストコメントです。これはダミーデータです。', type: 'comment', author: baseAuthor, createdAt: timestamp } case 'ai.syui.log.chat': const isQuestion = Math.random() > 0.5 return { $type: collectionType, post: basePost, text: isQuestion ? 'これはテスト用の質問です。' : 'これはテスト用のAI回答です。詳しく説明します。', type: isQuestion ? 'question' : 'answer', author: isQuestion ? baseAuthor : { did: 'did:plc:ai-test', handle: 'ai.syui.ai', displayName: 'ai', avatar: null }, createdAt: timestamp } case 'ai.syui.log.chat.lang': return { $type: collectionType, post: basePost, text: 'This is a test translation. Hello, this is a dummy English translation of the Japanese post.', type: 'en', author: { did: 'did:plc:ai-test', handle: 'ai.syui.ai', displayName: 'ai', avatar: null }, createdAt: timestamp } case 'ai.syui.log.chat.comment': return { $type: collectionType, post: basePost, text: 'これはAIによるテストコメントです。記事についての感想や補足情報を提供します。', author: { did: 'did:plc:ai-test', handle: 'ai.syui.ai', displayName: 'ai', avatar: null }, createdAt: timestamp } default: return {} } } const handleSubmit = async (e) => { e.preventDefault() if (!accessJwt.trim() || !handle.trim()) { setError('Access JWT and Handle are required') return } setLoading(true) setError(null) setSuccess(null) try { const recordData = generateDummyData(collection) const rkey = `test-${Date.now()}` const record = { repo: handle, // Use handle as is, without adding .bsky.social collection: collection, rkey: rkey, record: recordData } setLastRecord(record) // Direct API call with accessJwt const response = await fetch(`https://${env.pds}/xrpc/com.atproto.repo.putRecord`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${accessJwt}` }, body: JSON.stringify(record) }) if (!response.ok) { const errorData = await response.json() throw new Error(`API Error: ${response.status} - ${errorData.message || response.statusText}`) } const result = await response.json() setSuccess(`Record created successfully! URI: ${result.uri}`) } catch (err) { setError(err.message) } finally { setLoading(false) } } const handleDelete = async () => { if (!lastRecord || !accessJwt.trim()) { setError('No record to delete or missing access JWT') return } setLoading(true) setError(null) try { const deleteData = { repo: lastRecord.repo, collection: lastRecord.collection, rkey: lastRecord.rkey } const response = await fetch(`https://${env.pds}/xrpc/com.atproto.repo.deleteRecord`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${accessJwt}` }, body: JSON.stringify(deleteData) }) if (!response.ok) { const errorData = await response.json() throw new Error(`Delete Error: ${response.status} - ${errorData.message || response.statusText}`) } setSuccess('Record deleted successfully!') setLastRecord(null) } catch (err) { setError(err.message) } finally { setLoading(false) } } return (
OAuth不要のテスト用UI。accessJwtとhandleを直接入力して各collectionにダミーデータを投稿できます。
{showJson && ({JSON.stringify(generateDummyData(collection), null, 2)}
Collection: {lastRecord.collection}
RKey: {lastRecord.rkey}
Repo: {lastRecord.repo}