feat: add StatusBadge component and integrate action confirmation modal

- Introduced StatusBadge component for displaying various status indicators with customizable colors and icons.
- Updated ModulePageHeader to conditionally render badges based on props.
- Implemented ActionConfirmationModal for handling lifecycle actions (delete, activate, etc.) with support for forms and custom body rendering.
- Enhanced EnterpriseDetailPageProvider to manage action confirmation modal state and execution of actions.
- Added new modal configurations for various actions in EnterpriseDetailPageConfig.
- Updated theme provider to include ModalsProvider and Notifications for better user feedback.
This commit is contained in:
Firman Ramdhani
2026-07-15 17:27:29 +07:00
parent 7ce4ced7d6
commit 43f9d3d491
21 changed files with 966 additions and 93 deletions
@@ -6,6 +6,7 @@ import type {
RequestDescriptor,
ExecuteOptions,
DataServicesConfig,
EntityId,
} from './types';
import type { IDataTransformer } from './base-data.transformer';
import type { ApiResponse } from '../http-client/types';
@@ -242,16 +243,16 @@ export abstract class BaseRemoteDataServices<E extends BaseEntity = BaseEntity,
});
}
/** Delete a single entity by ID. */
delete(id: string, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
/** Delete a single entity by ID. Optionally sends form data as `meta` in the request body. */
delete(id: EntityId, meta?: Record<string, unknown>, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.delete, {
variableURL: { id },
config,
config: { ...config, ...(meta ? { data: { meta } } : {}) },
});
}
/** Delete multiple entities by IDs. */
batchDelete(ids: string[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
batchDelete(ids: EntityId[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.batchDelete, {
config: { ...config, data: { ids } },
});
@@ -259,31 +260,31 @@ export abstract class BaseRemoteDataServices<E extends BaseEntity = BaseEntity,
// ─── Activation Lifecycle ─────────────────────────────────────
/** Activate a single entity. */
activate(id: string, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
/** Activate a single entity. Optionally sends form data as `meta` in the request body. */
activate(id: EntityId, meta?: Record<string, unknown>, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.activate, {
variableURL: { id },
config,
config: { ...config, ...(meta ? { data: { meta } } : {}) },
});
}
/** Activate multiple entities. */
batchActivate(ids: string[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
batchActivate(ids: EntityId[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.batchActivate, {
config: { ...config, data: { ids } },
});
}
/** Deactivate a single entity. */
deactivate(id: string, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
/** Deactivate a single entity. Optionally sends form data as `meta` in the request body. */
deactivate(id: EntityId, meta?: Record<string, unknown>, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.deactivate, {
variableURL: { id },
config,
config: { ...config, ...(meta ? { data: { meta } } : {}) },
});
}
/** Deactivate multiple entities. */
batchDeactivate(ids: string[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
batchDeactivate(ids: EntityId[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.batchDeactivate, {
config: { ...config, data: { ids } },
});
@@ -291,31 +292,31 @@ export abstract class BaseRemoteDataServices<E extends BaseEntity = BaseEntity,
// ─── Data Processing Lifecycle ────────────────────────────────
/** Confirm processing of a single data record. */
confirmData(id: string, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
/** Confirm processing of a single data record. Optionally sends form data as `meta` in the request body. */
confirmData(id: EntityId, meta?: Record<string, unknown>, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.confirmData, {
variableURL: { id },
config,
config: { ...config, ...(meta ? { data: { meta } } : {}) },
});
}
/** Confirm processing of multiple data records. */
batchConfirmData(ids: string[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
batchConfirmData(ids: EntityId[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.batchConfirmData, {
config: { ...config, data: { ids } },
});
}
/** Cancel processing of a single data record. */
cancelData(id: string, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
/** Cancel processing of a single data record. Optionally sends form data as `meta` in the request body. */
cancelData(id: EntityId, meta?: Record<string, unknown>, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.cancelData, {
variableURL: { id },
config,
config: { ...config, ...(meta ? { data: { meta } } : {}) },
});
}
/** Cancel processing of multiple data records. */
batchCancelData(ids: string[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
batchCancelData(ids: EntityId[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.batchCancelData, {
config: { ...config, data: { ids } },
});
@@ -323,31 +324,31 @@ export abstract class BaseRemoteDataServices<E extends BaseEntity = BaseEntity,
// ─── Transaction Lifecycle ────────────────────────────────────
/** Rollback a transaction. */
rollbackData(id: string, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
/** Rollback a transaction. Optionally sends form data as `meta` in the request body. */
rollbackData(id: EntityId, meta?: Record<string, unknown>, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.rollbackData, {
variableURL: { id },
config,
config: { ...config, ...(meta ? { data: { meta } } : {}) },
});
}
/** Rollback multiple transactions. */
batchRollbackData(ids: string[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
batchRollbackData(ids: EntityId[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.batchRollbackData, {
config: { ...config, data: { ids } },
});
}
/** Hold a transaction. */
holdData(id: string, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
/** Hold a transaction. Optionally sends form data as `meta` in the request body. */
holdData(id: EntityId, meta?: Record<string, unknown>, config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.holdData, {
variableURL: { id },
config,
config: { ...config, ...(meta ? { data: { meta } } : {}) },
});
}
/** Hold multiple transactions. */
batchHoldData(ids: string[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
batchHoldData(ids: EntityId[], config?: AxiosRequestConfig): Promise<ApiResponse<void>> {
return this.execute<void>(DESCRIPTORS.batchHoldData, {
config: { ...config, data: { ids } },
});
+4 -2
View File
@@ -8,8 +8,10 @@ import type { IDataTransformer } from './base-data.transformer';
* Minimal entity contract. All domain entities must have
* an optional `id` field for CRUD operations.
*/
export type EntityId = string | number;
export interface BaseEntity {
id?: string;
id?: EntityId;
[key: string]: any;
}
@@ -95,7 +97,7 @@ export interface RequestDescriptor {
*/
export interface ExecuteOptions {
/** Dynamic URL parameters (e.g., `{ id: '42' }`). */
variableURL?: Record<string, string>;
variableURL?: Record<string, any>;
/** Additional Axios request config (params, data, headers, etc). */
config?: AxiosRequestConfig;
/** Per-request telemetry context for custom spans, tags, events. */