feat: add moduleType to configurations, introduce DetailPageProvider, and consolidate macOS detection into module provider context

This commit is contained in:
Firman Ramdhani
2026-07-13 15:39:10 +07:00
parent 0bbd376125
commit 383e2627e0
7 changed files with 41 additions and 41 deletions
@@ -46,6 +46,7 @@ export type ModuleActionType = (typeof ModuleAction)[keyof typeof ModuleAction]
* Defines the architectural category of the module (e.g., routed vs. modal-driven).
*/
export type ModuleCategoryType = 'SINGLE_PAGE' | 'FULL_PAGE';
type ModuleType = 'TRANSACTION' | 'MASTER_DATA';
/**
* Represents the current operational mode of a form instance.
@@ -95,6 +96,7 @@ export interface ModuleConfigEntity<E extends BaseEntity = BaseEntity> {
apiUrl: string;
tabTitle?: string;
moduleCategory: ModuleCategoryType;
moduleType: ModuleType;
translationNamespace: string;
singlePageFormConfig?: SinglePageConfig;
@@ -108,6 +110,7 @@ export interface ModuleConfigEntity<E extends BaseEntity = BaseEntity> {
export interface ConfigSlice<E extends BaseEntity = BaseEntity> {
config: ModuleConfigEntity<E>;
privileges: PrivilegeEntity;
IS_MACOS: boolean;
}
export interface DataServiceSlice<
@@ -187,20 +190,12 @@ export interface EnterpriseFormLifecycleHooks<E extends BaseEntity, TFormData =
afterGetData?: (data: E) => Promise<TFormData>;
}
export interface EnterpriseIndexPageConfig<E extends BaseEntity = BaseEntity> {
_data?: E; // Fix unused generic
export interface EnterpriseIndexPageConfig {
children?: ReactNode;
px?: string | number;
py?: string | number;
// customHiddenActions?: (selected: E[], defaultHidden: string[]) => string[];
// /** Strongly typed event handler to prevent arbitrary string usage for actions. */
// onCustomActionClick?: (key: ModuleActionType, data?: unknown) => void;
// filterDrawerContent?: ReactNode;
// registerRefreshCallback?: (callback: () => void) => void;
pageHeaderProps?: Omit<ModulePageHeaderProps, 'actions' | 'moduleKey'>;
// actions?: PageActionsProps['actions'];
customPageActions?: (actions: PageActionsProps['actions']) => PageActionsProps['actions'];
onClickCreate?: (key: string) => void;
}
@@ -227,11 +222,10 @@ export interface EnterpriseDetailPageConfig<E extends BaseEntity = BaseEntity> {
children?: ReactNode;
showPageHeader?: boolean;
useDefaultPadding?: boolean;
customHiddenActions?: (data: E | null, defaultHidden: string[]) => string[];
onCustomActionClick?: (key: ModuleActionType, data?: unknown) => void;
editMode?: 'FULL' | 'PARTIAL';
afterGetData?: (data: E) => Promise<unknown>;
pageHeaderProps?: Omit<ModulePageHeaderProps, 'actions' | 'moduleKey'>;
customPageActions?: (data: E, actions: PageActionsProps['actions']) => PageActionsProps['actions'];
}
export interface PrivilegeEntity {
@@ -1,20 +1,10 @@
import { createContext, useContext } from 'react';
import type { BaseEntity } from '@repo/core-api/data-services';
export interface IndexPageContextValue<E extends BaseEntity = BaseEntity> {
_data?: E; // Fix unused generic
// renderRowActions: (row: E) => React.ReactNode;
// refreshGrid: () => void;
// // State for batch modals
// isConfirmModalOpen: boolean;
// setIsConfirmModalOpen: (open: boolean) => void;
// isDeleteModalOpen: boolean;
// setIsDeleteModalOpen: (open: boolean) => void;
}
export interface IndexPageContextValue {}
export const IndexPageContext = createContext<IndexPageContextValue<any> | null>(null);
export const IndexPageContext = createContext<IndexPageContextValue | null>(null);
export function useIndexPageContext<E extends BaseEntity = BaseEntity>(): IndexPageContextValue<E> {
export function useIndexPageContext(): IndexPageContextValue {
const context = useContext(IndexPageContext);
if (!context) {
throw new Error('useIndexPageContext must be used within an IndexPageProvider');
@@ -0,0 +1,17 @@
import { BaseEntity } from '@repo/core-api/data-services';
import { DetailPageContext } from '../hooks/use-detail-page.context';
import { EnterpriseDetailPageConfig } from '../entities/entity';
export function EnterpriseDetailPageProvider<E extends BaseEntity = BaseEntity>(props: EnterpriseDetailPageConfig<E>) {
const {
children,
showPageHeader,
useDefaultPadding,
editMode,
pageHeaderProps,
customPageActions,
} = props;
return <DetailPageContext.Provider value={{}}></DetailPageContext.Provider>;
}
@@ -12,23 +12,12 @@ import {
} from '../hooks/use-module.context';
import { shortcutsData } from '../../../constants';
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
/** Detect macOS / iOS for displaying platform-specific shortcut labels. */
const IS_MAC = typeof navigator !== 'undefined' && /Mac|iPod|iPhone|iPad/.test(navigator.userAgent);
// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------
export function EnterpriseIndexPageProvider<E extends BaseEntity = BaseEntity>(props: EnterpriseIndexPageConfig<E>) {
export function EnterpriseIndexPageProvider(props: EnterpriseIndexPageConfig) {
const { children, pageHeaderProps, px, py, customPageActions, onClickCreate } = props;
const { t } = useEnterpriseModuleTranslationContext();
const navigation = useEnterpriseModuleNavigationContext();
const { config, privileges } = useEnterpriseModuleConfigContext();
const { config, privileges, IS_MACOS } = useEnterpriseModuleConfigContext();
const { moduleKey } = config;
const { ALLOW_CREATE } = privileges;
@@ -50,8 +39,8 @@ export function EnterpriseIndexPageProvider<E extends BaseEntity = BaseEntity>(p
/** Platform-aware shortcut label for the Create action. */
const CREATE_SHORTCUT_LABEL = useMemo(() => {
const shortcutData = shortcutsData.find((s) => s.key === 'collapse_sidebar');
return IS_MAC ? shortcutData?.macKeyIcons.join(' ') : shortcutData?.winKeyIcons.join(' ');
}, [IS_MAC]);
return IS_MACOS ? shortcutData?.macKeyIcons.join(' ') : shortcutData?.winKeyIcons.join(' ');
}, [IS_MACOS]);
useEffect(() => {
function onKeyDown(e: KeyboardEvent) {
@@ -20,6 +20,9 @@ export interface EnterpriseModuleProviderProps<E extends BaseEntity> {
dataServices: BaseRemoteDataServices<E>;
}
/** Detect macOS / iOS for displaying platform-specific shortcut labels. */
const IS_MACOS = typeof navigator !== 'undefined' && /Mac|iPod|iPhone|iPad/.test(navigator.userAgent);
export function EnterpriseModuleProvider<E extends BaseEntity>(props: EnterpriseModuleProviderProps<E>) {
const { children, config, dataServices } = props;
const navigate = useNavigate();
@@ -32,6 +35,7 @@ export function EnterpriseModuleProvider<E extends BaseEntity>(props: Enterprise
config,
// FIXME => IMPLEMENT PRIVILEGE
privileges: defaultPrivileges,
IS_MACOS: IS_MACOS,
};
}, [config]);