pf2tw
This commit is contained in:
@@ -37,207 +37,205 @@ import { Product, ProductService } from '@/src/service/product.service';
|
||||
InputNumberModule,
|
||||
DialogModule
|
||||
],
|
||||
template: `<div class="grid">
|
||||
<div class="col-12">
|
||||
<div class="card px-6 py-6">
|
||||
<p-toast></p-toast>
|
||||
<p-toolbar styleClass="mb-4">
|
||||
<ng-template #left>
|
||||
<div class="my-2">
|
||||
<button pButton pRipple severity="success" class="mr-2" (click)="openNew()">
|
||||
<i pButtonIcon class="pi plus mr-2"></i>
|
||||
<span pButtonLabel>New</span>
|
||||
</button>
|
||||
<button pButton pRipple severity="danger" (click)="deleteSelectedProducts()" [disabled]="!selectedProducts || !selectedProducts.length">
|
||||
<i pButtonIcon class="pi pi-trash mr-2"></i>
|
||||
<span pButtonLabel>Delete</span>
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
template: `
|
||||
<div>
|
||||
<div class="card">
|
||||
<p-toast></p-toast>
|
||||
<p-toolbar styleClass="mb-6">
|
||||
<ng-template #left>
|
||||
<div class="my-2">
|
||||
<button pButton pRipple severity="success" class="mr-2" (click)="openNew()">
|
||||
<i pButtonIcon class="pi plus mr-2"></i>
|
||||
<span pButtonLabel>New</span>
|
||||
</button>
|
||||
<button pButton pRipple severity="danger" (click)="deleteSelectedProducts()" [disabled]="!selectedProducts || !selectedProducts.length">
|
||||
<i pButtonIcon class="pi pi-trash mr-2"></i>
|
||||
<span pButtonLabel>Delete</span>
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #right>
|
||||
<p-fileupload mode="basic" accept="image/*" [maxFileSize]="1000000" label="Import" chooseLabel="Import" class="mr-2 inline-block"></p-fileupload>
|
||||
<button pButton pRipple severity="help" (click)="dt.exportCSV()">
|
||||
<i pButtonIcon class="pi upload"></i>
|
||||
<span pButtonLabel>Export</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</p-toolbar>
|
||||
|
||||
<p-table #dt [value]="products" [columns]="cols" responsiveLayout="scroll" [rows]="10" [globalFilterFields]="['name','country.name','representative.name','status']" [paginator]="true" [rowsPerPageOptions]="[10,20,30]" [showCurrentPageReport]="true" currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries" [(selection)]="selectedProducts" selectionMode="multiple" [rowHover]="true" dataKey="id">
|
||||
<ng-template #caption>
|
||||
<div class="flex flex-column md:flex-row md:justify-content-between md:align-items-center">
|
||||
<h5 class="m-0">Manage Products</h5>
|
||||
<span class="block mt-2 md:mt-0 p-input-icon-left">
|
||||
<ng-template #right>
|
||||
<p-fileupload mode="basic" accept="image/*" [maxFileSize]="1000000" label="Import" chooseLabel="Import" class="mr-2 inline-block"></p-fileupload>
|
||||
<button pButton pRipple severity="help" (click)="dt.exportCSV()">
|
||||
<i pButtonIcon class="pi upload"></i>
|
||||
<span pButtonLabel>Export</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</p-toolbar>
|
||||
<p-table #dt [value]="products" [columns]="cols" responsiveLayout="scroll" [rows]="10" [globalFilterFields]="['name','country.name','representative.name','status']" [paginator]="true" [rowsPerPageOptions]="[10,20,30]" [showCurrentPageReport]="true" currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries" [(selection)]="selectedProducts" selectionMode="multiple" [rowHover]="true" dataKey="id">
|
||||
<ng-template #caption>
|
||||
<div class="flex flex-col md:flex-row md:justify-between md:items-center">
|
||||
<h5 class="m-0">Manage Products</h5>
|
||||
<span class="block mt-2 md:mt-0 p-input-icon-left">
|
||||
<i class="pi pi-search"></i>
|
||||
<input pInputText type="text" (input)="onGlobalFilter(dt, $event)" placeholder="Search..." class="w-full sm:w-auto"/>
|
||||
</span>
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template #header>
|
||||
<tr>
|
||||
<th style="width: 3rem">
|
||||
<p-tableHeaderCheckbox></p-tableHeaderCheckbox>
|
||||
</th>
|
||||
<th pSortableColumn="code">Code <p-sortIcon field="code"></p-sortIcon></th>
|
||||
<th pSortableColumn="name">Name <p-sortIcon field="name"></p-sortIcon></th>
|
||||
<th>Image</th>
|
||||
<th pSortableColumn="price">Price <p-sortIcon field="price"></p-sortIcon></th>
|
||||
<th pSortableColumn="category">Category <p-sortIcon field="category"></p-sortIcon></th>
|
||||
<th pSortableColumn="rating">Reviews <p-sortIcon field="rating"></p-sortIcon></th>
|
||||
<th pSortableColumn="inventoryStatus">Status <p-sortIcon field="inventoryStatus"></p-sortIcon></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template #body let-product>
|
||||
<tr>
|
||||
<td>
|
||||
<p-tableCheckbox [value]="product"></p-tableCheckbox>
|
||||
</td>
|
||||
<td style="width:14%; min-width:10rem;"><span class="p-column-title">Code</span>
|
||||
{{product.code || product.id}}
|
||||
</td>
|
||||
<td style="width:14%; min-width:10rem;">
|
||||
<span class="p-column-title">Name</span>
|
||||
{{product.name}}
|
||||
</td>
|
||||
<td style="width:14%; min-width:10rem;"><span class="p-column-title">Image</span>
|
||||
<img [src]="'assets/demo/images/product/' + product.image" [alt]="product.name" width="100" class="shadow-4" />
|
||||
</td>
|
||||
<td style="width:14%; min-width:8rem;">
|
||||
<span class="p-column-title">Price</span>
|
||||
{{product.price | currency:'USD'}}
|
||||
</td>
|
||||
<td style="width:14%; min-width:10rem;">
|
||||
<span class="p-column-title">Category</span>
|
||||
{{product.category}}
|
||||
</td>
|
||||
<td style="width:14%; min-width: 10rem;"><span class="p-column-title">Reviews</span>
|
||||
<p-rating [ngModel]="product.rating" [readonly]="true"></p-rating>
|
||||
</td>
|
||||
<td style="width:14%; min-width: 10rem;"><span class="p-column-title">Status</span>
|
||||
<span [class]="'product-badge status-' + (product.inventoryStatus ? product.inventoryStatus.toLowerCase() : '')">{{product.inventoryStatus}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex">
|
||||
<button pButton pRipple severity="success" [rounded]="true" class="mr-2" (click)="editProduct(product)">
|
||||
<i pButtonIcon class="pi pi-pencil"></i>
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template #header>
|
||||
<tr>
|
||||
<th style="width: 3rem">
|
||||
<p-tableHeaderCheckbox></p-tableHeaderCheckbox>
|
||||
</th>
|
||||
<th pSortableColumn="code">Code <p-sortIcon field="code"></p-sortIcon></th>
|
||||
<th pSortableColumn="name">Name <p-sortIcon field="name"></p-sortIcon></th>
|
||||
<th>Image</th>
|
||||
<th pSortableColumn="price">Price <p-sortIcon field="price"></p-sortIcon></th>
|
||||
<th pSortableColumn="category">Category <p-sortIcon field="category"></p-sortIcon></th>
|
||||
<th pSortableColumn="rating">Reviews <p-sortIcon field="rating"></p-sortIcon></th>
|
||||
<th pSortableColumn="inventoryStatus">Status <p-sortIcon field="inventoryStatus"></p-sortIcon></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template #body let-product>
|
||||
<tr>
|
||||
<td>
|
||||
<p-tableCheckbox [value]="product"></p-tableCheckbox>
|
||||
</td>
|
||||
<td style="width:14%; min-width:10rem;"><span class="p-column-title">Code</span>
|
||||
{{product.code || product.id}}
|
||||
</td>
|
||||
<td style="width:14%; min-width:10rem;">
|
||||
<span class="p-column-title">Name</span>
|
||||
{{product.name}}
|
||||
</td>
|
||||
<td style="width:14%; min-width:10rem;"><span class="p-column-title">Image</span>
|
||||
<img [src]="'assets/demo/images/product/' + product.image" [alt]="product.name" width="100" class="shadow-lg" />
|
||||
</td>
|
||||
<td style="width:14%; min-width:8rem;">
|
||||
<span class="p-column-title">Price</span>
|
||||
{{product.price | currency:'USD'}}
|
||||
</td>
|
||||
<td style="width:14%; min-width:10rem;">
|
||||
<span class="p-column-title">Category</span>
|
||||
{{product.category}}
|
||||
</td>
|
||||
<td style="width:14%; min-width: 10rem;"><span class="p-column-title">Reviews</span>
|
||||
<p-rating [ngModel]="product.rating" [readonly]="true"></p-rating>
|
||||
</td>
|
||||
<td style="width:14%; min-width: 10rem;"><span class="p-column-title">Status</span>
|
||||
<span [class]="'product-badge status-' + (product.inventoryStatus ? product.inventoryStatus.toLowerCase() : '')">{{product.inventoryStatus}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex">
|
||||
<button pButton pRipple severity="success" [rounded]="true" class="mr-2" (click)="editProduct(product)">
|
||||
<i pButtonIcon class="pi pi-pencil"></i>
|
||||
</button>
|
||||
<button pButton pRipple severity="warn" [rounded]="true" (click)="deleteProduct(product)">
|
||||
<i pButtonIcon class="pi pi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
</div>
|
||||
|
||||
<p-dialog [(visible)]="productDialog" [style]="{width: '450px'}" header="Product Details" [modal]="true" class="p-fluid">
|
||||
<ng-template #content>
|
||||
<img [src]="'assets/demo/images/product/' + product.image" [alt]="product.image" width="150" class="mt-0 mx-auto mb-8 block shadow" *ngIf="product.image">
|
||||
<div class="field">
|
||||
<label for="name">Name</label>
|
||||
<input type="text" pInputText id="name" [(ngModel)]="product.name" required autofocus [ngClass]="{'ng-invalid ng-dirty' : submitted && !product.name}"/>
|
||||
<small class="ng-dirty ng-invalid" *ngIf="submitted && !product.name">Name is required.</small>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="description">Description</label>
|
||||
<textarea id="description" pTextarea [(ngModel)]="product.description" required rows="3" cols="20"></textarea>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="status">Inventory Status</label>
|
||||
<p-select [(ngModel)]="product.inventoryStatus" inputId="inventoryStatus" optionValue="label" [options]="statuses" placeholder="Select">
|
||||
<ng-template #selectedItem>
|
||||
<span *ngIf="product && product.inventoryStatus" [class]="'product-badge status-' + product.inventoryStatus.toString().toLowerCase()">{{product.inventoryStatus}}</span>
|
||||
</ng-template>
|
||||
<ng-template let-option #item>
|
||||
<span [class]="'product-badge status-' + option.value">{{option.label}}</span>
|
||||
</ng-template>
|
||||
</p-select>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="mb-4">Category</label>
|
||||
<div class="formgrid grid grid-cols-12 gap-4">
|
||||
<div class="field-radiobutton col-span-6">
|
||||
<p-radiobutton id="category1" name="category" value="Accessories" [(ngModel)]="product.category"></p-radiobutton>
|
||||
<label for="category1">Accessories</label>
|
||||
</div>
|
||||
<div class="field-radiobutton col-span-6">
|
||||
<p-radiobutton id="category2" name="category" value="Clothing" [(ngModel)]="product.category"></p-radiobutton>
|
||||
<label for="category2">Clothing</label>
|
||||
</div>
|
||||
<div class="field-radiobutton col-span-6">
|
||||
<p-radiobutton id="category3" name="category" value="Electronics" [(ngModel)]="product.category"></p-radiobutton>
|
||||
<label for="category3">Electronics</label>
|
||||
</div>
|
||||
<div class="field-radiobutton col-span-6">
|
||||
<p-radiobutton id="category4" name="category" value="Fitness" [(ngModel)]="product.category"></p-radiobutton>
|
||||
<label for="category4">Fitness</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="formgrid grid grid-cols-12 gap-4">
|
||||
<div class="field col">
|
||||
<label for="price">Price</label>
|
||||
<p-inputnumber id="price" [(ngModel)]="product.price" mode="currency" currency="USD" locale="en-US"></p-inputnumber>
|
||||
</div>
|
||||
<div class="field col">
|
||||
<label for="quantity">Quantity</label>
|
||||
<p-inputnumber id="quantity" [(ngModel)]="product.quantity"></p-inputnumber>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #footer>
|
||||
<button pButton pRipple [text]="true" (click)="hideDialog()">
|
||||
<i pButtonIcon class="pi times mr-2"></i>
|
||||
<span pButtonLabel>Cancel</span>
|
||||
</button>
|
||||
<button pButton pRipple severity="warn" [rounded]="true" (click)="deleteProduct(product)">
|
||||
<i pButtonIcon class="pi pi-trash"></i>
|
||||
<button pButton pRipple [text]="true" (click)="saveProduct()">
|
||||
<i pButtonIcon class="pi pi-check mr-2"></i>
|
||||
<span pButtonLabel>Save</span>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
</ng-template>
|
||||
</p-dialog>
|
||||
|
||||
<p-dialog [(visible)]="deleteProductDialog" header="Confirm" [modal]="true" [style]="{width:'450px'}">
|
||||
<div class="flex items-center justify-center">
|
||||
<i class="pi pi-exclamation-triangle mr-4" style="font-size: 2rem"></i>
|
||||
<span *ngIf="product">Are you sure you want to delete <b>{{product.name}}</b>?</span>
|
||||
</div>
|
||||
<ng-template #footer>
|
||||
<button pButton pRipple [text]="true" (click)="deleteProductDialog = false">
|
||||
<i pButtonIcon class="pi pi-times mr-2"></i>
|
||||
<span pButtonLabel>No</span>
|
||||
</button>
|
||||
<button pButton pRipple [text]="true" (click)="confirmDelete()">
|
||||
<i pButtonIcon class="pi pi-check mr-2"></i>
|
||||
<span pButtonLabel>Yes</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</p-dialog>
|
||||
|
||||
<p-dialog [(visible)]="deleteProductsDialog" header="Confirm" [modal]="true" [style]="{width:'450px'}">
|
||||
<div class="flex items-center justify-center">
|
||||
<i class="pi pi-exclamation-triangle mr-4" style="font-size: 2rem"></i>
|
||||
<span>Are you sure you want to delete selected products?</span>
|
||||
</div>
|
||||
<ng-template #footer>
|
||||
<button pButton pRipple [text]="true" (click)="deleteProductsDialog = false">
|
||||
<i pButtonIcon class="pi pi-times mr-2"></i>
|
||||
<span pButtonLabel>No</span>
|
||||
</button>
|
||||
<button pButton pRipple [text]="true" (click)="confirmDeleteSelected()">
|
||||
<i pButtonIcon class="pi pi-check mr-2"></i>
|
||||
<span pButtonLabel>Yes</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</p-dialog>
|
||||
</div>
|
||||
|
||||
<p-dialog [(visible)]="productDialog" [style]="{width: '450px'}" header="Product Details" [modal]="true" class="p-fluid">
|
||||
<ng-template #content>
|
||||
<img [src]="'assets/demo/images/product/' + product.image" [alt]="product.image" width="150" class="mt-0 mx-auto mb-5 block shadow-2" *ngIf="product.image">
|
||||
<div class="field">
|
||||
<label for="name">Name</label>
|
||||
<input type="text" pInputText id="name" [(ngModel)]="product.name" required autofocus [ngClass]="{'ng-invalid ng-dirty' : submitted && !product.name}"/>
|
||||
<small class="ng-dirty ng-invalid" *ngIf="submitted && !product.name">Name is required.</small>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="description">Description</label>
|
||||
<textarea id="description" pTextarea [(ngModel)]="product.description" required rows="3" cols="20"></textarea>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="status">Inventory Status</label>
|
||||
<p-select [(ngModel)]="product.inventoryStatus" inputId="inventoryStatus" optionValue="label" [options]="statuses" placeholder="Select">
|
||||
<ng-template #selectedItem>
|
||||
<span *ngIf="product && product.inventoryStatus" [class]="'product-badge status-' + product.inventoryStatus.toString().toLowerCase()">{{product.inventoryStatus}}</span>
|
||||
</ng-template>
|
||||
<ng-template let-option #item>
|
||||
<span [class]="'product-badge status-' + option.value">{{option.label}}</span>
|
||||
</ng-template>
|
||||
</p-select>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="mb-3">Category</label>
|
||||
<div class="formgrid grid">
|
||||
<div class="field-radiobutton col-6">
|
||||
<p-radiobutton id="category1" name="category" value="Accessories" [(ngModel)]="product.category"></p-radiobutton>
|
||||
<label for="category1">Accessories</label>
|
||||
</div>
|
||||
<div class="field-radiobutton col-6">
|
||||
<p-radiobutton id="category2" name="category" value="Clothing" [(ngModel)]="product.category"></p-radiobutton>
|
||||
<label for="category2">Clothing</label>
|
||||
</div>
|
||||
<div class="field-radiobutton col-6">
|
||||
<p-radiobutton id="category3" name="category" value="Electronics" [(ngModel)]="product.category"></p-radiobutton>
|
||||
<label for="category3">Electronics</label>
|
||||
</div>
|
||||
<div class="field-radiobutton col-6">
|
||||
<p-radiobutton id="category4" name="category" value="Fitness" [(ngModel)]="product.category"></p-radiobutton>
|
||||
<label for="category4">Fitness</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="formgrid grid">
|
||||
<div class="field col">
|
||||
<label for="price">Price</label>
|
||||
<p-inputnumber id="price" [(ngModel)]="product.price" mode="currency" currency="USD" locale="en-US"></p-inputnumber>
|
||||
</div>
|
||||
<div class="field col">
|
||||
<label for="quantity">Quantity</label>
|
||||
<p-inputnumber id="quantity" [(ngModel)]="product.quantity"></p-inputnumber>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #footer>
|
||||
<button pButton pRipple [text]="true" (click)="hideDialog()">
|
||||
<i pButtonIcon class="pi times mr-2"></i>
|
||||
<span pButtonLabel>Cancel</span>
|
||||
</button>
|
||||
<button pButton pRipple [text]="true" (click)="saveProduct()">
|
||||
<i pButtonIcon class="pi pi-check mr-2"></i>
|
||||
<span pButtonLabel>Save</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</p-dialog>
|
||||
|
||||
<p-dialog [(visible)]="deleteProductDialog" header="Confirm" [modal]="true" [style]="{width:'450px'}">
|
||||
<div class="flex align-items-center justify-content-center">
|
||||
<i class="pi pi-exclamation-triangle mr-3" style="font-size: 2rem"></i>
|
||||
<span *ngIf="product">Are you sure you want to delete <b>{{product.name}}</b>?</span>
|
||||
</div>
|
||||
<ng-template #footer>
|
||||
<button pButton pRipple [text]="true" (click)="deleteProductDialog = false">
|
||||
<i pButtonIcon class="pi pi-times mr-2"></i>
|
||||
<span pButtonLabel>No</span>
|
||||
</button>
|
||||
<button pButton pRipple [text]="true" (click)="confirmDelete()">
|
||||
<i pButtonIcon class="pi pi-check mr-2"></i>
|
||||
<span pButtonLabel>Yes</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</p-dialog>
|
||||
|
||||
<p-dialog [(visible)]="deleteProductsDialog" header="Confirm" [modal]="true" [style]="{width:'450px'}">
|
||||
<div class="flex align-items-center justify-content-center">
|
||||
<i class="pi pi-exclamation-triangle mr-3" style="font-size: 2rem"></i>
|
||||
<span>Are you sure you want to delete selected products?</span>
|
||||
</div>
|
||||
<ng-template #footer>
|
||||
<button pButton pRipple [text]="true" (click)="deleteProductsDialog = false">
|
||||
<i pButtonIcon class="pi pi-times mr-2"></i>
|
||||
<span pButtonLabel>No</span>
|
||||
</button>
|
||||
<button pButton pRipple [text]="true" (click)="confirmDeleteSelected()">
|
||||
<i pButtonIcon class="pi pi-check mr-2"></i>
|
||||
<span pButtonLabel>Yes</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</p-dialog>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
providers: [MessageService]
|
||||
})
|
||||
@@ -261,8 +259,6 @@ export class Crud implements OnInit {
|
||||
|
||||
statuses: any[] = [];
|
||||
|
||||
rowsPerPageOptions = [5, 10, 20];
|
||||
|
||||
private messageService = inject(MessageService);
|
||||
|
||||
private productService = inject(ProductService);
|
||||
|
||||
Reference in New Issue
Block a user