Adding Posts page

This commit is contained in:
Chris Troutner
2026-06-03 12:24:27 -07:00
parent a32ae73ba4
commit dbc0c298bd
4 changed files with 129 additions and 0 deletions
+2
View File
@@ -24,6 +24,7 @@ import SignMessage from './sign/index.js'
import ServerSelectView from './configuration/select-server-view'
import UserDataReview from './user-data-review'
import RecentProfiles from './recent-profiles'
import RecentPosts from './posts'
function AppBody (props) {
// Dependency injection through props
@@ -38,6 +39,7 @@ function AppBody (props) {
<Route path='/wallet' element={<Wallet appData={appData} />} />
<Route path='/slp-tokens' element={<SlpTokens appData={appData} />} />
<Route path='/profile/recent' element={<RecentProfiles />} />
<Route path='/posts/recent' element={<RecentPosts />} />
<Route path='/placeholder2' element={<Placeholder2 />} />
<Route path='/placeholder3' element={<Placeholder3 />} />
<Route path='/servers' element={<ServerSelectView appData={appData} />} />
+106
View File
@@ -0,0 +1,106 @@
/*
Display the most recent Memo posts from psf-memo-db.
*/
// Global npm libraries
import React, { useState, useEffect } from 'react'
import { Container, Row, Col, Spinner, Table } from 'react-bootstrap'
// Local libraries
import MemoDb from '../../../services/memo-db'
import '../../../App.css'
function truncate (str, maxLen = 16) {
if (!str || str.length <= maxLen) return str
const half = Math.floor((maxLen - 3) / 2)
return `${str.slice(0, half)}...${str.slice(-half)}`
}
function formatSeen (seen) {
if (!seen) return ''
const ms = seen > 1e12 ? seen : seen * 1000
return new Date(ms).toLocaleString()
}
function RecentPosts () {
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const [posts, setPosts] = useState([])
const [pagination, setPagination] = useState(null)
useEffect(() => {
const loadPosts = async () => {
try {
const memoDb = new MemoDb()
const data = await memoDb.getRecentPosts({ limit: 100, offset: 0 })
setPosts(data.posts || [])
setPagination(data.pagination || null)
} catch (err) {
setError(err.message || 'Failed to load recent posts')
}
setLoading(false)
}
loadPosts()
}, [])
return (
<Container>
<Row>
<Col>
<h1 className='mt-4'>Recent Posts</h1>
{pagination && (
<p className='text-muted'>
Showing {posts.length} of {pagination.total} posts
</p>
)}
{error && <p className='text-danger'>{error}</p>}
{loading && (
<div className='text-center my-5'>
<Spinner animation='border' role='status' variant='primary'>
<span className='visually-hidden'>Loading...</span>
</Spinner>
</div>
)}
{!loading && !error && (
<Table striped bordered hover responsive className='mt-3'>
<thead>
<tr>
<th>Address</th>
<th>Post</th>
<th>Block</th>
<th>Seen</th>
<th>TxID</th>
</tr>
</thead>
<tbody>
{posts.map((post) => (
<tr key={post.txid}>
<td>
<span style={{ fontFamily: 'monospace' }} title={post.addr}>
{truncate(post.addr, 24)}
</span>
</td>
<td>{post.text}</td>
<td>{post.blockHeight}</td>
<td>{formatSeen(post.seen)}</td>
<td>
<span style={{ fontFamily: 'monospace' }} title={post.txid}>
{truncate(post.txid, 20)}
</span>
</td>
</tr>
))}
</tbody>
</Table>
)}
</Col>
</Row>
</Container>
)
}
export default RecentPosts
+8
View File
@@ -62,6 +62,14 @@ function NavMenu (props) {
Profiles
</NavLink>
<NavLink
className={currentPath === '/posts/recent' ? 'nav-link-active' : 'nav-link-inactive'}
to='/posts/recent'
onClick={handleClickEvent}
>
Posts
</NavLink>
<NavLink
className={currentPath === '/wallet' ? 'nav-link-active' : 'nav-link-inactive'}
to='/wallet'
+13
View File
@@ -22,6 +22,19 @@ class MemoDb {
throw err
}
}
async getRecentPosts ({ limit = 100, offset = 0 } = {}) {
try {
const result = await this.axios.get(`${config.backend}/posts/recent`, {
params: { limit, offset }
})
return result.data
} catch (err) {
console.error('Error in getRecentPosts()')
throw err
}
}
}
export default MemoDb