Compare commits

...
2 Commits
Author SHA1 Message Date
Chris Troutner 8a982d2ef2 Merge pull request #25 from Permissionless-Software-Foundation/dh-user-data-page
fix(user-data): Reconfigured user data page
2025-06-26 06:00:58 -07:00
Daniel Gonzalez 24bb18c77c fix(user-data): Reconfigured user data page 2025-06-25 18:58:24 -04:00
3 changed files with 79 additions and 64 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ function AppBody (props) {
<Route path='/nostr-post' element={<NostrPost appData={appData} />} /> <Route path='/nostr-post' element={<NostrPost appData={appData} />} />
<Route path='/nostr-read' element={<NostrRead appData={appData} />} /> <Route path='/nostr-read' element={<NostrRead appData={appData} />} />
<Route path='/global-feed' element={<GlobalFeed appData={appData} />} /> <Route path='/global-feed' element={<GlobalFeed appData={appData} />} />
<Route path='/user-data/:cid' element={<UserDataReview appData={appData} />} /> <Route path='/user-data/:tokenId' element={<UserDataReview appData={appData} />} />
<Route path='/offers' element={<Offers appData={appData} />} /> <Route path='/offers' element={<Offers appData={appData} />} />
</Routes> </Routes>
{/** Show in all paths except the servers view */} {/** Show in all paths except the servers view */}
@@ -102,7 +102,7 @@ function InfoButton (props) {
<Col xs={4}><b>User Data</b>:</Col> <Col xs={4}><b>User Data</b>:</Col>
<Col xs={8}> <Col xs={8}>
<a <a
href={`/user-data/${mutableDataCid}`} href={`/user-data/${props.token.tokenId}`}
target='_blank' target='_blank'
rel='noopener noreferrer' rel='noopener noreferrer'
className='btn btn-link p-0' className='btn btn-link p-0'
+77 -62
View File
@@ -5,25 +5,34 @@
// Global npm libraries // Global npm libraries
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
import { Container, Row, Col, Tabs, Tab, Spinner, Carousel } from 'react-bootstrap' import { Container, Row, Col, Spinner, Carousel } from 'react-bootstrap'
import ReactMarkdown from 'react-markdown' import ReactMarkdown from 'react-markdown'
function UserDataReview (props) { function UserDataReview (props) {
const appData = props.appData const appData = props.appData
const [media, setMedia] = useState([]) const [media, setMedia] = useState([])
const [markdown, setMarkdown] = useState('') const [markdown, setMarkdown] = useState('')
const [activeTab, setActiveTab] = useState('media')
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true)
const [error, setError] = useState(null) const [error, setError] = useState(null)
const [tokenData, setTokenData] = useState(null)
// Get the id parameter from the URL // Get the id parameter from the URL
const { cid } = useParams() const { tokenId } = useParams()
useEffect(() => { useEffect(() => {
const loadMedia = async () => { const loadData = async () => {
setLoading(true)
try { try {
const tokenData = await appData.wallet.getTokenData(tokenId)
setTokenData(tokenData)
setLoading(true)
if (!tokenData.mutableData) throw new Error('Mutable data not found')
const cid = parseCid(tokenData.mutableData)
const { json } = await appData.wallet.cid2json({ cid }) const { json } = await appData.wallet.cid2json({ cid })
const userDataString = json.userData const userDataString = json.userData
if (userDataString) { if (userDataString) {
const userData = JSON.parse(userDataString) const userData = JSON.parse(userDataString)
setMedia(userData.media) setMedia(userData.media)
@@ -34,74 +43,80 @@ function UserDataReview (props) {
} }
setLoading(false) setLoading(false)
} }
loadMedia() loadData()
}, [cid, appData.wallet]) }, [tokenId, appData.wallet])
// Get Cid from url
const parseCid = (url) => {
// get the cid from the url format 'ipfs://bafybeicem27xbzs65uvbcgykcmscsgln3lmhbfrcoec3gdttkdgtxv5acq
if (url && url.includes('ipfs://')) {
const cid = url.split('ipfs://')[1]
return cid
}
return url
}
return ( return (
<Container> <Container>
<Row> <Row>
<Col> <Col>
{/** Error message */}
{error && <p className='text-danger'>{error}</p>} {error && <p className='text-danger'>{error}</p>}
{loading
? ( {/** Loading spinner */}
{loading &&
(
<div className='text-center my-5'> <div className='text-center my-5'>
<Spinner animation='border' role='status' variant='primary'> <Spinner animation='border' role='status' variant='primary'>
<span className='visually-hidden'>Loading...</span> <span className='visually-hidden'>Loading...</span>
</Spinner> </Spinner>
</div> </div>
) )}
: ( {/** User data */}
<Tabs {!loading && !error && (
activeKey={activeTab} <div className='text-center'>
onSelect={(k) => setActiveTab(k)} {/** Name */}
className='mb-4' <h1>{tokenData.genesisData.name}</h1>
>
<Tab eventKey='media' title='Media'> {/** Media Content Carousel */}
{media && media.length > 0 {media && media.length > 0
? ( ? (
<div className='mt-3 mb-5'> <div className='my-5 '>
<Carousel> <Carousel>
{media.map((item, index) => ( {media.map((item, index) => (
<Carousel.Item key={index}> <Carousel.Item key={index}>
<img <img
className='d-block w-100' className='d-block w-100'
src={item.url} src={item.url}
alt={`Review media ${index + 1}`} alt={`Review media ${index + 1}`}
style={{ height: '400px', objectFit: 'contain' }} style={{ height: '400px', objectFit: 'contain' }}
/> />
<Carousel.Caption> <Carousel.Caption>
<p>Image {index + 1} of {media.length}</p> <p>Image {index + 1} of {media.length}</p>
</Carousel.Caption> </Carousel.Caption>
</Carousel.Item> </Carousel.Item>
))} ))}
</Carousel> </Carousel>
<style>{` <style>{'.carousel-control-next,.carousel-control-prev, .carousel-indicators {filter: invert(100%); } '}
.carousel-control-next, </style>
.carousel-control-prev, </div>
.carousel-indicators { )
filter: invert(100%); : (
} <p className='mt-3'>No media content available</p>
`} )}
</style>
</div> {/** Markdown Content */}
) {markdown
: ( ? (
<p className='mt-3'>No media content available</p> <div className='markdown-content my-5 text-center'>
)} <ReactMarkdown>{markdown}</ReactMarkdown>
</Tab> </div>
<Tab eventKey='markdown' title='Content'> )
{markdown : (
? ( <p className='mt-3'>No content available</p>
<div className='markdown-content mt-3'> )}
<ReactMarkdown>{markdown}</ReactMarkdown> </div>
</div> )}
)
: (
<p className='mt-3'>No content available</p>
)}
</Tab>
</Tabs>
)}
</Col> </Col>
</Row> </Row>
</Container> </Container>