Files
hipmi-mobile/components/_ShareComponent/PageWrapper.tsx
bagasbanuna e3b5d3ddb1 feat: Implement PageWrapper and migrate all Job screens
Create PageWrapper component that routes to:
- iOS: NewWrapper (stable, tested)
- Android: NewWrapper_V2 (keyboard handling fix)

New Files:
- components/_ShareComponent/PageWrapper.tsx
- docs/PAGEWRAPPER-USAGE.md

Migrated Job Screens (10):
- screens/Job/ScreenJobCreate.tsx: NewWrapper_V2 → PageWrapper
- screens/Job/ScreenJobEdit.tsx: NewWrapper_V2 → PageWrapper
- screens/Job/ScreenArchive.tsx: ViewWrapper → PageWrapper
- screens/Job/ScreenArchive2.tsx: NewWrapper_V2 → PageWrapper
- screens/Job/ScreenBeranda2.tsx: NewWrapper_V2 → PageWrapper
- screens/Job/MainViewStatus2.tsx: NewWrapper_V2 → PageWrapper
- app/(application)/(user)/job/[id]/index.tsx: ViewWrapper → PageWrapper
- app/(application)/(user)/job/[id]/archive.tsx: ViewWrapper → PageWrapper
- app/(application)/(user)/job/[id]/[status]/detail.tsx: NewWrapper_V2 → PageWrapper

Benefits:
- iOS users (70%+) get stable NewWrapper
- Android users get keyboard handling fix
- Clean API - no Platform.OS checks in screens
- Easy future migration path

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-04-06 14:41:54 +08:00

230 lines
6.5 KiB
TypeScript

/**
* PageWrapper - Platform-specific wrapper component
*
* Routes to:
* - iOS: NewWrapper (stable, tested)
* - Android: NewWrapper_V2 (with keyboard handling fix)
*
* Props are automatically adjusted based on platform.
*
* @example
* <PageWrapper
* footerComponent={buttonFooter}
* enableKeyboardHandling
* keyboardScrollOffset={100}
* >
* {children}
* </PageWrapper>
*/
import { Platform } from "react-native";
import { NewWrapper_V2 } from "./NewWrapper_V2";
import type { NativeSafeAreaViewProps } from "react-native-safe-area-context";
import type { ScrollViewProps, FlatListProps } from "react-native";
import NewWrapper from "./NewWrapper";
// ========== Base Props ==========
interface BaseProps {
withBackground?: boolean;
headerComponent?: React.ReactNode;
footerComponent?: React.ReactNode;
floatingButton?: React.ReactNode;
hideFooter?: boolean;
edgesFooter?: NativeSafeAreaViewProps["edges"];
style?: any;
refreshControl?: ScrollViewProps["refreshControl"];
}
// ========== Static Mode Props ==========
interface StaticModeProps extends BaseProps {
children: React.ReactNode;
listData?: never;
renderItem?: never;
}
// ========== List Mode Props ==========
interface ListModeProps extends BaseProps {
children?: never;
listData?: any[];
renderItem?: FlatListProps<any>["renderItem"];
onEndReached?: () => void;
ListHeaderComponent?: React.ReactElement | null;
ListFooterComponent?: React.ReactElement | null;
ListEmptyComponent?: React.ReactElement | null;
keyExtractor?: FlatListProps<any>["keyExtractor"];
}
// ========== PageWrapper Props ==========
interface PageWrapperBaseProps extends BaseProps {
/**
* Enable keyboard handling (Android only - NewWrapper_V2)
* iOS ignores this prop
* @default false
*/
enableKeyboardHandling?: boolean;
/**
* Scroll offset when keyboard appears (Android only)
* iOS ignores this prop
* @default 100
*/
keyboardScrollOffset?: number;
/**
* Extra padding bottom for content (Android only)
* iOS ignores this prop
* @default 80
*/
contentPaddingBottom?: number;
/**
* Padding Top for content container (Android only)
* iOS ignores this prop
* @default 8
*/
contentPaddingTop?: number;
/**
* Padding Horizontal for content container (Android only)
* iOS ignores this prop
* @default 0
*/
contentPaddingHorizontal?: number;
}
interface PageWrapperStaticProps extends PageWrapperBaseProps {
children: React.ReactNode;
listData?: never;
renderItem?: never;
}
interface PageWrapperListProps extends PageWrapperBaseProps {
children?: never;
listData?: any[];
renderItem?: FlatListProps<any>["renderItem"];
onEndReached?: () => void;
ListHeaderComponent?: React.ReactElement | null;
ListFooterComponent?: React.ReactElement | null;
ListEmptyComponent?: React.ReactElement | null;
keyExtractor?: FlatListProps<any>["keyExtractor"];
}
type PageWrapperProps = PageWrapperStaticProps | PageWrapperListProps;
export function PageWrapper(props: PageWrapperProps) {
const {
withBackground,
headerComponent,
footerComponent,
floatingButton,
hideFooter,
edgesFooter,
style,
refreshControl,
enableKeyboardHandling,
keyboardScrollOffset,
contentPaddingBottom,
contentPaddingTop,
contentPaddingHorizontal,
...restProps
} = props;
// ========== Android: Use NewWrapper_V2 with keyboard handling ==========
if (Platform.OS === "android") {
if ("listData" in props) {
// List mode
const listProps = props as PageWrapperListProps;
return (
<NewWrapper_V2
listData={listProps.listData}
renderItem={listProps.renderItem}
onEndReached={listProps.onEndReached}
ListHeaderComponent={listProps.ListHeaderComponent}
ListFooterComponent={listProps.ListFooterComponent}
ListEmptyComponent={listProps.ListEmptyComponent}
keyExtractor={listProps.keyExtractor}
withBackground={withBackground}
headerComponent={headerComponent}
footerComponent={footerComponent}
floatingButton={floatingButton}
hideFooter={hideFooter}
edgesFooter={edgesFooter}
style={style}
refreshControl={refreshControl}
enableKeyboardHandling={enableKeyboardHandling}
keyboardScrollOffset={keyboardScrollOffset}
contentPaddingBottom={contentPaddingBottom}
contentPaddingTop={contentPaddingTop}
contentPaddingHorizontal={contentPaddingHorizontal}
/>
);
}
// Static mode
const staticProps = props as PageWrapperStaticProps;
return (
<NewWrapper_V2
withBackground={withBackground}
headerComponent={headerComponent}
footerComponent={footerComponent}
floatingButton={floatingButton}
hideFooter={hideFooter}
edgesFooter={edgesFooter}
style={style}
refreshControl={refreshControl}
enableKeyboardHandling={enableKeyboardHandling}
keyboardScrollOffset={keyboardScrollOffset}
contentPaddingBottom={contentPaddingBottom}
contentPaddingTop={contentPaddingTop}
contentPaddingHorizontal={contentPaddingHorizontal}
>
{staticProps.children}
</NewWrapper_V2>
);
}
// ========== iOS: Use NewWrapper (stable) ==========
if ("listData" in props) {
// List mode
const listProps = props as PageWrapperListProps;
return (
<NewWrapper
listData={listProps.listData}
renderItem={listProps.renderItem}
onEndReached={listProps.onEndReached}
ListHeaderComponent={listProps.ListHeaderComponent}
ListFooterComponent={listProps.ListFooterComponent}
ListEmptyComponent={listProps.ListEmptyComponent}
keyExtractor={listProps.keyExtractor}
withBackground={withBackground}
headerComponent={headerComponent}
footerComponent={footerComponent}
floatingButton={floatingButton}
hideFooter={hideFooter}
edgesFooter={edgesFooter}
style={style}
refreshControl={refreshControl}
/>
);
}
// Static mode
const staticProps = props as PageWrapperStaticProps;
return (
<NewWrapper
withBackground={withBackground}
headerComponent={headerComponent}
footerComponent={footerComponent}
floatingButton={floatingButton}
hideFooter={hideFooter}
edgesFooter={edgesFooter}
style={style}
refreshControl={refreshControl}
>
{staticProps.children}
</NewWrapper>
);
}
export default PageWrapper;