Skip to content

Instantly share code, notes, and snippets.

@realfakenerd
Last active July 3, 2019 22:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save realfakenerd/1ac189d5af453e69d108d7779034d9e5 to your computer and use it in GitHub Desktop.
Save realfakenerd/1ac189d5af453e69d108d7779034d9e5 to your computer and use it in GitHub Desktop.
...
class Bind {
constructor(model, view, ...props) {
let proxy = ProxyFactory.create(model, props, model => {
view.update(model)
});
view.update(model);
return proxy;
}
}
class DateHelper {
constructor() {
throw new Error('DateHelper não pode ser instanciado!!!')
}
static formataData(data) {
return `${data.getDate()}`
/ `${data.getMonth() + 1}`
/ `${data.getFullYear()}`
}
static textoParaData(texto) {
if (!/\d{2}\/\d{2}\/\d{4}/.test(texto)) {
throw new Error('Deve estar no formato dd/mm/aaaa');
}
return new Date(...texto.split('/').reverse().map((item, indice) => item - indice % 2));
}
}
class HttpService {
get(url) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
resolve(JSON.parse(xhr.responseText));
} else {
reject(xhr.responseText);
}
}
}
xhr.send();
});
}
post(url, dado) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'aplication/json');
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
resolve(JSON.parse(xhr.responseText));
} else {
reject(xhr.responseText);
}
}
};
xhr.send(JSON.stringify(dado));
});
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Negociações</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<script src="app/pollyfill/es6.js"></script>
</head>
<body class="container">
<h1 class="text-center display-4">Negociações</h1>
<div id="mensagemView"></div>
<form class="form" onsubmit="negociacaoController.adiciona(event)">
<div class="form-group">
<label for="data">Data:</label>
<input type="text" id="data" class="form-control" placeholder="dd/mm/yyyy" required autofocus />
</div>
<div class="form-row">
<div class="form-group col-6">
<label for="quantidade">Quantidade:</label>
<input type="number" min="1" step="1" id="quantidade" class="form-control" value="1" required />
</div>
<div class="form-group col-6">
<label for="valor">Valor:</label>
<input id="valor" type="number" class="form-control" min="0.01" step="0.01" value="0.0" required />
</div>
</div>
<button class="btn btn-primary" type="submit">Incluir</button>
</form>
<div class="text-center">
<button onclick="negociacaoController.importaNegociacoes()" class="btn btn-primary" type="button">
Importar Negociações
</button>
<button onclick="negociacaoController.remove()" class="btn btn-primary" type="button">
Apagar
</button>
</div>
<br>
<br>
<div id="negociacoesView"></div>
<script src="app/models/Negociacao.js"></script>
<script src="app/models/ListaNegociacoes.js"></script>
<script src="app/models/Mensagens.js"></script>
<script src="app/controllers/NegociacaoController.js"></script>
<script src="app/helpers/DateHelper.js"></script>
<script src="app/views/Views.js"></script>
<script src="app/views/NegociacoesView.js"></script>
<script src="app/views/MensagensView.js"></script>
<script src="app/services/ProxyFactory.js"></script>
<script src="app/helpers/Bind.js"></script>
<script src="app/services/NegociacaoService.js"></script>
<script src="app/services/HttpService.js"></script>
<script src="app/services/ConnectionFactory.js"></script>
<script src="app/dao/NegociacaoDAO.js"></script>
<script>
var negociacaoController = new NegociacaoController();
</script>
</body>
</html>
class ListaNegociacoes {
constructor(armadilha) {
this._negociacoes = [];
}
adiciona(negociacao) {
this._negociacoes.push(negociacao);
}
get negociacoes() {
return [].concat(this._negociacoes);
}
esvazia() {
this._negociacoes = [];
}
get volumeTotal() {
return this._negociacoes.reduce((total, n) => total + n.volume, 0.0);
}
ordena(criterio){
this._negociacoes.sort(criterio);
}
inverteOrdem(){
this._negociacoes.reverse();
}
}
class Mensagens {
constructor(texto) {
this._texto = texto || '';
}
get texto(){
return this._texto;
}
set texto(texto){
this._texto = texto;
}
}
class MensagensView extends Views {
constructor(elemento) {
super(elemento)
}
template(model) {
return model.texto ? `<p class="alert alert-info">${model.texto}</p>` : `<p></p>`;
}
}
class Negociacao {
constructor(data, quantidade, valor) {
this._data = new Date(data.getTime());
this._quantidade = quantidade;
this._valor = valor;
Object.freeze(this);
}
get volume(){
return this._quantidade * this._valor;
}
get data(){
return new Date(this._data.getTime());
}
get quantidade(){
return this._quantidade;
}
get valor(){
return this._valor;
}
}
class NegociacaoController {
constructor() {
let $ = document.querySelector.bind(document);
this._ordemAtual = '';
this._inputData = $("#data");
this._inputQuantidade = $("#quantidade");
this._inputValor = $("#valor");
this._listaNegociacoes = new Bind(
new ListaNegociacoes(),
new NegociacoesView($("#negociacoesView")),
'adiciona', 'esvazia', 'ordena', 'inverteOrdem'
);
this._mensagem = new Bind(
new Mensagens(),
new MensagensView($("#mensagemView")),
'texto'
);
ConnectionFactory
.getConnection()
.then(connection => new NegociacaoDAO(connection).listAll())
.then(negociacoes => negociacoes.forEach(negociacao => this._listaNegociacoes.adiciona(negociacao)))
.catch(err => console.log(err))
}
adiciona(event) {
event.preventDefault();
ConnectionFactory
.getConnection()
.then(conexao => {
let negociacao = this._criaNegociacao();
new NegociacaoDAO(conexao)
.adiciona(negociacao)
.then(() => {
this._listaNegociacoes.adiciona(this._criaNegociacao());
this._mensagem.texto = 'Negociação concluida com sucesso!';
this._limpaForm();
})
.catch(err => this._mensagem.texto = err);
})
}
importaNegociacoes() {
let service = new NegociacaoService();
service.getNegociacao()
.then(negociacoes => {
negociacoes.forEach(negociacao => this._listaNegociacoes.adiciona(negociacao));
this._mensagem.texto = 'Negociação importada com sucesso!'
}).catch(err => this._mensagem.texto = err);
}
remove() {
this._listaNegociacoes.esvazia();
this._mensagem.texto = 'Negociações apagadas com sucesso';
}
_criaNegociacao() {
return new Negociacao(
DateHelper.textoParaData(this._inputData.value),
parseInt(this._inputQuantidade.value),
parseFloat(this._inputValor.value),
);
}
_limpaForm() {
this._inputData.value = '';
this._inputQuantidade.value = 1;
this._inputValor.value = 0.0;
this._inputData.focus();
}
ordena(col) {
if (this._ordemAtual == col) {
this._listaNegociacoes.inverteOrdem();
} else {
this._listaNegociacoes.ordena((a, b) => a[col] - b[col]);
}
this._ordemAtual = col;
}
}
class NegociacaoDAO {
constructor(connection) {
this._connection = connection;
this._store = 'negociacoes';
}
adiciona(negociacao) {
return new Promise((resolve, reject) => {
let request = this._connection
.transaction([this._store], 'readwrite')
.objectStore(this._store)
.add(negociacao);
request.onsuccess = (e) => {
resolve();
}
request.onerror = (e) => {
console.log(e.target.result);
reject('Não foi possível adicionar a negociação');
}
});
}
listAll() {
return new Promise((resolve, reject) => {
let cursor = this._connection
.transaction([this._store], "readwrite")
.objectStore(this._store)
.openCursor();
let negociacoes = [];
cursor.onsuccess = e => {
let atual = e.target.result;
if (atual) {
let dado = atual.value;
negociacoes.push(new Negociacao(dado._data, dado._quantidade, dado._valor));
atual.continue();
} else {
resolve(negociacoes);
}
}
cursor.onerror = e => {
console.log(e.target.error);
reject('Não foi possível listar as negociações');
}
});
}
}
class NegociacaoService {
constructor() {
this._http = new HttpService();
}
getNegociacaoSemana() {
return this._http
.get('negociacoes/semana')
.then(negociacoes => {
return negociacoes.map(objeto => new Negociacao(new Date(objeto.data), objeto.quantidade, objeto.valor));
})
.catch(err => {
console.log(err);
throw new Error('Não foi possível obter as negociações da semana!');
});
}
getNegociacaoSemanaPassada() {
return this._http
.get('negociacoes/anterior')
.then(negociacoes => {
return negociacoes.map(objeto => new Negociacao(new Date(objeto.data), objeto.quantidade, objeto.valor));
})
.catch(err => {
console.log(err);
throw new Error('Não foi possível obter as negociações da semana passada!');
});
}
getNegociacaoSemanaRetrasada() {
return this._http
.get('negociacoes/retrasada')
.then(negociacoes => {
return negociacoes.map(objeto => new Negociacao(new Date(objeto.data), objeto.quantidade, objeto.valor));
})
.catch(err => {
console.log(err);
throw new Error('Não foi possível obter as negociações da semana retrasada!');
});
}
getNegociacao() {
return Promise.all([
this.getNegociacaoSemana(),
this.getNegociacaoSemanaPassada(),
this.getNegociacaoSemanaRetrasada()
]).then(periodos => {
let negociacoes = periodos.reduce((dados, periodo) => dados.concat(periodo), []);
return negociacoes;
}).catch(err => {
throw new Error(err)
})
}
}
class NegociacoesView extends Views {
constructor(elemento) {
super(elemento)
}
template(model) {
return `
<table class="table table-hover table-bordered">
<thead class="thead-light">
<tr>
<th onclick="negociacaoController.ordena('data')">DATA</th>
<th onclick="negociacaoController.ordena('quantidade')">QUANTIDADE</th>
<th onclick="negociacaoController.ordena('valor')">VALOR</th>
<th onclick="negociacaoController.ordena('volume')">VOLUME</th>
</tr>
</thead>
<tbody>
${model.negociacoes.map(n => `
<tr>
<td>${DateHelper.formataData(n.data)}</td>
<td>${n.quantidade}</td>
<td>${n.valor}</td>
<td>${n.volume}</td>
</tr>
`).join('')}
</tbody>
<tfoot>
<td colspan='3'></td>
<td>
${model.volumeTotal}
</td>
</tfoot>
</table>
`;
}
}
class ProxyFactory {
static create(objeto, props, acao) {
return new Proxy(new ListaNegociacoes(), {
get(target, prop, receiver) {
if (props.includes(prop) && ProxyFactory._ehFunction(target[prop])) {
return function () {
let retorno = Reflect.apply(target[prop], target, arguments);
acao(target);
return retorno;
}
}
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
let retorno = Reflect.set(target, prop, value, receiver);
if (props.includes(prop)) {
console.log(`Interceptado: ${prop}`)
acao(target);
}
return retorno;
}
})
}
static _ehFunction(func) {
return typeof (func) == typeof (Function);
}
}
class Views {
constructor(elemento) {
this._elemento = elemento;
}
template(){
throw new Error('O método template deve ser implementado!');
}
update(model) {
this._elemento.innerHTML = this.template(model);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment