fix: weitere fehlende Umlaute (Hinzufuegen, Eintraege, Passwoerter, erhaelt, enthaelt etc)
This commit is contained in:
@@ -2,7 +2,7 @@ import jwt from 'jsonwebtoken';
|
||||
import pool from '../config/database.js';
|
||||
|
||||
// Verifiziert JWT und stellt req.user bereit
|
||||
// req.user enthaelt: { id, email, name, rolle, tenant_id }
|
||||
// req.user enthält: { id, email, name, rolle, tenant_id }
|
||||
// tenant_id ist NULL für SuperAdmins.
|
||||
export const authenticateToken = (req, res, next) => {
|
||||
const authHeader = req.headers['authorization'];
|
||||
|
||||
@@ -15,7 +15,7 @@ router.post('/:kunde_id', upload.single('foto'), async (req, res) => {
|
||||
const [[k]] = await pool.query('SELECT id FROM kunden WHERE id=? AND tenant_id=?',
|
||||
[req.params.kunde_id, req.user.tenant_id]);
|
||||
if (!k) {
|
||||
// Datei aufraeumen
|
||||
// Datei aufräumen
|
||||
try { fs.unlinkSync(req.file.path); } catch {}
|
||||
return res.status(404).json({ error: 'Kunde nicht gefunden' });
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ router.post('/', upload.single('foto'), [
|
||||
if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() });
|
||||
const foto_url = req.file ? `/uploads/${req.file.filename}` : null;
|
||||
try {
|
||||
// Sicherstellen: kunde_id + artikel_id gehoeren dem Tenant
|
||||
// Sicherstellen: kunde_id + artikel_id gehören dem Tenant
|
||||
const [[k]] = await pool.query('SELECT id FROM kunden WHERE id=? AND tenant_id=?',
|
||||
[req.body.kunde_id, req.user.tenant_id]);
|
||||
const [[a]] = await pool.query('SELECT id FROM artikel WHERE id=? AND tenant_id=?',
|
||||
|
||||
@@ -90,7 +90,7 @@ router.put('/:id', [
|
||||
});
|
||||
|
||||
router.delete('/:id', requireRole(['admin']), async (req, res) => {
|
||||
if (req.params.id === req.user.id) return res.status(400).json({ error: 'Sie koennen sich nicht selbst löschen' });
|
||||
if (req.params.id === req.user.id) return res.status(400).json({ error: 'Sie können sich nicht selbst löschen' });
|
||||
try {
|
||||
const [r] = await pool.query('DELETE FROM mitarbeiter WHERE id=? AND tenant_id=?',
|
||||
[req.params.id, req.user.tenant_id]);
|
||||
|
||||
@@ -57,7 +57,7 @@ bootstrapSuperAdmin()
|
||||
.catch(err => console.error('Bootstrap-Fehler:', err))
|
||||
.finally(() => {
|
||||
app.listen(PORT, '0.0.0.0', () => {
|
||||
console.log(`Backend laeuft auf Port ${PORT}`);
|
||||
console.log(`Backend läuft auf Port ${PORT}`);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ export default function PasswordChange() {
|
||||
const submit = async (e) => {
|
||||
e.preventDefault();
|
||||
if (form.newPassword.length < 6) return setErr('Neues Passwort min. 6 Zeichen');
|
||||
if (form.newPassword !== form.confirm) return setErr('Passwoerter stimmen nicht überein');
|
||||
if (form.newPassword !== form.confirm) return setErr('Passwörter stimmen nicht überein');
|
||||
setBusy(true);
|
||||
try {
|
||||
await api.changePassword(form.currentPassword, form.newPassword);
|
||||
|
||||
@@ -96,7 +96,7 @@ export default function AdminDashboard() {
|
||||
</div>
|
||||
|
||||
{selectedKunde ? (
|
||||
rows.length === 0 ? <div className="card text-center text-slate-500">Keine Eintraege im Zeitraum.</div> : (
|
||||
rows.length === 0 ? <div className="card text-center text-slate-500">Keine Einträge im Zeitraum.</div> : (
|
||||
<div className="card overflow-x-auto p-0">
|
||||
<table className="min-w-full text-sm">
|
||||
<thead className="bg-slate-50 text-xs uppercase text-slate-600">
|
||||
|
||||
@@ -61,7 +61,7 @@ export default function VorgangsListe({ refreshFlag, mode }) {
|
||||
{loading ? (
|
||||
<div className="text-center text-slate-500 py-12">Lade…</div>
|
||||
) : view.length === 0 ? (
|
||||
<div className="card text-center text-slate-500">Keine Eintraege.</div>
|
||||
<div className="card text-center text-slate-500">Keine Einträge.</div>
|
||||
) : (
|
||||
<ul className="space-y-2">
|
||||
{view.map(item => (
|
||||
|
||||
@@ -47,7 +47,7 @@ export default function MitarbeiterVerwaltung({ user }) {
|
||||
<option value="admin">Admin</option>
|
||||
</select>
|
||||
</div>
|
||||
<button onClick={add} className="btn-primary mt-3"><FaPlus /> Hinzufuegen</button>
|
||||
<button onClick={add} className="btn-primary mt-3"><FaPlus /> Hinzufügen</button>
|
||||
</div>
|
||||
|
||||
<div className="card overflow-x-auto p-0">
|
||||
|
||||
@@ -171,7 +171,7 @@ function CreatedInfoModal({ info, onClose }) {
|
||||
<div onClick={onClose} className="fixed inset-0 z-50 bg-slate-900/60 flex items-center justify-center p-4">
|
||||
<div onClick={e => e.stopPropagation()} className="bg-white rounded-xl max-w-md w-full p-6 shadow-soft space-y-3">
|
||||
<h3 className="text-lg font-semibold text-emerald-700">Demo-Account angelegt</h3>
|
||||
<p className="text-sm text-slate-600">Der Interessent erhaelt eine Einladungs-Mail. Hier zur Sicherheit die Daten:</p>
|
||||
<p className="text-sm text-slate-600">Der Interessent erhält eine Einladungs-Mail. Hier zur Sicherheit die Daten:</p>
|
||||
<dl className="bg-slate-50 rounded-lg p-3 text-sm space-y-1.5">
|
||||
<div><dt className="inline text-slate-500">Slug: </dt><dd className="inline font-mono">{info.slug}</dd></div>
|
||||
<div><dt className="inline text-slate-500">E-Mail: </dt><dd className="inline">{info.admin_email}</dd></div>
|
||||
|
||||
Reference in New Issue
Block a user