Aller au contenu

Create Screen

Crée un nouvel écran React Native avec sa route Expo Router.

Arguments

  • name (requis) : Nom de l'écran en PascalCase (ex: WalletScreen)

Instructions

  1. Demander à l'utilisateur :
  2. L'écran est-il public ou authentifié ?
  3. L'écran fait-il partie des tabs ou est-ce une page modale/détail ?
  4. Y a-t-il des paramètres de route (ex: [id]) ?

  5. Créer la structure :

Structure de l'écran

src/screens/{featureName}/
├── {ScreenName}.tsx
├── components/
│   └── (composants spécifiques à l'écran)
└── hooks/
    └── (hooks spécifiques à l'écran, optionnel)

Route Expo Router

src/app/(authenticated)/(tabs)/{routeName}.tsx
# ou
src/app/(authenticated)/{routeName}/index.tsx
# ou
src/app/(public)/{routeName}.tsx

Templates

Route : src/app/.../{routeName}.tsx

export { {{ScreenName}} as default } from "@screens/{{featureName}}/{{ScreenName}}";

Route dynamique : src/app/.../[id].tsx

export { {{ScreenName}} as default } from "@screens/{{featureName}}/{{ScreenName}}";

Screen : src/screens/{featureName}/{ScreenName}.tsx

import { Box } from "@bricks-common/uimmo/components/Box";
import { SafeAreaBox } from "@bricks-common/uimmo/components/SafeAreaBox";
import { Text } from "@bricks-common/uimmo/components/Text";
import { useTranslation } from "react-i18next";

export const {{ScreenName}} = () => {
  const { t } = useTranslation();

  return (
    <SafeAreaBox edges={["top"]} fill bg="white">
      <Box p="xl" fill>
        <Text variant="heading/lg">{t("screenTitle.{{featureName}}")}</Text>
        {/* TODO: Implement screen content */}
      </Box>
    </SafeAreaBox>
  );
};

Screen avec paramètre : src/screens/{featureName}/{ScreenName}.tsx

import { Box } from "@bricks-common/uimmo/components/Box";
import { SafeAreaBox } from "@bricks-common/uimmo/components/SafeAreaBox";
import { Text } from "@bricks-common/uimmo/components/Text";
import { useLocalSearchParams } from "expo-router";
import { useTranslation } from "react-i18next";

export const {{ScreenName}} = () => {
  const { t } = useTranslation();
  const { id } = useLocalSearchParams<{ id: string }>();

  return (
    <SafeAreaBox edges={["top"]} fill bg="white">
      <Box p="xl" fill>
        <Text variant="heading/lg">{t("screenTitle.{{featureName}}")}</Text>
        {/* TODO: Use id parameter */}
      </Box>
    </SafeAreaBox>
  );
};

Screen avec données API

import { Box } from "@bricks-common/uimmo/components/Box";
import { SafeAreaBox } from "@bricks-common/uimmo/components/SafeAreaBox";
import { Text } from "@bricks-common/uimmo/components/Text";
import { useTranslation } from "react-i18next";
import { useProperty } from "@api/property/useProperty";
import { PropertySkeleton } from "./components/PropertySkeleton";
import { ErrorScreen } from "@components/ErrorScreen";

export const {{ScreenName}} = () => {
  const { t } = useTranslation();
  const { id } = useLocalSearchParams<{ id: string }>();
  const { data, isLoading, isError, refetch } = useProperty(id);

  if (isLoading) return <PropertySkeleton />;
  if (isError || !data) return <ErrorScreen onRetry={refetch} />;

  return (
    <SafeAreaBox edges={["top"]} fill bg="white">
      <Box p="xl" fill>
        <Text variant="heading/lg">{data.name}</Text>
      </Box>
    </SafeAreaBox>
  );
};

Ajouter la traduction

Dans src/i18n/locales/fr.json :

{
  "screenTitle": {
    "{{featureName}}": "Titre de l'écran"
  }
}

Checklist finale

  • [ ] Screen créé dans src/screens/{feature}/
  • [ ] Route créée dans src/app/
  • [ ] Route exporte uniquement le screen (pas de logique)
  • [ ] SafeAreaBox pour les zones sûres
  • [ ] Traduction ajoutée pour le titre
  • [ ] Early returns pour loading/error si données API
  • [ ] Skeleton créé si nécessaire

Règles appliquées

  • front-expo-routing.mdc
  • front-api-data-fetching.mdc
  • front-i18n.mdc
  • front-cross-platform.mdc