Initial commit
This commit is contained in:
252
src/app/pages/property-manager/property-manager.html
Normal file
252
src/app/pages/property-manager/property-manager.html
Normal file
@@ -0,0 +1,252 @@
|
||||
<p-toolbar styleClass="mb-6">
|
||||
<ng-template #start>
|
||||
<p-button i18n-label label="Neu" icon="pi pi-plus" severity="secondary" class="mr-2" (onClick)="openNew()" />
|
||||
<p-button i18n-label label="Löschen" icon="pi pi-trash" severity="danger" outlined (onClick)="deleteSelected()" [disabled]="!selectedProperties || !selectedProperties.length" />
|
||||
</ng-template>
|
||||
|
||||
<ng-template #end>
|
||||
<p-button i18n-label 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" i18n>Verwalte Liegenschaften</h5>
|
||||
<p-iconfield>
|
||||
<p-inputicon styleClass="pi pi-search" />
|
||||
<input pInputText type="text" (input)="onGlobalFilter(dt, $event)" i18n-placeholder 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" i18n>
|
||||
Nr.
|
||||
<p-sortIcon field="nr" />
|
||||
</th>
|
||||
<th pSortableColumn="name" style="min-width:8rem" i18n>
|
||||
Name
|
||||
<p-sortIcon field="name" />
|
||||
</th>
|
||||
<th pSortableColumn="owner" style="min-width:8rem" i18n>
|
||||
Eigentümer
|
||||
<p-sortIcon field="owner" />
|
||||
</th>
|
||||
<th pSortableColumn="street" style="min-width: 8rem" i18n>
|
||||
Straße
|
||||
<p-sortIcon field="street" />
|
||||
</th>
|
||||
<th pSortableColumn="houseNumber" style="min-width:8rem" i18n>
|
||||
Hausnummer
|
||||
<p-sortIcon field="houseNumber" />
|
||||
</th>
|
||||
<th pSortableColumn="zipCode" style="min-width: 12rem" i18n>
|
||||
Postleitzahl
|
||||
<p-sortIcon field="zipCode" />
|
||||
</th>
|
||||
<th pSortableColumn="city" style="min-width: 12rem" i18n>
|
||||
Stadt
|
||||
<p-sortIcon field="city" />
|
||||
</th>
|
||||
<th pSortableColumn="bundesland" style="min-width:8rem" i18n>
|
||||
Bundesland
|
||||
<p-sortIcon field="bundesland" />
|
||||
</th>
|
||||
<th pSortableColumn="Einheiten" style="min-width:8rem" i18n>
|
||||
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 i18n-label label="Abbrechen" icon="pi pi-times" text (click)="hideDialog()" />
|
||||
<p-button i18n-label label="Speichern" icon="pi pi-check" (click)="saveProperty()" />
|
||||
</ng-template>
|
||||
</p-dialog>
|
||||
|
||||
<p-confirmdialog [style]="{ width: '450px' }" />
|
||||
Reference in New Issue
Block a user