Initial scaffold: React/Vite/TS PWA + Express/Prisma/Postgres backend
Materialschein & Kabelrechner für BergVOLT Elektrotechnik, portiert von der vorherigen Single-File-HTML-Version. Microsoft-Entra-ID-Login (MSAL), Projekt- Dashboard statt einer Datei pro Kunde, Retour-Buchen-Zusammenführung, 111 Kabeltypen aus den offiziellen Meinhart-Datenblättern. gitops/ nach PROX/deploy-standard: git-backed Portainer-Stack, versionierte Docker-Images, CI-Commit-back auf gitops/stack.yml. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import { Router } from 'express';
|
||||
import { prisma } from '../prisma.js';
|
||||
import type { AuthedRequest } from '../auth.js';
|
||||
|
||||
export const materialRouter = Router();
|
||||
|
||||
// GET /api/material?projektId=xxx
|
||||
materialRouter.get('/', async (req, res) => {
|
||||
const projektId = String(req.query.projektId ?? '');
|
||||
if (!projektId) { res.status(400).json({ error: 'projektId erforderlich.' }); return; }
|
||||
const items = await prisma.material.findMany({
|
||||
where: { projektId },
|
||||
orderBy: { createdAt: 'asc' }
|
||||
});
|
||||
res.json(items);
|
||||
});
|
||||
|
||||
materialRouter.post('/', async (req: AuthedRequest, res) => {
|
||||
const { projektId, bezeichnung, artNr, menge, einheit, notiz } = req.body ?? {};
|
||||
if (!projektId || !bezeichnung || menge === undefined || !einheit) {
|
||||
res.status(400).json({ error: 'projektId, bezeichnung, menge und einheit sind erforderlich.' });
|
||||
return;
|
||||
}
|
||||
const item = await prisma.material.create({
|
||||
data: {
|
||||
projektId,
|
||||
bezeichnung,
|
||||
artNr: artNr || null,
|
||||
menge,
|
||||
einheit,
|
||||
notiz: notiz || null,
|
||||
erstelltVon: req.user?.email ?? null
|
||||
}
|
||||
});
|
||||
res.status(201).json(item);
|
||||
});
|
||||
|
||||
materialRouter.patch('/:id', async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const { menge, notiz } = req.body ?? {};
|
||||
const data: Record<string, unknown> = {};
|
||||
if (menge !== undefined) data.menge = menge;
|
||||
if (notiz !== undefined) data.notiz = notiz || null;
|
||||
try {
|
||||
const item = await prisma.material.update({ where: { id }, data });
|
||||
res.json(item);
|
||||
} catch {
|
||||
res.status(404).json({ error: 'Position nicht gefunden.' });
|
||||
}
|
||||
});
|
||||
|
||||
materialRouter.delete('/:id', async (req, res) => {
|
||||
const { id } = req.params;
|
||||
try {
|
||||
await prisma.material.delete({ where: { id } });
|
||||
res.status(204).end();
|
||||
} catch {
|
||||
res.status(404).json({ error: 'Position nicht gefunden.' });
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
import { Router } from 'express';
|
||||
import { prisma } from '../prisma.js';
|
||||
import type { AuthedRequest } from '../auth.js';
|
||||
|
||||
export const projekteRouter = Router();
|
||||
|
||||
projekteRouter.get('/', async (_req, res) => {
|
||||
const projekte = await prisma.projekt.findMany({ orderBy: { createdAt: 'desc' } });
|
||||
res.json(projekte);
|
||||
});
|
||||
|
||||
projekteRouter.post('/', async (req: AuthedRequest, res) => {
|
||||
const { titel, auftraggeber, datum, monteur, notiz } = req.body ?? {};
|
||||
if (!titel || typeof titel !== 'string' || !titel.trim()) {
|
||||
res.status(400).json({ error: 'Titel (Projekt/Baustelle) ist erforderlich.' });
|
||||
return;
|
||||
}
|
||||
const projekt = await prisma.projekt.create({
|
||||
data: {
|
||||
titel: titel.trim(),
|
||||
auftraggeber: auftraggeber || null,
|
||||
datum: datum ? new Date(datum) : null,
|
||||
monteur: monteur || null,
|
||||
notiz: notiz || null
|
||||
}
|
||||
});
|
||||
res.status(201).json(projekt);
|
||||
});
|
||||
|
||||
projekteRouter.patch('/:id', async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const { titel, auftraggeber, datum, monteur, notiz, status } = req.body ?? {};
|
||||
const data: Record<string, unknown> = {};
|
||||
if (titel !== undefined) data.titel = titel;
|
||||
if (auftraggeber !== undefined) data.auftraggeber = auftraggeber || null;
|
||||
if (datum !== undefined) data.datum = datum ? new Date(datum) : null;
|
||||
if (monteur !== undefined) data.monteur = monteur || null;
|
||||
if (notiz !== undefined) data.notiz = notiz || null;
|
||||
if (status !== undefined) data.status = status;
|
||||
try {
|
||||
const projekt = await prisma.projekt.update({ where: { id }, data });
|
||||
res.json(projekt);
|
||||
} catch {
|
||||
res.status(404).json({ error: 'Projekt nicht gefunden.' });
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user