This commit introduces the ability to fetch dropdown options asynchronously, enhancing the component's flexibility for large datasets or dynamic content. Key changes include: - **`fetchOptions` prop:** A new prop `fetchOptions` is added to allow external functions to provide options based on the current search query. - **Internal state for options:** `internalOptions` state is introduced to manage options, which can be populated either from the initial `options` prop or by `fetchOptions`. - **Loading state:** `isLoading` state is added to indicate when options are being fetched. - **Improved search handling:** The `handleSearchInputChange` function now triggers `fetchOptions` when available, allowing real-time filtering from an external source. - **Option type update:** The `Option` type now uses `name` instead of `label` for consistency. - **Selected option display:** The displayed selected option now uses `value` instead of `label` for consistency. These changes make the `BaseDropdown` component more robust and adaptable to various data sources, especially for scenarios requiring dynamic or remote option loading.
240 lines
6.4 KiB
TypeScript
240 lines
6.4 KiB
TypeScript
export enum FieldTypes {
|
||
رشته_عادی = 0,
|
||
رشته_فارسی = 1,
|
||
رشته_لاتین = 2,
|
||
رشته_چندخطی = 3,
|
||
عدد_صحیح = 4,
|
||
عدد_اعشاری = 5,
|
||
تاریخ = 6,
|
||
ساعت = 7,
|
||
پول = 8,
|
||
کدملی = 9,
|
||
تلفن_همراه = 10,
|
||
پلاک_ماشین = 11,
|
||
رایانامه = 12,
|
||
آدرس_پایگاه_اینترنتی = 13,
|
||
کشویی = 14,
|
||
رادیویی = 15,
|
||
چندانتخابی = 16,
|
||
تصویر = 17,
|
||
فایل = 18,
|
||
توضیحات = 19,
|
||
محاسباتی = 20,
|
||
فرآیند_والد = 21,
|
||
فرآیند_فرزند = 22,
|
||
ویرایشگر_پارسر = 23,
|
||
چارت_سازمانی = 24,
|
||
پلاک_خودرو = 25,
|
||
جستجوی_شخص = 26,
|
||
}
|
||
|
||
export interface FieldDefinition {
|
||
AllowNull: boolean;
|
||
CalculationField_Async: boolean;
|
||
CalculationField_IsFunctionOutput: boolean;
|
||
CalculationField_ReCalculateAfterSave: boolean;
|
||
|
||
Calculation_Formula: string;
|
||
Calculation_ParsedFormula: string;
|
||
Calculation_ParsedFormulaL2: string;
|
||
|
||
Child_OpenAgain: boolean;
|
||
Child_ProcessID: number;
|
||
Child_ShowCalendar: boolean;
|
||
|
||
Date_Type: string;
|
||
|
||
DefaultValue: string;
|
||
|
||
Description_HasSaving: boolean;
|
||
Description_IsParser: boolean;
|
||
Description_Text: string;
|
||
|
||
Document: string;
|
||
|
||
FieldStyle_3Col: boolean;
|
||
FieldStyle_4Col: boolean;
|
||
|
||
File_Extentions: string;
|
||
File_MaxSize: string;
|
||
|
||
Help: string;
|
||
|
||
ID: number;
|
||
|
||
IsDashboardField: boolean;
|
||
IsNumeric: boolean;
|
||
IsUnique: boolean;
|
||
|
||
LatinName: string;
|
||
Length: number | null;
|
||
|
||
LockFirstValue: boolean;
|
||
|
||
MaxValue: number | null;
|
||
MinValue: number | null;
|
||
|
||
Name: string;
|
||
NameOrID: string;
|
||
|
||
Option_IsChips: boolean;
|
||
Option_Options: string; // JSON string
|
||
|
||
OrderNumber: number;
|
||
|
||
Parent_CanBeSave: boolean;
|
||
Parent_DependentFields: string; // JSON string
|
||
Parent_FieldID: number;
|
||
Parent_Formula: string;
|
||
Parent_IsMultiSelection: boolean;
|
||
Parent_IsPersonParent: boolean;
|
||
Parent_LoadAll: boolean;
|
||
Parent_OpenSearchList: boolean;
|
||
Parent_ParsedFormula: string;
|
||
Parent_ProcessID: number;
|
||
Parent_SelectRemainOption: boolean;
|
||
Parent_ShowInTree: boolean;
|
||
Parent_Type: string;
|
||
|
||
ParsedValidation: string; // JSON string
|
||
ParsedValidationL2: string;
|
||
|
||
ShowCondition: string;
|
||
|
||
ShowInChildTable: boolean;
|
||
|
||
Status: boolean;
|
||
|
||
StepID: number;
|
||
StepName: string;
|
||
|
||
TabTitle: string;
|
||
|
||
Time_HasSecond: boolean;
|
||
|
||
Type: number | string; // → FieldTypes enum عددی تو داری
|
||
|
||
Unit: string;
|
||
|
||
Validation: string; // JSON string
|
||
|
||
ViewPermissionCount: number;
|
||
// Add typeValue for client-side enum mapping
|
||
typeValue?: FieldTypes;
|
||
// Add parsed options and validation for client-side use
|
||
parsedOptions?: { label: string; value: string }[];
|
||
parsedValidationRules?: { regex: string; message: string }[];
|
||
}
|
||
|
||
// Regex Validators
|
||
export const regexValidators = {
|
||
persian: /^[\u0600-\u06FF\s]+$/, // Persian characters and spaces
|
||
latin: /^[a-zA-Z0-9\s]+$/, // English characters, numbers, and spaces
|
||
mobile: /^09[0-9]{9}$/, // Iranian mobile number format
|
||
nationalId: /^[0-9]{10}$/, // Iranian national ID (Kodemeli)
|
||
email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, // Basic email validation
|
||
url: /^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/, // Basic URL validation
|
||
carPlate: /^(\d{2}[آ-ی]\d{3}|\d{3}[آ-ی]\d{2})$/, // Example: 12ب345 or 123ب45 (simplified)
|
||
};
|
||
|
||
// Input Normalization (can be expanded as needed)
|
||
export const normalizeInput = (type: FieldTypes, value: any): any => {
|
||
if (value === null || value === undefined) return value;
|
||
|
||
switch (type) {
|
||
case FieldTypes.عدد_صحیح:
|
||
case FieldTypes.عدد_اعشاری:
|
||
case FieldTypes.پول:
|
||
return Number(value);
|
||
default:
|
||
return value;
|
||
}
|
||
};
|
||
|
||
// Field type mapping (can be expanded to map to specific components)
|
||
export const fieldTypeMap = (type: number): string => {
|
||
switch (type) {
|
||
case FieldTypes.رشته_عادی:
|
||
case FieldTypes.رشته_فارسی:
|
||
case FieldTypes.رشته_لاتین:
|
||
case FieldTypes.کدملی:
|
||
case FieldTypes.تلفن_همراه:
|
||
case FieldTypes.رایانامه:
|
||
case FieldTypes.آدرس_پایگاه_اینترنتی:
|
||
case FieldTypes.پلاک_ماشین:
|
||
case FieldTypes.پلاک_خودرو:
|
||
case FieldTypes.جستجوی_شخص: // Map new type to text input
|
||
return "text";
|
||
case FieldTypes.رشته_چندخطی:
|
||
return "textarea";
|
||
case FieldTypes.عدد_صحیح:
|
||
return "number";
|
||
case FieldTypes.عدد_اعشاری:
|
||
return "decimal"; // Custom type for decimal input
|
||
case FieldTypes.تاریخ:
|
||
return "date";
|
||
case FieldTypes.ساعت:
|
||
return "time";
|
||
case FieldTypes.پول:
|
||
return "currency"; // Custom type for currency input
|
||
case FieldTypes.کشویی:
|
||
return "select";
|
||
case FieldTypes.رادیویی:
|
||
return "radio";
|
||
case FieldTypes.چندانتخابی:
|
||
return "multi-select";
|
||
case FieldTypes.تصویر:
|
||
return "image-upload";
|
||
case FieldTypes.فایل:
|
||
return "file-upload";
|
||
case FieldTypes.ویرایشگر_پارسر:
|
||
return "html-editor";
|
||
case FieldTypes.توضیحات:
|
||
return "description";
|
||
default:
|
||
return "text";
|
||
}
|
||
};
|
||
|
||
// Placeholder for FormService
|
||
export const FormService = {
|
||
submitDynamicForm: async (
|
||
processId: number,
|
||
stepId: number,
|
||
values: Record<string, any>
|
||
) => {
|
||
console.log("Submitting form:", { processId, stepId, values });
|
||
// In a real application, this would make an API call
|
||
return new Promise((resolve) =>
|
||
setTimeout(() => resolve({ success: true }), 1000)
|
||
);
|
||
},
|
||
fetchDependentOptions: async (
|
||
parentFieldId: number,
|
||
parentFieldValue: any
|
||
): Promise<{ label: string; value: string }[]> => {
|
||
console.log("Fetching dependent options for:", {
|
||
parentFieldId,
|
||
parentFieldValue,
|
||
});
|
||
// Simulate an API call to fetch options based on parentFieldValue
|
||
return new Promise((resolve) =>
|
||
setTimeout(() => {
|
||
if (parentFieldValue === "Option1") {
|
||
resolve([
|
||
{ label: "SubOption A", value: "SubOptionA" },
|
||
{ label: "SubOption B", value: "SubOptionB" },
|
||
]);
|
||
} else if (parentFieldValue === "Option2") {
|
||
resolve([
|
||
{ label: "SubOption C", value: "SubOptionC" },
|
||
{ label: "SubOption D", value: "SubOptionD" },
|
||
]);
|
||
} else {
|
||
resolve([]);
|
||
}
|
||
}, 500)
|
||
);
|
||
},
|
||
};
|