Sidebar: Mieter zu Mieterverwaltung mit Untermenüs Mietereinladungen/Mieterdaten umbauen
This commit is contained in:
parent
33881db9e1
commit
23d58e48d9
@ -131,6 +131,7 @@ const CONTRACT_DOCUMENTS_SELECT = {
|
||||
select: {
|
||||
id: true,
|
||||
fullName: true,
|
||||
email: true,
|
||||
phoneNumber: true,
|
||||
firstResidenceAddress: true,
|
||||
idDocumentFrontUrl: true,
|
||||
|
||||
@ -450,6 +450,17 @@
|
||||
.nav-item .nav-icon { font-size: 15px; width: 18px; text-align: center; }
|
||||
.nav-item:hover { background: var(--bg); }
|
||||
.nav-item.active { background: var(--green-bg); color: var(--green); font-weight: 600; }
|
||||
.nav-group-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
padding: 10px 12px 2px;
|
||||
font-size: 13.5px;
|
||||
color: var(--text);
|
||||
font-weight: 600;
|
||||
}
|
||||
.nav-subitem { padding-left: 34px; font-size: 13px; }
|
||||
|
||||
.content-area { flex: 1; min-width: 0; }
|
||||
.page { display: none; }
|
||||
@ -578,7 +589,9 @@
|
||||
<div class="sidebar-brand">WG Nackenheim<span>Vermieter-Cockpit</span></div>
|
||||
<nav id="sidebarNav">
|
||||
<button class="nav-item active" data-page="page-overview" onclick="switchPage('page-overview')"><span class="nav-icon">🏠</span>Übersicht</button>
|
||||
<button class="nav-item" data-page="page-tenants" onclick="switchPage('page-tenants')"><span class="nav-icon">👥</span>Mieter</button>
|
||||
<div class="nav-group-title"><span class="nav-icon">👥</span>Mieterverwaltung</div>
|
||||
<button class="nav-item nav-subitem" data-page="page-tenant-invites" onclick="switchPage('page-tenant-invites')">Mietereinladungen</button>
|
||||
<button class="nav-item nav-subitem" data-page="page-tenant-data" onclick="switchPage('page-tenant-data')">Mieterdaten</button>
|
||||
<button class="nav-item" data-page="page-tickets" onclick="switchPage('page-tickets')"><span class="nav-icon">🛠️</span>Tickets & Handwerker</button>
|
||||
<button class="nav-item" data-page="page-cleaning" onclick="switchPage('page-cleaning')"><span class="nav-icon">🧹</span>Putzplan</button>
|
||||
<button class="nav-item" data-page="page-finance" onclick="switchPage('page-finance')"><span class="nav-icon">💶</span>WG-Kasse</button>
|
||||
@ -649,7 +662,7 @@
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="page" id="page-tenants">
|
||||
<div class="page" id="page-tenant-invites">
|
||||
|
||||
<section id="inviteSection" style="display:none">
|
||||
<h2>Mieter einladen</h2>
|
||||
@ -703,6 +716,15 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="page" id="page-tenant-data">
|
||||
|
||||
<section id="tenantDataSection" style="display:none">
|
||||
<h2>Mieterdaten</h2>
|
||||
<div class="ticket-list" id="tenantDataList"></div>
|
||||
</section>
|
||||
|
||||
<section id="ratingsSection">
|
||||
<h2>Mieter-Bewertung</h2>
|
||||
<div class="invite-card" style="margin-bottom:16px;">
|
||||
@ -1449,6 +1471,7 @@
|
||||
|
||||
const isLandlord = currentUser.role === 'LANDLORD' || currentUser.role === 'ADMIN';
|
||||
document.getElementById('inviteSection').style.display = isLandlord ? 'block' : 'none';
|
||||
document.getElementById('tenantDataSection').style.display = isLandlord ? 'block' : 'none';
|
||||
document.getElementById('rentSectionTitle').textContent = isLandlord ? 'Miet-Ampel je Zimmer' : 'Meine Miete';
|
||||
document.getElementById('cleaningAssignSection').style.display = isLandlord ? 'block' : 'none';
|
||||
document.getElementById('cleaningSectionTitle').textContent = isLandlord ? 'Putzplan (alle Mieter)' : 'Mein Putzplan';
|
||||
@ -1495,6 +1518,7 @@
|
||||
loadContractDocuments();
|
||||
loadContractArchive();
|
||||
loadAnnouncements();
|
||||
if (isLandlord) loadTenantData();
|
||||
|
||||
setInterval(loadData, REFRESH_INTERVAL_MS);
|
||||
setInterval(loadCleaningTasks, REFRESH_INTERVAL_MS);
|
||||
@ -1512,6 +1536,7 @@
|
||||
setInterval(loadContractDocuments, REFRESH_INTERVAL_MS);
|
||||
setInterval(loadContractArchive, REFRESH_INTERVAL_MS);
|
||||
setInterval(loadAnnouncements, REFRESH_INTERVAL_MS);
|
||||
if (isLandlord) setInterval(loadTenantData, REFRESH_INTERVAL_MS);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
@ -3576,6 +3601,43 @@
|
||||
return wrap;
|
||||
}
|
||||
|
||||
// Mieterdaten-Übersicht (nur Vermieter/Admin): eine Zeile je aktivem
|
||||
// Vertrag mit Kontaktdaten + derselben Profil-Vollständigkeits-/Schufa-
|
||||
// Anzeige wie bei den Vertragsdokumenten — nutzt bewusst denselben
|
||||
// Endpunkt (/contracts/documents), statt die Daten zu duplizieren.
|
||||
async function loadTenantData() {
|
||||
try {
|
||||
const data = await apiFetch('/contracts/documents');
|
||||
renderTenantData(data.contracts || []);
|
||||
} catch (err) {
|
||||
console.error('[tenantData] Laden fehlgeschlagen:', err.message);
|
||||
}
|
||||
}
|
||||
|
||||
function renderTenantData(contracts) {
|
||||
const list = document.getElementById('tenantDataList');
|
||||
list.innerHTML = '';
|
||||
if (!contracts.length) {
|
||||
list.appendChild(el('div', 'empty-state', 'Keine aktiven Mieter gefunden.'));
|
||||
return;
|
||||
}
|
||||
contracts.forEach(c => {
|
||||
const card = el('div', 'ticket-row');
|
||||
card.style.flexDirection = 'column';
|
||||
card.style.alignItems = 'stretch';
|
||||
card.style.gap = '10px';
|
||||
|
||||
const top = el('div');
|
||||
top.appendChild(el('div', 'title', `${c.user.fullName} · ${c.room.roomNumber}`));
|
||||
top.appendChild(el('div', 'meta-text',
|
||||
`${c.user.email}${c.user.phoneNumber ? ' · ' + c.user.phoneNumber : ''}`));
|
||||
card.appendChild(top);
|
||||
|
||||
card.appendChild(buildProfileCompletenessBadge(c.user));
|
||||
list.appendChild(card);
|
||||
});
|
||||
}
|
||||
|
||||
function renderContractDocuments(contracts) {
|
||||
const isLandlord = currentUser.role === 'LANDLORD' || currentUser.role === 'ADMIN';
|
||||
const list = document.getElementById('contractDocumentsList');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user