add Ko-fi bean
This commit is contained in:
101
frontend/src/pages/JournalEntryPage.tsx
Normal file
101
frontend/src/pages/JournalEntryPage.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import { useState } from 'react'
|
||||
import { useParams, useNavigate } from 'react-router-dom'
|
||||
import { useRun } from '../hooks/useRuns'
|
||||
import { useBossResults, useGameBosses } from '../hooks/useBosses'
|
||||
import {
|
||||
useJournalEntry,
|
||||
useUpdateJournalEntry,
|
||||
useDeleteJournalEntry,
|
||||
} from '../hooks/useJournal'
|
||||
import { JournalEntryView } from '../components/journal/JournalEntryView'
|
||||
import { JournalEditor } from '../components/journal/JournalEditor'
|
||||
|
||||
export function JournalEntryPage() {
|
||||
const { runId, entryId } = useParams<{ runId: string; entryId: string }>()
|
||||
const navigate = useNavigate()
|
||||
const runIdNum = Number(runId)
|
||||
const [isEditing, setIsEditing] = useState(false)
|
||||
|
||||
const { data: run, isLoading: runLoading } = useRun(runIdNum)
|
||||
const { data: entry, isLoading: entryLoading, error } = useJournalEntry(runIdNum, entryId ?? null)
|
||||
const { data: bossResults } = useBossResults(runIdNum)
|
||||
const { data: bosses } = useGameBosses(run?.gameId ?? null)
|
||||
const updateEntry = useUpdateJournalEntry(runIdNum, entryId ?? '')
|
||||
const deleteEntry = useDeleteJournalEntry(runIdNum)
|
||||
|
||||
const isLoading = runLoading || entryLoading
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="max-w-3xl mx-auto p-8 flex justify-center">
|
||||
<div className="w-8 h-8 border-4 border-blue-600 border-t-transparent rounded-full animate-spin" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (error || !entry || !run) {
|
||||
return (
|
||||
<div className="max-w-3xl mx-auto p-8">
|
||||
<div className="rounded-lg bg-status-failed-bg p-4 text-status-failed">
|
||||
Failed to load journal entry.
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => navigate(`/runs/${runId}`)}
|
||||
className="inline-block mt-4 text-blue-600 hover:underline"
|
||||
>
|
||||
Back to run
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const linkedBossResult = entry.bossResultId
|
||||
? bossResults?.find((br) => br.id === entry.bossResultId)
|
||||
: null
|
||||
const linkedBoss = linkedBossResult
|
||||
? bosses?.find((b) => b.id === linkedBossResult.bossBattleId)
|
||||
: null
|
||||
|
||||
const handleSave = (data: { title: string; body: string; bossResultId: number | null }) => {
|
||||
updateEntry.mutate(data, {
|
||||
onSuccess: () => setIsEditing(false),
|
||||
})
|
||||
}
|
||||
|
||||
const handleDelete = () => {
|
||||
deleteEntry.mutate(entry.id, {
|
||||
onSuccess: () => navigate(`/runs/${runId}?tab=journal`),
|
||||
})
|
||||
}
|
||||
|
||||
if (isEditing) {
|
||||
return (
|
||||
<div className="max-w-3xl mx-auto p-8">
|
||||
<h1 className="text-2xl font-bold text-text-primary mb-6">Edit Journal Entry</h1>
|
||||
<JournalEditor
|
||||
entry={entry}
|
||||
bossResults={bossResults}
|
||||
bosses={bosses}
|
||||
onSave={handleSave}
|
||||
onDelete={handleDelete}
|
||||
onCancel={() => setIsEditing(false)}
|
||||
isSaving={updateEntry.isPending}
|
||||
isDeleting={deleteEntry.isPending}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="max-w-3xl mx-auto p-8">
|
||||
<JournalEntryView
|
||||
entry={entry}
|
||||
bossResult={linkedBossResult}
|
||||
boss={linkedBoss}
|
||||
onEdit={() => setIsEditing(true)}
|
||||
onBack={() => navigate(`/runs/${runId}?tab=journal`)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user