write/server/routes/characters.js
2026-06-26 18:13:18 -04:00

92 lines
3.9 KiB
JavaScript

import { Router } from 'express'
import db from '../db.js'
import { auth } from '../middleware/auth.js'
const router = Router({ mergeParams: true })
router.use(auth)
function getStory(storyId, userId) {
return db.prepare('SELECT id FROM stories WHERE id = ? AND user_id = ?').get(storyId, userId)
}
// GET /api/stories/:storyId/characters
router.get('/', (req, res) => {
if (!getStory(req.params.storyId, req.user.id)) return res.status(404).json({ error: 'Not found' })
const rows = db.prepare(
'SELECT * FROM characters WHERE story_id = ? AND user_id = ? ORDER BY name ASC'
).all(req.params.storyId, req.user.id)
res.json(rows)
})
// POST /api/stories/:storyId/characters
router.post('/', (req, res) => {
if (!getStory(req.params.storyId, req.user.id)) return res.status(404).json({ error: 'Not found' })
const { name = 'New Character', role = 'supporting', age = '', description = '', notes = '', photo = null } = req.body || {}
const { lastInsertRowid } = db.prepare(
'INSERT INTO characters (story_id, user_id, name, role, age, description, notes, photo) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
).run(req.params.storyId, req.user.id, name, role, age, description, notes, photo)
res.json(db.prepare('SELECT * FROM characters WHERE id = ?').get(lastInsertRowid))
})
// POST /api/stories/:storyId/characters/import-from
router.post('/import-from', (req, res) => {
if (!getStory(req.params.storyId, req.user.id)) return res.status(404).json({ error: 'Not found' })
const { from_story_id, character_ids } = req.body || {}
if (!from_story_id || !Array.isArray(character_ids) || character_ids.length === 0)
return res.status(400).json({ error: 'Missing from_story_id or character_ids' })
if (!getStory(from_story_id, req.user.id)) return res.status(404).json({ error: 'Source story not found' })
const placeholders = character_ids.map(() => '?').join(',')
const sourceChars = db.prepare(
`SELECT * FROM characters WHERE id IN (${placeholders}) AND story_id = ? AND user_id = ?`
).all(...character_ids, from_story_id, req.user.id)
const insert = db.prepare(
'INSERT INTO characters (story_id, user_id, name, role, age, description, notes, photo) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
)
const inserted = db.transaction(() =>
sourceChars.map(c => {
const { lastInsertRowid } = insert.run(
req.params.storyId, req.user.id, c.name, c.role, c.age, c.description, c.notes, c.photo ?? null
)
return db.prepare('SELECT * FROM characters WHERE id = ?').get(lastInsertRowid)
})
)()
res.json(inserted)
})
// PUT /api/stories/:storyId/characters/:charId
router.put('/:charId', (req, res) => {
const char = db.prepare(
'SELECT * FROM characters WHERE id = ? AND story_id = ? AND user_id = ?'
).get(req.params.charId, req.params.storyId, req.user.id)
if (!char) return res.status(404).json({ error: 'Not found' })
const { name, role, age, description, notes, photo } = req.body || {}
db.prepare(
'UPDATE characters SET name = ?, role = ?, age = ?, description = ?, notes = ?, photo = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?'
).run(
name !== undefined ? name : char.name,
role !== undefined ? role : char.role,
age !== undefined ? age : char.age,
description !== undefined ? description : char.description,
notes !== undefined ? notes : char.notes,
photo !== undefined ? photo : char.photo,
char.id
)
res.json(db.prepare('SELECT * FROM characters WHERE id = ?').get(char.id))
})
// DELETE /api/stories/:storyId/characters/:charId
router.delete('/:charId', (req, res) => {
const char = db.prepare(
'SELECT * FROM characters WHERE id = ? AND story_id = ? AND user_id = ?'
).get(req.params.charId, req.params.storyId, req.user.id)
if (!char) return res.status(404).json({ error: 'Not found' })
db.prepare('DELETE FROM characters WHERE id = ?').run(char.id)
res.json({ ok: true })
})
export default router