import { Ionicons } from "@expo/vector-icons";
import type { ReactNode } from "react";
import { Text, TouchableOpacity, useColorScheme, View } from "react-native";
import { EmptyScreen } from "./EmptyScreen";
import { Header } from "./Header";
import { LoadingSpinner } from "./LoadingSpinner";
import { getColors } from "@/constants/colors";
type IoniconName = keyof typeof Ionicons.glyphMap;
interface EmptyStateConfig {
icon: IoniconName;
headline: string;
description: string;
buttonText?: string;
onButtonPress?: () => void;
}
interface ScreenWrapperProps {
/** Whether data is currently loading */
loading?: boolean;
/** Error message to display, if any */
error?: string | null;
/** Callback for retry button in error state */
onRetry?: () => void;
/** Custom title for error state (default: "Unable to load data") */
errorTitle?: string;
/** Whether to show empty state */
isEmpty?: boolean;
/** Configuration for empty state display */
emptyProps?: EmptyStateConfig;
/** Whether to show the header (default: true) */
showHeader?: boolean;
/** Content to render when not in loading/error/empty state */
children: ReactNode;
}
/**
* Wrapper component that handles common screen states: loading, error, and empty.
* Renders the appropriate UI based on the current state.
*
* @example
* ```tsx
*
*
*
* ```
*/
export function ScreenWrapper({
loading,
error,
onRetry,
errorTitle = "Unable to load data",
isEmpty,
emptyProps,
showHeader = true,
children,
}: ScreenWrapperProps) {
const colorScheme = useColorScheme();
const isDark = colorScheme === "dark";
const theme = getColors(isDark);
const errorIconColor = theme.destructive;
if (loading) {
return (
{showHeader && }
);
}
if (error) {
return (
{showHeader && }
{errorTitle}
{error}
{onRetry && (
Retry
)}
);
}
if (isEmpty && emptyProps) {
return (
{showHeader && }
);
}
return (
{showHeader && }
{children}
);
}
export type { EmptyStateConfig, ScreenWrapperProps };