feat: add refresh functionality to various components
- Implemented refresh event emission in multiple list components across partner and superAdmin modules. - Updated consumers and customers list components to handle refresh actions. - Enhanced dashboard component to fetch partner info on initialization. - Introduced new API method in PartnerService to retrieve current partner data. - Modified PartnerStore to utilize the new API method for fetching partner information. - Updated UI elements to reflect changes in partner and license management, including new fields for license renewals. - Added a new POS display component for better presentation of POS terminal information. - Updated layout service and top bar to reflect new titles and improve user experience. - Refactored existing components to ensure consistency and maintainability.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
export * from './pos-display';
|
||||
@@ -0,0 +1,133 @@
|
||||
# POS Display Component
|
||||
|
||||
A reusable component for displaying Point-of-Sale (POS) terminal information with configurable variants.
|
||||
|
||||
## Overview
|
||||
|
||||
The `PosDisplayComponent` displays POS entity information in a card-based layout with support for different visibility variants ('consumer', 'partner', 'full').
|
||||
|
||||
## Features
|
||||
|
||||
- **Variant Support**: Choose from 'consumer', 'partner', or 'full' display modes
|
||||
- **Conditional Field Visibility**: Fields are dynamically shown/hidden based on variant
|
||||
- **Edit Mode**: Toggle between view and edit modes
|
||||
- **Responsive Grid**: Displays up to 3 columns with gap-4 spacing
|
||||
- **More Actions**: Optional button for additional actions
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```typescript
|
||||
import { PosDisplayComponent, IPosEntity } from '@/app/components';
|
||||
|
||||
@Component({
|
||||
selector: 'app-my-component',
|
||||
template: `
|
||||
<app-pos-display
|
||||
variant="consumer"
|
||||
[pos]="posData"
|
||||
[editMode]="isEditing"
|
||||
(onMoreAction)="handleMoreAction()"
|
||||
(editModeChange)="editModeChange($event)"
|
||||
/>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [PosDisplayComponent],
|
||||
})
|
||||
export class MyComponent {
|
||||
posData = signal<IPosEntity>({
|
||||
id: '123',
|
||||
name: 'Terminal 1',
|
||||
pos_type: 'PSP',
|
||||
serial_number: 'SN123',
|
||||
model: 'Model X',
|
||||
status: 'active',
|
||||
complex: { id: 'c1', name: 'Complex 1' },
|
||||
device: { id: 'd1', name: 'Device A' },
|
||||
provider: { id: 'p1', name: 'Provider A' },
|
||||
});
|
||||
|
||||
isEditing = signal(false);
|
||||
|
||||
handleMoreAction(): void {
|
||||
console.log('More action clicked');
|
||||
}
|
||||
|
||||
editModeChange(editing: boolean): void {
|
||||
this.isEditing.set(editing);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Variants
|
||||
|
||||
### Consumer Variant
|
||||
Displays: name, pos_type, serial_number, device, model, provider (6 fields)
|
||||
|
||||
### Partner Variant
|
||||
Displays: name, pos_type, serial_number (3 fields)
|
||||
|
||||
### Full Variant
|
||||
Displays: name, pos_type, serial_number, device, model, provider (6 fields - same as consumer)
|
||||
|
||||
## Inputs
|
||||
|
||||
| Input | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `variant` | 'consumer' \| 'partner' \| 'full' | 'full' | Display variant mode |
|
||||
| `pos` | Signal<IPosEntity \| undefined> | undefined | POS entity data |
|
||||
| `editMode` | Signal<boolean> | false | Edit mode state |
|
||||
| `cardTitle` | string | 'اطلاعات پایانهی فروش' | Card header title |
|
||||
| `showMoreActions` | boolean | true | Show more actions button |
|
||||
|
||||
## Outputs
|
||||
|
||||
| Output | Payload | Description |
|
||||
|--------|---------|-------------|
|
||||
| `editModeChange` | boolean | Emitted when edit mode toggled |
|
||||
| `onMoreAction` | void | Emitted when more actions button clicked |
|
||||
| `onSubmit` | void | Emitted on form submission |
|
||||
|
||||
## Model (IPosEntity)
|
||||
|
||||
```typescript
|
||||
interface IPosEntity {
|
||||
id: string;
|
||||
name: string;
|
||||
serial_number: string;
|
||||
model?: string;
|
||||
status: string;
|
||||
pos_type: string;
|
||||
complex: ISummary;
|
||||
device?: ISummary;
|
||||
provider?: ISummary;
|
||||
}
|
||||
```
|
||||
|
||||
## Integration in Existing Component
|
||||
|
||||
To replace the inline display in your POS single view:
|
||||
|
||||
```typescript
|
||||
// Before: Manual field rendering
|
||||
<app-key-value label="عنوان" [value]="pos()?.name" />
|
||||
<app-key-value label="نوع پایانه" [value]="pos()?.pos_type" />
|
||||
// ... more fields
|
||||
|
||||
// After: Use the component
|
||||
<app-pos-display
|
||||
variant="full"
|
||||
[pos]="pos"
|
||||
[editMode]="editMode"
|
||||
(onMoreAction)="toPosLanding()"
|
||||
/>
|
||||
```
|
||||
|
||||
## Files
|
||||
|
||||
- `pos-display.component.ts` - Component logic
|
||||
- `pos-display.component.html` - Template
|
||||
- `pos-display.component.scss` - Styles
|
||||
- `models/posEntity.model.ts` - TypeScript interfaces and types
|
||||
- `index.ts` - Barrel export
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './models/posEntity.model';
|
||||
export * from './pos-display.component';
|
||||
@@ -0,0 +1,27 @@
|
||||
import ISummary from '@/core/models/summary';
|
||||
|
||||
export type PosVariant = 'consumer' | 'partner' | 'full';
|
||||
|
||||
export interface IPosEntity {
|
||||
id: string;
|
||||
name: string;
|
||||
serial_number: string;
|
||||
model?: string;
|
||||
status: string;
|
||||
pos_type: string;
|
||||
complex: ISummary;
|
||||
device?: ISummary;
|
||||
provider?: ISummary;
|
||||
}
|
||||
|
||||
export interface IPosDisplayConfig {
|
||||
variant: PosVariant;
|
||||
editable?: boolean;
|
||||
showMoreActions?: boolean;
|
||||
}
|
||||
|
||||
export const POS_VARIANT_FIELDS: Record<PosVariant, Array<keyof IPosEntity>> = {
|
||||
consumer: ['name', 'pos_type', 'serial_number', 'device', 'model', 'provider'],
|
||||
partner: ['name', 'pos_type', 'serial_number'],
|
||||
full: ['name', 'pos_type', 'serial_number', 'device', 'model', 'provider'],
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
<app-card-data [cardTitle]="cardTitle" [editable]="true" [editMode]="isEditing()" (editModeChange)="toggleEditMode()">
|
||||
<ng-template #moreActions>
|
||||
@if (showMoreActions) {
|
||||
<p-button type="button" variant="outlined" (onClick)="handleMoreAction()"> ورود به پایانه </p-button>
|
||||
}
|
||||
</ng-template>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="grid grid-cols-3 gap-4 items-center">
|
||||
@for (field of visibleFields(); track field) {
|
||||
@if (isFieldVisible(field)) {
|
||||
<app-key-value [label]="fieldLabels[field]" [value]="getFieldValue(field)" />
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</app-card-data>
|
||||
@@ -0,0 +1,78 @@
|
||||
import { AppCardComponent, KeyValueComponent } from '@/shared/components';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, effect, EventEmitter, Input, Output, signal } from '@angular/core';
|
||||
import { Button } from 'primeng/button';
|
||||
import { IPosEntity, POS_VARIANT_FIELDS, PosVariant } from './models/posEntity.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-pos-entity-display',
|
||||
standalone: true,
|
||||
imports: [CommonModule, AppCardComponent, Button, KeyValueComponent],
|
||||
templateUrl: './pos-display.component.html',
|
||||
})
|
||||
export class PosDisplayComponent {
|
||||
@Input() variant: PosVariant = 'full';
|
||||
@Input() pos = signal<IPosEntity | undefined>(undefined);
|
||||
@Input() editMode = signal<boolean>(false);
|
||||
@Input() cardTitle = 'اطلاعات پایانهی فروش';
|
||||
@Input() showMoreActions = true;
|
||||
|
||||
@Output() editModeChange = new EventEmitter<boolean>();
|
||||
@Output() onMoreAction = new EventEmitter<void>();
|
||||
@Output() onSubmit = new EventEmitter<void>();
|
||||
|
||||
visibleFields = signal<Array<keyof IPosEntity>>([]);
|
||||
isEditing = signal<boolean>(false);
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
this.visibleFields.set(POS_VARIANT_FIELDS[this.variant] || POS_VARIANT_FIELDS.full);
|
||||
});
|
||||
|
||||
effect(() => {
|
||||
this.isEditing.set(this.editMode());
|
||||
});
|
||||
}
|
||||
|
||||
get fieldLabels(): Record<string, string> {
|
||||
return {
|
||||
name: 'عنوان',
|
||||
pos_type: 'نوع پایانه',
|
||||
serial_number: 'شماره سریال',
|
||||
device: 'نوع دستگاه',
|
||||
model: 'مدل دستگاه',
|
||||
provider: 'ارایهدهنده',
|
||||
};
|
||||
}
|
||||
|
||||
isFieldVisible(field: keyof IPosEntity): boolean {
|
||||
return this.visibleFields().includes(field);
|
||||
}
|
||||
|
||||
getFieldValue(field: keyof IPosEntity): any {
|
||||
const posData = this.pos();
|
||||
if (!posData) return null;
|
||||
|
||||
if (field === 'device' && posData.device) {
|
||||
return posData.device.name;
|
||||
}
|
||||
if (field === 'provider' && posData.provider) {
|
||||
return posData.provider.name;
|
||||
}
|
||||
return posData[field];
|
||||
}
|
||||
|
||||
toggleEditMode(): void {
|
||||
const newMode = !this.isEditing();
|
||||
this.isEditing.set(newMode);
|
||||
this.editModeChange.emit(newMode);
|
||||
}
|
||||
|
||||
handleMoreAction(): void {
|
||||
this.onMoreAction.emit();
|
||||
}
|
||||
|
||||
handleSubmit(): void {
|
||||
this.onSubmit.emit();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user