Name des Mieters bei Einladung erfassen und anzeigen
This commit is contained in:
parent
29ebb2e6b7
commit
e36a65e63c
@ -20,13 +20,13 @@ function inviteLinkFor(req: Request, token: string): string {
|
||||
return `${baseUrl.replace(/\/$/, '')}/?invite=${token}`;
|
||||
}
|
||||
|
||||
// POST /v1/invitations (nur Vermieter/Admin) — { email, roomId?, role? } -> { invitation, inviteLink }
|
||||
// POST /v1/invitations (nur Vermieter/Admin) — { email, fullName?, roomId?, role? } -> { invitation, inviteLink }
|
||||
invitationsRouter.post(
|
||||
'/invitations',
|
||||
requireAuth,
|
||||
requireRole('LANDLORD', 'ADMIN'),
|
||||
async (req: AuthedRequest, res: Response) => {
|
||||
const { email, roomId, role } = req.body || {};
|
||||
const { email, fullName, roomId, role } = req.body || {};
|
||||
if (!email || !String(email).trim()) {
|
||||
return res.status(400).json({ error: 'E-Mail-Adresse erforderlich' });
|
||||
}
|
||||
@ -64,6 +64,7 @@ invitationsRouter.post(
|
||||
const invitation = await prisma.invitation.create({
|
||||
data: {
|
||||
email: normalizedEmail,
|
||||
fullName: typeof fullName === 'string' && fullName.trim() ? fullName.trim() : null,
|
||||
token,
|
||||
role: invitedRole,
|
||||
roomId: roomId || null,
|
||||
@ -124,6 +125,7 @@ invitationsRouter.get('/invitations/:token/preview', async (req: Request, res: R
|
||||
}
|
||||
res.status(200).json({
|
||||
email: invitation.email,
|
||||
fullName: invitation.fullName,
|
||||
role: invitation.role,
|
||||
room: invitation.room,
|
||||
expiresAt: invitation.expiresAt,
|
||||
|
||||
@ -237,6 +237,7 @@ model Room {
|
||||
model Invitation {
|
||||
id String @id @default(uuid())
|
||||
email String
|
||||
fullName String? @map("full_name")
|
||||
token String @unique
|
||||
role UserRole @default(TENANT)
|
||||
roomId String? @map("room_id")
|
||||
|
||||
@ -656,6 +656,10 @@
|
||||
<div class="invite-card">
|
||||
<div id="inviteFormError" style="display:none" class="form-error"></div>
|
||||
<form id="inviteForm" class="invite-form-row">
|
||||
<div class="field">
|
||||
<label for="inviteName">Name des Mieters (optional)</label>
|
||||
<input type="text" id="inviteName" placeholder="Max Mustermann" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="inviteEmail">E-Mail-Adresse des Mieters</label>
|
||||
<input type="email" id="inviteEmail" required placeholder="mieter@beispiel.de" />
|
||||
@ -674,7 +678,7 @@
|
||||
</div>
|
||||
<table class="invite-table" id="inviteTable" style="display:none">
|
||||
<thead>
|
||||
<tr><th>E-Mail</th><th>Zimmer</th><th>Status</th><th>Eingeladen am</th><th></th></tr>
|
||||
<tr><th>Name</th><th>E-Mail</th><th>Zimmer</th><th>Status</th><th>Eingeladen am</th><th></th></tr>
|
||||
</thead>
|
||||
<tbody id="inviteTableBody"></tbody>
|
||||
</table>
|
||||
@ -1305,6 +1309,7 @@
|
||||
sub.textContent = `Einladung als ${ROLE_LABEL[preview.role] || preview.role}` +
|
||||
(preview.room ? ` für ${preview.room.roomNumber}` : '') + '. Bitte Passwort festlegen.';
|
||||
document.getElementById('acceptEmail').value = preview.email;
|
||||
if (preview.fullName) document.getElementById('acceptFullName').value = preview.fullName;
|
||||
form.style.display = 'flex';
|
||||
form.style.flexDirection = 'column';
|
||||
|
||||
@ -1511,14 +1516,16 @@
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = 'Lädt ein…';
|
||||
try {
|
||||
const fullName = document.getElementById('inviteName').value.trim() || undefined;
|
||||
const email = document.getElementById('inviteEmail').value.trim();
|
||||
const roomId = document.getElementById('inviteRoom').value || undefined;
|
||||
const data = await apiFetch('/invitations', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ email, roomId }),
|
||||
body: JSON.stringify({ email, fullName, roomId }),
|
||||
});
|
||||
document.getElementById('inviteLinkText').textContent = data.inviteLink;
|
||||
document.getElementById('inviteLinkResult').style.display = 'flex';
|
||||
document.getElementById('inviteName').value = '';
|
||||
document.getElementById('inviteEmail').value = '';
|
||||
loadInvitations();
|
||||
} catch (err) {
|
||||
@ -1551,6 +1558,7 @@
|
||||
table.style.display = 'table';
|
||||
data.invitations.forEach(inv => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.appendChild(el('td', '', inv.fullName || '–'));
|
||||
tr.appendChild(el('td', '', inv.email));
|
||||
tr.appendChild(el('td', '', inv.room ? inv.room.roomNumber : '–'));
|
||||
tr.appendChild(el('td', '', `<span class="invite-status-chip ${inv.status}">${INVITE_STATUS_LABEL[inv.status] || inv.status}</span>`));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user