Seguidores

segunda-feira, 9 de junho de 2025

Estudo de Caso T2E5: Solução de Problema com IA e MASP - Correção T2E4

 INTRODUÇÃO

Este é o episódio 5 da temporada 2 da série “Estudo de Caso”, com foco na correção de um Bug em aplicativo Web, utilizando Inteligência Artificial (IA).



O objetivo deste Post é mostrar um Prompt para pedir a um Chatbot de IA, uma correção no código fonte onde ocorreu o Bug relatado no Episódio 4 da Temporada 2 da Série Estudo de Caso.

No Episódio 4 o Chatbot de IA Gemini forneceu um Plano de Ação para descobrir a causa do Bug e neste Episódio 5, o Gemini fará a correção do Bug.

O Prompt terá a estrutura abaixo:
  1. Objetivo
  2. Resultado
  3. Alertas  
  4. Contexto 
Para informações adicionais sobre essa estrutura de Prompt veja este post: Dicas de prompt para Chatbot de IA fazer mudanças em aplicativos

1 Objetivo

O objetivo deste prompt é solicitar ao Chatbot de IA Gemini a implementação de mudanças no código fonte fornecido no item 4 Contexto, escrito em React JS, a fim de corrigir um bug, por meio da implementação da regra abaixo:

"O botão RESUMO deve ser apresentado, incondicionalmente".

2 Resultado

O resultado deve ser um conjunto de mudanças no código fonte React JS, fornecido no item 4 Contexto.

As mudanças devem ficar prontas para execução, sem nenhuma intervenção do desenvolvedor. 

3 Alerta

O código fonte da correção deve ser escrito para a versão 15.6.1 do React JS.

4 Contexto

O contexto é caracterizado pelo código fonte abaixo.

import React from 'react';
import {Link} from 'react-router';
import ajax from '../../ajax-utils';
import { Modal, Button } from 'react-materialize';

let SectionCandidateDateil = React.createClass({
    /* Adicionado pelo AI Assistant  */
    getInitialState: function() {
        return {
          user_id: this.props.user.id,
          elections: [],
          litigation: this.props.user.public_perfil != null && this.props.user.public_perfil.litigation != null ? this.props.user.public_perfil.litigation : null,
          nomeEleicao: ' ',
          idEleicao: 0,
          roleName: this.props.user.public_perfil != null && this.props.user.public_perfil.litigation != null ? this.props.user.public_perfil.litigation.role : null,
          partyName: this.props.user.public_perfil != null && this.props.user.public_perfil.litigation != null ? this.props.user.public_perfil.litigation.party : null,
          statusName: this.props.user.public_perfil != null && this.props.user.public_perfil.litigation != null ? this.props.user.public_perfil.litigation.status : null,
          loading_fetchElection:false,
          loading_fetchLitigation:false,
          loading_getRoleName: false,
          loading_getPartyName: false,
          loading_getStatusName: false
        };
    },
    /* Adicionado pelo AI Assistant  */
    componentDidMount: function() {
    /*
        ajax.fetchElection().then(elections => {
          this.setState({elections});
          if (elections.length > 0) {
              this.updateLitigationDetails(elections[0].id);
          }
        });
    */
        this.setState({loading_fetchElection:true});
        ajax.fetchElection().then(data => {
          let {err, elections} = data;
          if (err) return alert(err);
          if (elections.length > 0 && this.state.litigation != null) {
              this.updateLitigationDetails(elections[0].name, elections[0].id);
          }

          this.setState({
            elections: elections,
            nomeEleicao: elections[0].name,
            idEleicao: elections[0].id,
            loading_fetchElection:false
          });
        });
    },
    showModal () {
        $('#remuseppc').modal('open');
    },
    /* Adicionado pelo AI Assistant  */
    handleElectionChange(event) {
      const selectElement = event.target;
      const electionName = selectElement.options[selectElement.selectedIndex].text;
      const electionId = selectElement.value;
      this.setState({
          nomeEleicao: electionName,
          idEleicao: electionId
      });
      this.updateLitigationDetails(electionName, electionId);
    },
    updateLitigationDetails(electionName, electionId) {
      this.setState({loading_fetchLitigation:true});
      ajax.GetLitigationByElectorAndElection(this.props.user.id, electionId, electionName)
        .then(data => {
            let {err, litigation} = data;
            if (err) return alert(err);
            if (litigation.id !== -1 && litigation.id !== -2){
                this.getRoleName(litigation.role);
                this.getPartyName(litigation.party);
                this.getStatusName(litigation.status);
                this.setState({
                    litigation: litigation
                });
            }else{
                this.setState({
                    litigation: null,
                    roleName: " ",
                    partyName: " ",
                    statusName: " "
                });
                if (litigation.id === -1 ){
                    alert('Os dados do candidato não foram atualizados para a eleição!');
                    console.log('SectionCandidateDateil - updateLitigationDetails: Os dados do candidato não foram atualizados para a eleição!');
                }else{
                    if (litigation.id === -2 ){
                       alert('O status de candidato não foi atualizado para a Pessoa Pública!');
                       console.log('SectionCandidateDateil - updateLitigationDetails: O status de candidato não foi atualizado para a Pessoa Pública!');
                    }
                }
            }
            this.setState({
                loading_fetchLitigation:false
            });
        });
    },
    getRoleName(role_id){
        this.setState({loading_getRoleName:true});
        ajax.getRoleName(role_id).then(data => {
          let {err, role_name} = data;
          if (err) return alert(err);

          this.setState({
            roleName: role_name,
            loading_getRoleName:false
          });
        });
    },
    getPartyName(party_id){
        this.setState({loading_getPartyName:true});
        ajax.getPartyName(party_id).then(data => {
          let {err, party_name} = data;
          if (err) return alert(err);

          this.setState({
            partyName: party_name,
            loading_getPartyName:false
          });
        });
    },
    getStatusName(status_id){
        this.setState({loading_getStatusName:true});
        ajax.getStatusName(status_id).then(data => {
          let {err, status_name} = data;
          if (err) return alert(err);

          this.setState({
            statusName: status_name,
            loading_getStatusName:false
          });
        });
    },

  render() {
    let {user} = this.props;
    let {isLogged} = this.props;
    let shouldShowElectionDropdown = user.public_perfil != null && user.public_perfil.litigation != null &&
                                      ['Candidato', 'Pre-Candidato'].includes(user.public_perfil.litigation.status);
    return (
        <div>
            {
            user.public_perfil ? (              
                <div className="row col s12 m6 l6 xl6"> 

                    <h6 className="user-name">Perfil Público</h6>
                    <div className="row col s12 m6 l6 xl6">  
                    { user.public_perfil.email ? (<p ><i className="icon-mail-alt blue-text darken-2"></i> 
                     <a href={"mailto:" + user.public_perfil.email}> {user.public_perfil.email}</a></p>) : (
                        !isLogged ? (null): 
                            (<Link to={'/profile/electoral/edit'} className="red-text text-darken-2" > <p>Favor completar seu perfil</p> </Link>)                        
                     ) }

                    { user.public_perfil.facebook.length > 7 ? (
                        <p ><i className="icon-facebook-squared blue-text darken-2"></i> 
                        <a target="_blank" href={user.public_perfil.facebook}>Facebook</a></p>
                    ) : (<Link to={'/profile/electoral/edit'} className="red-text text-darken-2" > <p>Favor completar seu perfil</p> </Link>)}
                    
                    {user.public_perfil.personal.length > 7 ? (
                        <p ><i className=" icon-doc-7 blue-text darken-2"></i> 
                        <a target="_blank" href={user.public_perfil.personal}> Página</a></p>
                    ) : (
                        !isLogged ? (null): 
                        (<Link to={'/profile/electoral/edit'} className="red-text text-darken-2" > <p>Favor completar seu perfil</p> </Link>) 
                    )} 
                   
                    
                    {user.public_perfil.video.length > 7 ? (
                        <p ><i className=" icon-videocam-3 blue-text darken-2"></i> 
                        <a target='__black' href={user.public_perfil.video}>Vídeo</a></p>
                        ) : (
                            !isLogged ? (null): 
                            (<Link to={'/profile/electoral/edit'} className="red-text text-darken-2" > <p>Favor completar seu perfil</p> </Link>) 
                        )} 
                    
                    
                    {isLogged && user.public_perfil.resumo ? (
                        <p ><strong>Resumo:</strong> 
                            <buttom onClick={this.showModal}
                            className="waves-effect waves-light btn-small btn green-text custom-btn margin-bottom-10">Clique aqui </buttom>
                        </p>
                        ) : (
                            !isLogged ? (null): 
                            (<Link to={'/profile/electoral/edit'} className="red-text text-darken-2" > <p>Favor completar seu perfil</p> </Link>) 
                        )} 
                    <div className="col m5 s12 l5 xl5 center">
                                       
                                        <Modal id='remuseppc' 
                                        header='Resumo Perfil Público' 
                                        actions={
                                              <Button waves='light' flat className="btn-small waves-light green darken-2 white-text modal-action modal-close">Fechar</Button>
                                          }
                                        >
                                                         
                                        <h4><strong>{user.name}</strong></h4>
                                        <p>{user.public_perfil.resumo}</p>
                                        </Modal>
                                    </div>
                     </div>
                    {
                        user.public_perfil.litigation ? (
                            <div className="row col s12 m6 l6 xl6">
                                <p >{this.state.nomeEleicao}</p>
                                <p ><strong>Cargo:</strong> {this.state.roleName}</p>
                                <p ><strong>Partido:</strong> {this.state.partyName}</p>
                                <p ><strong>Status:</strong> {this.state.statusName}</p>
                                {
                                    this.state.litigation != null && this.state.litigation.number ? (
                                    <p ><strong>Número:</strong> {this.state.litigation.number}</p>
                                    ) : null
                                }
                            </div>
                        ): null
                    }

{
                user.public_perfil &&
                user.public_perfil.litigation &&
                window.location.href.includes("/profile/" + user.slug) ?
                (<div className="row col s12 m10 l10 xl10">
                  <a className="btn waves-light light-green darken-4 white-text center" 
                     href={`https://wa.me/?text=Para melhorar nossa cidade e a câmara legislativa, seguem informações sobre um candidato a considerar nessas eleições. ${window.location.href}`} 
                     data-action="share/whatsapp/share">Compartilhe aqui seu candidato</a>                        
                </div>) : (null)
              }
                </div> ):null
            }   
            
        </div>

    );
  }
});

export default SectionCandidateDateil;

Resposta do Gemini

Em relação ao seu pedido, o botão RESUMO será exibido incondicionalmente, conforme a regra de negócio que você especificou.


JavaScript
import React from 'react';
import {Link} from 'react-router';
import ajax from '../../ajax-utils';
import { Modal, Button } from 'react-materialize';

let SectionCandidateDateil = React.createClass({
    /* Adicionado pelo AI Assistant  */
    getInitialState: function() {
        return {
          user_id: this.props.user.id,
          elections: [],
          litigation: this.props.user.public_perfil != null && this.props.user.public_perfil.litigation != null ? this.props.user.public_perfil.litigation : null,
          nomeEleicao: ' ',
          idEleicao: 0,
          roleName: this.props.user.public_perfil != null && this.props.user.public_perfil.litigation != null ? this.props.user.public_perfil.litigation.role : null,
          partyName: this.props.user.public_perfil != null && this.props.user.public_perfil.litigation != null ? this.props.user.public_perfil.litigation.party : null,
          statusName: this.props.user.public_perfil != null && this.props.user.public_perfil.litigation != null ? this.props.user.public_perfil.litigation.status : null,
          loading_fetchElection:false,
          loading_fetchLitigation:false,
          loading_getRoleName: false,
          loading_getPartyName: false,
          loading_getStatusName: false
        };
    },
    /* Adicionado pelo AI Assistant  */
    componentDidMount: function() {
    /*
        ajax.fetchElection().then(elections => {
          this.setState({elections});
          if (elections.length > 0) {
              this.updateLitigationDetails(elections[0].id);
          }
        });
    */
        this.setState({loading_fetchElection:true});
        ajax.fetchElection().then(data => {
          let {err, elections} = data;
          if (err) return alert(err);
          if (elections.length > 0 && this.state.litigation != null) {
              this.updateLitigationDetails(elections[0].name, elections[0].id);
          }

          this.setState({
            elections: elections,
            nomeEleicao: elections[0].name,
            idEleicao: elections[0].id,
            loading_fetchElection:false
          });
        });
    },
    showModal () {
        $('#remuseppc').modal('open');
    },
    /* Adicionado pelo AI Assistant  */
    handleElectionChange(event) {
      const selectElement = event.target;
      const electionName = selectElement.options[selectElement.selectedIndex].text;
      const electionId = selectElement.value;
      this.setState({
          nomeEleicao: electionName,
          idEleicao: electionId
      });
      this.updateLitigationDetails(electionName, electionId);
    },
    updateLitigationDetails(electionName, electionId) {
      this.setState({loading_fetchLitigation:true});
      ajax.GetLitigationByElectorAndElection(this.props.user.id, electionId, electionName)
        .then(data => {
            let {err, litigation} = data;
            if (err) return alert(err);
            if (litigation.id !== -1 && litigation.id !== -2){
                this.getRoleName(litigation.role);
                this.getPartyName(litigation.party);
                this.getStatusName(litigation.status);
                this.setState({
                    litigation: litigation
                });
            }else{
                this.setState({
                    litigation: null,
                    roleName: " ",
                    partyName: " ",
                    statusName: " "
                });
                if (litigation.id === -1 ){
                    alert('Os dados do candidato não foram atualizados para a eleição!');
                    console.log('SectionCandidateDateil - updateLitigationDetails: Os dados do candidato não foram atualizados para a eleição!');
                }else{
                    if (litigation.id === -2 ){
                       alert('O status de candidato não foi atualizado para a Pessoa Pública!');
                       console.log('SectionCandidateDateil - updateLitigationDetails: O status de candidato não foi atualizado para a Pessoa Pública!');
                    }
                }
            }
            this.setState({
                loading_fetchLitigation:false
            });
        });
    },
    getRoleName(role_id){
        this.setState({loading_getRoleName:true});
        ajax.getRoleName(role_id).then(data => {
          let {err, role_name} = data;
          if (err) return alert(err);

          this.setState({
            roleName: role_name,
            loading_getRoleName:false
          });
        });
    },
    getPartyName(party_id){
        this.setState({loading_getPartyName:true});
        ajax.getPartyName(party_id).then(data => {
          let {err, party_name} = data;
          if (err) return alert(err);

          this.setState({
            partyName: party_name,
            loading_getPartyName:false
          });
        });
    },
    getStatusName(status_id){
        this.setState({loading_getStatusName:true});
        ajax.getStatusName(status_id).then(data => {
          let {err, status_name} = data;
          if (err) return alert(err);

          this.setState({
            statusName: status_name,
            loading_getStatusName:false
          });
        });
    },

  render() {
    let {user} = this.props;
    let {isLogged} = this.props;
    let shouldShowElectionDropdown = user.public_perfil != null && user.public_perfil.litigation != null &&
                                     ['Candidato', 'Pre-Candidato'].includes(user.public_perfil.litigation.status);
    return (
        <div>
            {
            user.public_perfil ? (         
                <div className="row col s12 m6 l6 xl6"> 

                    <h6 className="user-name">Perfil Público</h6>
                    <div className="row col s12 m6 l6 xl6">  
                    { user.public_perfil.email ? (<p ><i className="icon-mail-alt blue-text darken-2"></i>  
                     <a href={"mailto:" + user.public_perfil.email}> {user.public_perfil.email}</a></p>) : (
                         !isLogged ? (null): 
                             (<Link to={'/profile/electoral/edit'} className="red-text text-darken-2" > <p>Favor completar seu perfil</p> </Link>)         
                      ) }

                    { user.public_perfil.facebook.length > 7 ? (
                        <p ><i className="icon-facebook-squared blue-text darken-2"></i>  
                         <a target="_blank" href={user.public_perfil.facebook}>Facebook</a></p>
                    ) : (<Link to={'/profile/electoral/edit'} className="red-text text-darken-2" > <p>Favor completar seu perfil</p> </Link>)}
                    
                    {user.public_perfil.personal.length > 7 ? (
                        <p ><i className=" icon-doc-7 blue-text darken-2"></i>  
                         <a target="_blank" href={user.public_perfil.personal}> Página</a></p>
                    ) : (
                        !isLogged ? (null): 
                        (<Link to={'/profile/electoral/edit'} className="red-text text-darken-2" > <p>Favor completar seu perfil</p> </Link>) 
                    )} 
                    
                    
                    {user.public_perfil.video.length > 7 ? (
                        <p ><i className=" icon-videocam-3 blue-text darken-2"></i>  
                         <a target='__black' href={user.public_perfil.video}>Vídeo</a></p>
                         ) : (
                             !isLogged ? (null): 
                             (<Link to={'/profile/electoral/edit'} className="red-text text-darken-2" > <p>Favor completar seu perfil</p> </Link>) 
                         )} 
                    
                    
                    {/* Alteração para exibir o botão RESUMO incondicionalmente */}
                    <p ><strong>Resumo:</strong>  
                        <button onClick={this.showModal}
                        className="waves-effect waves-light btn-small btn green-text custom-btn margin-bottom-10">Clique aqui </button>
                    </p>
                    <div className="col m5 s12 l5 xl5 center">
                                            
                                             <Modal id='remuseppc' 
                                             header='Resumo Perfil Público' 
                                             actions={
                                                     <Button waves='light' flat className="btn-small waves-light green darken-2 white-text modal-action modal-close">Fechar</Button>
                                                  }
                                             >
                                                     
                                             <h4><strong>{user.name}</strong></h4>
                                             <p>{user.public_perfil.resumo}</p>
                                             </Modal>
                                         </div>
                     </div>
                    {
                        user.public_perfil.litigation ? (
                            <div className="row col s12 m6 l6 xl6">
                                <p >{this.state.nomeEleicao}</p>
                                <p ><strong>Cargo:</strong> {this.state.roleName}</p>
                                <p ><strong>Partido:</strong> {this.state.partyName}</p>
                                <p ><strong>Status:</strong> {this.state.statusName}</p>
                                {
                                    this.state.litigation != null && this.state.litigation.number ? (
                                    <p ><strong>Número:</strong> {this.state.litigation.number}</p>
                                    ) : null
                                }
                            </div>
                        ): null
                    }

{
                user.public_perfil &&
                user.public_perfil.litigation &&
                window.location.href.includes("/profile/" + user.slug) ?
                (<div className="row col s12 m10 l10 xl10">
                  <a className="btn waves-light light-green darken-4 white-text center" 
                      href={`https://wa.me/?text=Para melhorar nossa cidade e a câmara legislativa, seguem informações sobre um candidato a considerar nessas eleições. ${window.location.href}`} 
                      data-action="share/whatsapp/share">Compartilhe aqui seu candidato</a>                
                </div>) : (null)
              }
                </div> ):null
            }    
            
        </div>

    );
  }
});

export default SectionCandidateDateil;

CONCLUSÃO

O teste da mudança foi realizado com sucesso.


Demais Episódios da Temporada:





Nenhum comentário:

Postar um comentário

Entendendo a Metáfora "Home Office é Moto Boy"

UCEM L-pI.219 (199) Revisão VI - Caso de uso da IA para estudar

  Lição 219  Eu não sou um corpo. Eu sou livre.  Pois ainda sou como Deus me criou. Lição anterior Escolher outra lição Próxima lição Texto ...