feat: add moduleType to configurations, introduce DetailPageProvider, and consolidate macOS detection into module provider context
This commit is contained in:
@@ -19,4 +19,7 @@ export const FullPageModuleConfig: ModuleConfigEntity = {
|
|||||||
|
|
||||||
/** Architectural category of the module, used for rendering and routing logic */
|
/** Architectural category of the module, used for rendering and routing logic */
|
||||||
moduleCategory: 'FULL_PAGE',
|
moduleCategory: 'FULL_PAGE',
|
||||||
|
|
||||||
|
/** */
|
||||||
|
moduleType: 'MASTER_DATA',
|
||||||
} as const;
|
} as const;
|
||||||
|
|||||||
+3
@@ -19,4 +19,7 @@ export const SinglePageModuleConfig: ModuleConfigEntity = {
|
|||||||
|
|
||||||
/** Architectural category of the module, used for rendering and routing logic */
|
/** Architectural category of the module, used for rendering and routing logic */
|
||||||
moduleCategory: 'SINGLE_PAGE',
|
moduleCategory: 'SINGLE_PAGE',
|
||||||
|
|
||||||
|
/** */
|
||||||
|
moduleType: 'MASTER_DATA',
|
||||||
} as const;
|
} as const;
|
||||||
|
|||||||
@@ -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).
|
* Defines the architectural category of the module (e.g., routed vs. modal-driven).
|
||||||
*/
|
*/
|
||||||
export type ModuleCategoryType = 'SINGLE_PAGE' | 'FULL_PAGE';
|
export type ModuleCategoryType = 'SINGLE_PAGE' | 'FULL_PAGE';
|
||||||
|
type ModuleType = 'TRANSACTION' | 'MASTER_DATA';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the current operational mode of a form instance.
|
* Represents the current operational mode of a form instance.
|
||||||
@@ -95,6 +96,7 @@ export interface ModuleConfigEntity<E extends BaseEntity = BaseEntity> {
|
|||||||
apiUrl: string;
|
apiUrl: string;
|
||||||
tabTitle?: string;
|
tabTitle?: string;
|
||||||
moduleCategory: ModuleCategoryType;
|
moduleCategory: ModuleCategoryType;
|
||||||
|
moduleType: ModuleType;
|
||||||
translationNamespace: string;
|
translationNamespace: string;
|
||||||
|
|
||||||
singlePageFormConfig?: SinglePageConfig;
|
singlePageFormConfig?: SinglePageConfig;
|
||||||
@@ -108,6 +110,7 @@ export interface ModuleConfigEntity<E extends BaseEntity = BaseEntity> {
|
|||||||
export interface ConfigSlice<E extends BaseEntity = BaseEntity> {
|
export interface ConfigSlice<E extends BaseEntity = BaseEntity> {
|
||||||
config: ModuleConfigEntity<E>;
|
config: ModuleConfigEntity<E>;
|
||||||
privileges: PrivilegeEntity;
|
privileges: PrivilegeEntity;
|
||||||
|
IS_MACOS: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DataServiceSlice<
|
export interface DataServiceSlice<
|
||||||
@@ -187,20 +190,12 @@ export interface EnterpriseFormLifecycleHooks<E extends BaseEntity, TFormData =
|
|||||||
afterGetData?: (data: E) => Promise<TFormData>;
|
afterGetData?: (data: E) => Promise<TFormData>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EnterpriseIndexPageConfig<E extends BaseEntity = BaseEntity> {
|
export interface EnterpriseIndexPageConfig {
|
||||||
_data?: E; // Fix unused generic
|
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
px?: string | number;
|
px?: string | number;
|
||||||
py?: 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'>;
|
pageHeaderProps?: Omit<ModulePageHeaderProps, 'actions' | 'moduleKey'>;
|
||||||
// actions?: PageActionsProps['actions'];
|
|
||||||
customPageActions?: (actions: PageActionsProps['actions']) => PageActionsProps['actions'];
|
customPageActions?: (actions: PageActionsProps['actions']) => PageActionsProps['actions'];
|
||||||
onClickCreate?: (key: string) => void;
|
onClickCreate?: (key: string) => void;
|
||||||
}
|
}
|
||||||
@@ -227,11 +222,10 @@ export interface EnterpriseDetailPageConfig<E extends BaseEntity = BaseEntity> {
|
|||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
showPageHeader?: boolean;
|
showPageHeader?: boolean;
|
||||||
useDefaultPadding?: boolean;
|
useDefaultPadding?: boolean;
|
||||||
customHiddenActions?: (data: E | null, defaultHidden: string[]) => string[];
|
|
||||||
onCustomActionClick?: (key: ModuleActionType, data?: unknown) => void;
|
|
||||||
|
|
||||||
editMode?: 'FULL' | 'PARTIAL';
|
editMode?: 'FULL' | 'PARTIAL';
|
||||||
afterGetData?: (data: E) => Promise<unknown>;
|
|
||||||
|
pageHeaderProps?: Omit<ModulePageHeaderProps, 'actions' | 'moduleKey'>;
|
||||||
|
customPageActions?: (data: E, actions: PageActionsProps['actions']) => PageActionsProps['actions'];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PrivilegeEntity {
|
export interface PrivilegeEntity {
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
import { createContext, useContext } from 'react';
|
import { createContext, useContext } from 'react';
|
||||||
import type { BaseEntity } from '@repo/core-api/data-services';
|
|
||||||
|
|
||||||
export interface IndexPageContextValue<E extends BaseEntity = BaseEntity> {
|
export interface IndexPageContextValue {}
|
||||||
_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 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);
|
const context = useContext(IndexPageContext);
|
||||||
if (!context) {
|
if (!context) {
|
||||||
throw new Error('useIndexPageContext must be used within an IndexPageProvider');
|
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';
|
} from '../hooks/use-module.context';
|
||||||
import { shortcutsData } from '../../../constants';
|
import { shortcutsData } from '../../../constants';
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
export function EnterpriseIndexPageProvider(props: EnterpriseIndexPageConfig) {
|
||||||
// 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>) {
|
|
||||||
const { children, pageHeaderProps, px, py, customPageActions, onClickCreate } = props;
|
const { children, pageHeaderProps, px, py, customPageActions, onClickCreate } = props;
|
||||||
|
|
||||||
const { t } = useEnterpriseModuleTranslationContext();
|
const { t } = useEnterpriseModuleTranslationContext();
|
||||||
const navigation = useEnterpriseModuleNavigationContext();
|
const navigation = useEnterpriseModuleNavigationContext();
|
||||||
const { config, privileges } = useEnterpriseModuleConfigContext();
|
const { config, privileges, IS_MACOS } = useEnterpriseModuleConfigContext();
|
||||||
const { moduleKey } = config;
|
const { moduleKey } = config;
|
||||||
const { ALLOW_CREATE } = privileges;
|
const { ALLOW_CREATE } = privileges;
|
||||||
|
|
||||||
@@ -50,8 +39,8 @@ export function EnterpriseIndexPageProvider<E extends BaseEntity = BaseEntity>(p
|
|||||||
/** Platform-aware shortcut label for the Create action. */
|
/** Platform-aware shortcut label for the Create action. */
|
||||||
const CREATE_SHORTCUT_LABEL = useMemo(() => {
|
const CREATE_SHORTCUT_LABEL = useMemo(() => {
|
||||||
const shortcutData = shortcutsData.find((s) => s.key === 'collapse_sidebar');
|
const shortcutData = shortcutsData.find((s) => s.key === 'collapse_sidebar');
|
||||||
return IS_MAC ? shortcutData?.macKeyIcons.join(' ') : shortcutData?.winKeyIcons.join(' ');
|
return IS_MACOS ? shortcutData?.macKeyIcons.join(' ') : shortcutData?.winKeyIcons.join(' ');
|
||||||
}, [IS_MAC]);
|
}, [IS_MACOS]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function onKeyDown(e: KeyboardEvent) {
|
function onKeyDown(e: KeyboardEvent) {
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ export interface EnterpriseModuleProviderProps<E extends BaseEntity> {
|
|||||||
dataServices: BaseRemoteDataServices<E>;
|
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>) {
|
export function EnterpriseModuleProvider<E extends BaseEntity>(props: EnterpriseModuleProviderProps<E>) {
|
||||||
const { children, config, dataServices } = props;
|
const { children, config, dataServices } = props;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -32,6 +35,7 @@ export function EnterpriseModuleProvider<E extends BaseEntity>(props: Enterprise
|
|||||||
config,
|
config,
|
||||||
// FIXME => IMPLEMENT PRIVILEGE
|
// FIXME => IMPLEMENT PRIVILEGE
|
||||||
privileges: defaultPrivileges,
|
privileges: defaultPrivileges,
|
||||||
|
IS_MACOS: IS_MACOS,
|
||||||
};
|
};
|
||||||
}, [config]);
|
}, [config]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user