All files / web/src/app/api/admin/constant-images/phi-explore/alignment route.ts

0% Statements 0/97
0% Branches 0/1
0% Functions 0/1
0% Lines 0/97

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98                                                                                                                                                                                                   
import { NextResponse } from 'next/server'
import { readFile, writeFile, mkdir } from 'fs/promises'
import path from 'path'
import { withAuth } from '@/lib/auth/withAuth'

interface AlignmentConfig {
  scale: number
  rotation: number
  offsetX: number
  offsetY: number
}

type AlignmentData = Record<string, Record<string, AlignmentConfig>>

const ALIGNMENT_DIR = path.join(process.cwd(), 'public/images/constants/phi-explore')
const ALIGNMENT_FILE = path.join(ALIGNMENT_DIR, 'alignment.json')

async function readAlignment(): Promise<AlignmentData> {
  try {
    const raw = await readFile(ALIGNMENT_FILE, 'utf-8')
    return JSON.parse(raw)
  } catch {
    return {}
  }
}

/**
 * GET /api/admin/constant-images/phi-explore/alignment
 *
 * Returns the current alignment data for all subjects.
 * Format: { [subjectId]: { [theme]: AlignmentConfig } }
 */
export const GET = withAuth(
  async () => {
    const data = await readAlignment()
    return NextResponse.json(data)
  },
  { role: 'admin' }
)

/**
 * POST /api/admin/constant-images/phi-explore/alignment
 *
 * Body: { subjectId: string, theme: 'light' | 'dark', alignment: AlignmentConfig }
 * Merges the alignment for the given subject+theme and writes back.
 */
export const POST = withAuth(
  async (request) => {
    try {
      const body = await request.json()
      const { subjectId, theme, alignment } = body

      if (typeof subjectId !== 'string' || !subjectId) {
        return NextResponse.json({ error: 'subjectId is required' }, { status: 400 })
      }

      if (theme !== 'light' && theme !== 'dark') {
        return NextResponse.json({ error: 'theme must be "light" or "dark"' }, { status: 400 })
      }

      if (
        !alignment ||
        typeof alignment.scale !== 'number' ||
        typeof alignment.rotation !== 'number' ||
        typeof alignment.offsetX !== 'number' ||
        typeof alignment.offsetY !== 'number'
      ) {
        return NextResponse.json(
          { error: 'alignment must have numeric scale, rotation, offsetX, offsetY' },
          { status: 400 }
        )
      }

      const data = await readAlignment()
      if (!data[subjectId]) {
        data[subjectId] = {}
      }
      data[subjectId][theme] = {
        scale: alignment.scale,
        rotation: alignment.rotation,
        offsetX: alignment.offsetX,
        offsetY: alignment.offsetY,
      }

      await mkdir(ALIGNMENT_DIR, { recursive: true })
      await writeFile(ALIGNMENT_FILE, JSON.stringify(data, null, 2) + '\n', 'utf-8')

      return NextResponse.json(data)
    } catch (err) {
      return NextResponse.json(
        { error: err instanceof Error ? err.message : 'Unknown error' },
        { status: 500 }
      )
    }
  },
  { role: 'admin' }
)