Módulo 5 PROJETOS

Atividade 25: O Mini Portfólio (Rotas Manuais)

A Consagração do App! Crie Múltiplas Visões (Telas) Trocando componentes como Cartas com o poder supremo do useState e o Renders Condicionais.

🎯 O que vamos construir

  • Multi-Telas Sem Lib (React Navigation/Router): const [tela, setTela] = useState('Home')
  • Extrair Códigos JS para Funcões Renrerizadoras (function TelaHome() { return <View/>... })
  • Menu Bottom Navigation Falso de Alta Performance feito com Flexbox

🧭 Navegação Falsa Baseada em Componentes

A maior Dúvida dos Desenvolvedores Web ao chegar no Mobile: "Como eu abro outra página se não existe o <a href> do HTML"?. Enquanto usamos Bibliotecas complexas reais para Aplicativos enormes Empresariais, nós podemos criar Aplicativos Menores Múltiplos com abas de forma MANUAL em 2 minutos!

A Tática do Switch e do If

Se dividirmos nosso código em blocos de Componentes Independentes, nós podemos pedir pro React Renderizar na Tela só o bloco Específico que casa com a variável de estado que tá Ativa! Os outros blocos (outras telas) ficam mortos no limbo de RAM economizando processador.

const [telaAtual, setTelaAtual] = useState('HOME');

// E no seu Render principal do App.js:
return (
   <View>
      { telaAtual === 'HOME' && <ComponenteDeHome /> }
      { telaAtual === 'SOBRE_MIM' && <ComponenteSobre /> }
      { telaAtual === 'PROJETOS' && <ComponenteProjetos /> }
   </View>
);

💻 O Super Portal Tab-Bar

Abra o Expo Snack. Vamos codar a estrutura inteira de Abas Inferiores flutuantes que mudam de cor conforme a Rota selecionada e alteram os Gigantescos Blocos Visuais que rodam no meio!

App.js
import React, { useState } from 'react';
import { View, Text, TouchableOpacity, ScrollView, StyleSheet } from 'react-native';

export default function App() {
  
  // 1) O Roteador Central (Router Root State)
  const [telaAtiva, setTelaAtiva] = useState('HOME');

  // ==============================================
  // 2) MINI COMPONENTES DE TELA
  // ==============================================
  
  const TelaHome = () => (
     <View style={styles.telaRender}>
         <Text style={styles.tituloSecao}>🏠 Bem Vindo!</Text>
         <Text style={styles.textoCorpo}>Este é o meu Mini Portfólio construído em React Native puro, sem depender de pesados Routers Externos. A mágica é toda baseada em Troca de Componentes visuais! Navegue nos botões abaixo para ver minha experiência.</Text>
     </View>
  )

  const TelaSkill = () => (
     <View style={styles.telaRender}>
         <Text style={styles.tituloSecao}>⚙️ Habilidades</Text>
         <View style={styles.pillsContainer}>
             <Text style={styles.pill}>React Native</Text>
             <Text style={styles.pill}>Javascript</Text>
             <Text style={styles.pill}>Tailwind CSS</Text>
             <Text style={styles.pill}>PHP Backend</Text>
             <Text style={styles.pill}>MySQL Server</Text>
         </View>
     </View>
  )

  const TelaCases = () => (
     <View style={styles.telaRender}>
         <Text style={styles.tituloSecao}>🚀 Meus Projetos</Text>
         
         <View style={styles.cardCase}>
            <Text style={styles.caseName}>App de Tarefas V2</Text>
            <Text style={styles.textoCorpo}>To-Do List profissional com Arrays Invertidas e Filtros Inteligentes de Checkboxes.</Text>
         </View>

         <View style={styles.cardCase}>
            <Text style={styles.caseName}>Calculadora de Neon</Text>
            <Text style={styles.textoCorpo}>Flexbox UI Calculator que utiliza Parseamento Matemático de Expressões no Native C++.</Text>
         </View>
     </View>
  )

  // ==============================================
  // 3) RENDERIZAÇÃO MESTRE DA PÁGINA FIXA (MOLDURA)
  // ==============================================
  return (
    <View style={styles.container}>

       <View style={styles.headerMestre}>
          <Text style={styles.logoText}>MeuPortfolio.APP</Text>
       </View>
       
       {/* AREA DO MEIO: CHROMA SCREEN QUE MUDA DINAMICAMENTE */}
       <ScrollView style={styles.areaConteudo}>
          
          { telaAtiva === 'HOME' && <TelaHome /> }
          { telaAtiva === 'SKILLS' && <TelaSkill /> }
          { telaAtiva === 'CASES' && <TelaCases /> }

       </ScrollView>

       {/* O BOTTOM TAB BAR FIXO LÁ EMBAIXO! */}
       <View style={styles.tabBar}>
          
          <TouchableOpacity 
             style={[styles.tabBtn, telaAtiva === 'HOME' && styles.tabAtiva]} 
             onPress={() => setTelaAtiva('HOME')}
          >
             <Text style={[styles.tabTxt, telaAtiva === 'HOME' && styles.tabTxtAtivo]}>Início</Text>
          </TouchableOpacity>

          <TouchableOpacity 
             style={[styles.tabBtn, telaAtiva === 'SKILLS' && styles.tabAtiva]} 
             onPress={() => setTelaAtiva('SKILLS')}
          >
             <Text style={[styles.tabTxt, telaAtiva === 'SKILLS' && styles.tabTxtAtivo]}>Skills</Text>
          </TouchableOpacity>

          <TouchableOpacity 
             style={[styles.tabBtn, telaAtiva === 'CASES' && styles.tabAtiva]} 
             onPress={() => setTelaAtiva('CASES')}
          >
             <Text style={[styles.tabTxt, telaAtiva === 'CASES' && styles.tabTxtAtivo]}>Projetos</Text>
          </TouchableOpacity>

       </View>

    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: '#fdf4ff' },
  headerMestre: { paddingTop: 60, paddingBottom: 20, backgroundColor: '#1e1b4b', alignItems: 'center' },
  logoText: { color: 'white', fontWeight: '900', fontSize: 18, letterSpacing: 2 },
  
  areaConteudo: { flex: 1, padding: 25 },
  telaRender: { paddingBottom: 50 }, // Margem pra conseguir scrollar por causa do tab
  
  tituloSecao: { fontSize: 28, fontWeight: 'bold', color: '#312e81', marginBottom: 20 },
  textoCorpo: { fontSize: 16, color: '#4f46e5', lineHeight: 24 },
  
  pillsContainer: { flexDirection: 'row', flexWrap: 'wrap', gap: 10 },
  pill: { backgroundColor: '#818cf8', color: 'white', paddingHorizontal: 15, paddingVertical: 8, borderRadius: 20, fontWeight: 'bold' },
  
  cardCase: { backgroundColor: 'white', padding: 20, borderRadius: 15, marginBottom: 15, elevation: 4, shadowColor: '#4f46e5', shadowOpacity: 0.1 },
  caseName: { fontSize: 18, fontWeight: 'bold', color: '#312e81', borderBottomWidth: 1, borderColor: '#e0e7ff', paddingBottom: 10, marginBottom: 10 },

  tabBar: { flexDirection: 'row', backgroundColor: 'white', padding: 15, paddingBottom: 30, borderTopColor: '#e0e7ff', borderTopWidth: 1, elevation: 20 },
  tabBtn: { flex: 1, alignItems: 'center', paddingVertical: 10 },
  tabTxt: { color: '#a5b4fc', fontWeight: 'bold', fontSize: 14 },
  
  tabAtiva: { backgroundColor: '#eef2ff', borderRadius: 10 },
  tabTxtAtivo: { color: '#4f46e5' }
});

📝 Quiz - Rotas Lógicas