Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Mostrar o valor de uma expressão regular

Cavalheiros, estou com um pequeno problema em um trecho de código. Preciso preencher uma coluna com a somatória de horas retornadas de um método, mas não estou conseguindo. Segue o código:

<tfoot>
    <td colspan="5"></td>
    <td>
        ${
            (function(){
                var soma = '00:00';
                modelo.listaCadastroPontos.forEach(cp => {
                    soma = TimeHelper.stringToTime([soma,cp.horasTrabalhadas], 'soma');
                    return soma;
                });
            })();
        }
    </td>
</tfoot>

Footer da Classe que gera o template da view:

Código da Classe TimeHelper que é utilizado pela chamada da View, essa classe converte Strings em minutos e depois devolve o valor já formatado em string novamente:

class TimeHelper{
    constructor(){
        throw new Error('TimeHelper não pode ser instânciada!');
    }

    static horasTrabalhadas(minutosTrabalhados){

        let horas = 0;
        let minutos = 0;
        let arrayMinutos = [];

        if(typeof(minutosTrabalhados) == 'object'){
            for(var i = 0; i < minutosTrabalhados.length; i++){

                horas += parseInt((minutosTrabalhados[i] / 60).toFixed(0));
                minutos += minutosTrabalhados[i] % 60;
            }
        }

            arrayMinutos.push(horas);
            arrayMinutos.push(minutos);

        return arrayMinutos;
    }

    static stringToTime(campos, info){

        let soma;
        let horas;
        let minutos;
        let arrayMinutos = [];
        let arrayMinutosSoma = [];
        let minutosTrabalhados;
        let arrayHorasMinutos;

        if(info == 'soma'){
            for(var i = 0; i <= (campos.length -1); i++){


                if(campos[i].length < 5)
                        arrayMinutosSoma.push(parseInt(campos[i].slice(0,1) * 60) + parseInt(campos[i].slice(2,4)));


                if(campos[i].length == 5)
                    arrayMinutosSoma.push(parseInt(campos[i].slice(0,2) * 60) + parseInt(campos[i].slice(3,5)));


            };

            soma = this.horasTrabalhadas(arrayMinutosSoma);

            horas = soma[0];
            minutos = soma[1];

            return `${horas}:${minutos}`;
        }
}

A saída no console mostra que o método esta devolvendo uma string e a variável na view recebe o valor mas não estou conseguindo imprimir o valor na coluna.

Desde já agradeço quem puder ajudar!

7 respostas

Esse trecho isolado funciona?

var soma = '00:00';
                modelo.listaCadastroPontos.forEach(cp => {
                    soma = TimeHelper.stringToTime([soma,cp.horasTrabalhadas], 'soma');
                    return soma;
                });

Você esta usando return dentro de um forEach. A lógica desse trecho não faz sentido ser usada com for each. Difícil de compreender o que você quer nesse trecho.

Seu código da iife não retorna valor algum. Por isso nada é exibido.

Só você corrigir seu código isoladamente primeiro que o valor será impresso na coluna.

Aguardo o teste da sua lógica nova.

solução!

Bom..sem eu testar talvez você queira isso

${
            (function(){
                var soma = '00:00';
                modelo.listaCadastroPontos.forEach(cp => {
                    soma = TimeHelper.stringToTime([soma,cp.horasTrabalhadas], 'soma');
                });
               return soma;
            })();
}

Para ficar melhor do que já esta tente usar reduce no lugar do forEach.

Flavio, boa noite! Deu super certo cara, muitíssimo obrigado, eu nem me toquei que o retorno estava dentro do for each, a variável recebia o valor mas não printava na coluna. Vou fazer utilizando o reduce, creio que fica mais elegante.

Mais uma vez obrigado, abraço!

Ou vc pode criar um método no seu modelo que já devolve o total. Vai ficar lindo e simplificar seu template.

Se inspira nesse exercício:

https://cursos.alura.com.br/course/javascript-es6-orientacao-a-objetos-parte-2/task/17511

Cole o resultado aqui para eu ver!

Flávio, missão cumprida! Ficou da seguinte forma:

Classe Lista de Cadastros

class ListaCadastroPontos{

    constructor(){

        this._listaCadastroPontos = [];
    }

    get listaCadastroPontos(){
        return [].concat(this._listaCadastroPontos);
    }

    get somaHorasTrabalhadas(){
        return this.listaCadastroPontos.reduce((soma, cp) => soma = TimeHelper.stringToTime([soma,cp.horasTrabalhadas], 'soma'),'00:00');
    }

    adicionar(cadastroPonto){

        this._listaCadastroPontos.push(cadastroPonto);
    }

    remover(){

        this._listaCadastroPontos = [];    
    }

}

Classe da View com a template

class CadastroPontoView{

    constructor(elemento){
        this._elemento = elemento;
    }

    _template(modelo){

        return `
                <table>
                    <thead>
                        <tr>
                            <th>Data </th>
                            <th>Hora de Entrada</th>
                            <th>Início do Intervalo</th>
                            <th>Retorno do Intervalo</th>
                            <th>Hora de Saída</th>
                            <th>Horas Trabalhadas</th>
                        </tr>
                    </thead>

                    <tbody>
                        ${
                            modelo.listaCadastroPontos.map(cp => {
                                return `
                                        <tr>
                                            <td>${DateHelper.dateToString(cp.dataDia)}</td>
                                            <td>${cp.horaEntrada}</td>
                                            <td>${cp.inicioIntervalo}</td>
                                            <td>${cp.fimIntervalo}</td>
                                            <td>${cp.horaSaida}</td>
                                            <td>${cp.horasTrabalhadas}</td>
                                        </tr>
                                        `
                        }).join('')
                        }

                    </tbody>

                    <tfoot>
                        <td colspan="5"></td>
                        <td>${modelo.somaHorasTrabalhadas}</td>
                    </tfoot>
                </table>
            `;
    }

    update(modelo){

        this._elemento.innerHTML = this._template(modelo);
    }    
}

Muito mais enxuto, elegante e OO. Obrigado pelas dicas e pela ajuda! Abraço!

Ficou excelente! Então, a dica é sempre essa: sempre que dentro do seu template tiver alguma lógica, extraia para um método (ou um getter) do módulo que é usado pelo template e chame esse método ou getter no template. Assim ele fica mais fácil de visualizar e de dar manutenção. Por exemplo, se você trocar de template, a lógica continua no modelo e você não perde.

Sucesso e bom estudo, meu aluno, promissor cangaceiro em JavaScript!