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: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
fullName: true,
|
fullName: true,
|
||||||
|
email: true,
|
||||||
phoneNumber: true,
|
phoneNumber: true,
|
||||||
firstResidenceAddress: true,
|
firstResidenceAddress: true,
|
||||||
idDocumentFrontUrl: true,
|
idDocumentFrontUrl: true,
|
||||||
|
|||||||
@ -450,6 +450,17 @@
|
|||||||
.nav-item .nav-icon { font-size: 15px; width: 18px; text-align: center; }
|
.nav-item .nav-icon { font-size: 15px; width: 18px; text-align: center; }
|
||||||
.nav-item:hover { background: var(--bg); }
|
.nav-item:hover { background: var(--bg); }
|
||||||
.nav-item.active { background: var(--green-bg); color: var(--green); font-weight: 600; }
|
.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; }
|
.content-area { flex: 1; min-width: 0; }
|
||||||
.page { display: none; }
|
.page { display: none; }
|
||||||
@ -578,7 +589,9 @@
|
|||||||
<div class="sidebar-brand">WG Nackenheim<span>Vermieter-Cockpit</span></div>
|
<div class="sidebar-brand">WG Nackenheim<span>Vermieter-Cockpit</span></div>
|
||||||
<nav id="sidebarNav">
|
<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 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-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-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>
|
<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>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="page" id="page-tenants">
|
<div class="page" id="page-tenant-invites">
|
||||||
|
|
||||||
<section id="inviteSection" style="display:none">
|
<section id="inviteSection" style="display:none">
|
||||||
<h2>Mieter einladen</h2>
|
<h2>Mieter einladen</h2>
|
||||||
@ -703,6 +716,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</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">
|
<section id="ratingsSection">
|
||||||
<h2>Mieter-Bewertung</h2>
|
<h2>Mieter-Bewertung</h2>
|
||||||
<div class="invite-card" style="margin-bottom:16px;">
|
<div class="invite-card" style="margin-bottom:16px;">
|
||||||
@ -1449,6 +1471,7 @@
|
|||||||
|
|
||||||
const isLandlord = currentUser.role === 'LANDLORD' || currentUser.role === 'ADMIN';
|
const isLandlord = currentUser.role === 'LANDLORD' || currentUser.role === 'ADMIN';
|
||||||
document.getElementById('inviteSection').style.display = isLandlord ? 'block' : 'none';
|
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('rentSectionTitle').textContent = isLandlord ? 'Miet-Ampel je Zimmer' : 'Meine Miete';
|
||||||
document.getElementById('cleaningAssignSection').style.display = isLandlord ? 'block' : 'none';
|
document.getElementById('cleaningAssignSection').style.display = isLandlord ? 'block' : 'none';
|
||||||
document.getElementById('cleaningSectionTitle').textContent = isLandlord ? 'Putzplan (alle Mieter)' : 'Mein Putzplan';
|
document.getElementById('cleaningSectionTitle').textContent = isLandlord ? 'Putzplan (alle Mieter)' : 'Mein Putzplan';
|
||||||
@ -1495,6 +1518,7 @@
|
|||||||
loadContractDocuments();
|
loadContractDocuments();
|
||||||
loadContractArchive();
|
loadContractArchive();
|
||||||
loadAnnouncements();
|
loadAnnouncements();
|
||||||
|
if (isLandlord) loadTenantData();
|
||||||
|
|
||||||
setInterval(loadData, REFRESH_INTERVAL_MS);
|
setInterval(loadData, REFRESH_INTERVAL_MS);
|
||||||
setInterval(loadCleaningTasks, REFRESH_INTERVAL_MS);
|
setInterval(loadCleaningTasks, REFRESH_INTERVAL_MS);
|
||||||
@ -1512,6 +1536,7 @@
|
|||||||
setInterval(loadContractDocuments, REFRESH_INTERVAL_MS);
|
setInterval(loadContractDocuments, REFRESH_INTERVAL_MS);
|
||||||
setInterval(loadContractArchive, REFRESH_INTERVAL_MS);
|
setInterval(loadContractArchive, REFRESH_INTERVAL_MS);
|
||||||
setInterval(loadAnnouncements, REFRESH_INTERVAL_MS);
|
setInterval(loadAnnouncements, REFRESH_INTERVAL_MS);
|
||||||
|
if (isLandlord) setInterval(loadTenantData, REFRESH_INTERVAL_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
@ -3576,6 +3601,43 @@
|
|||||||
return wrap;
|
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) {
|
function renderContractDocuments(contracts) {
|
||||||
const isLandlord = currentUser.role === 'LANDLORD' || currentUser.role === 'ADMIN';
|
const isLandlord = currentUser.role === 'LANDLORD' || currentUser.role === 'ADMIN';
|
||||||
const list = document.getElementById('contractDocumentsList');
|
const list = document.getElementById('contractDocumentsList');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user