Commit Graph

41 Commits

Author SHA1 Message Date
33881db9e1 Fälligkeitsdatum-Anzeige zeitzonenunabhängig formatieren 2026-08-13 17:48:55 +00:00
89d2a911e1 Fälligkeit der Miete bei Vertragserstellung (1./15.) + endgültiges Löschen zurückgezogener Einladungen 2026-08-13 17:45:29 +00:00
3111f64ecd Einladung: Vertragsbeginn/-ende inkl. datumsbewusster Zimmer-Plausibilitätsprüfung 2026-08-13 17:28:12 +00:00
41c18d078f Merge: Namensfeld bei Einladung + Vertragslaufzeit-Plausibilitätsprüfung 2026-08-13 17:24:28 +00:00
e36a65e63c Name des Mieters bei Einladung erfassen und anzeigen 2026-08-13 17:24:01 +00:00
53834cc509 Fix: Auto-Refresh in Vertragsdokumente ueberschreibt keine Formulareingaben mehr 2026-08-13 16:35:18 +00:00
29ebb2e6b7 ADMIN-Rolle im UI ebenfalls als 'Vermieter' anzeigen
ADMIN hat bereits überall dieselben Rechte wie LANDLORD — jetzt auch
dieselbe Bezeichnung im Dashboard, statt 'Verwaltung'.
2026-08-13 14:10:08 +00:00
1ac31b1032 Ankündigungen: Mieter können Handwerker/Schornsteinfeger-Termine bestätigen
Jeder Mieter kann für Ankündigungen mit Termin markieren, ob die Person
tatsächlich da war ('War da'/'War nicht da') — nicht nur der Vermieter.
Ankündigungen mit Termin erscheinen jetzt außerdem als Eintrag im
gemeinsamen Putzplan-Kalender, inkl. Rückmeldestatus.
2026-08-13 13:49:40 +00:00
0b43e9fcba Müll-Kalender: wer die Tonne rausgestellt hat sichtbar machen
Erledigte Termine zeigen jetzt '✓ Vorname' im Kalender-Event, damit im
Nachhinein nachvollziehbar ist, wer sich zuverlässig um den Müll kümmert.
2026-08-13 13:41:22 +00:00
a35fa1ddda Müll-Erinnerung erst 3 Tage vorher statt 7 Tage anzeigen 2026-08-13 13:36:59 +00:00
778cb94b3a Müll-Erinnerung gemeinschaftlich abhakbar machen
Jeder Mieter kann eine Mülltonne als rausgestellt markieren; danach
verschwindet die Erinnerung für alle Mieter, nicht nur für den, der sie
abgehakt hat.
2026-08-13 13:31:55 +00:00
b15ba77336 Nachrichten-Übersicht für Mieter + Vermieter-Ankündigungen hinzufügen
Neue Ankündigungen (z. B. Schornsteinfeger, Handwerkertermin), nur vom
Vermieter anlegbar, für alle sichtbar. Zusätzlich eine gebündelte
'Für dich diese Woche'-Übersicht für Mieter mit fälligem Putzplan,
fälliger Miete, anstehendem Mülltermin und Ankündigungen der nächsten
7 Tage.
2026-08-13 13:24:21 +00:00
ca1c1fdfb7 Putzplan: Kalender nach Abhaken/Bestätigen einer Aufgabe sofort aktualisieren
War zuvor bis zum nächsten Auto-Refresh (20s) veraltet, weil nur die
Aufgabenliste, nicht der Kalender neu geladen wurde.
2026-08-13 13:14:59 +00:00
0d871d9ad5 Putzplan-Kalender: farbige Legende für Erledigungsstatus ergänzen 2026-08-13 13:12:08 +00:00
c385947e80 Putzplan-Kalender: Erledigungsstatus je Aufgabe sichtbar machen
Kalender-Badges zeigen jetzt Offen/Erledigt/Bestätigt/Verpasst per Icon
und Farbe, statt nur Bereich und zuständige Person.
2026-08-13 13:09:49 +00:00
fdf98a70e5 Smart-Lock-Gastcodes zu Smart-Lock/Alarmanlagen-Code umgebaut
Statt zeitlich begrenzter Gästecodes, die jeder selbst ausstellen konnte,
gibt es jetzt einen dauerhaften Code je Mieter, den ausschließlich der
Vermieter vergibt/widerruft. Der Mieter sieht nur seinen eigenen Code
(read-only).
2026-08-13 12:55:29 +00:00
f576cddf6a Putzplan: feste Bereichsliste durch frei erweiterbare Bereiche ersetzen
Vermieter kann jetzt eigene Putzbereiche anlegen (CleaningAreaOption
statt festem Enum). Neue Standardbereiche: Balkon oben, Terrasse unten,
Gehweg unten, Flur unten (Eingangstür), Flur Wendeltreppe, Flur oben,
Bad oben, Bad unten, Wohnzimmer, Küche.
2026-08-13 12:44:53 +00:00
78810002b4 Passwort-ändern-Funktion für alle Rollen hinzufügen
Neuer Endpoint POST /v1/auth/change-password (verlangt aktuelles Passwort
zur Bestätigung) sowie Modal + Button im Topbar für Vermieter und Mieter.
2026-08-13 12:38:23 +00:00
dd24d7217a Preview uploaded documents in an in-page modal instead of a new tab
Chrome blocks top-level navigation to data: URLs (anti-phishing), so
the earlier target="_blank" preview links silently opened a blank tab
for every uploaded document — real bug, caught by live testing.
Replaces that with a same-tab modal: clicking a document name opens
it in an overlay (<iframe> for PDFs, <img> for images — data: URLs
work fine for embedding, just not top-level navigation), with its own
download button and a close control. The small ⬇ icon next to each
chip still downloads directly, unaffected since the `download`
attribute uses a different code path than navigation.
2026-08-13 12:18:17 +00:00
92101e3077 Let uploaded documents open as a preview, download separately
Every uploaded-document link (contract PDFs, ID front/back, Schufa
report — active and archived) previously forced a download on click
via the `download` attribute, with no way to just look at the file
first. New shared buildDocumentChip() renders the filename as a
target="_blank" link (browsers preview PDFs/images natively) plus a
small ⬇ icon next to it for an explicit download, reused across all
three places these chips are rendered.
2026-08-13 12:11:08 +00:00
48fb4118fd Compress ID/Schufa photos client-side before upload, raise server limit further
Server-side testing showed the 30mb express.json limit itself was
fine for payloads up to 30MB, but real phone photos (15-25MB each,
×3 files) can still exceed that. Adds readFileAsCompressedDataUrl:
downscales image uploads to max 1800px on the long edge at 0.82 JPEG
quality via canvas before converting to a data URL — typically
shrinks a multi-MB phone photo to a few hundred KB, which is more than
sufficient resolution for a legible ID/Schufa scan. PDFs pass through
uncompressed. Also raises the raw pre-upload size check to 25MB/file
and the server body limit to 50mb as a safety margin for PDF-heavy
cases the client-side compression doesn't touch.
2026-08-13 11:52:12 +00:00
8f4b985f79 Fix HTTP 413 when accepting a tenant invite with ID/Schufa uploads
Accepting an invitation as TENANT now sends up to three files (ID
front, ID back, optional Schufa) as base64 data URLs in one JSON body.
Raises express.json's limit from 10mb to 30mb so three real phone
photos fit. Also adds a client-side 8MB-per-file check with a clear
error message instead of letting an oversized file hit the server
limit and surface a bare "Status 413".
2026-08-13 11:46:39 +00:00
284a90222a Only offer vacant rooms in the tenant-invite room dropdown
The "Mieter einladen" form previously listed every room regardless of
occupancy, letting a landlord accidentally assign a new invite to an
already-occupied room. Filters lastRooms to status === 'VACANT' for
that select only — ticket/inventory room pickers still show all rooms
since those aren't about assigning a tenancy.
2026-08-13 11:36:02 +00:00
e77e33d7ff Require phone, current address and ID copy for new tenants
Accepting an invitation as a TENANT now mandates phone number, current
first-residence address (Erstwohnsitz), and both sides of an ID
document — the accept endpoint rejects the request with a clear error
if any are missing. A Schufa credit report upload stays optional, but
if provided its issue date must be within the last 3 months or the
request is rejected.

New User fields: phoneNumber was already there; added
firstResidenceAddress, idDocumentFrontUrl, idDocumentBackUrl,
schufaDocumentUrl, schufaDocumentDate. Kept nullable at the DB level
(existing accounts have none of this and shouldn't be broken) —
enforcement lives in the accept-invitation route, not a DB constraint.

Landlords now see a completeness badge ("Profil vollständig" /
"Unvollständig: X fehlt") plus a Schufa freshness badge on each
contract card in Verträge & Abrechnung, with direct download links for
the uploaded ID/Schufa files.
2026-08-13 11:25:57 +00:00
3e87ff3476 Allow re-admitting an archived tenant via a brand-new contract
Adds "Wieder aufnehmen" to each archived contract card: landlord picks
a vacant room, move-in date, rent and deposit, then POST
/contracts/reactivate creates a fresh Contract row for that user (new
id, new terms, no carried-over documents/signature) and re-assigns the
room. The old contract is never touched — it stays exactly as-is in
the archive as a historical record, per the requirement that the
original tenancy documentation must be preserved even after rejoining.

New GET /contracts/vacant-rooms lists rooms with no active contract,
used to populate the room picker and prefill sensible rent/deposit
defaults from the room's base rent.
2026-08-13 11:10:20 +00:00
a6fb15cd41 Add tenant move-out with permanent archive instead of deletion
Landlords can now remove a tenant from their room via a "Mieter
ausziehen lassen" button on the contract card. This never deletes
anything: POST /contracts/:id/move-out sets Contract.isActive=false
(with an endDate), frees the room (User.roomId=null,
Room.status=VACANT) so it can be re-assigned via the existing invite
flow, and leaves the contract row — along with every linked payment,
ticket, rating, handover protocol, and contract document — untouched
and permanently queryable.

GET /contracts/documents now only lists active contracts; the new
GET /contracts/archive (landlord/admin only) lists deactivated ones,
rendered in a new "Archiv — ausgezogene Mieter" section on the
Verträge-page with their historical documents still downloadable.
2026-08-13 10:59:16 +00:00
410db93c30 Restructure generated contract as a full-format rental agreement
Rewrites contractDocumentGenerator.ts from a short summary into a
proper Wohnraummietvertrag layout: numbered §§ for Vertragsparteien,
Mieträume, Mietzeit, Miete/Nebenkosten, Kaution, Instandhaltung/
Schönheitsreparaturen, Hausordnung, Tierhaltung/Untervermietung,
Mietanpassung, sonstige Vereinbarungen, salvatorische Klausel, plus
signature lines for both landlord and tenant (with the drawn signature
embedded once signed) and a page-footer disclaimer instead of a
top-of-document warning box.

Adds Contract.landlordName/landlordAddress/propertyAddress so the
document can show a real letterhead — addresses default to a
"please fill in" placeholder rather than a fabricated address, since
this is a real WG's data. Landlord fills them once via new fields in
the contract generator form; persisted per contract like the other
template options.
2026-08-13 10:37:57 +00:00
bba4fc318b Add click-based contract generator + digital tenant signature
Landlords configure a contract via checkboxes/selects (WLAN included,
furnished, utility billing model, notice period, deposit, rent
adjustment clause) and generate a PDF (pdfkit) that's automatically
attached to the contract's document list. Tenants sign their own
contract in-app by drawing a signature on a canvas; signing embeds the
signature image into a freshly generated final PDF and marks the
contract as signed with a timestamp.

New: Contract.wifiIncluded/furnished/utilityBillingModel (+ new
UtilityBillingModel enum), Contract.tenantSignatureUrl/signedAt.
New endpoints: POST /contracts/:id/generate-document (landlord/admin),
POST /contracts/:id/sign (tenant on own contract, or landlord/admin).

Explicitly a documentation template generated from app data, not a
legally reviewed contract — noted in the PDF itself.
2026-08-13 10:23:27 +00:00
a8dc999180 Add multi-file contract document uploads (Verträge & Abrechnung)
Replaces the unused, never-wired-up single contractPdfUrl field with
contractDocumentUrls (String[]) so landlords can attach several files
per contract (signed lease, addenda, ...) instead of just one. New
endpoints: GET /contracts/documents (tenant sees own contract only,
landlord sees all — same visibility rule as the rest of the app),
POST/DELETE /contracts/:id/documents (landlord/admin only). Frontend
reuses the existing FileReader-to-data-URL upload pattern already used
for inventory photos, so files are stored inline like everywhere else
in this app rather than introducing a new storage mechanism.
2026-08-13 09:52:56 +00:00
aa59ab452a Replace flat trash list with a real month-calendar view (FullCalendar)
Rebuilds the "Müll-Kalender" as a proper color-coded FullCalendar (v6,
MIT-licensed, CDN, no build step) month grid instead of a bare list of
type+date rows. Adds a manual "Kalender aktualisieren" action for
landlords (POST /v1/trash-schedule/sync) that re-runs the same KAW
sync job as the daily cron, instead of letting them delete individual
calendar entries by clicking — accidental single-click deletion of
official data was too easy and had no real justification, since a
missing date just gets re-added by the next sync anyway.
2026-08-13 09:20:54 +00:00
3b505d231a Restructure dashboard into sidebar navigation with grouped sections
20 flat scrolling sections replaced with a 10-item sidebar nav (Übersicht,
Mieter, Tickets & Handwerker, Putzplan, WG-Kasse, Inventar & Übergabe,
Zugang, Küche & Müll, Dokumente, Verträge & Abrechnung). One page visible
at a time, collapsible off-canvas menu on mobile. No backend/API changes.
2026-08-13 08:45:25 +00:00
791b9bb01e Add peer rating system for tenants
Implements the previously-deferred "Bewertungssystem für Zwischenmieter"
requirement, which existed only as a vague idea with no model, route, or
UI. Design (confirmed with user): any authenticated user can rate any
tenant (1-5 + optional comment), freestanding (not tied to a contract,
creatable any time), visible only to LANDLORD/ADMIN — tenants can submit
ratings but not view them, to keep WG-internal friction out of the open.

- prisma: TenantRating model + User relations. Also pins the Prisma
  Client `output` path explicitly: since schema.prisma lives at the repo
  root (no package.json there) while node_modules only exists under
  backend/, `prisma generate`'s root-inference walked up past the repo
  and wrote into an unrelated ancestor directory when invoked from a
  fresh checkout. The explicit relative output keeps repo-root schema +
  backend-only deps working the same locally and in Docker.
- backend: GET/POST /v1/ratings (role-gated read), GET /v1/ratings/tenants
  (name+room only, any authenticated user, for the picker).
- dashboard: rating form for everyone, landlord-only ratings/summary view.
2026-08-13 07:39:32 +00:00
4ba0100d31 Add 1-click PDF export for tickets (craftsman handoff)
Implements the "1-Klick-PDF-Export für Handwerker" requirement from
the ticketing module spec, which existed only as a schema stub
(HandoverProtocol.pdfUrl) with no actual generator anywhere in the
codebase. Adds a server-side PDF endpoint (pdfkit, no headless
browser needed) summarizing a ticket's category, priority, status,
room, reporter and description, plus a "PDF" button in the landlord
cockpit that downloads it via an authenticated blob fetch (the API
uses a Bearer token, not cookies, so a plain <a href> wouldn't carry
auth).
2026-08-13 07:27:01 +00:00
c8a5984f8b Dateien nach "web-dashboard" hochladen 2026-08-12 21:56:12 +00:00
007ed74527 index.html final korrigiert (byte-exact reupload) 2026-08-12 21:28:30 +00:00
7bfa45a400 Add Putzplan calendar/absences UI 2026-08-12 19:57:54 +00:00
544eb4d745 Add Putzplan UI section 2026-08-12 19:11:21 +00:00
e3ac1e9c4a Add ticket reporting UI and role-scoped rendering (tenant privacy) 2026-08-12 18:39:17 +00:00
6d8cbd7f42 add login + invite UI to web dashboard 2026-08-12 18:03:24 +00:00
35b887d954 add web-dashboard/Dockerfile 2026-08-12 16:46:21 +00:00
1a2701576f add web-dashboard/index.html 2026-08-12 16:46:20 +00:00