Podcast workflow: per-lane season number set on the page, only that season shown; v2.16.1

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-12 08:28:04 -04:00
1 parent 900a3efee3
commit 3a69e03e60
4 files changed
+71 -19

No files matched your search

+38 -9
View File
@@ -1825,7 +1825,8 @@ interface PodcastWorkflowItem {
state: PodcastWorkflowState
}
function PodcastWorkflowAdmin({ laneA, laneB }: { laneA: { title: string; season?: number }; laneB: { title: string; season?: number } }) {
function PodcastWorkflowAdmin({ laneA, laneB }: { laneA: { title: string }; laneB: { title: string } }) {
const [laneSeasons, setLaneSeasons] = useState<{ A: string; B: string }>({ A: '', B: '' })
const [items, setItems] = useState<PodcastWorkflowItem[]>([])
const [feedOk, setFeedOk] = useState(true)
const [loading, setLoading] = useState(true)
@@ -1839,13 +1840,25 @@ function PodcastWorkflowAdmin({ laneA, laneB }: { laneA: { title: string; season
const reload = () =>
fetch('/api/admin/podcast-workflow')
.then(r => r.json())
.then(d => { setItems(d.items ?? []); setFeedOk(d.feedOk !== false) })
.then(d => { setItems(d.items ?? []); setFeedOk(d.feedOk !== false); setLaneSeasons(d.laneSeasons ?? { A: '', B: '' }) })
.catch(() => setError('Could not load episodes.'))
.finally(() => setLoading(false))
useEffect(() => { reload() }, [])
const laneSeason = lane === 'A' ? laneA.season : lane === 'B' ? laneB.season : undefined
const laneSeason = lane === 'A' || lane === 'B' ? laneSeasons[lane] : ''
const saveLaneSeason = async (value: string) => {
if (lane === 'other') return
setError('')
const r = await fetch('/api/admin/podcast-workflow-lane-seasons', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ [lane]: value }),
})
if (!r.ok) { const d = await r.json(); setError(d.message ?? 'Could not save season.'); return }
setSelectedKey('')
reload()
}
const hasOther = items.some(i => i.lane === 'other')
const inLane = items.filter(i => i.lane === lane)
const upcoming = inLane.filter(i => !i.released)
@@ -1875,7 +1888,7 @@ function PodcastWorkflowAdmin({ laneA, laneB }: { laneA: { title: string; season
const r = await fetch('/api/admin/podcast-workflow/planned', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ season: laneSeason ? String(laneSeason) : '', episodeNumber: newNumber, title: newTitle, lane }),
body: JSON.stringify({ season: laneSeason, episodeNumber: newNumber, title: newTitle, lane }),
})
const d = await r.json()
if (!r.ok) { setError(d.message ?? 'Could not add episode.'); return }
@@ -1899,7 +1912,7 @@ function PodcastWorkflowAdmin({ laneA, laneB }: { laneA: { title: string; season
reload()
}
const label = (i: PodcastWorkflowItem) => `${i.episodeNumber ? `Ep ${i.episodeNumber}` : 'Ep'}${i.title ? ` — ${i.title}` : ''}`
const label = (i: PodcastWorkflowItem) => `${i.season ? `S${i.season} ` : ''}${i.episodeNumber ? `Ep ${i.episodeNumber}` : 'Ep'}${i.title ? ` — ${i.title}` : ''}`
const doneCount = (i: PodcastWorkflowItem) => (i.released ? PODCAST_STEP_DEFS.length : PODCAST_STEP_DEFS.filter(s => i.state.steps[s.key]).length)
const row = (i: PodcastWorkflowItem) => (
@@ -1937,12 +1950,28 @@ function PodcastWorkflowAdmin({ laneA, laneB }: { laneA: { title: string; season
))}
{hasOther && (
<button type="button" className={lane === 'other' ? 'btn-admin-save' : 'btn-admin-ghost'} onClick={() => { setLane('other'); setSelectedKey('') }}>
Other ({items.filter(i => i.lane === 'other' && !i.released).length} in progress)
Other seasons ({items.filter(i => i.lane === 'other' && !i.released).length} in progress)
</button>
)}
</div>
{lane !== 'other' && !laneSeason && (
<p className="admin-stats-note">Set this lane’s Podcast Season Number in Current Series to match episodes automatically, or assign episodes to this lane by hand.</p>
{lane !== 'other' ? (
<div style={{ display: 'flex', gap: 8, alignItems: 'center', margin: '0 0 12px', flexWrap: 'wrap' }}>
<label htmlFor="pw-season">Season number for Lane {lane}</label>
<input
key={`${lane}-${laneSeason}`}
id="pw-season"
type="number"
min={1}
defaultValue={laneSeason}
style={{ width: 80 }}
onBlur={e => { if (e.target.value !== laneSeason) saveLaneSeason(e.target.value) }}
/>
<span className="admin-stats-note">
{laneSeason ? `Only season ${laneSeason} episodes are shown here.` : 'Set a season number so this lane picks up its episodes, or assign episodes by hand.'}
</span>
</div>
) : (
<p className="admin-stats-note">Episodes from other seasons (finished or not assigned to a lane).</p>
)}
{loading ? <p className="admin-stats-note">Loading…</p> : (
@@ -6230,7 +6259,7 @@ const [dashboardNow, setDashboardNow] = useState(() => new Date())
)}
{/* EPISODE SCRIPTS */}
{adminView === 'podcast:workflow' && <PodcastWorkflowAdmin laneA={{ title: form.seriesTitle, season: form.seriesSeason }} laneB={{ title: form.secondSeries?.title ?? '', season: form.secondSeries?.season }} />}
{adminView === 'podcast:workflow' && <PodcastWorkflowAdmin laneA={{ title: form.seriesTitle }} laneB={{ title: form.secondSeries?.title ?? '' }} />}
{adminView === 'podcast:scripts' && (
<section className="admin-panel-section">
<div className="admin-panel-head">