Chame no Whatsapp

Post-IA-06: Uso de IA na Criação de um WebApp – Parte 4

Colocando para funcionar o webapp

Prompts em azul, meus comentários em verde, soluções da IA em preto, comentários da IA em marrom.

IAs Utilizadas neste Post

  • Copilot

No post parte-1 desta série, vimos as características recomendadas pela IA para um sistema de ponto inteligente bem como os requisitos legais necessários para tal sistema. enquanto que na parte-2 , concluímos que a melhor opção seria o uso de micro serviços para construir o sistema e a IA definiu a arquitetura desse sistema,listando os módulos necessários.

Na (parte-3) a IA criou o programa do webapp em react bem como definiu como estruturar a pasta src que o contém bem como os mock de dados e mock de api para testar nosso app,

Então, começamos o teste do programa criado pela IA.

  • Ativar a câmera automaticamente
  • Capturar a localização via GPS
  • Simular reconhecimento facial com um ID fixo
  • Registrar o ponto no mock e exibe o resultado

Devemos antes de começar checar os seguintes pontos, no vscode:

  • O React foi carregado(npm create vite@latest controle-ponto-pwa — –template react
  • Você selecionou o react durante a instalação. (não usar o default que ~e Vanilla)
  • Nossa estrutura de arquivos está conforme indicada no post anterior? –OK
  • Nosso public/manifest.json está de acordo com o indicado no post anterior? –OK
  • Nossa pasta src está estruturada de acordo com o indicado no post anterior? –OK
  • Nossos mocks estão corretos src/services/mockApi.js e src/mocks/fakeData.js? –OK
  • O react script em src/pages/RegistroPonto.jsx está correto? –OK
  • O react script em src/app.jsx está correto? –OK

Tudo checado, abrimos um terminal no vscode e inserimos o comando npm run dev

Execução do projeto no terminal com npm run dev
Execução do projeto no terminal com npm run dev

Se então abrirmos no browser (chrome) e autorizamos as visualizações de câmera e a localização e clicarmos em registrar o ponto,Nos será apresentada a tela.

Tela do PWA antes do Tailwind: Registro de Ponto com câmera, status de ponto registrado às 13:12:34, usuário Marcelo Gatti e localização.
Tela 1 — Antes do Tailwind (layout simples e funcional)

Como pode ser visto, na parte de baixo, o app indicou o nome do usuário (fake) e a localização (verdadeira).

 
Nosso app já está funcionando. Agora vamos melhorar sua aparência usando o tailwind nesse caso, faremos o seguinte prompt ao copilot:

Vamos agora usando tailwind, melhorar a aparência do nosso app

Aqui está um guia claro para transformar seu app React sem Tailwind em uma versão com Tailwind bem mais profissional

Transformando o app para usar Tailwind CS

1.Instalar Tailwind e dependências

No Terminal: npm install -D tailwindcss postcss autoprefixer @tailwindcss/postcss

2.Criar arquivos de configuração

No arquivo: tailwind.config.js (na raiz)

export default {
  content: ["./index.html", "./src/**/*.{js,jsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};

No arquivo: postcss.config.js (na raiz)

export default {
  plugins: {
    '@tailwindcss/postcss': {},
    autoprefixer: {},
  },
};

3.Configurar o css principal

No arquivo src/index.css troque tudo por

@tailwind base;
@tailwind components;
@tailwind utilities;

Não se preocupe se esses links indicarem erro, é uma inconsistência do vscode…. Vai funcionar mesmo assim

No arquivo src/main.jsx certifique se que

import './index.css'

4 No arquivo src/pages/RegistroPonto.jsx 4. Substituir estilos manuais por classes Tailwind (preto) em vermelho (vermelho)

Na verdade, as classes tailwind já estavam no código desde o primeiro arquivo src/pages/RegistroPonto.jsx que eu lhes apresentei no post anterior. Mas não estavam funcionando, até eu instalar e chamar o tailwind como fizemos neste post.

Isto foi feito para indicar o efeito do tailwind na formatação das telas.

import { useState, useEffect, useRef } from "react";
import { getUserByFaceId, registerPoint } from "../services/mockApi";

const RegistroPontoTail = () => {
  const [location, setLocation] = useState(null);
  const [user, setUser] = useState(null);
  const [status, setStatus] = useState("");
  const [error, setError] = useState("");
  const videoRef = useRef(null);

  const handleRegistro = () => {
    setStatus("Capturando localização...");
    setError("");

    navigator.geolocation.getCurrentPosition(
      (pos) => {
        const coords = [pos.coords.latitude, pos.coords.longitude];
        setLocation(coords);
        setStatus("Capturando imagem...");

        const fakeFaceId = "ana123";
        const foundUser = getUserByFaceId(fakeFaceId);

        if (foundUser) {
          setUser(foundUser);
          const result = registerPoint(foundUser.id, coords);
          setStatus(`✅ Ponto registrado às ${new Date(result.timestamp).toLocaleTimeString()}`);
        } else {
          setStatus("❌ Usuário não reconhecido.");
        }
      },
      (err) => {
        setError("Erro ao obter localização: " + err.message);
        setStatus("");
      },
      {
        enableHighAccuracy: true,
        timeout: 30000,
        maximumAge: 0,
      }
    );
  };

  useEffect(() => {
    navigator.mediaDevices
      .getUserMedia({ video: true })
      .then((stream) => {
        if (videoRef.current) {
          videoRef.current.srcObject = stream;
        }
      })
      .catch(() => {
        setError("Erro ao acessar câmera.");
      });
  }, []);

  return (
    <div className="min-h-screen flex items-center justify-center bg-gray-100 px-4">
      <div className="bg-white shadow-lg rounded-lg p-6 w-full max-w-md">
        <h2 className="text-2xl font-bold text-teal-700 mb-4 text-center">Registro de Ponto</h2>

        <video
          ref={videoRef}
          autoPlay
          className="w-full h-64 object-cover rounded border mb-4"
        />

        <button
          onClick={handleRegistro}
          className="w-full bg-teal-600 text-white py-2 px-4 rounded hover:bg-teal-700 transition"
        >
          Registrar Ponto
        </button>

        <div className="mt-4 text-sm">
          {status && <p className="text-gray-700 mb-2">{status}</p>}
          {error && <p className="text-red-600">{error}</p>}
          {user && (
            <div className="mt-2 text-gray-800">
              <p><strong>Usuário:</strong> {user.name}</p>
              <p><strong>Localização:</strong> {location?.[0]}, {location?.[1]}</p>
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

export default RegistroPonto;

Se quiser, posso te ajudar a aplicar estilos reais no seu app ou configurar navegação entre páginas. Quer seguir com isso?
Você pode remover qualquer style={{…}} inline e substituir por classes Tailwind. Isso deixa o código mais limpo, responsivo e fácil de manter.
Se quiser, posso revisar seu RegistroPonto.jsx atual e te mostrar exatamente onde aplicar cada classe Tailwind. Quer que eu faça isso agora?

Como vemos , o tailwind define na propriedade classname do html a formatação desejada, incluindo responsiveness. Vamos testar o que foi criado até agora, antes de prosseguirmos inserindo o comando npm run dev no terminal e carregar no browser o endereço localhost:5173

No chrome se pressionar F12, teremos a visão deste app em um celular

Tela do PWA após Tailwind: Registro de Ponto com câmera, botão estilizado Registrar Ponto, cartão de status com ponto registrado às 13:12:34, usuário Marcelo Gatti e localização.
Tela 2 — Depois do Tailwind (layout melhorado e organizado)

Como vimos , ficou muito melhor.

 
A IA ofereceu melhorar a aparência mais ainda usando o tailwind.

Porém, ainda estamos usando dados fake para o reconhecimento facial e estamos ansiosos para ver a coisa toda funcionando, então ao invés de melhorar a aparência do app, vamos no próximo post ligar este app com uma biblioteca real de reconhecimento facial.

Para isso, emitiremos o post:

Vamos seguir agora para a simulação do reconhecimento facial com uma biblioteca real

Pessoal até o próximo post….

Referências