feat: implement stock keeping unit management form and list components
- Added StockKeepingUnitFormComponent for creating and editing stock keeping units. - Introduced StockKeepingUnitsComponent for listing stock keeping units with pagination. - Integrated form fields for code, name, VAT, and SKU type in the stock keeping unit form. - Created API routes for stock keeping units with CRUD operations. - Updated input components to handle numeric and price types with Persian/Arabic digit normalization. - Enhanced key-value component to support tag display instead of badge. - Adjusted layout styles for sidebar menu. - Added AGENT.md for repository-specific coding guidelines and practices. - Implemented good management form with file upload and category selection.
This commit is contained in:
@@ -4,9 +4,10 @@ import { Maybe } from '../models';
|
||||
import { ToastService } from './toast.service';
|
||||
|
||||
interface INativeBridgeHost {
|
||||
pay?: ((payload: string) => unknown) | ((amount: number, id: Maybe<string>) => unknown);
|
||||
print?: (payload: string) => unknown;
|
||||
pay?: (amount: number, id: Maybe<string>) => unknown;
|
||||
print?: (payload: INativePrintRequest) => unknown;
|
||||
isEnabled?: () => boolean;
|
||||
getUUID?: () => Maybe<string>;
|
||||
}
|
||||
|
||||
export interface INativePayRequest {
|
||||
@@ -15,8 +16,11 @@ export interface INativePayRequest {
|
||||
}
|
||||
|
||||
export interface INativePrintRequest {
|
||||
invoiceId?: string;
|
||||
code?: string;
|
||||
title: string;
|
||||
items: {
|
||||
label: string;
|
||||
value: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface INativeBridgeResult<T = unknown> {
|
||||
@@ -31,15 +35,14 @@ export class NativeBridgeService {
|
||||
|
||||
private get host(): INativeBridgeHost | undefined {
|
||||
const globalWindow = window as unknown as {
|
||||
AndroidBridge?: INativeBridgeHost;
|
||||
Android?: INativeBridgeHost;
|
||||
AndroidPSP?: INativeBridgeHost;
|
||||
NativeBridge?: INativeBridgeHost;
|
||||
};
|
||||
|
||||
return globalWindow.AndroidPSP || globalWindow.AndroidBridge || globalWindow.Android;
|
||||
return globalWindow.NativeBridge;
|
||||
}
|
||||
|
||||
isEnabled(): boolean {
|
||||
if (!this.host) return false;
|
||||
const hostEnabled = this.host?.isEnabled;
|
||||
if (typeof hostEnabled === 'function') {
|
||||
try {
|
||||
@@ -60,27 +63,20 @@ export class NativeBridgeService {
|
||||
return this.isEnabled() && typeof this.host?.print === 'function';
|
||||
}
|
||||
|
||||
pay(request: INativePayRequest): INativeBridgeResult {
|
||||
pay(request: INativePayRequest): any {
|
||||
this.toastService.info({ text: 'در حال پردازش پرداخت...', life: 3000 });
|
||||
const fn = this.host?.pay;
|
||||
if (typeof fn !== 'function') {
|
||||
return { success: false, error: 'Native method "pay" is not available.' };
|
||||
this.toastService.error({ text: 'متاسفانه پرداخت امکانپذیر نیست.', life: 3000 });
|
||||
return { success: false, error: 'متاسفانه پرداخت امکانپذیر نیست.' };
|
||||
}
|
||||
|
||||
try {
|
||||
let raw: unknown;
|
||||
if (fn.length >= 2) {
|
||||
raw = (fn as (amount: number, id: Maybe<string>) => unknown)(request.amount, request.id);
|
||||
} else {
|
||||
raw = (fn as (payload: string) => unknown)(JSON.stringify(request));
|
||||
}
|
||||
fn(request.amount, request.id);
|
||||
|
||||
const parsed = this.tryParse(raw);
|
||||
if (parsed && typeof parsed === 'object' && 'success' in parsed) {
|
||||
return parsed as INativeBridgeResult;
|
||||
}
|
||||
return { success: true };
|
||||
|
||||
return { success: true, data: parsed ?? raw };
|
||||
// return { success: true, data: parsed ?? raw };
|
||||
} catch (error) {
|
||||
return { success: false, error: (error as Error).message };
|
||||
}
|
||||
@@ -90,25 +86,25 @@ export class NativeBridgeService {
|
||||
return this.invokePrint(request);
|
||||
}
|
||||
|
||||
private invokePrint(payload: object): INativeBridgeResult {
|
||||
private invokePrint(payload: INativePrintRequest): INativeBridgeResult {
|
||||
const fn = this.host?.print;
|
||||
if (typeof fn !== 'function') {
|
||||
return { success: false, error: 'Native method "print" is not available.' };
|
||||
return { success: false, error: 'متاسفانه چاپ امکانپذیر نیست.' };
|
||||
}
|
||||
|
||||
try {
|
||||
const raw = fn(JSON.stringify(payload));
|
||||
const parsed = this.tryParse(raw);
|
||||
if (parsed && typeof parsed === 'object' && 'success' in parsed) {
|
||||
return parsed as INativeBridgeResult;
|
||||
}
|
||||
fn(payload);
|
||||
|
||||
return { success: true, data: parsed ?? raw };
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
return { success: false, error: (error as Error).message };
|
||||
return { success: false, error: 'متاسفانه چاپ امکانپذیر نیست.' };
|
||||
}
|
||||
}
|
||||
|
||||
getNativeDeviceId(): Maybe<string> {
|
||||
return typeof this.host?.getUUID === 'function' ? this.host.getUUID!() : null;
|
||||
}
|
||||
|
||||
private tryParse(value: unknown): unknown {
|
||||
if (typeof value !== 'string') return value;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user