diff --git a/packages/core-i18n/src/languages/en/common.json b/packages/core-i18n/src/languages/en/common.json index 31e0767..b0d0b88 100644 --- a/packages/core-i18n/src/languages/en/common.json +++ b/packages/core-i18n/src/languages/en/common.json @@ -97,13 +97,28 @@ "hold": { "title": "Hold Data", "description": "Are you sure you want to hold this data?" + }, + "save": { + "title": "Save Data", + "description": "Are you sure you want to save this data?" } }, "draft": { "recoveryTitle": "Draft Found", "recoveryMessage": "You have an unsaved draft from {{date}}. Would you like to continue editing?", "continueEditing": "Continue Editing", - "discardDraft": "Start Fresh" + "discardDraft": "Start Fresh", + "autoSaved": "Draft auto-saved", + "expired": "Previous draft has expired and was discarded" + }, + "formPage": { + "createTitle": "Create {{module}}", + "editTitle": "Edit {{module}}", + "duplicateTitle": "Duplicate {{module}}", + "loadingData": "Loading data...", + "loadError": "Failed to load data", + "saveError": "Failed to save data", + "validationError": "Please fix the form errors before saving" }, "bulkAction": { "totalData": "Total Data", diff --git a/packages/core-i18n/src/languages/id/common.json b/packages/core-i18n/src/languages/id/common.json index cbfa935..66eeb6d 100644 --- a/packages/core-i18n/src/languages/id/common.json +++ b/packages/core-i18n/src/languages/id/common.json @@ -97,13 +97,28 @@ "hold": { "title": "Hold Data", "description": "Apakah Anda yakin ingin menahan data ini?" + }, + "save": { + "title": "Simpan Data", + "description": "Apakah Anda yakin ingin menyimpan data ini?" } }, "draft": { "recoveryTitle": "Draf Ditemukan", "recoveryMessage": "Anda memiliki draf yang belum disimpan dari {{date}}. Apakah Anda ingin melanjutkan?", "continueEditing": "Lanjutkan", - "discardDraft": "Mulai Baru" + "discardDraft": "Mulai Baru", + "autoSaved": "Draf tersimpan otomatis", + "expired": "Draf sebelumnya telah kedaluwarsa dan dihapus" + }, + "formPage": { + "createTitle": "Buat {{module}}", + "editTitle": "Ubah {{module}}", + "duplicateTitle": "Duplikat {{module}}", + "loadingData": "Memuat data...", + "loadError": "Gagal memuat data", + "saveError": "Gagal menyimpan data", + "validationError": "Mohon perbaiki kesalahan formulir sebelum menyimpan" }, "bulkAction": { "totalData": "Total Data", diff --git a/packages/ui/src/foundations/enterprise-module/components/action-confirmation-modal/index.tsx b/packages/ui/src/foundations/enterprise-module/components/action-confirmation-modal/index.tsx index ad450a9..a668387 100644 --- a/packages/ui/src/foundations/enterprise-module/components/action-confirmation-modal/index.tsx +++ b/packages/ui/src/foundations/enterprise-module/components/action-confirmation-modal/index.tsx @@ -63,6 +63,11 @@ export const ACTION_TRANSLATION_MAP: Record) => string; } -// --------------------------------------------------------------------------- -// Page-Level Configurations -// --------------------------------------------------------------------------- - -/** - * Lifecycle interceptors for form processing. - * @template E The base database entity. - * @template TFormData The payload structure (defaults to Partial for DTOs). - */ -export interface EnterpriseFormLifecycleHooks> { - onValidate?: (data: TFormData) => Promise; - beforeSave?: (data: TFormData) => Promise; - /** Overrides the default repository save implementation. */ - save?: (data: TFormData) => Promise; - afterSave?: (result: E) => Promise; - afterGetData?: (data: E) => Promise; -} - -interface BasePageConfig { - children?: ReactNode; - px?: string | number; - py?: string | number; - pageHeaderProps?: Omit; -} -export interface EnterpriseIndexPageConfig extends BasePageConfig { - customPageActions?: (actions: PageActionsProps['actions']) => PageActionsProps['actions']; - onClickCreate?: (key: string) => void; -} - -export interface EnterpriseFormPageConfig extends EnterpriseFormLifecycleHooks { - children?: ReactNode; - showPageHeader?: boolean; - useDefaultPadding?: boolean; - customHiddenActions?: (data: Partial, defaultHidden: string[]) => string[]; - /** Strongly typed event handler for custom form interactions. */ - onCustomActionClick?: (key: ModuleActionType, data?: unknown) => void; - - draftConfig?: DraftConfig; - /** Type-safe array of entity keys to exclude during an update operation. */ - ignoreKeyUpdate?: (keyof E)[]; - /** Type-safe array of entity keys to exclude when duplicating a record. */ - ignoreKeyDuplicate?: (keyof E)[]; - initialValue?: Partial; - - presetDuplicate?: (data: E) => Promise>; -} - // --------------------------------------------------------------------------- // Action Confirmation Modal Configuration // --------------------------------------------------------------------------- @@ -336,10 +289,46 @@ export interface BulkActionResult { messages?: string[]; } +export interface PrivilegeEntity { + ALLOW_VIEW: boolean; + ALLOW_CREATE: boolean; + ALLOW_EDIT: boolean; + ALLOW_DELETE: boolean; + + ALLOW_PRINT: boolean; + ALLOW_PRINT_COPY: boolean; + + ALLOW_APPROVAL: boolean; + ALLOW_ACTIVATE: boolean; + ALLOW_DEACTIVATE: boolean; + + ALLOW_CONFIRM: boolean; + ALLOW_CANCEL: boolean; + ALLOW_ROLLBACK: boolean; + ALLOW_HOLD: boolean; + + ALLOW_LOGS: boolean; + ALLOW_NOTES: boolean; +} + +// --------------------------------------------------------------------------- +// Page-Level Configurations +// --------------------------------------------------------------------------- +interface BasePageConfig { + children?: ReactNode; + px?: string | number; + py?: string | number; + pageHeaderProps?: Omit; +} +export interface EnterpriseIndexPageConfig extends BasePageConfig { + customPageActions?: (actions: PageActionsProps['actions']) => PageActionsProps['actions']; + onClickCreate?: (key: string) => void; +} + export interface EnterpriseDetailPageConfig extends BasePageConfig { editMode?: 'FULL' | 'PARTIAL'; customPageActions?: (data: E, actions: PageActionsProps['actions']) => PageActionsProps['actions']; - onDetailLoaded?: (data: E) => void; + onDataLoaded?: (data: E) => void; showHighlightData?: boolean; showHighlightDataOnBreadcrumbs?: boolean; @@ -375,24 +364,24 @@ export interface EnterpriseDetailPageConfig e holdModalConfig?: ActionModalConfig; } -export interface PrivilegeEntity { - ALLOW_VIEW: boolean; - ALLOW_CREATE: boolean; - ALLOW_EDIT: boolean; - ALLOW_DELETE: boolean; +export interface EnterpriseFormPageConfig extends BasePageConfig { + formPageType: FormPageType; + customPageActions?: (data: E, actions: PageActionsProps['actions']) => PageActionsProps['actions']; + onDataLoaded?: (data: E) => void; - ALLOW_PRINT: boolean; - ALLOW_PRINT_COPY: boolean; + showHighlightData?: boolean; + showHighlightDataOnBreadcrumbs?: boolean; + highlightDataKey?: string; - ALLOW_APPROVAL: boolean; - ALLOW_ACTIVATE: boolean; - ALLOW_DEACTIVATE: boolean; + /** Key to reference status data in the entity, used to render the status badge automatically. @default 'status' */ + statusKey?: string; + /** Custom callback to provide dynamic status badge properties */ + getCustomStatusBadgeConfig?: (status: string) => Partial; - ALLOW_CONFIRM: boolean; - ALLOW_CANCEL: boolean; - ALLOW_ROLLBACK: boolean; - ALLOW_HOLD: boolean; - - ALLOW_LOGS: boolean; - ALLOW_NOTES: boolean; + /** Type-safe array of entity keys to exclude during an update operation. */ + ignoreKeyUpdate?: (keyof E)[]; + /** Type-safe array of entity keys to exclude when duplicating a record. */ + ignoreKeyDuplicate?: (keyof E)[]; + initialValueCreate?: Partial; + presetDuplicate?(payload: any): Promise; } diff --git a/packages/ui/src/foundations/enterprise-module/providers/detail-page.provider.tsx b/packages/ui/src/foundations/enterprise-module/providers/detail-page.provider.tsx index 3aee758..0ba877d 100644 --- a/packages/ui/src/foundations/enterprise-module/providers/detail-page.provider.tsx +++ b/packages/ui/src/foundations/enterprise-module/providers/detail-page.provider.tsx @@ -20,17 +20,17 @@ import { shortcutsData } from '../../../constants'; export function EnterpriseDetailPageProvider(props: EnterpriseDetailPageConfig) { const { children, - editMode = 'FULL', pageHeaderProps, px, py, + editMode = 'FULL', showHighlightData = true, showHighlightDataOnBreadcrumbs = true, highlightDataKey = 'code', statusKey = 'status', getCustomStatusBadgeConfig, - onDetailLoaded, + onDataLoaded, customPageActions, onClickCreate, @@ -77,7 +77,7 @@ export function EnterpriseDetailPageProvider( if (response && response.data) { const data = response.data?.data; setDetailData(data as E); - if (onDetailLoaded) onDetailLoaded(data as E); + if (onDataLoaded) onDataLoaded(data as E); } } catch (error: any) { notifications.show({ @@ -377,7 +377,7 @@ export function EnterpriseDetailPageProvider( /** Platform-aware shortcut label for the Create action. */ const CREATE_SHORTCUT_LABEL = useMemo(() => { - const shortcutData = shortcutsData.find((s) => s.key === 'collapse_sidebar'); + const shortcutData = shortcutsData.find((s) => s.key === 'create_data'); return IS_MACOS ? shortcutData?.macKeyIcons.join(' ') : shortcutData?.winKeyIcons.join(' '); }, [IS_MACOS]); diff --git a/packages/ui/src/foundations/enterprise-module/providers/index-page.provider.tsx b/packages/ui/src/foundations/enterprise-module/providers/index-page.provider.tsx index f29206a..77fb022 100644 --- a/packages/ui/src/foundations/enterprise-module/providers/index-page.provider.tsx +++ b/packages/ui/src/foundations/enterprise-module/providers/index-page.provider.tsx @@ -37,7 +37,7 @@ export function EnterpriseIndexPageProvider(props: EnterpriseIndexPageConfig) { /** Platform-aware shortcut label for the Create action. */ const CREATE_SHORTCUT_LABEL = useMemo(() => { - const shortcutData = shortcutsData.find((s) => s.key === 'collapse_sidebar'); + const shortcutData = shortcutsData.find((s) => s.key === 'create_data'); return IS_MACOS ? shortcutData?.macKeyIcons.join(' ') : shortcutData?.winKeyIcons.join(' '); }, [IS_MACOS]); diff --git a/packages/utils/package.json b/packages/utils/package.json index b9b2a8f..810c3d0 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -13,12 +13,14 @@ }, "dependencies": { "crypto-js": "^4.2.0", - "dayjs": "^1.11.19" + "dayjs": "^1.11.19", + "lodash": "^4.18.1" }, "devDependencies": { "@repo/eslint-config": "workspace:*", "@repo/typescript-config": "workspace:*", "@types/crypto-js": "^4.2.2", + "@types/lodash": "^4.17.24", "eslint": "^8.57.1", "typescript": "5.5.4", "vitest": "^4.0.17" diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 017eb39..89abad7 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -4,3 +4,4 @@ export * from './encryption/encryption.utils'; export * from './date/date.utils'; export * from './currency/currency.utils'; export * from './string/string.utils'; +export * from './lodash/lodash.utils'; diff --git a/packages/utils/src/lodash/lodash.utils.ts b/packages/utils/src/lodash/lodash.utils.ts new file mode 100644 index 0000000..8728c95 --- /dev/null +++ b/packages/utils/src/lodash/lodash.utils.ts @@ -0,0 +1,3 @@ +import lodash from 'lodash'; + +export { lodash }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd04a69..a833d8e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -670,6 +670,9 @@ importers: dayjs: specifier: ^1.11.19 version: 1.11.19 + lodash: + specifier: ^4.18.1 + version: 4.18.1 devDependencies: '@repo/eslint-config': specifier: workspace:* @@ -680,6 +683,9 @@ importers: '@types/crypto-js': specifier: ^4.2.2 version: 4.2.2 + '@types/lodash': + specifier: ^4.17.24 + version: 4.17.24 eslint: specifier: ^8.57.1 version: 8.57.1 @@ -3835,6 +3841,10 @@ packages: resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} dev: true + /@types/lodash@4.17.24: + resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} + dev: true + /@types/markdown-it@14.1.2: resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} dependencies: @@ -8815,6 +8825,10 @@ packages: /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + /lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + dev: false + /log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'}