
Iniciamos fazendo a criação das pastas e páginas
iniciais do projeto.
Em seguida baixamos a versão a ser utilizada do
Bootstrap (v3.3.6) no modo customizado (sem Javascript,
sem JQuery e sem Magic). Essa função pode ser executada
no site do Bootstrap na opção
Customize.
Em seguida inserimos uma navbar simples cujo
modelo foi retirado do próprio site do
Bootstrap (procurar os modelos de código
diretamente em components)
Em seguida criamos um arquivo config.js que
preenche em princípio o <title> e o link da
navbar. Foi feito isso utilizando o objeto
document, através do atributo
title para a tag <title> e
getElementById para a navbar.

Na sequencia criamos o arquivo com a lógica principal da
aplicação. Nesse arquivo vamos criar um array de objetos
com os atributos de cada um. Essa lista foi criada
apenas para testar a lógica que será construida.
Em seguida fizemos uma função que recebe a lista como
parametro e executa um laço for / in para
recuperar cos valores e quantidades do array de
produtos, executar a multiplicação entre eles e atribuir
a uma variável total.

Agora iniciamos a criação da tabela que irá mostrar os
produtos no app.
Utilizamos uma contrução básica do Bootstrap iniciando
com um
container seguido de uma <table> padrão
(consultar a documentação do Bootstrap). Em seguida
criamos uma tabela estática apenas para visualisar a
interface.
Para criar a tabela dinamicamente vamos passar as tags
da tabela todas através de uma função JS.
Criamos primeiramente uma variável que receberá uma
string com todas as tags iniciais da tabela (sem
espaçamento ou formatação) até a tag de início do corpo
da tabela <tbody>.
Em seguida populamos a tabela com os dados do array
utilizando o
fo / in para todos os elementos e concatenando
seus valores com as tags da tabela. Desse modo, criamos
uma grande string com todos os valores em html
acrescidos dos valores de cada atributo do array e
inserimos essa string com o innerHTML dentro do
elemento <table> através de
getElementById().

Aqui fizemos a formatação dos valores que serão
apresentados na tabela.
Para a descrição criamos uma função que recebe o valor
da descrição, converte todos os caracteres para
lower case, para uniformizar o texto. Em seguida
selecionamos o primeiro caractere e convertemos para
uppercase, e por fim concatenamos esse caractere
com o resto da string através do slice() que
quebra a string a partir do segundo caractere.
Para o valor, primeiramente convertemos a string de
numero para um número do tipo float com
parseFloat().fixed(2) com duas casa decimais
fixas. Feito isso concatenamos com um valor ' ', para
reconverter esse numero para string. Utilizamos então o
replace() para substituir o '.' por ',' e
concatenamos essa string com o '$' para apresentar o
valor no formato desejado.

Para criar os campos de inserção de dados primeiramente
criamos os elementos no html. Criamos uma estrutura
Bootstrap de formulário com a classe
form-inline onde inserimos os <input> e o
<button>. O evento onclick do botão dispara
uma função para adicionar os itens.
Para adicionar os itens na lista recuperamos os dados de
cada input com document.getElementById().value.
Em seguida criamos uma entrada no array
list utilizando o método
unshift() (adiciona elementos no início do
array) e recarregamos a função setList() para
atualizar a exibição da lista. Entretanto nesse momento
os itens adicionados são perdidos quando atualizamos o
app pois a adição é temporária.

Criamos aqui dois botões que terão a função de salvar os
dados e resetar os campos digitados.
Em seguida vamos inserir na string que cria os dados na
tabela um <button> que irá executar no evento
onclick a função setUpdate() que terá
como parâmetro a variável local key que
identifica cada registro da lista.
Os botões criados anteriormente foram colocados em uma
<span>. Essa tag que encapsula os dois botões vai
receber um
style="display: none" para ser exibida apenas
quando clicamos no botão Edit.
Na função setUpdate() recebemos o id ddo
elemento clicado e setamos os valores da tags
<input> com o método
document.getElementById(id_do_input).value. Com
isso preenchemos os <input> com os valores do
elemento a ser alterado.
Para finalizar alteramos o style da <span> que
encapsula os botões para inline-block e o estilo
do <button> add para display: 'none'.
Com isso alteramos a exibição dos botões de acordo com a
função a ser executada.
Criamos uma função resetForm() para limpar os
campos de edição e voltar os botões para a definição
inicial.

Para recuperarmos os dados para atualização foi
utilizado uma forma que não achei muito interessante.
Primeiro criamos uma <span> dentro da <span> dos
botões que receberá um <input> do tipo
hidden onde será armazenado o valor do 'id' do
elemento editado. Esse <input> é adicionado ao html
pelo JS com a string abaixo:
document.getElementById("inputIDUpdate").innerHTML
= '<input type="hidden" id="idUpdate" value="' +
id + '" />"'
O valor desse campo deve ser limpo na função de
resetForm() também.
Em seguida implementamos a função
updateData() que é executada quando clicamos no
botão 'Save'.
Essa função armazena em variáveis os valores dos campos
<input> (inclusive do campo oculto) e recria o
objeto no array com os dados novos.
O problema aqui, e o professor menciona que pode ser
feito dessa forma, é que seria mais fácil recuperar o id
através de uma variável global no JS ao invés de criar a
tag <input type="hidden">.

Para implementar a função de deletar um item, primeiro
copiamos a estrutura do botão igual a do botão
Edit. Para este botão vamos criar uma função
deleteData().
Nesta função vamos fazer um teste lógico para confirmar
a exclusão do registro portanto a lófica ficará dentro
de um
if(confirm()) que irá solicitar uma confirmação
da ação. Caso seja retornado 'true' a primeira lógica
será verificar se é o último item do array para podermos
utilizar o método pop(). Para isto testamos se
o registro solicitado tem o 'id === list.length - 1'.
Nesse caso o registro selecionado é o último portanto
podemos utilizar o pop(). Utilizamos a mesma
lógica para remover o primeiro item da lista, mas nesse
caso ao invés de utilizar o pop() utilizamos o
shift() para o 'id === 0'.
Para remover os itens do meio do array utilizamos a
seguinte técnica.
Criamos duas variáveis que vão armazenar os itens do
array até o índice selecionado e outra que irá armazenar
os itens do indice selecionado + 1 até o final. Para
isso utilizamos o método
slice() Em seguida concatenamos os dois arrays
resultantes que será o array original menos o item
excluido com o método concat(). A rotina é a
seguinte:
var arrAuxIni = list.slice(0, id);
var arrAuxEnd = list.slice(id + 1);
list = arrAuxIni.concat(arrAuxEnd);

Vamos validar nossos dados para evitar que sejam
adicionados campos vazios ou com valores incorretos.
Para iniciar criamos uma função
formatAmount() que converte em inteiro com
parseInt() o valor digitado no campo 'Amount'.
Isso faz com que o valor seja sempre um número ou
retorne 'NaN'.
Em seguida vamos criar uma função de validação de dados.
Essa função fará testes lógicos de cada valor que pode
ser adicionado nos campos de <input>. Esses testes
verfificam se o campo está vazio e nos casos em que o
valor deve ser numérico se atende a esse requisito. Em
caso de erro gera uma mensagem para cada tipo. Ao final
verifica se exitem erros e se sim (return 0) retorna a
mensagem em uma tag de errors.
A função validation() será inserida nas funções
addData() e updateData() como parte de
um teste lógico. Se o valor for '0' (false no caso
representado por '!') retorna a mensagem da função
validation(). Caso contrário mantém a execução
normal do app.
Para finalizar ajustamos o display do elemento
que insere as imagens de erro para que as mensagens
saiam quando o retorno for 'true'.
Finalizando fizemos alguma estilizações em na mensagerm
de erro maipulando os estilos um a um no JS.

Para implementarmos o valor total no app utilizamos uma
'navbar' padrão do Bootstrap do tipo 'fixed to bottom'.
Para apresentarmos o valor apenas inserimos o valor
recuperado em
getTotal() e incluirmos no <span> da
'navbar' que apresenta o valor total.
Para atualisarmos o valor total a cada manipulação da
lista inserimos a função getTotal ao final da
função setList() que é responsável por
atualizar a lista de elementos.

Neste módulo inserimos uma <span> para encapsular o
botão 'Add' e incluir mais dois botões. O botão de
'Reset' para limpar os dados dos 'inputs' que reutilizou
a função resetForm() e um botão 'Delete List'
para limpar a lista.
A função deleteList() simplesmente atribui um
valor '[ ]' para o array da lista.

Para gravar os dados no 'Local Storage' criamos duas
funções. A primeira é responsável por gravar os dados.
Para isso criamos um JSON com os dados do array
utilizando JSON.stringify(). Esse 'JSON' é
enviado para o 'Local Storage' com o método
localStorage.setItem('nome_do_indice',
arquivo_json).
Em seguida criamos a função
initListStorage() que recupera os dados de
'Local Storage' com o método
localStorage.getItem(). Ele faz o teste para
ver se existe dados no indice e se sim recupera os dados
com o método
JSON.parse(lista_em_local_storage) e chama a
função setList() para apresentar os dados na
tela.