Files
enerport-web-app/src/app/pages/property-manager/property-manager.html
Murat Özkorkmaz e901aefbf5 Several fixes
- added organizations
- added industries
- added logo in 2 colors for light and dark theme
- improved authorization to allow multi tenancy
2025-11-13 19:56:50 +01:00

253 lines
11 KiB
HTML

<p-toolbar styleClass="mb-6">
<ng-template #start>
<p-button label="Neu" icon="pi pi-plus" severity="secondary" class="mr-2" (onClick)="openNew()" />
<p-button label="Löschen" icon="pi pi-trash" severity="danger" outlined (onClick)="deleteSelected()" [disabled]="!selectedProperties || !selectedProperties.length" />
</ng-template>
<ng-template #end>
<p-button label="Exportieren" icon="pi pi-upload" severity="secondary" (onClick)="exportCSV()" />
</ng-template>
</p-toolbar>
<p-table
#dt
[value]="properties()"
[rows]="10"
[columns]="cols"
[paginator]="true"
[globalFilterFields]="['name', 'street', 'houseNumber', 'zipCode', 'city', 'country', 'notes']"
[tableStyle]="{ 'min-width': '75rem' }"
[(selection)]="selectedProperties"
[rowHover]="true"
dataKey="id"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} properties"
[showCurrentPageReport]="true"
[rowsPerPageOptions]="[10, 20, 30]"
>
<ng-template #caption>
<div class="flex items-center justify-between">
<h5 class="m-0" >Verwalte Liegenschaften</h5>
<p-iconfield>
<p-inputicon styleClass="pi pi-search" />
<input pInputText type="text" (input)="onGlobalFilter(dt, $event)" placeholder="Suche..." />
</p-iconfield>
</div>
</ng-template>
<ng-template #header>
<tr>
<th style="width: 3rem">
<p-tableHeaderCheckbox />
</th>
<th pSortableColumn="nr" style="min-width:8rem" >
Nr.
<p-sortIcon field="nr" />
</th>
<th pSortableColumn="name" style="min-width:8rem" >
Name
<p-sortIcon field="name" />
</th>
<th pSortableColumn="owner" style="min-width:8rem" >
Eigentümer
<p-sortIcon field="owner" />
</th>
<th pSortableColumn="street" style="min-width: 8rem" >
Straße
<p-sortIcon field="street" />
</th>
<th pSortableColumn="houseNumber" style="min-width:8rem" >
Hausnummer
<p-sortIcon field="houseNumber" />
</th>
<th pSortableColumn="zipCode" style="min-width: 12rem" >
Postleitzahl
<p-sortIcon field="zipCode" />
</th>
<th pSortableColumn="city" style="min-width: 12rem" >
Stadt
<p-sortIcon field="city" />
</th>
<th pSortableColumn="bundesland" style="min-width:8rem" >
Bundesland
<p-sortIcon field="bundesland" />
</th>
<th pSortableColumn="Einheiten" style="min-width:8rem" >
Einheiten
<p-sortIcon field="Einheiten" />
</th>
<th pSortableColumn="Status" style="min-width:8rem">
Status
<p-sortIcon field="Status" />
</th>
<th pSortableColumn="Projekte" style="min-width:8rem">
Projekte
<p-sortIcon field="Projekte" />
</th>
<th pSortableColumn="Labels" style="min-width:8rem">
Labels
<p-sortIcon field="Labels" />
</th>
<th pSortableColumn="country.name" style="min-width: 6rem">
Land
<p-sortIcon field="country.name" />
</th>
<th style="min-width: 12rem"></th>
</tr>
</ng-template>
<ng-template #body let-property>
<tr>
<td>
<p-tableCheckbox [value]="property" />
</td>
<td>Nr...</td>
<td>{{ property.name }}</td>
<td>Eigentümer...</td>
<td>{{ property.street }}</td>
<td class="text-right">{{ property.houseNumber }}</td>
<td class="text-right">{{ property.zipCode }}</td>
<td>{{ property.city }}</td>
<td>Bundesland...</td>
<td>Einheiten...</td>
<td>Status...</td>
<td>Projekte...</td>
<td>Labels...</td>
<td class="text-center">
<div class="flex items-center gap-2">
<img src="https://primefaces.org/cdn/primeng/images/demo/flag/flag_placeholder.png" [class]="'flag flag-' + (property.country | lowercase)" width="30" />
<span>{{ property.country?.name }}</span>
</div>
</td>
<td class="text-center">
<p-button icon="pi pi-pencil" class="mr-2" [rounded]="true" [outlined]="true" (click)="editProperty(property)" />
<p-button icon="pi pi-trash" severity="danger" [rounded]="true" [outlined]="true" (click)="deleteProperty(property)" />
</td>
</tr>
</ng-template>
</p-table>
<p-dialog [(visible)]="propertyDialog" [style]="{ width: '900px' }" i18n-header header="Liegenschaft Details" [modal]="true">
<ng-template #content>
<div class="grid gap-4 max-w-3xl mx-auto p-4">
<!-- Name -->
<div class="flex flex-col">
<label for="name" class="block font-bold mb-3">Name</label>
<input type="text" pInputText id="name" [(ngModel)]="property().name" required autofocus fluid />
@if (submitted && !property().name) {
<small class="text-red-500">Name is required.</small>
}
</div>
<!-- Street + Housenumber -->
<div class="grid gap-4 grid-cols-1 sm:grid-cols-3">
<div class="flex flex-col sm:col-span-2">
<label for="street" class="block font-bold mb-3">Straße</label>
<input type="text" pInputText id="street" [(ngModel)]="property().street" required autofocus fluid />
@if (submitted && !property().street) {
<small class="text-red-500">Street is required.</small>
}
</div>
<div class="flex flex-col">
<label for="houseNumber" class="block font-bold mb-3">Hausnummer</label>
<input type="text" pInputText id="houseNumber" [(ngModel)]="property().houseNumber" required autofocus fluid />
@if (submitted && !property().houseNumber) {
<small class="text-red-500">House number is required.</small>
}
</div>
</div>
<!-- ZipCode + City -->
<div class="grid gap-4 grid-cols-1 sm:grid-cols-3">
<div class="flex flex-col">
<label for="zipCode" class="block font-bold mb-3">Postleitzahl</label>
<input type="text" pInputText id="zipCode" [(ngModel)]="property().zipCode" required autofocus fluid />
@if (submitted && !property().zipCode) {
<small class="text-red-500">Zip code is required.</small>
}
</div>
<div class="flex flex-col sm:col-span-2">
<label for="city" class="block font-bold mb-3">Stadt</label>
<input type="text" pInputText id="city" [(ngModel)]="property().city" required autofocus fluid />
@if (submitted && !property().city) {
<small class="text-red-500">City is required.</small>
}
</div>
</div>
<!-- Country -->
<div class="flex flex-col">
<label for="country" class="mb-1 font-medium">Land</label>
<p-select id="country" [options]="countries" [(ngModel)]="property().country" optionLabel="name" optionValue="code" placeholder="Select a country" class="w-full md:w-56">
<ng-template #selectedItem let-selectedOption>
@if (selectedOption) {
<div class="flex items-center gap-2">
<img
src="https://primefaces.org/cdn/primeng/images/demo/flag/flag_placeholder.png"
[class]="'flag flag-' + selectedOption.code.toLowerCase()"
style="width: 18px"
/>
<div>{{ selectedOption.name }}</div>
</div>
}
</ng-template>
<ng-template let-country #item>
<div class="flex items-center gap-2">
<img
src="https://primefaces.org/cdn/primeng/images/demo/flag/flag_placeholder.png"
[class]="'flag flag-' + country.code.toLowerCase()"
style="width: 18px"
/>
<div>{{ country.name }}</div>
</div>
</ng-template>
<ng-template #dropdownicon>
<i class="pi pi-map"></i>
</ng-template>
</p-select>
</div>
<!-- Notes -->
<div class="flex flex-col">
<label for="notes" class="block font-bold mb-3">Bemerkungen</label>
<p-editor #notes="ngModel"
[(ngModel)]="property().notes"
name="notes"
[style]="{ height: '320px' }">
</p-editor>
</div>
<!-- Uploads -->
@if (property().id) {
<div class="flex flex-col">
<p-fieldset i18n-legend legend="Anhänge" [toggleable]="true">
<div class="flex flex-wrap gap-2 mb-2">
@for (attachment of property().attachments; track attachment.id) {
<p-chip label="{{ attachment.fileName }}" icon="pi pi-file">
<p-button icon="pi pi-times" [rounded]="true" severity="danger" size="small" (click)="confirmRemoveAttachment($event, property(), attachment)"/>
</p-chip>
}
</div>
<p-fileupload name="attachments" url="{{ environment.apiBaseUrl }}/properties/{{ property().id }}/upload" (onUpload)="onUpload($event)" [multiple]="true" accept="image/*,.pdf" maxFileSize="1000000000" mode="advanced">
<ng-template #empty>
<div>Drag and drop files to here to upload.</div>
</ng-template>
</p-fileupload>
</p-fieldset>
</div>
}
</div>
</ng-template>
<ng-template #footer>
<p-button label="Abbrechen" icon="pi pi-times" text (click)="hideDialog()" />
<p-button label="Speichern" icon="pi pi-check" (click)="saveProperty()" />
</ng-template>
</p-dialog>
<p-confirmdialog [style]="{ width: '450px' }" />