feat: add auth system, boss pokemon details, moves/abilities API, and run ownership
Add user authentication with login/signup/protected routes, boss pokemon detail fields and result team tracking, moves and abilities selector components and API, run ownership and visibility controls, and various UI improvements across encounters, run list, and journal pages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,18 @@
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useParams, Link } from 'react-router-dom'
|
||||
import { useAuth } from '../contexts/AuthContext'
|
||||
import { useRun, useUpdateRun, useNamingCategories } from '../hooks/useRuns'
|
||||
import { useGameRoutes } from '../hooks/useGames'
|
||||
import { useCreateEncounter, useUpdateEncounter } from '../hooks/useEncounters'
|
||||
import { CustomRulesDisplay, StatCard, PokemonCard, RuleBadges, StatusChangeModal, EndRunModal } from '../components'
|
||||
import type { RunStatus, EncounterDetail } from '../types'
|
||||
import {
|
||||
CustomRulesDisplay,
|
||||
StatCard,
|
||||
PokemonCard,
|
||||
RuleBadges,
|
||||
StatusChangeModal,
|
||||
EndRunModal,
|
||||
} from '../components'
|
||||
import type { RunStatus, EncounterDetail, RunVisibility } from '../types'
|
||||
|
||||
type TeamSortKey = 'route' | 'level' | 'species' | 'dex'
|
||||
|
||||
@@ -49,6 +57,7 @@ export function RunDashboard() {
|
||||
const runIdNum = Number(runId)
|
||||
const { data: run, isLoading, error } = useRun(runIdNum)
|
||||
const { data: routes } = useGameRoutes(run?.gameId ?? null)
|
||||
const { user } = useAuth()
|
||||
const createEncounter = useCreateEncounter(runIdNum)
|
||||
const updateEncounter = useUpdateEncounter(runIdNum)
|
||||
const updateRun = useUpdateRun(runIdNum)
|
||||
@@ -57,6 +66,9 @@ export function RunDashboard() {
|
||||
const [showEndRun, setShowEndRun] = useState(false)
|
||||
const [teamSort, setTeamSort] = useState<TeamSortKey>('route')
|
||||
|
||||
const isOwner = user && run?.owner?.id === user.id
|
||||
const canEdit = isOwner || !run?.owner
|
||||
|
||||
const encounters = run?.encounters ?? []
|
||||
const alive = useMemo(
|
||||
() =>
|
||||
@@ -190,11 +202,31 @@ export function RunDashboard() {
|
||||
<CustomRulesDisplay customRules={run.rules?.customRules ?? ''} />
|
||||
</div>
|
||||
|
||||
{/* Visibility */}
|
||||
{canEdit && (
|
||||
<div className="mb-6">
|
||||
<h2 className="text-sm font-medium text-text-tertiary mb-2">Visibility</h2>
|
||||
<select
|
||||
value={run.visibility}
|
||||
onChange={(e) => updateRun.mutate({ visibility: e.target.value as RunVisibility })}
|
||||
className="text-sm border border-border-default rounded-lg px-3 py-1.5 bg-surface-1 text-text-primary"
|
||||
>
|
||||
<option value="public">Public</option>
|
||||
<option value="private">Private</option>
|
||||
</select>
|
||||
<p className="mt-1 text-xs text-text-tertiary">
|
||||
{run.visibility === 'private'
|
||||
? 'Only you can see this run'
|
||||
: 'Anyone can view this run'}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Naming Scheme */}
|
||||
{namingCategories && namingCategories.length > 0 && (
|
||||
<div className="mb-6">
|
||||
<h2 className="text-sm font-medium text-text-tertiary mb-2">Naming Scheme</h2>
|
||||
{isActive ? (
|
||||
{isActive && canEdit ? (
|
||||
<select
|
||||
value={run.namingScheme ?? ''}
|
||||
onChange={(e) => updateRun.mutate({ namingScheme: e.target.value || null })}
|
||||
@@ -246,7 +278,7 @@ export function RunDashboard() {
|
||||
<PokemonCard
|
||||
key={enc.id}
|
||||
encounter={enc}
|
||||
onClick={isActive ? () => setSelectedEncounter(enc) : undefined}
|
||||
onClick={isActive && canEdit ? () => setSelectedEncounter(enc) : undefined}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -263,7 +295,7 @@ export function RunDashboard() {
|
||||
key={enc.id}
|
||||
encounter={enc}
|
||||
showFaintLevel
|
||||
onClick={isActive ? () => setSelectedEncounter(enc) : undefined}
|
||||
onClick={isActive && canEdit ? () => setSelectedEncounter(enc) : undefined}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -272,7 +304,7 @@ export function RunDashboard() {
|
||||
|
||||
{/* Quick Actions */}
|
||||
<div className="mt-8 flex gap-3">
|
||||
{isActive && (
|
||||
{isActive && canEdit && (
|
||||
<>
|
||||
<Link
|
||||
to={`/runs/${runId}/encounters`}
|
||||
|
||||
Reference in New Issue
Block a user