Weitere übersetzungen

This commit is contained in:
Cay 2026-02-02 12:20:51 -01:00
parent 3f70e1f7f9
commit 65bb75d437
10 changed files with 255 additions and 154 deletions

View File

@ -13,14 +13,27 @@ const safe = (v) => {
* GET: Firmendaten anzeigen
*/
async function getCompanySettings(req, res) {
const [[company]] = await db.promise().query(
"SELECT * FROM company_settings LIMIT 1"
);
try {
const [[company]] = await db
.promise()
.query("SELECT * FROM company_settings LIMIT 1");
res.render("admin/company-settings", {
user: req.user,
company: company || {}
});
res.render("admin/company-settings", {
layout: "layout", // 🔥 wichtig
title: "Firmendaten", // 🔥 DAS FEHLTE
active: "companySettings", // 🔥 Sidebar aktiv
sidebarPartial: "partials/admin-sidebar",
company: company || {},
user: req.session.user, // 🔥 konsistent
lang: req.session.lang || "de"
// t kommt aus res.locals
});
} catch (err) {
console.error(err);
res.status(500).send("Datenbankfehler");
}
}
/**

View File

@ -8,9 +8,15 @@ async function showDashboard(req, res) {
const waitingPatients = await getWaitingPatients(db);
res.render("dashboard", {
layout: "layout", // 🔥 DAS FEHLTE
title: "Dashboard",
active: "dashboard",
sidebarPartial: "partials/sidebar",
waitingPatients,
user: req.session.user,
waitingPatients
lang: req.session.lang || "de"
});
} catch (err) {
console.error(err);

View File

@ -66,7 +66,8 @@
"dashboard": {
"welcome": "Willkommen",
"waitingRoom": "Wartezimmer-Monitor",
"noWaitingPatients": "Keine Patienten im Wartezimmer."
"noWaitingPatients": "Keine Patienten im Wartezimmer.",
"title":"Dashboard"
},
"adminSidebar": {
@ -75,7 +76,8 @@
"user":"Benutzer",
"invocieoverview":"Rechnungsübersicht",
"seriennumber":"Seriennummer",
"databasetable":"Datenbank"
"databasetable":"Datenbank",
"companysettings":"Firmendaten"
},
"adminuseroverview": {

View File

@ -39,7 +39,7 @@
"birthday":"Fecha de nacimiento",
"email":"Correo electrónico",
"phone":"Teléfono",
"address":"AdreDirecciónsse",
"address":"Dirección",
"country":"País",
"notice":"Notas",
"create":"Creado",
@ -67,7 +67,8 @@
"dashboard": {
"welcome": "Bienvenido",
"waitingRoom": "Monitor sala de espera",
"noWaitingPatients": "No hay pacientes en la sala de espera."
"noWaitingPatients": "No hay pacientes en la sala de espera.",
"title":"Dashboard"
},
"adminSidebar": {
@ -76,7 +77,8 @@
"user":"usuario",
"invocieoverview":"Resumen de facturas",
"seriennumber":"número de serie",
"databasetable":"base de datos"
"databasetable":"base de datos",
"companysettings":"Datos de la empresa"
},
"adminuseroverview": {

View File

@ -6,6 +6,7 @@ const path = require("path");
const { exec } = require("child_process");
const multer = require("multer");
const { NodeSSH } = require("node-ssh");
const uploadLogo = require("../middleware/uploadLogo");
// ✅ Upload Ordner für Restore Dumps
@ -31,6 +32,13 @@ const { loadConfig, saveConfig } = require("../config-manager");
// ✅ DB (für resetPool)
const db = require("../db");
// ✅ Firmendaten
const {
getCompanySettings,
saveCompanySettings
} = require("../controllers/companySettings.controller");
/* ==========================
VERWALTUNG (NUR ADMIN)
========================== */
@ -485,4 +493,20 @@ router.post("/database/restore", requireAdmin, async (req, res) => {
========================== */
router.get("/invoices", requireAdmin, showInvoiceOverview);
/* ==========================
Firmendaten
========================== */
router.get(
"/company-settings",
requireAdmin,
getCompanySettings
);
router.post(
"/company-settings",
requireAdmin,
uploadLogo.single("logo"),
saveCompanySettings
);
module.exports = router;

View File

@ -1,19 +1,21 @@
const express = require("express");
const router = express.Router();
const { requireArzt } = require("../middleware/auth.middleware");
const { requireAdmin } = require("../middleware/auth.middleware");
const uploadLogo = require("../middleware/uploadLogo");
const {
getCompanySettings,
saveCompanySettings,
} = require("../controllers/companySettings.controller");
router.get("/admin/company-settings", requireArzt, getCompanySettings);
// ✅ NUR der relative Pfad
router.get("/company-settings", requireAdmin, getCompanySettings);
router.post(
"/admin/company-settings",
requireArzt,
uploadLogo.single("logo"), // 🔑 MUSS VOR DEM CONTROLLER KOMMEN
saveCompanySettings,
"/company-settings",
requireAdmin,
uploadLogo.single("logo"),
saveCompanySettings
);
module.exports = router;

View File

@ -1,132 +1,196 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Firmendaten</title>
<link rel="stylesheet" href="/css/bootstrap.min.css">
</head>
<body class="bg-light">
<%- include("../partials/page-header", {
user,
title,
subtitle: "",
showUserName: true
}) %>
<div class="container mt-4">
<h3 class="mb-4">🏢 Firmendaten</h3>
<div class="content p-4">
<form method="POST" action="/admin/company-settings" enctype="multipart/form-data">
<%- include("../partials/flash") %>
<div class="row g-3">
<div class="container-fluid">
<div class="card shadow-sm">
<div class="card-body">
<h5 class="mb-4">
<i class="bi bi-building"></i>
<%= title %>
</h5>
<form
method="POST"
action="/admin/company-settings"
enctype="multipart/form-data"
>
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">Firmenname</label>
<input class="form-control" name="company_name"
value="<%= company.company_name || '' %>" required>
<label class="form-label">Firmenname</label>
<input
class="form-control"
name="company_name"
value="<%= settings.company_name || '' %>"
required
>
</div>
<div class="col-md-6">
<label class="form-label">Rechtsform</label>
<input class="form-control" name="company_legal_form"
value="<%= company.company_legal_form || '' %>">
<label class="form-label">Rechtsform</label>
<input
class="form-control"
name="company_legal_form"
value="<%= settings.company_legal_form || '' %>"
>
</div>
<div class="col-md-6">
<label class="form-label">Inhaber / Geschäftsführer</label>
<input class="form-control" name="company_owner"
value="<%= company.company_owner || '' %>">
<label class="form-label">Inhaber / Geschäftsführer</label>
<input
class="form-control"
name="company_owner"
value="<%= settings.company_owner || '' %>"
>
</div>
<div class="col-md-6">
<label class="form-label">E-Mail</label>
<input class="form-control" name="email"
value="<%= company.email || '' %>">
<label class="form-label">E-Mail</label>
<input
class="form-control"
name="email"
value="<%= settings.email || '' %>"
>
</div>
<div class="col-md-8">
<label class="form-label">Straße</label>
<input class="form-control" name="street"
value="<%= company.street || '' %>">
<label class="form-label">Straße</label>
<input
class="form-control"
name="street"
value="<%= settings.street || '' %>"
>
</div>
<div class="col-md-4">
<label class="form-label">Hausnummer</label>
<input class="form-control" name="house_number"
value="<%= company.house_number || '' %>">
<label class="form-label">Hausnummer</label>
<input
class="form-control"
name="house_number"
value="<%= settings.house_number || '' %>"
>
</div>
<div class="col-md-4">
<label class="form-label">PLZ</label>
<input class="form-control" name="postal_code"
value="<%= company.postal_code || '' %>">
<label class="form-label">PLZ</label>
<input
class="form-control"
name="postal_code"
value="<%= settings.postal_code || '' %>"
>
</div>
<div class="col-md-8">
<label class="form-label">Ort</label>
<input class="form-control" name="city"
value="<%= company.city || '' %>">
<label class="form-label">Ort</label>
<input
class="form-control"
name="city"
value="<%= settings.city || '' %>"
>
</div>
<div class="col-md-6">
<label class="form-label">Land</label>
<input class="form-control" name="country"
value="<%= company.country || 'Deutschland' %>">
<label class="form-label">Land</label>
<input
class="form-control"
name="country"
value="<%= settings.country || 'Deutschland' %>"
>
</div>
<div class="col-md-6">
<label class="form-label">USt-ID / Steuernummer</label>
<input class="form-control" name="vat_id"
value="<%= company.vat_id || '' %>">
<label class="form-label">USt-ID / Steuernummer</label>
<input
class="form-control"
name="vat_id"
value="<%= settings.vat_id || '' %>"
>
</div>
<div class="col-md-6">
<label class="form-label">Bank</label>
<input class="form-control" name="bank_name"
value="<%= company.bank_name || '' %>">
<label class="form-label">Bank</label>
<input
class="form-control"
name="bank_name"
value="<%= settings.bank_name || '' %>"
>
</div>
<div class="col-md-6">
<label class="form-label">IBAN</label>
<input class="form-control" name="iban"
value="<%= company.iban || '' %>">
<label class="form-label">IBAN</label>
<input
class="form-control"
name="iban"
value="<%= settings.iban || '' %>"
>
</div>
<div class="col-md-6">
<label class="form-label">BIC</label>
<input class="form-control" name="bic"
value="<%= company.bic || '' %>">
<label class="form-label">BIC</label>
<input
class="form-control"
name="bic"
value="<%= settings.bic || '' %>"
>
</div>
<div class="col-12">
<label class="form-label">Rechnungs-Footer</label>
<textarea class="form-control" rows="3"
name="invoice_footer_text"><%= company.invoice_footer_text || '' %></textarea>
<label class="form-label">Rechnungs-Footer</label>
<textarea
class="form-control"
rows="3"
name="invoice_footer_text"
><%= settings.invoice_footer_text || '' %></textarea>
</div>
<div class="col-12">
<label class="form-label">Firmenlogo</label>
<input
type="file"
name="logo"
class="form-control"
accept="image/png, image/jpeg"
>
<label class="form-label">Firmenlogo</label>
<input
type="file"
name="logo"
class="form-control"
accept="image/png, image/jpeg"
>
<% if (company.invoice_logo_path) { %>
<div class="mt-2">
<small class="text-muted">Aktuelles Logo:</small><br>
<img
src="<%= company.invoice_logo_path %>"
style="max-height:80px; border:1px solid #ccc; padding:4px;"
>
</div>
<% } %>
<% if (settings.invoice_logo_path) { %>
<div class="mt-2">
<small class="text-muted">Aktuelles Logo:</small><br>
<img
src="<%= settings.invoice_logo_path %>"
style="max-height:80px; border:1px solid #ccc; padding:4px;"
>
</div>
<% } %>
</div>
</div>
</div>
<div class="mt-4">
<button class="btn btn-primary">💾 Speichern</button>
<a href="/dashboard" class="btn btn-secondary">Zurück</a>
</div>
<div class="mt-4 d-flex gap-2">
<button class="btn btn-primary">
<i class="bi bi-save"></i>
<%= t.global.save %>
</button>
</form>
<a href="/dashboard" class="btn btn-secondary">
Zurück
</a>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,66 +1,43 @@
<div class="layout">
<!-- KEIN layout, KEINE sidebar, KEIN main -->
<!-- ✅ SIDEBAR -->
<%- include("partials/sidebar", { user, active: "patients", lang }) %>
<%- include("partials/page-header", {
user,
title: t.dashboard.title,
subtitle: "",
showUserName: true,
hideDashboardButton: true
}) %>
<!-- ✅ MAIN -->
<div class="main">
<div class="content p-4">
<!-- ✅ HEADER (inkl. Uhrzeit) -->
<%- include("partials/page-header", {
user,
title: "Dashboard",
subtitle: "",
showUserName: true,
hideDashboardButton: true
}) %>
<%- include("partials/flash") %>
<div class="content p-4">
<div class="waiting-monitor">
<h5 class="mb-3">🪑 <%= t.dashboard.waitingRoom %></h5>
<!-- Flash Messages -->
<%- include("partials/flash") %>
<!-- =========================
WARTEZIMMER MONITOR
========================= -->
<div class="waiting-monitor">
<h5 class="mb-3">🪑 <%=t.global.waitingroomtext%></h5>
<div class="waiting-grid">
<% if (waitingPatients && waitingPatients.length > 0) { %>
<% waitingPatients.forEach(p => { %>
<% if (user.role === 'arzt') { %>
<form method="POST" action="/patients/<%= p.id %>/call" style="width:100%; margin:0;">
<button type="submit" class="waiting-slot occupied clickable waiting-btn">
<div class="patient-text">
<div class="name"><%= p.firstname %> <%= p.lastname %></div>
<div class="birthdate">
<%= new Date(p.birthdate).toLocaleDateString("de-DE") %>
</div>
</div>
</button>
</form>
<% } else { %>
<div class="waiting-slot occupied">
<div class="patient-text">
<div class="name"><%= p.firstname %> <%= p.lastname %></div>
<div class="birthdate">
<%= new Date(p.birthdate).toLocaleDateString("de-DE") %>
</div>
</div>
</div>
<% } %>
<% }) %>
<div class="waiting-grid">
<% if (waitingPatients && waitingPatients.length > 0) { %>
<% waitingPatients.forEach(p => { %>
<% if (user.role === "arzt") { %>
<form method="POST" action="/patients/<%= p.id %>/call">
<button class="waiting-slot occupied clickable">
<div><%= p.firstname %> <%= p.lastname %></div>
</button>
</form>
<% } else { %>
<div class="text-muted"><%=t.global.waitingroomtextnopatient%></div>
<div class="waiting-slot occupied">
<div><%= p.firstname %> <%= p.lastname %></div>
</div>
<% } %>
</div>
</div>
<% }) %>
<% } else { %>
<div class="text-muted">
<%= t.dashboard.noWaitingPatients %>
</div>
<% } %>
</div>
</div>
</div>

View File

@ -20,7 +20,6 @@
<body>
<div class="layout">
<!-- ✅ Sidebar dynamisch -->
<% if (typeof sidebarPartial !== "undefined" && sidebarPartial) { %>
<%- include(sidebarPartial, {

View File

@ -26,6 +26,18 @@
<div class="sidebar-menu">
<!-- ✅ Firmendaten Verwaltung -->
<a
href="<%= hrefIfAllowed(isAdmin, '/admin/company-settings') %>"
class="nav-item <%= active === 'companySettings' ? 'active' : '' %> <%= lockClass(isAdmin) %>"
title="<%= isAdmin ? '' : 'Nur Admin' %>"
>
<i class="bi bi-people"></i> <%= t.adminSidebar.companysettings %>
<% if (!isAdmin) { %>
<span style="margin-left:auto;"><i class="bi bi-lock-fill"></i></span>
<% } %>
</a>
<!-- ✅ User Verwaltung -->
<a
href="<%= hrefIfAllowed(isAdmin, '/admin/users') %>"