420 lines
19 KiB
HTML
420 lines
19 KiB
HTML
<div class="card">
|
|
<p-toast />
|
|
<p-toolbar class="mb-6">
|
|
<ng-template #start>
|
|
<p-button label="New Vendor" icon="pi pi-plus" class="mr-2" (onClick)="openNew()" />
|
|
</ng-template>
|
|
|
|
<ng-template #end>
|
|
<p-button label="Export" icon="pi pi-upload" severity="secondary" (onClick)="exportCSV()" styleClass="mx-2" />
|
|
<p-button label="Refresh" icon="pi pi-refresh" severity="info" (onClick)="loadAllVendors()" />
|
|
</ng-template>
|
|
</p-toolbar>
|
|
|
|
<p-table
|
|
#dt
|
|
[value]="isLoading ? skeletonData : vendors"
|
|
[rows]="10"
|
|
[columns]="cols"
|
|
[paginator]="true"
|
|
[globalFilterFields]="['name', 'code', 'panNo', 'msmeNo']"
|
|
[tableStyle]="{ 'min-width': '75rem' }"
|
|
[(selection)]="selectedVendors"
|
|
[rowHover]="true"
|
|
dataKey="id"
|
|
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"
|
|
[showCurrentPageReport]="true"
|
|
>
|
|
<ng-template #caption>
|
|
<div class="flex justify-content-between align-items-center">
|
|
<h4 class="m-0">Manage Vendors</h4>
|
|
<p-iconfield>
|
|
<p-inputicon class="pi pi-search" />
|
|
<input pInputText type="text" (input)="onSearch($event)" placeholder="Search..." />
|
|
</p-iconfield>
|
|
</div>
|
|
</ng-template>
|
|
<ng-template #header>
|
|
<tr>
|
|
<th style="width: 3rem">#</th>
|
|
<th style="min-width: 5rem">Code</th>
|
|
<th pSortableColumn="name">
|
|
<div class="flex items-center gap-2">
|
|
Name
|
|
<p-sortIcon field="name" />
|
|
</div>
|
|
</th>
|
|
<th pSortableColumn="panNo" style="min-width: 10rem">
|
|
<div class="flex items-center gap-2">
|
|
PAN No.
|
|
<p-sortIcon field="panNo" />
|
|
</div>
|
|
</th>
|
|
<th pSortableColumn="msmeNo" style="min-width: 10rem">
|
|
<div class="flex items-center gap-2">
|
|
MSME No.
|
|
<p-sortIcon field="msmeNo" />
|
|
</div>
|
|
</th>
|
|
<th pSortableColumn="updatedAt" style="width: 13rem">
|
|
<div class="flex items-center gap-2">
|
|
Updated At
|
|
<p-sortIcon field="updatedAt" />
|
|
</div>
|
|
</th>
|
|
<th pSortableColumn="updatedUser" style="min-width: 12rem">
|
|
<div class="flex items-center gap-2">
|
|
Updated By
|
|
<p-sortIcon field="updatedUser" />
|
|
</div>
|
|
</th>
|
|
<th pSortableColumn="active" style="width: 4rem">
|
|
<div class="flex items-center gap-2">
|
|
Status
|
|
<p-sortIcon field="active" />
|
|
</div>
|
|
</th>
|
|
<th style="min-width: 8rem"></th>
|
|
</tr>
|
|
</ng-template>
|
|
<ng-template #body let-vendor let-rowIndex="rowIndex">
|
|
<tr *ngIf="!isLoading">
|
|
<td>{{ rowIndex + 1 }}</td>
|
|
<td style="width: 5rem">{{ vendor.code }}</td>
|
|
<td>{{ vendor.name }}</td>
|
|
<td>{{ vendor.panNo || '-' }}</td>
|
|
<td>{{ vendor.msmeNo || '-' }}</td>
|
|
<td>{{ vendor.updatedAt | date:'dd/MM/yyyy HH:mm:ss' }}</td>
|
|
<td>
|
|
<span *ngIf="vendor.updatedUser; else noUpdatedUser">
|
|
{{ vendor.updatedUser }}
|
|
</span>
|
|
<ng-template #noUpdatedUser>
|
|
<em class="text-500 ">Not Available</em>
|
|
</ng-template>
|
|
</td>
|
|
<td>
|
|
<p-tag [value]="vendor.active ? 'Active' : 'Inactive'" [severity]="getSeverity(vendor.active)" />
|
|
</td>
|
|
<td>
|
|
<p-button icon="pi pi-pencil" class="mr-2" [rounded]="true" [outlined]="true" (click)="editVendor(vendor)" />
|
|
<p-button [icon]="vendor.active ? 'pi pi-ban' : 'pi pi-check'" [severity]="vendor.active ? 'danger' : 'success'" [rounded]="true" [outlined]="true" (click)="toggleActive(vendor)" />
|
|
</td>
|
|
</tr>
|
|
<tr *ngIf="isLoading">
|
|
<td><p-skeleton width="2rem" height="1.5rem"></p-skeleton></td>
|
|
<td><p-skeleton width="4rem" height="1.5rem"></p-skeleton></td>
|
|
<td><p-skeleton width="10rem" height="1.5rem"></p-skeleton></td>
|
|
<td><p-skeleton width="8rem" height="1.5rem"></p-skeleton></td>
|
|
<td><p-skeleton width="8rem" height="1.5rem"></p-skeleton></td>
|
|
<td><p-skeleton width="10rem" height="1.5rem"></p-skeleton></td>
|
|
<td><p-skeleton width="8rem" height="1.5rem"></p-skeleton></td>
|
|
<td><p-skeleton width="4rem" height="1.5rem"></p-skeleton></td>
|
|
<td><p-skeleton width="2rem" height="1.5rem"></p-skeleton></td>
|
|
</tr>
|
|
</ng-template>
|
|
</p-table>
|
|
|
|
<!-- Vendor Dialog -->
|
|
<p-dialog [(visible)]="vendorDialog" [style]="{'width': '70vw'}" [breakpoints]="{ '960px': '85vw', '640px': '95vw' }" header="Vendor Details" [modal]="true">
|
|
<ng-template #content>
|
|
<div class="card p-3">
|
|
<form [formGroup]="vendorForm" class="mt-2">
|
|
<div class="grid mt-0">
|
|
<div class="col-12 md:col-3">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="code"
|
|
pInputText
|
|
formControlName="code"
|
|
fluid
|
|
[class.p-invalid]="isFieldInvalid('code')"
|
|
pTooltip="{{ getErrorMessage('code') }}"
|
|
tooltipPosition="top"
|
|
autofocus
|
|
/>
|
|
<label for="code">Code <span class="text-red-500">*</span></label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-9">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="name"
|
|
pInputText
|
|
formControlName="name"
|
|
fluid
|
|
[class.p-invalid]="isFieldInvalid('name')"
|
|
pTooltip="{{ getErrorMessage('name') }}"
|
|
tooltipPosition="top"
|
|
/>
|
|
<label for="name">Vendor Name <span class="text-red-500">*</span></label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-4">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="panNo"
|
|
pInputText
|
|
formControlName="panNo"
|
|
fluid
|
|
[class.p-invalid]="isFieldInvalid('panNo')"
|
|
pTooltip="{{ getErrorMessage('panNo') }}"
|
|
tooltipPosition="top"
|
|
/>
|
|
<label for="panNo">PAN No.</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-4">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="cinNo"
|
|
pInputText
|
|
formControlName="cinNo"
|
|
fluid
|
|
[class.p-invalid]="isFieldInvalid('cinNo')"
|
|
pTooltip="{{ getErrorMessage('cinNo') }}"
|
|
tooltipPosition="top"
|
|
/>
|
|
<label for="cinNo">CIN No.</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-4">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="msmeNo"
|
|
pInputText
|
|
formControlName="msmeNo"
|
|
fluid
|
|
[class.p-invalid]="isFieldInvalid('msmeNo')"
|
|
pTooltip="{{ getErrorMessage('msmeNo') }}"
|
|
tooltipPosition="top"
|
|
/>
|
|
<label for="msmeNo">MSME No.</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="card mt-3 p-3">
|
|
<div class="flex justify-content-between align-items-center mb-3">
|
|
<h5 class="m-0">Vendor Branches</h5>
|
|
<p-button label="Add Branch" icon="pi pi-plus" size="small" (onClick)="openNewBranch()" />
|
|
</div>
|
|
|
|
<p-table [value]="currentVendorBranches" [scrollable]="true" scrollHeight="300px">
|
|
<ng-template #header>
|
|
<tr>
|
|
<th>Code</th>
|
|
<th>Name</th>
|
|
<th>City</th>
|
|
<th>State</th>
|
|
<th>Contact No</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</ng-template>
|
|
<ng-template #body let-branch let-i="rowIndex">
|
|
<tr>
|
|
<td>{{ branch.branchCode }}</td>
|
|
<td>{{ branch.branchName }}</td>
|
|
<td>{{ branch.cityName }}</td>
|
|
<td>{{ branch.stateName }}</td>
|
|
<td>{{ branch.contactNo }}</td>
|
|
<td>
|
|
<p-button icon="pi pi-pencil" [text]="true" severity="info" (onClick)="editBranch(branch, i)" />
|
|
<p-button icon="pi pi-trash" [text]="true" severity="danger" (onClick)="deleteBranch(i)" />
|
|
</td>
|
|
</tr>
|
|
</ng-template>
|
|
<ng-template #emptymessage>
|
|
<tr>
|
|
<td colspan="6" class="text-center">No branches added yet.</td>
|
|
</tr>
|
|
</ng-template>
|
|
</p-table>
|
|
</div>
|
|
|
|
</ng-template>
|
|
|
|
<ng-template #footer>
|
|
<p-button label="Cancel" icon="pi pi-times" text (click)="hideDialog()" />
|
|
<p-button label="Save" icon="pi pi-check" (click)="saveVendor()" />
|
|
</ng-template>
|
|
</p-dialog>
|
|
|
|
<!-- Branch Dialog -->
|
|
<p-dialog [(visible)]="branchDialog" [style]="{'width': '50vw'}" [breakpoints]="{ '960px': '75vw', '640px': '90vw' }" header="Branch Details" [modal]="true">
|
|
<ng-template #content>
|
|
<form [formGroup]="branchForm" class="mt-2" autocomplete="off">
|
|
<div class="grid mt-0">
|
|
<div class="col-12 md:col-6">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="branchCode"
|
|
pInputText
|
|
formControlName="branchCode"
|
|
fluid
|
|
[class.p-invalid]="isFieldInvalid('branchCode', branchForm, submittedBranch)"
|
|
pTooltip="{{ getErrorMessage('branchCode', branchForm) }}"
|
|
tooltipPosition="top"
|
|
autofocus
|
|
/>
|
|
<label for="branchCode">Branch Code <span class="text-red-500">*</span></label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-6">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="branchName"
|
|
pInputText
|
|
formControlName="branchName"
|
|
fluid
|
|
[class.p-invalid]="isFieldInvalid('branchName', branchForm, submittedBranch)"
|
|
pTooltip="{{ getErrorMessage('branchName', branchForm) }}"
|
|
tooltipPosition="top"
|
|
/>
|
|
<label for="branchName">Branch Name <span class="text-red-500">*</span></label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-12">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="officeNo"
|
|
pInputText
|
|
formControlName="officeNo"
|
|
fluid
|
|
/>
|
|
<label for="officeNo">Office No., Floor, Building</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-6">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="street"
|
|
pInputText
|
|
formControlName="street"
|
|
fluid
|
|
/>
|
|
<label for="street">Street</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-6">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="locality"
|
|
pInputText
|
|
formControlName="locality"
|
|
fluid
|
|
/>
|
|
<label for="locality">Locality</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-6">
|
|
<p-floatlabel variant="on">
|
|
<p-autoComplete
|
|
id="cityName"
|
|
formControlName="cityName"
|
|
[suggestions]="branchSuggestions"
|
|
optionLabel="display"
|
|
[scrollHeight]="'160px'"
|
|
appendTo="body"
|
|
(completeMethod)="searchBranchCities($event)"
|
|
(onSelect)="onSelectBranchCity($event)"
|
|
fluid
|
|
/>
|
|
<label for="cityName">City</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-6">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="stateName"
|
|
pInputText
|
|
formControlName="stateName"
|
|
fluid
|
|
/>
|
|
<label for="stateName">State</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-6">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="pinCode"
|
|
pInputText
|
|
formControlName="pinCode"
|
|
fluid
|
|
[class.p-invalid]="isFieldInvalid('pinCode', branchForm, submittedBranch)"
|
|
pTooltip="{{ getErrorMessage('pinCode', branchForm) }}"
|
|
tooltipPosition="top"
|
|
/>
|
|
<label for="pinCode">Pincode</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-6">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="emailId"
|
|
pInputText
|
|
formControlName="emailId"
|
|
fluid
|
|
[class.p-invalid]="isFieldInvalid('emailId', branchForm, submittedBranch)"
|
|
pTooltip="{{ getErrorMessage('emailId', branchForm) }}"
|
|
tooltipPosition="top"
|
|
/>
|
|
<label for="emailId">Email ID</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-6">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="contactNo"
|
|
pInputText
|
|
formControlName="contactNo"
|
|
fluid
|
|
[class.p-invalid]="isFieldInvalid('contactNo', branchForm, submittedBranch)"
|
|
pTooltip="{{ getErrorMessage('contactNo', branchForm) }}"
|
|
tooltipPosition="top"
|
|
/>
|
|
<label for="contactNo">Contact No.</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-6">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="contactPerson"
|
|
pInputText
|
|
formControlName="contactPerson"
|
|
fluid
|
|
[class.p-invalid]="isFieldInvalid('contactPerson', branchForm, submittedBranch)"
|
|
pTooltip="{{ getErrorMessage('contactPerson', branchForm) }}"
|
|
tooltipPosition="top"
|
|
/>
|
|
<label for="contactPerson">Contact Person</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
<div class="col-12 md:col-6">
|
|
<p-floatlabel variant="on">
|
|
<input
|
|
id="gstNo"
|
|
pInputText
|
|
formControlName="gstNo"
|
|
fluid
|
|
[class.p-invalid]="isFieldInvalid('gstNo', branchForm, submittedBranch)"
|
|
pTooltip="{{ getErrorMessage('gstNo', branchForm) || 'Example: 22AAAAA0000A1Z5' }}"
|
|
tooltipPosition="top"
|
|
/>
|
|
<label for="gstNo">GST No.</label>
|
|
</p-floatlabel>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</ng-template>
|
|
<ng-template #footer>
|
|
<p-button label="Cancel" icon="pi pi-times" text (click)="hideBranchDialog()" />
|
|
<p-button label="Save Branch" icon="pi pi-check" (click)="saveBranch()" />
|
|
</ng-template>
|
|
</p-dialog>
|
|
|
|
<p-confirmDialog [style]="{ width: '450px' }" />
|
|
</div>
|