Add Environment & Archive module: Eco metrics, Digital Archive, Government Portal, NAS settings
New Module: 'Umwelt & Archiv' (Eco & Archive) — 4 tabs: 1. Umwelt (Eco Dashboard): - Paper savings tracker (sheets, grams, CO2, water, trees) - Monthly trend bar chart - Hero card with environmental mission statement - EcoMetric model: daily tracking of paper/CO2/water/trees saved 2. Archiv (Digital Archive): - Full-text searchable document archive (OCR text search) - Document types: Report Card, Certificate, Enrollment, Letter, Contract - Categories: Student, Staff, Finance, Admin, Legal - Confidential documents with lock indicator - Upload dialog with drag-and-drop area - ArchivedDocument model with checksum, retention date, access level 3. Behörden (Government Portal): - Report types: Schulstatistik, Schulbesuch, Förderung, Personal, Bildungsbericht - Status tracking: DRAFT → SUBMITTED → ACKNOWLEDGED/REJECTED - Info box about German government portal integration - GovernmentReport model with submission tracking 4. Speicher (NAS/Storage Settings): - NAS server connection (SMB/NFS/WebDAV/S3) - Host, port, share, credentials configuration - Backup frequency (hourly/daily/weekly) - Optional cloud backup (Nextcloud/ownCloud/S3) - StorageConfig model New Prisma models: ArchivedDocument, GovernmentReport, EcoMetric, StorageConfig New API routes: /api/archived-documents, /api/government-reports, /api/eco-metrics, /api/storage-config New view: EcoArchiveView registered in nav, store, role-access
This commit is contained in:
1 parent
59de7b692b
commit
231d8449e7
12 files changed
+851
-2
No files matched your search
@@ -0,0 +1,28 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { db } from '@/lib/db'
|
||||
import { getSession } from '@/lib/auth'
|
||||
|
||||
export async function GET(request: Request, { params }: { params: Promise<{ id: string }> }) {
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
|
||||
const { id } = await params
|
||||
const doc = await db.archivedDocument.findUnique({ where: { id } })
|
||||
if (!doc) return NextResponse.json({ error: 'Not found' }, { status: 404 })
|
||||
return NextResponse.json(doc)
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ error: e.message }, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(request: Request, { params }: { params: Promise<{ id: string }> }) {
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
|
||||
const { id } = await params
|
||||
await db.archivedDocument.delete({ where: { id } })
|
||||
return NextResponse.json({ success: true })
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ error: e.message }, { status: 500 })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { db } from '@/lib/db'
|
||||
import { getSession } from '@/lib/auth'
|
||||
|
||||
export async function GET(request: Request) {
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
|
||||
|
||||
const { searchParams } = new URL(request.url)
|
||||
const schoolId = searchParams.get('schoolId') || session.user.schoolId
|
||||
if (!schoolId) return NextResponse.json([])
|
||||
|
||||
const category = searchParams.get('category')
|
||||
const documentType = searchParams.get('documentType')
|
||||
const search = searchParams.get('search')
|
||||
|
||||
const where: any = { schoolId }
|
||||
if (category) where.category = category
|
||||
if (documentType) where.documentType = documentType
|
||||
if (search) where.OR = [
|
||||
{ title: { contains: search } },
|
||||
{ ocrText: { contains: search } },
|
||||
{ tags: { contains: search } },
|
||||
]
|
||||
|
||||
const docs = await db.archivedDocument.findMany({
|
||||
where,
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 100,
|
||||
})
|
||||
return NextResponse.json(docs)
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ error: e.message }, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
|
||||
|
||||
const role = session.user.role
|
||||
if (role !== 'SCHOOL_ADMIN' && role !== 'SUPER_ADMIN' && role !== 'TEACHER') {
|
||||
return NextResponse.json({ error: 'Forbidden' }, { status: 403 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const doc = await db.archivedDocument.create({
|
||||
data: { ...body, schoolId: session.user.schoolId, uploadedBy: session.user.id },
|
||||
})
|
||||
return NextResponse.json(doc, { status: 201 })
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ error: e.message }, { status: 500 })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { db } from '@/lib/db'
|
||||
import { getSession } from '@/lib/auth'
|
||||
|
||||
export async function GET(request: Request) {
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
|
||||
const schoolId = session.user.schoolId
|
||||
if (!schoolId) return NextResponse.json([])
|
||||
|
||||
const metrics = await db.ecoMetric.findMany({
|
||||
where: { schoolId },
|
||||
orderBy: { date: 'desc' },
|
||||
take: 365,
|
||||
})
|
||||
|
||||
// Aggregate totals
|
||||
const totals = metrics.reduce((acc, m) => ({
|
||||
paperSavedSheets: acc.paperSavedSheets + m.paperSavedSheets,
|
||||
paperSavedGrams: acc.paperSavedGrams + m.paperSavedGrams,
|
||||
co2SavedKg: acc.co2SavedKg + m.co2SavedKg,
|
||||
waterSavedLiters: acc.waterSavedLiters + m.waterSavedLiters,
|
||||
treesSaved: acc.treesSaved + m.treesSaved,
|
||||
}), { paperSavedSheets: 0, paperSavedGrams: 0, co2SavedKg: 0, waterSavedLiters: 0, treesSaved: 0 })
|
||||
|
||||
return NextResponse.json({ metrics, totals })
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ error: e.message }, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
|
||||
const body = await request.json()
|
||||
const metric = await db.ecoMetric.create({
|
||||
data: { ...body, schoolId: session.user.schoolId! },
|
||||
})
|
||||
return NextResponse.json(metric, { status: 201 })
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ error: e.message }, { status: 500 })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { db } from '@/lib/db'
|
||||
import { getSession } from '@/lib/auth'
|
||||
|
||||
export async function PUT(request: Request, { params }: { params: Promise<{ id: string }> }) {
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
|
||||
const { id } = await params
|
||||
const body = await request.json()
|
||||
const report = await db.governmentReport.update({ where: { id }, data: body })
|
||||
return NextResponse.json(report)
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ error: e.message }, { status: 500 })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { db } from '@/lib/db'
|
||||
import { getSession } from '@/lib/auth'
|
||||
|
||||
export async function GET(request: Request) {
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
|
||||
const schoolId = session.user.schoolId
|
||||
if (!schoolId) return NextResponse.json([])
|
||||
|
||||
const reports = await db.governmentReport.findMany({
|
||||
where: { schoolId },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
})
|
||||
return NextResponse.json(reports)
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ error: e.message }, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
|
||||
const role = session.user.role
|
||||
if (role !== 'SCHOOL_ADMIN' && role !== 'SUPER_ADMIN') {
|
||||
return NextResponse.json({ error: 'Forbidden' }, { status: 403 })
|
||||
}
|
||||
const body = await request.json()
|
||||
const report = await db.governmentReport.create({
|
||||
data: { ...body, schoolId: session.user.schoolId!, createdBy: session.user.id },
|
||||
})
|
||||
return NextResponse.json(report, { status: 201 })
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ error: e.message }, { status: 500 })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { db } from '@/lib/db'
|
||||
import { getSession } from '@/lib/auth'
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
|
||||
const schoolId = session.user.schoolId
|
||||
if (!schoolId) return NextResponse.json(null)
|
||||
|
||||
const config = await db.storageConfig.findUnique({ where: { schoolId } })
|
||||
return NextResponse.json(config)
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ error: e.message }, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
|
||||
const role = session.user.role
|
||||
if (role !== 'SCHOOL_ADMIN' && role !== 'SUPER_ADMIN') {
|
||||
return NextResponse.json({ error: 'Forbidden' }, { status: 403 })
|
||||
}
|
||||
const schoolId = session.user.schoolId!
|
||||
const body = await request.json()
|
||||
|
||||
const config = await db.storageConfig.upsert({
|
||||
where: { schoolId },
|
||||
update: { ...body },
|
||||
create: { ...body, schoolId },
|
||||
})
|
||||
return NextResponse.json(config)
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ error: e.message }, { status: 500 })
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user