feat: add RowActions component for enhanced row-level actions in data grids

- Introduced RowActions component to manage row-level actions with tooltips and dropdown menus.
- Created types for row actions and page actions to standardize action properties.
- Implemented utility function to map action intents to Mantine theme colors.
- Updated CoreAppShell component to support optional slots for better flexibility.
- Added enterprise module structure with context hooks for managing module state and actions.
- Implemented draft management for forms to enhance user experience during data entry.
- Established context providers for detail, form, and index pages to streamline data handling.
- Updated dependencies to ensure compatibility with the latest versions.
This commit is contained in:
Firman Ramdhani
2026-07-01 17:04:20 +07:00
parent 1c2090f4fb
commit 8f14c4bc7b
60 changed files with 2188 additions and 442 deletions
+1
View File
@@ -1,4 +1,5 @@
export { setupI18n, type SupportedLanguage } from './setup';
export { changeLanguage, applyTenantOverrides } from './manager';
export { registerModuleNamespace, isNamespaceRegistered } from './registry';
export { useTranslation, Trans } from 'react-i18next';
export { default as i18n } from 'i18next';
@@ -5,8 +5,10 @@
"success": "Success",
"error": "Error",
"settings": "Settings",
"loading": "Loading...",
"loading": "Loading",
"delete": "Delete",
"edit": "Edit"
"edit": "Edit",
"duplicate": "Duplicate",
"view": "View"
}
}
}
@@ -5,8 +5,10 @@
"success": "Sukses",
"error": "Galat",
"settings": "Pengaturan",
"loading": "Memuat...",
"loading": "Memuat",
"delete": "Hapus",
"edit": "Ubah"
"edit": "Ubah",
"duplicate": "Duplikat",
"view": "Lihat"
}
}
}
+69
View File
@@ -0,0 +1,69 @@
import i18n from 'i18next';
// ---------------------------------------------------------------------------
// Module Namespace Registry
// ---------------------------------------------------------------------------
/**
* Tracks which namespaces have already been registered to prevent
* double-registration and detect accidental namespace collisions.
*/
const registeredNamespaces = new Set<string>();
/**
* Resources shape expected by registerModuleNamespace.
* Keys are language codes, values are flat or nested translation objects.
*
* @example
* ```ts
* const resources = {
* en: { title: 'Full Page', fields: { name: 'Name' } },
* id: { title: 'Halaman Penuh', fields: { name: 'Nama' } },
* };
* ```
*/
export type ModuleNamespaceResources = Record<string, Record<string, unknown>>;
/**
* Registers a module's translation namespace into the global i18n instance.
*
* **Must be called at module scope** (outside any React component) to ensure
* resources are available before the first render. The function is idempotent —
* calling it multiple times with the same namespace is a safe no-op.
*
* @param namespace - Unique namespace identifier (should match the JSON filename, e.g. 'full-page').
* @param resources - An object keyed by language code containing the translation dictionaries.
*
* @example
* ```ts
* import fullPageEn from '../locales/en/full-page.json';
* import fullPageId from '../locales/id/full-page.json';
*
* // ✅ Called at module scope — safe, idempotent, outside React render
* registerModuleNamespace('full-page', {
* en: fullPageEn,
* id: fullPageId,
* });
* ```
*/
export function registerModuleNamespace(namespace: string, resources: ModuleNamespaceResources): void {
if (registeredNamespaces.has(namespace)) {
return; // Already registered — no-op
}
registeredNamespaces.add(namespace);
for (const [lng, bundle] of Object.entries(resources)) {
// deep: true → merges with any existing keys under this namespace
// overwrite: false → does NOT replace keys that already exist (e.g. tenant overrides)
i18n.addResourceBundle(lng, namespace, bundle, true, false);
}
}
/**
* Checks whether a namespace has been registered.
* Useful for debugging or conditional loading logic.
*/
export function isNamespaceRegistered(namespace: string): boolean {
return registeredNamespaces.has(namespace);
}