Files
OCR/frontend/src/app/pages/account/vendor/vendor.component.html
2026-05-21 21:33:37 +05:30

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>