test blog profile
This commit is contained in:
133
oauth/src/components/ProfileRecordList.jsx
Normal file
133
oauth/src/components/ProfileRecordList.jsx
Normal file
@@ -0,0 +1,133 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { collections } from '../api/atproto.js'
|
||||
import AvatarImage from './AvatarImage.jsx'
|
||||
import LoadingSkeleton from './LoadingSkeleton.jsx'
|
||||
|
||||
const ProfileRecordList = ({ apiConfig, user, agent, onRecordDeleted }) => {
|
||||
const [profiles, setProfiles] = useState([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (apiConfig?.admin && apiConfig?.collection) {
|
||||
fetchProfiles()
|
||||
}
|
||||
}, [apiConfig])
|
||||
|
||||
const fetchProfiles = async () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
|
||||
const adminProfiles = await collections.getProfiles(
|
||||
apiConfig.pds,
|
||||
apiConfig.admin,
|
||||
apiConfig.collection
|
||||
)
|
||||
|
||||
// Sort profiles: admin type first, then user type
|
||||
const sortedProfiles = adminProfiles.sort((a, b) => {
|
||||
if (a.value.type === 'admin' && b.value.type !== 'admin') return -1
|
||||
if (a.value.type !== 'admin' && b.value.type === 'admin') return 1
|
||||
return 0
|
||||
})
|
||||
|
||||
setProfiles(sortedProfiles)
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch profiles:', err)
|
||||
setError('プロフィールの読み込みに失敗しました')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDelete = async (uri) => {
|
||||
if (!user || !agent) return
|
||||
if (!confirm('このプロフィールを削除しますか?')) return
|
||||
|
||||
try {
|
||||
const rkey = uri.split('/').pop()
|
||||
await agent.api.com.atproto.repo.deleteRecord({
|
||||
repo: user.did,
|
||||
collection: `${apiConfig.collection}.profile`,
|
||||
rkey: rkey
|
||||
})
|
||||
|
||||
// Invalidate cache and refresh
|
||||
collections.invalidateCache(`${apiConfig.collection}.profile`)
|
||||
await fetchProfiles()
|
||||
|
||||
if (onRecordDeleted) {
|
||||
onRecordDeleted()
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to delete profile:', err)
|
||||
setError('プロフィールの削除に失敗しました')
|
||||
}
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return <LoadingSkeleton count={3} showTitle={true} />
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="error-state">
|
||||
<p>{error}</p>
|
||||
<button onClick={fetchProfiles} className="retry-btn">再試行</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (profiles.length === 0) {
|
||||
return (
|
||||
<div className="empty-state">
|
||||
<p>プロフィールがありません</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="record-list profile-record-list">
|
||||
{profiles.map((profile) => (
|
||||
<div key={profile.uri} className={`record-item comment-style ${profile.value.type}`}>
|
||||
<div className="message-header">
|
||||
<div className="avatar">
|
||||
<AvatarImage
|
||||
src={profile.value.author.avatar}
|
||||
alt={profile.value.author.displayName || profile.value.author.handle}
|
||||
size={40}
|
||||
/>
|
||||
</div>
|
||||
<div className="user-info">
|
||||
<div className="display-name">
|
||||
{profile.value.author.displayName || profile.value.author.handle}
|
||||
{profile.value.type === 'admin' && (
|
||||
<span className="admin-badge">Admin</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="handle">@{profile.value.author.handle}</div>
|
||||
<div className="timestamp">
|
||||
{new Date(profile.value.createdAt).toLocaleString()}
|
||||
</div>
|
||||
</div>
|
||||
{user && (
|
||||
<div className="record-actions">
|
||||
<button
|
||||
onClick={() => handleDelete(profile.uri)}
|
||||
className="delete-btn"
|
||||
title="削除"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="message-content">{profile.value.text}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProfileRecordList
|
Reference in New Issue
Block a user