Appearance
Project Structure - Estrutura do Projeto
Stack Tecnologico
| Categoria | Tecnologia | Versao |
|---|---|---|
| Framework | React Native | 0.81.5 |
| Plataforma | Expo SDK | 54 |
| Linguagem | TypeScript | 5.9 |
| Roteamento | Expo Router | 6.x |
| Estado | Zustand | latest |
| UI Library | React Native Reusables | latest |
| CSS Framework | NativeWind (Tailwind CSS) | 4.x |
| HTTP Client | Axios | 1.x |
| i18n | i18next + react-i18next | latest |
| Icones | Lucide React Native | latest |
| Armazenamento | Expo SecureStore | latest |
| Camera | Expo Camera | latest |
| Auth | Expo AuthSession + WebBrowser | latest |
Convencoes de Nomenclatura
| Elemento | Padrao | Exemplo |
|---|---|---|
| Componentes | PascalCase (pasta + ComponentName.tsx) | BorrowerHeader/BorrowerHeader.tsx |
| UI Components | PascalCase (pasta + ComponentName.tsx) | Card/Card.tsx |
| Hooks | camelCase com prefixo use | use-auth.ts |
| Services | camelCase com sufixo Service | getActiveContractService |
| Contexts | PascalCase (pasta + index.tsx) | AuthContext/index.tsx |
| Types/Interfaces | PascalCase | ProviderContract |
| Enums | PascalCase | ContractStatus |
| Pages/Screens | kebab-case (Expo Router) | complete-profile.tsx |
| Arquivos de estilo | styles.ts dentro da pasta | BorrowerHeader/styles.ts |
| Locales | linguagem-PAIS | pt-BR.json, en.json |
Estrutura de Pastas
/
├── app/ # Rotas (Expo Router file-based routing)
│ ├── _layout.tsx # Root: providers + auth gate
│ ├── (auth)/ # Grupo de rotas de autenticacao
│ │ ├── _layout.tsx
│ │ ├── login.tsx
│ │ ├── complete-profile.tsx
│ │ └── select-company.tsx
│ ├── (tabs)/ # Grupo de rotas com bottom tabs
│ │ ├── _layout.tsx # Bottom tabs (5 abas)
│ │ ├── index.tsx # Home
│ │ ├── hours/ # Stack dentro da tab
│ │ ├── compliance/ # Stack dentro da tab
│ │ ├── history.tsx
│ │ └── profile.tsx
│ ├── notifications.tsx # Modal
│ └── qr-scanner.tsx # Modal
├── components/ # UI compartilhada entre modulos (2+ consumidores)
│ ├── ui/ # Primitivos e compostos reutilizaveis (React Native Reusables + app)
│ │ ├── Button/
│ │ ├── Card/
│ │ ├── Badge/
│ │ ├── Avatar/
│ │ ├── Input/
│ │ ├── Text/
│ │ └── Progress/
│ └── HapticTab/
├── config/ # Configuracoes (API, i18n)
│ ├── api.ts # Instancia Axios + interceptors
│ └── i18n.ts # Configuracao i18next
├── locales/ # Arquivos de traducao
│ ├── pt-BR.json
│ └── en.json
├── domain/ # Tipos, enums e constantes de dominio
│ ├── common/
│ │ ├── types.ts
│ │ ├── enums.ts
│ │ └── index.ts
│ ├── auth/
│ │ ├── types.ts
│ │ ├── enums.ts
│ │ ├── constants.ts
│ │ └── index.ts
│ ├── contract/
│ │ ├── types.ts
│ │ ├── enums.ts
│ │ └── index.ts
│ ├── compliance/
│ │ ├── types.ts
│ │ ├── enums.ts
│ │ └── index.ts
│ ├── hours/
│ │ ├── types.ts
│ │ └── index.ts
│ └── index.ts
├── modules/ # Modulos de features
│ ├── auth/
│ │ ├── components/
│ │ ├── contexts/
│ │ │ └── AuthContext/
│ │ ├── hooks/
│ │ │ ├── use-auth.ts
│ │ │ └── use-oauth.ts
│ │ └── services/
│ │ └── auth.ts
│ └── provider/
│ ├── components/
│ │ ├── BorrowerHeader/
│ │ ├── DocumentListItem/
│ │ ├── HoursSummaryCard/
│ │ ├── ComplianceSummaryCard/
│ │ ├── ComplianceStepRow/
│ │ ├── PeriodHistoryItem/
│ │ ├── ProfileField/
│ │ └── ContractInfoRow/
│ ├── contexts/
│ │ └── ContractContext/
│ ├── hooks/
│ │ ├── use-contract.ts
│ │ ├── use-hours.ts
│ │ ├── use-compliance.ts
│ │ └── use-compliance-screen.ts
│ ├── stores/
│ │ └── compliance.ts
│ └── services/
│ └── provider.ts
├── lib/ # Utilitarios do framework
│ ├── utils.ts # cn() - clsx + tailwind-merge
│ └── theme.ts # NAV_THEME para React Navigation
├── hooks/ # Hooks globais
│ ├── use-color-scheme.ts
│ └── use-theme-color.ts
├── utils/ # Funcoes utilitarias puras
│ ├── string.ts
│ ├── date.ts
│ ├── file.ts
│ └── compliance.ts
├── assets/ # Imagens, fontes, etc.
├── docs/ # Documentacao
│ ├── architecture/
│ └── business/
└── constants/ # Constantes globais (legado - migrar para domain/)Arquitetura Modular
Cada modulo segue a estrutura:
modules/[nome-modulo]/
├── components/ # UI exclusiva do modulo
│ └── ComponentName/ # PascalCase
│ ├── ComponentName.tsx
│ └── styles.ts # ClassNames e variantes (NativeWind)
├── constants/ # Constantes do modulo
├── contexts/ # React Context do modulo
│ └── ContextName/
│ └── index.tsx
├── helpers/ # Funcoes puras internas
├── hooks/ # Estado Zustand + hooks de tela (use-*.ts)
├── models/ # Types, props e state shapes
├── screens/ # Telas exportadas
├── services/ # Chamadas de API
└── utils/ # Funcoes puras do modulo (opcional)Regras de colocacao:
- UI usada por 2 ou mais modulos →
components/ui/, nunca dentro de um modulo feature - UI, skeletons e layouts de um unico modulo →
modules/[modulo]/components/ - Proibido pasta
stores/— estado somente emhooks/use-*.ts
Padrao de Componentes
Todos os componentes seguem:
ComponentName/
├── ComponentName.tsx # export const ComponentName: FC<Props> = () => {}
└── styles.ts # export const containerClassName = '...'Regras:
- PascalCase para nomes de componentes e pastas
- Um componente por arquivo (proibido componentes aninhados)
- export const para componentes (nunca export default, exceto screens)
- FC type para tipagem do componente
- styles.ts exporta className strings (NativeWind) ou variantes cva
- Proibido StyleSheet.create() e style= inline
Ordem dos providers no root (app/_layout.tsx)
GestureHandlerRootView
UpdateProvider
ThemeProvider
SwrProvider
ConnectivityProvider
AuthProvider
ContractProvider
BottomSheetModalProvider <- portal host dos sheets
<View className="flex-1"> ... Stack ... </View>
PortalHost <- portal host do rn-primitivesBottomSheetModalProvider e PortalHost precisam ficar por dentro de AuthProvider. O BottomSheetModalProvider monta um PortalProvider/PortalHost interno, e todo BottomSheetModal teleporta seu conteudo para essa altura da arvore React. Se o provider estiver acima do AuthProvider, qualquer componente montado dentro de um sheet que chame useAuth (direto ou via useTheme, que le company para o branding) estoura com useAuth must be used within an AuthProvider.
O sintoma engana: o sheet abre normalmente enquanto o conteudo so recebe cores por prop (o hook rodou no componente pai, que esta na arvore normal). O crash so aparece quando um componente de dentro do sheet chama o hook no proprio corpo, como TemplateEditorFaithfulDocument no preview de documento.
Variaveis de Ambiente
env
EXPO_PUBLIC_API_URL="https://api.contrasync.com"Scripts de Desenvolvimento
| Script | Descricao |
|---|---|
npx expo start | Servidor de desenvolvimento |
npx expo start --android | Iniciar no Android |
npx expo start --ios | Iniciar no iOS |
npx expo lint | Lint com ESLint |