Files
speedBB/frontend/src/pages/CategoryView.jsx
2025-12-24 11:52:49 +01:00

122 lines
4.3 KiB
JavaScript

import { useEffect, useState } from 'react'
import { Button, Card, Col, Container, Form, Row } from 'react-bootstrap'
import { Link, useParams } from 'react-router-dom'
import { createThread, getCategory, listThreadsByCategory } from '../api/client'
import { useAuth } from '../context/AuthContext'
export default function CategoryView() {
const { id } = useParams()
const { token } = useAuth()
const [category, setCategory] = useState(null)
const [threads, setThreads] = useState([])
const [error, setError] = useState('')
const [loading, setLoading] = useState(true)
const [title, setTitle] = useState('')
const [body, setBody] = useState('')
const [saving, setSaving] = useState(false)
useEffect(() => {
setLoading(true)
Promise.all([getCategory(id), listThreadsByCategory(id)])
.then(([categoryData, threadData]) => {
setCategory(categoryData)
setThreads(threadData)
})
.catch((err) => setError(err.message))
.finally(() => setLoading(false))
}, [id])
const handleSubmit = async (event) => {
event.preventDefault()
setSaving(true)
setError('')
try {
await createThread({ title, body, categoryId: id })
setTitle('')
setBody('')
const updated = await listThreadsByCategory(id)
setThreads(updated)
} catch (err) {
setError(err.message)
} finally {
setSaving(false)
}
}
return (
<Container className="py-5">
{loading && <p className="bb-muted">Loading category...</p>}
{error && <p className="text-danger">{error}</p>}
{category && (
<>
<div className="bb-hero mb-4">
<p className="bb-chip">Category</p>
<h2 className="mt-3">{category.name}</h2>
<p className="bb-muted mb-0">
{category.description || 'No description added yet.'}
</p>
</div>
<Row className="g-4">
<Col lg={7}>
<h4 className="bb-section-title mb-3">Threads</h4>
{threads.length === 0 && (
<p className="bb-muted">No threads here yet. Start one below.</p>
)}
{threads.map((thread) => (
<Card className="bb-card mb-3" key={thread.id}>
<Card.Body>
<Card.Title>{thread.title}</Card.Title>
<Card.Text className="bb-muted">
{thread.body.length > 160 ? `${thread.body.slice(0, 160)}...` : thread.body}
</Card.Text>
<Link to={`/thread/${thread.id}`} className="stretched-link">
View thread
</Link>
</Card.Body>
</Card>
))}
</Col>
<Col lg={5}>
<h4 className="bb-section-title mb-3">Start a thread</h4>
<div className="bb-form">
{!token && (
<p className="bb-muted mb-3">Log in to create a new thread.</p>
)}
<Form onSubmit={handleSubmit}>
<Form.Group className="mb-3">
<Form.Label>Title</Form.Label>
<Form.Control
type="text"
placeholder="Topic headline"
value={title}
onChange={(event) => setTitle(event.target.value)}
disabled={!token || saving}
required
/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Body</Form.Label>
<Form.Control
as="textarea"
rows={5}
placeholder="Share the context and your question."
value={body}
onChange={(event) => setBody(event.target.value)}
disabled={!token || saving}
required
/>
</Form.Group>
<Button type="submit" variant="dark" disabled={!token || saving}>
{saving ? 'Posting...' : 'Create thread'}
</Button>
</Form>
</div>
</Col>
</Row>
</>
)}
</Container>
)
}