Pesquisar na Comunidade
Mostrando resultados para as tags ''livewire''.
Encontrado 17 registros
-
Fazer modal no PHP ou no Laravel foi bem difícil para mim, pois eu não tinha nenhuma familiaridade com o JavaScript. Já o Livewire trouxe um novo conceito, onde você divide o HTML em várias partes, e você vai exibindo de acordo com a necessidade. No meu caso, eu dividi o HTML em $modal, $modal2 e $modal3. Dentro do primeiro $modal existem dezenas de "submodais" que são controlados pela variável $comando. $modal2 mostra a nota do fornecedor onde tem quantidade e preço. O $modal3 mostra a mesma nota, mas com o CFOP e o NCM. arquivo app > Livewire > NotaFiscal.php <?php namespace App\Livewire; use App\Models\tbdiario; use App\Models\tbpessoa; use App\Models\tbhistprod; use App\Models\tbprod; use Illuminate\Support\Facades\DB; use Livewire\Attributes\Layout; use Livewire\Component; use Livewire\WithFileUploads; #[Layout('components.layouts.app',['titulo'=>'NF do Fornecedor'])] class NotaFiscal extends Component { use WithFileUploads; public $comando="pegar xml",$criterio,$difAliqICMS,$inativos=[],$indicador,$lcto; public $modal=true,$modal2,$modal3; public $nNF,$opcoes=[],$previa=[],$quant,$soma,$xNome,$XmlFile,$vNF; function updatedXmlFile() { $this->previa=[]; $xmlContent=file_get_contents($this->XmlFile->getRealPath()); $nfe=simplexml_load_string($xmlContent); $itens=$nfe->NFe->infNFe->det; $this->difAliqICMS=0; $aliquotaInterna=0.18; foreach ($itens as $item) { if ((float)$item->prod->CFOP == 6102 || (float)$item->prod->CFOP ==6101) { $vBC = (float)$item->imposto->ICMS->ICMS10->vBC; $vBC = $vBC ? $vBC : (float)$item->imposto->ICMS->ICMS00->vBC; $vICMS = (float)$item->imposto->ICMS->ICMS10->vICMS; $vICMS = $vICMS ? $vICMS : (float)$item->imposto->ICMS->ICMS00->vICMS; $this->difAliqICMS += round(($vBC * $aliquotaInterna - $vICMS+0.00001),2); } } $this->vNF = (float)$nfe->NFe->infNFe->total->ICMSTot->vNF; $this->nNF = (string)$nfe->NFe->infNFe->ide->nNF; $this->xNome = (string)$nfe->NFe->infNFe->emit->xNome; $nome = explode(" ", $this->xNome)[0]; $codp = tbpessoa::where('pessoa','like','%'.$nome.'%')->value('codp'); $this->soma=0; foreach ($itens as $item) { $codforn = (string)$item->prod->cProd; $criterio= strtolower($nome[0].$codforn); $consulta = tbprod::where('codforn','like','%'.$criterio.'%')->get(); $cfop = (string)$item->prod->CFOP; $ncm = (string)$item->prod->NCM; if (count($consulta) == 1) { $codprod = $consulta[0]->codprod; if(substr($consulta[0]->cfop,0,1)==0) { $this->inativos[]=$consulta[0]->codprod; } $class=($cfop == substr($consulta[0]->cfop,-4)) ? "w-[50px] text-right" : "w-[50px] text-red-500 text-right"; $class2=($ncm == $consulta[0]->cf) ? "w-[100px] text-right" : "w-[100px] text-red-500 text-right"; } if (count($consulta) > 1) { $consulta2 = tbprod::where('codforn','like','%'.$criterio)->get(); if(count($consulta2) == 1){ $codprod = $consulta2[0]->codprod; $consulta = $consulta2; } else { $codprod = "mult"; } } if (count($consulta)==0) { $codprod = "none"; } $produto = substr((string)$item->prod->xProd,0,79); $quantidade = (float)$item->prod->qCom; if($cfop==6101 || $cfop==6102 || $cfop==5101) { $cfop=5102; } if($cfop==6401 || $cfop==6402 || $cfop==6403 || $cfop==5401 || $cfop==5403 || $cfop==5655) { $cfop=5405; } if (is_numeric($codprod)) { $produtoDobrado = [506, 507, 508, 509, 510, 519, 1768, 1770, 1772]; if (in_array($codprod, $produtoDobrado)) { $quantidade = 2 * $quantidade; } $produtox5=[1798]; if (in_array($codprod,$produtox5 )) { $quantidade = 5 * $quantidade; } $produtoX10 = [2192,1782,2456]; if (in_array($codprod, $produtoX10)) { $quantidade = 10 * $quantidade; } $produtox12 = [2403,2406,2496,2497,2498,2499]; if (in_array($codprod, $produtox12)) { $quantidade = 12 * $quantidade; } $produtox24 = [2493,2405,2494,2495,2409]; if (in_array($codprod, $produtox24)) { $quantidade = 24 * $quantidade; } } $vICMSST1 = ((float)$item->imposto->ICMS->ICMS10->vICMSST) ? (float)$item->imposto->ICMS->ICMS10->vICMSST : null; $vICMSST2 = ((float)$item->imposto->ICMS->ICMSSN202->vICMSST) ? (float)$item->imposto->ICMS->ICMSSN202->vICMSST : null; $vICMSST = $vICMSST1 ? $vICMSST1 : $vICMSST2; $difAliq = 0; if ((float)$item->prod->CFOP == 6102 || (float)$item->prod->CFOP == 6101){ $vBC = (float)$item->imposto->ICMS->ICMS10->vBC; $vBC = $vBC ? $vBC : (float)$item->imposto->ICMS->ICMS00->vBC; $vICMS = (float)$item->imposto->ICMS->ICMS10->vICMS; $vICMS = $vICMS ? $vICMS : (float)$item->imposto->ICMS->ICMS00->vICMS; $difAliq = round(($vBC * $aliquotaInterna - $vICMS+0.00001),2); } $vIPI =(isset($item->imposto->IPI->IPITrib->vIPI) && (float)$item->imposto->IPI->IPITrib->vIPI) ? (float)$item->imposto->IPI->IPITrib->vIPI : 0; $vProd = (string)$item->prod->vProd; $valorTotal = $vProd + $vICMSST + $difAliq + $vIPI; $this->soma += $valorTotal; $custoAtual = intval($valorTotal / $quantidade * 100) / 100; $custoAnterior=0; $marg=0; $cclass="w-[70px] text-right"; $nclass="w-[100px] text-right"; $fclass="w-[50px] text-right"; if (is_numeric($codprod)) { $consulta = tbprod::where('codprod',$codprod)->first(); $custoAnterior = $consulta->custo; $marg=$consulta->marg; if (abs($custoAnterior - $custoAtual) > 0.02) { $cclass = 'w-[70px] text-right text-red-500'; } if ($ncm !== $consulta->cf) { $nclass = 'w-[100px] text-right text-red-500'; } if (trim($cfop) !== trim(substr($consulta->cfop,-4))) { $fclass = 'w-[50px] text-right text-red-500'; } } $this->previa[]=['codforn'=>$codforn,'codprod'=>$codprod,'prod'=>$produto, 'qt'=>$quantidade,'custoanterior'=>$custoAnterior,'custoatual'=>$custoAtual, 'custototal'=>$valorTotal, 'fclass'=>$fclass, 'cfop'=>$cfop,'codp'=>$codp,'ncm'=>$ncm,'nclass'=>$nclass,'cclass'=>$cclass, 'marg'=>$marg]; } $this->modal=false; $this->modal2=true; } function atualizarCfop($indicador) { $codprod=$this->previa[$indicador]['codprod']; $cfop=$this->previa[$indicador]['cfop']; DB::table('tbprod')->where('codprod',$codprod) ->update(['cfop' => DB::raw("CONCAT(LEFT(cfop, LENGTH(cfop) - 4), $cfop)")]); $this->previa[$indicador]['fclass']='w-[50px] text-right'; } function atualizarNcm($indicador) { $codprod=$this->previa[$indicador]['codprod']; $ncm=$this->previa[$indicador]['ncm']; tbprod::where('codprod',$codprod)->update(['cf'=>$ncm]); $this->previa[$indicador]['nclass']='w-[100px] text-right'; } function cancelar() { $this->modal=false; } function custo($indicador) { $this->indicador=$indicador; $this->comando="alterar custo"; $this->modal=true; } function custoConfirmado() { $custo=$this->previa[$this->indicador]['custoatual']; $codprod=$this->previa[$this->indicador]['codprod']; $this->previa[$this->indicador]['cclass']="w-[70px] text-right"; tbprod::where('codprod',$codprod)->update(['custo'=>$custo]); $this->modal=false; } function mostrarMais() { if($this->modal2) { $this->modal2=false; $this->modal3=true; } else { $this->modal2=true; $this->modal3=false; } } function multiplo($indicador) { $this->criterio=$this->previa[$indicador]['codforn']; $consulta=tbprod::where('codforn','like',"%$this->criterio")->get(); $this->opcoes=[]; foreach($consulta as $c) { $this->opcoes[]=['indicador'=>$indicador,'codprod'=>$c->codprod,'prod'=>$c->prod]; } $this->modal=true; } function qtDefinir($indicador) { $this->indicador=$indicador; $this->comando="qt"; $this->modal=true; } function qtDefinida() { $quant=$this->quant; $custo=round($this->previa[$this->indicador]['custototal']/$quant,2); $this->previa[$this->indicador]['qt']=$quant; $this->previa[$this->indicador]['custoatual']=$custo; $this->previa[$this->indicador]['cclass']="w-[50px] text-right text-red-500"; $this->modal=false; } function selecionado($chave) { $indicador=$this->opcoes[$chave]['indicador']; $codprod=$this->opcoes[$chave]['codprod']; $this->previa[$indicador]['codprod']=$codprod; $consulta=tbprod::where('codprod',$codprod)->first(); $this->previa[$indicador]['marg']=$consulta->marg; $this->previa[$indicador]['custoanterior']=$consulta->custo; if($this->previa[$indicador]['custoanterior'] !== $this->previa[$indicador]['custoatual']) { $previa[$indicador]['pclass']="w-[50px] text-right text-red-200"; } $this->modal=false; } function transferir() { if(count(tbhistprod::where('lcto',$this->lcto)->get())>0){ $this->comando="transferido"; $this->modal=true; } else { $dia=tbdiario::where('lcto',$this->lcto)->value('dia'); foreach($this->previa as $p) { tbhistprod::create(['codprod'=>$p['codprod'],'dia'=>$dia,'qt'=>$p['qt'], 'custototal'=>$p['custototal'],'codp'=>$p['codp'],'lcto'=>$this->lcto]); } return redirect('ldiario'); } } } arquivo resources > views > livewire > nota-fiscal.blade.php <div> @if($modal) <div class="fixed inset-0 flex items-center justify-center z-10" style="background-color: rgba(243,244,246,0.5)"> <div class="bg-white p-6 rounded shadow-lg"> @if($comando=="pegar xml") <flux:input type="file" wire:model="XmlFile" label="Pegar arquivo xml"/> @endif @if($comando=="escolher produto") @foreach($opcoes as $chave => $o) <flux:button wire:click="selecionado({{$chave}})">{{ $o['codprod']." ".$o['prod'] }} </flux:button> @endforeach <p>Existem muitos produtos com o critério {{$criterio}}. Escolha um.</p> @endif @if($comando=="alterar custo") <div class=w-[300px]> <flux:input.group> <flux:input.group.prefix>Custo Anterior</flux:input.group.prefix> <flux:input value="{{dec($previa[$indicador]['custoanterior'])}}" /> </flux:input.group> <flux:input.group> <flux:input.group.prefix>Custo Atual</flux:input.group.prefix> <flux:input value="{{ dec($previa[$indicador]['custoatual']) }}" /> </flux:input.group> <flux:button wire:click="custoConfirmado">Confirmar</flux:button> </div> @endif @if($comando=="qt") <div class=w-[300px]> <flux:input.group> <flux:input.group.prefix>Definir Quantidade</flux:input.group.prefix> <flux:input wire:model="quant" wire:change="qtDefinida" autofocus autocomplete="off" /> </flux:input.group> <flux:button wire:click="cancelar" class="mt-5">Cancelar</flux:button> </div> @endif @if($comando=="transferido") <div class="text-lg">Documento já transferido anteriormente</div> @endif </div> </div> @endif @if($modal2 || $modal3) @if(count($inativos)) <div class=mt-5>{{ "verificar ".print_r($inativos) }}</div> @endif <div class=flex> <div class=w-[530px]>NF {{ $nNF." ".$xNome }}</div> <div class="w-[100px] text-right">{{ dec($vNF) }}</div> </div> @if($difAliqICMS!==0) <div class="flex"> <div class="w-[530px] text-right">Diferença de Alíquota de ICMS</div> <div class="w-[100px] text-right"><?=dec($difAliqICMS)?></div> </div> <div class="flex"> <div class="w-[530px] text-right">Total a conferir</div> <div class="w-[100px] text-right"><?=dec($difAliqICMS+$vNF)?></div> </div> @endif @if($modal2) <div class="flex even:bg-gray-200"> <div class="w-[70px] text-right">Cforn</div> <div class="w-[50px] text-right">Cod</div> <div class="w-[288px] px-2">Produto</div> <div class="w-[50px] text-right">Mg</div> <div class="w-[50px] text-right">Qt</div> <div class="w-[70px] text-right">Preço</div> <div class="w-[100px] text-right font-semibold" wire:click=mostrarMais>Total</div> </div> @foreach($previa as $key => $p) <div class="flex even:bg-gray-200"> <div class="w-[70px] text-right truncate">{{$p['codforn']}}</div> @if($p['codprod']=="none") <div class="w-[50px] text-right text-red-500">{{$p['codprod']}}</div> @endif @if($p['codprod']=="mult") <div class="w-[50px] text-right text-red-500" wire:click="multiplo({{$key}})"> {{ $p['codprod']}} </div> @endif @if($p['codprod']!=="none" && $p['codprod']!=="mult") <div class="w-[50px] text-right">{{$p['codprod']}}</div> @endif <div class="w-[288px] px-2 truncate">{{$p['prod']}}</div> <div class="w-[50px] text-right">{{$p['marg']}}</div> <div class="w-[50px] text-right" wire:click="qtDefinir({{$key}})">{{$p['qt']}}</div> <div class="{{ $p['cclass']}}" wire:click="custo({{$key}})">{{dec($p['custoatual'])}}</div> <div class="w-[100px] text-right">{{dec($p['custototal'])}}</div> </div> @endforeach @endif @if($modal3) <div class="flex even:bg-gray-200"> <div class="w-[70px] text-right">Cforn</div> <div class="w-[50px] text-right">Cod</div> <div class="w-[358px] px-2">Produto</div> <div class="w-[50px] text-right">CFOP</div> <div class="w-[100px] text-right font-semibold" wire:click="mostrarMais">NCM</div> </div> @foreach($previa as $key => $p) <div class="flex even:bg-gray-200"> <div class="w-[70px] text-right truncate">{{$p['codforn']}}</div> @if($p['codprod']=="none") <div class="w-[50px] text-right text-red-500">{{$p['codprod']}}</div> @endif @if($p['codprod']=="mult") <div class="w-[50px] text-right text-red-500" wire:click="multiplo({{$key}})"> {{ $p['codprod']}} </div> @endif @if($p['codprod']!=="none" && $p['codprod']!=="mult") <div class="w-[50px] text-right">{{$p['codprod']}}</div> @endif <div class="w-[358px] px-2 truncate">{{$p['prod']}}</div> <div class="{{$p['fclass']}}" wire:click="atualizarCfop({{ $key }})"> {{$p['cfop']}} </div> <div class="{{$p['nclass']}}" wire:click="atualizarNcm({{ $key }})"> {{$p['ncm']}} </div> </div> @endforeach @endif <div class=flex> <div class="w-[300px]"> <flux:input.group> <flux:button>Enviar para Lançamento</flux:button> <flux:input wire:model="lcto" wire:change="transferir" /> </flux:input.group> </div> <div class="w-[330px] text-right">{{ dec($soma) }}</div> </div> @endif </div>
-
É possível gravar numa célula da matriz a informação com a sua formatação (lá no Blade você usa a diretriz {!! ... !!} para recuperar a informação já formatada), o problema é quando você precisar trabalhar só com a informação; assim, a minha sugestão é trabalhar com duas células, uma com a informação e a outra com a formatação correspondente, assim: arquivo app > Livewire > Teste.php <?php namespace App\Livewire; use Livewire\Component; class Teste extends Component { public $previa=[]; function mount() { $dado=dec(12); $this->previa[]=['codigo'=>$dado,'cor1'=>null]; $this->previa[]=['codigo'=>$dado,'cor1'=>null]; $this->previa[]=['codigo'=>$dado,'cor1'=>'text-red-500']; } function mudarCor($indicador){ $cor=$this->previa[$indicador]['cor1']; if($cor==null) { $this->previa[$indicador]['cor1']="text-red-500"; } else { $this->previa[$indicador]['cor1']=null; } } } arquivo teste.blade.php <div> @foreach($previa as $key => $p) <div class="{{$p['cor1']}}" wire:click="mudarCor({{$key}})"> {{$p['codigo']}} </div> @endforeach </div>
-
O Livewire simplificou bastante o upload, mesmo assim, para cada tipo de arquivo, o procedimento é diferente. O código seguinte faz o upload de até 20 arquivos csv (para um número maior aí vai precisar mexer no WampServ ou ou o servidor que você usar). arquivo app > Livewire > Bling.php <?php namespace App\Livewire; use App\Models\tbprod; use App\Models\tbprodbling; use Illuminate\Support\Facades\DB; use Livewire\Attributes\Layout; use Livewire\Component; use Livewire\WithFileUploads; #[Layout('components.layouts.app',['titulo'=>'Diferença na Bling'])] class Bling extends Component { use WithFileUploads; public $contaProdBling,$contaProduto,$dif=[],$files=[]; function updatedFiles() { DB::table('tbprodbling')->truncate(); foreach($this->files as $arquivo) { $dados=explode(PHP_EOL,$arquivo->get()); foreach($dados as $linha) { if($linha<>"") { $campos=explode(';',$linha); if(aspas($campos[1])!=="Código") { $codprod=intval(trim(aspas($campos[1]))); $un=aspas($campos[3]); $prod=aspas($campos[2]); $custo=deca(aspas($campos[11])); $codbar=trim(aspas($campos[19])); $cf=deca(aspas($campos[4])); $venda=deca(aspas($campos[6])); tbprodbling::create(['codprod'=>$codprod,'un'=>$un, 'prod'=>$prod,'custo'=>$custo,'codbar'=>$codbar, 'cf'=>$cf,'venda'=>$venda]); } } } } $produto=tbprod::where('loc','<>','a24')->get(); $prodBling=tbprodbling::all(); $this->contaProduto=count($produto); $this->contaProdBling=count($prodBling); if($this->contaProdBling>$this->contaProduto) { $prod=$produto->pluck('codprod'); $pBling=$prodBling->pluck('codprod'); $difs=$pBling->diff($prod); foreach($difs as $d) { echo "problema no codprod $d na Bling <br>"; } dd('parada total'); } foreach($produto as $key=>$pr) { $codprod=$pr->codprod; $previa=tbprodBling::where('codprod',$codprod)->get(); if(count($previa)==0) { $this->dif[$key][]=['Codigo'=>$codprod]; $this->dif[$key][]=['Incluir'=>$codprod,'Incluir2'=>'Incluir']; } else { $a=tbprodBling::where('codprod',$codprod)->first(); $un=($pr->un==$a->un) ? 1 : 0; $prod=($pr->prod==$a->prod) ? 1 : 0; $custo=($pr->custo==$a->custo) ? 1 : 0; $codbar=($pr->codbar==$a->codbar) ? 1 : 0; $cf=($pr->cf==$a->cf) ? 1 : 0; $venda=($pr->venda==$a->venda) ? 1 : 0; if($un.$prod.$custo.$codbar.$cf.$venda !== '111111') { $this->dif[$key][]=['Codigo'=>$pr->codprod,'Codigo2'=>$a->codprod]; if($pr->prod!==$a->prod) { $this->dif[$key][]=['Descricao'=>$pr->prod,'Descricao2'=>$a->prod]; } if($pr->custo!==$a->custo) { if($pr->custo || $a->custo<>0) { $this->dif[$key][]=['Custo'=>$pr->custo,'Custo2'=>$a->custo]; } } if($pr->codbar!=$a->codbar) { $this->dif[$key][]=['Codigo de Barra'=>$pr->codbar,'Codigo de Barra2'=>$a->codbar]; } if($pr->cf!==$a->cf) { if($pr->cf || $a->cf) { $this->dif[$key][]=['NCM'=>$pr->cf,'NCM2'=>$a->cf]; } } if($pr->venda!==$a->venda) { $this->dif[$key][]=['Venda'=>$pr->venda,'Venda2'=>$a->venda]; } if($pr->un!==$a->un) { $this->dif[$key][]=['Un'=>$pr->un,'Un2'=>$a->un]; } } } } } } arquivo resources > views > livewire > bling.blade.php <div> <flux:input type="file" wire:model="files" multiple /> <script> function copiar(elemento) { conteudo=elemento.innerText || elemento.textContent navigator.clipboard.writeText(conteudo) elemento.parentElement.style.display="none" } </script> <div class="font-semibold flex"> <div class=w-[100px]>Código</div> <div class=w-[100px]>Campo</div> <div class=w-[100px]>MySQL</div> <div class=w-[100px]>Bling</div> </div> <div class=flex> <div class=w-[100px]></div> <div class=w-[100px]>Produtos</div> <div class=w-[100px]>{{ $contaProduto }}</div> <div class=w-[100px]>{{ $contaProdBling }}</div> </div> @foreach($dif as $d) @foreach($d as $v) @if(array_keys($v)[0]=="Codigo") @php $codigo=array_values($v)[0]; @endphp @else @if(array_keys($v)[0]!=="Descricao") <div class="flex"> <div class=w-[100px]>{{$codigo}}</div> <div class=w-[100px]>{{array_keys($v)[0]}}</div> <div class=w-[100px] onclick=copiar(this)> <pre class="font-sans"><?=array_values($v)[0]?></pre> </div> <div class=w-[100px]> <pre class="font-sans"><?=array_values($v)[1]?></pre> </div> </div> @else <div class=flex> <div class=w-[100px]>{{$codigo}}</div> <div class=w-[100px]>{{array_keys($v)[0]}}</div> <div class=w-[100px] onclick=copiar(this)> <pre class="font-sans"><?=array_values($v)[0]?></pre> </div> </div> <div class=flex> <div class=w-[200px]></div> <div class=w-[100px] onclick=copiar(this)> <pre class="font-sans"><?=array_values($v)[1]?></pre> </div> </div> @endif @endif @endforeach @endforeach </div> A seguir o código para fazer o upload de um arquivo xml: arquivo app > Livewire > Cfop.php <?php namespace App\Livewire; use App\Models\tbnf; use App\Models\tbpessoa; use App\Models\tbprod; use Illuminate\Support\Facades\DB; use Livewire\Attributes\Layout; use Livewire\Component; use Livewire\WithFileUploads; #[Layout('components.layouts.app',['titulo'=>'NF CFOP'])] class Cfop extends Component { use WithFileUploads; public $xmlFile,$inativos=[],$nNF,$previa=[],$xNome; function updatedXmlFile() { tbnf::truncate(); DB::statement('alter table tbnf auto_increment=1'); $inativos=[]; $xmlContent=file_get_contents($this->xmlFile->getRealPath()); $nfe=simplexml_load_string($xmlContent); $itens=$nfe->NFe->infNFe->det; $this->nNF = (float)$nfe->NFe->infNFe->ide->nNF; $this->xNome = (string)$nfe->NFe->infNFe->emit->xNome; $nome = explode(" ", $this->xNome)[0]; $codp = tbpessoa::where('pessoa','like','%'.$nome.'%')->value('codp'); foreach ($itens as $item) { $codforn = (string)$item->prod->cProd; $criterio= strtolower($nome[0].$codforn); $consulta = tbprod::where('codforn','like','%'.$criterio.'%')->get(); $codprod = 'null'; if (count($consulta) == 1) { $codprod = $consulta[0]->codprod; } if (count($consulta) > 1) { $consulta2 = tbprod::where('codforn','like','%'.$criterio)->get(); if(count($consulta2) == 1){ $codprod = $consulta2[0]->codprod; $consulta = $consulta2; } else { echo "existem vários produtos com codforn com o critério $criterio"; foreach($consulta as $c) { echo "<br>".$c->codprod." ".$c->prod; } exit; } } if (count($consulta)==0) { echo "nenhum produto encontrado com o critério $criterio"; exit; } $produto = substr((string)$item->prod->xProd,0,79); $cfop = (string)$item->prod->CFOP; if($cfop==6101 || $cfop==6102 || $cfop==5101) { $cfop=5102; } if($cfop==6401 || $cfop==6402 || $cfop==6403 || $cfop==5401 || $cfop==5403 || $cfop==5655) { $cfop=5405; } $class=($cfop == substr($consulta[0]->cfop,-4)) ? "w-[50px] text-right" : "w-[50px] text-red-500 text-right"; if(substr($consulta[0]->cfop,0,1)==0) { $inativos[]=$consulta[0]->codprod; } $ncm = (string)$item->prod->NCM; $class2=($ncm == $consulta[0]->cf) ? "w-[100px] text-right" : "w-[100px] text-red-500 text-right"; tbnf::create(['codforn'=>$codforn,'codprod'=>$codprod,'prod'=>$produto, 'cfop'=>$cfop,'codp'=>$codp,'ncm'=>$ncm,'class'=>$class,'class2'=>$class2]); } $this->previa=tbnf::all(); } function atualizarCfop($cfop,$codprod) { DB::table('tbprod')->where('codprod',$codprod) ->update(['cfop' => DB::raw("CONCAT(LEFT(cfop, LENGTH(cfop) - 4), $cfop)")]); tbnf::where('codprod',$codprod) ->update(['class'=>"w-[50px] text-right"]); $this->previa=tbnf::all(); } function atualizarNcm($codprod,$ncm) { tbprod::where('codprod',$codprod) ->update(['cf'=>$ncm]); tbnf::where('codprod',$codprod) ->update(['class2'=>"w-[100px] text-right"]); $this->previa=tbnf::all(); } } arquivo resources > views > livewire > cfop.blade.php <div> <flux:input type="file" wire:model="xmlFile" /> <div class=mt-5>{{ print_r($inativos) }}</div> <div>NF {{ $nNF." ".$xNome }}</div> <div class="flex bg-gray-200"> <div class="w-[70px] text-right">Cforn</div> <div class="w-[50px] text-right">Cod</div> <div class="w-[358px] px-2">Produto</div> <div class="w-[50px] text-right">CFOP</div> <div class="w-[100px] text-right">NCM</div> </div> @foreach($previa as $p) <div class="flex odd:bg-gray-200"> <div class="w-[70px] text-right truncate"><?=$p->codforn?></div> <div class="w-[50px] text-right"><?=$p->codprod?></div> <div class="w-[358px] px-2 truncate"><?=$p->prod?></div> <div class="{{$p->class}}" wire:click="atualizarCfop({{$p->cfop}},{{$p->codprod}})"> {{$p->cfop}} </div> <div class="{{$p->class2}}" wire:click="atualizarNcm({{$p->codprod}},{{$p->ncm}})"> {{$p->ncm}} </div> </div> @endforeach </div>
-
arquivo resources > views > livewire > loutros.blade.php <div> <div class="h-1"></div> <flux:button href='lestoqueBaixar' wire:navigate size="xs" variant="filled">Baixar Estoque</flux:button> <flux:button href="lbalancete/1" size="xs">Criar TBW</flux:button> <flux:button href="lnfArquivo" wire:navigate size="xs" variant="filled">CFOP</flux:button> <flux:button href=lprodutoDescontinuar wire:navigate size="xs">Descontinuar Produto</flux:button> <flux:button href="lnfArquivo" wire:navigate size="xs" variant="filled">Diferença Bling</flux:button> <flux:button href=estoqueDiferenca wire:navigate size="xs">Diferença Estoque</flux:button> <div class="h-1"></div> <flux:button href=lentrada wire:navigate size="xs" variant="filled">Entrada de Produtos</flux:button> <flux:button href=lmegasena wire:navigate size="xs">Mega-Sena</flux:button> <flux:button href=diarioMercado wire:navigate size="xs" variant="filled">Mercado Pago</flux:button> <flux:button href=lnfArquivo wire:navigate size="xs">Nota do Fornecedor</flux:button> <flux:button href="simples" wire:navigate size="xs" variant="filled">Simples</flux:button> <div class=flex> <div class=w-[200px]>session('codp')</div> <div>{{$vetor['codp']}}</div> </div> <div class="flex bg-gray-200"> <div class=w-[200px]>session('codprod')</div> <div>{{$vetor['codprod']}}</div> </div> <div class="flex"> <div class=w-[200px]>session('criterio')</div> <div class=truncate>{{$vetor['criterio']}}</div> </div> <div class="flex bg-gray-200"> <div class=w-[200px]>session('criterioPessoa')</div> <div>{{$vetor['criterioPessoa']}}</div> </div> <div class="flex"> <div class=w-[200px]>session('dia')</div> <div>{{dbr($vetor['dia'])}}</div> </div> <div class="flex bg-gray-200"> <div class=w-[200px]>session('end')</div> <div>{{$vetor['end']}}</div> </div> <div class="flex"> <div class=w-[200px]>session('id')</div> <div>{{$vetor['id']}}</div> </div> <div class="flex bg-gray-200"> <div class=w-[200px]>session('lcto')</div> <div>{{$vetor['lcto']}}</div> </div> <div class="flex"> <div class=w-[200px]>session('pessoa')</div> <div>{{$vetor['pessoa']}}</div> </div> <div class="flex bg-gray-200"> <div class=w-[200px]>env('lctoBaixaEstoque')</div> <div class=w-[100px]>{{$baixa}}</div> <div class='w-[100px] text-red-600 text-right'>{{dec($valorBaixa)}}</div> </div> <div class="flex"> <div class=w-[200px]>env('lctoAcertoMais')</div> <div class=w-[100px]>{{$mais}}</div> <div class='w-[100px] text-red-600 text-right'>{{dec($valorMais)}}</div> </div> <div class="flex bg-gray-200"> <div class=w-[200px]>env('lctoAcertoMenos')</div> <div class=w-[100px]>{{$menos}}</div> <div class='w-[100px] text-red-600 text-right'>{{dec($valorMenos)}}</div> </div> <div class="flex"> <div class=w-[200px]>env('diaAcerto')</div> <div>{{dbr($diaAcerto)}}</div> </div> </div>
-
O Livewire é basicamente um par de componente e seu Blade correspondente. O Copilot disse que não é possível acessar um método do Livewire pelo roteador, ele disse que o correto é eu invocar o método desejado através do Blade. Eu não gostei da resposta do Copilot, mas com a ajuda dele eu fiz a seguinte gambiarra: arquivo routes > web.php (parcial) <?php use App\Livewire\Lbalancete; Route::middleware(['auth','verified'])->group(function() { Route::get('lbalancete/{opcao?}',Lbalancete::class)->name('lbalancete'); } arquivo resources > views > livewire > loutros.blade.php (parcial) <a href="lbalancete/1" class="text-gray-500 font-semibold">Criar TBW</a> arquivo app > Livewire > Lbalancete.php (parcial) class Lbalancete extends Component { function mount($opcao = null) { if($opcao==1) { $this->tbw() ;} $this->atualizar(); } function tbw() { $ultimoDia=tbdiario::orderBy('dia','desc')->value('dia'); session(['apuracao'=>$ultimoDia]); $balancete=$this->balancete()->balancete; DB::table('tbw')->truncate(); foreach($balancete as $conta) { $inicio=$conta->inicio ?? 'null' ; $debito=$conta->debito ?? 'null '; $credito=$conta->credito ?? 'null'; $fim=$conta->fim ?? 'null'; tbw::create(['conta'=>$conta->conta,'descricao'=>$conta->descricao, 'inicio'=>$inicio,'debito'=>$debito,'credito'=>$credito,'fim'=>$fim]); } session()->forget('apuracao'); return redirect()->to("https://123.456.78.900:8443/phpmyadmin/index.php"); } }
-
No tempo do PHP e Laravel, eu usei o <form> para fazer uma ponte entre o view e o controller, mas no Livewire acredito que o <form> só serve para usar as regras de validação. Em vários tutoriais do Livewire você vai encontrar coisa do tipo unique:user, ou seja, o Livewire vai procurar a informação na tabela user. No meu caso, o nome da minha tabela é tbusuarios. Mesmo que eu tenho colocado a tabela no model User, o código no Livewire só vai funcionar se eu usar unique:tbusuarios. <?php // Teste.php namespace App\Livewire; use Livewire\Component; class Teste extends Component { public $email; function register() { $data=$this->validate(['email'=>'required|email|unique:tbusuarios']); dd("creating a user with email $this->email"); } } ?> <form wire:submit.prevent="register" class="w-25"> <!-- teste.blade.php --> <div class="h-5"></div> <flux:input wire:model="email" /> <div class="h-5"></div> <flux:button type=submit>Register</flux:button> <div class="h-5"></div> @error('email'){{ $message }}@enderror </form>
-
Eu tentei testar o código que aparece logo no portal do livewire.laravel.com, ao invés de usar a tabela user, eu usei a tabela de produtos, mas o VS Code disse que encontrou um erro por eu não ter definido a propriedade produto no componente. O VS Code tem razão, o portal do Livewire apresenta um péssimo exemplo de programação, aonde deveria ser @foreach($users as $user), o rapaz escreveu $this->users.
-
Hoje eu estudei o <wire:loading>, mas nenhum dos exemplos do tutorial funcionou comigo. O único que deu certo foi um que muda a cor de uma opção que foi selecionada: <div wire:click="multiploAtualiza" wire:loading.class="text-red-500" class="text-gray-500 font-semibold"> Atualizar Produtos Vinculados </div>
-
Apesar do Livewire ser uma extensão do Laravel, aqui eu já considero como um novo recurso do PHP, principalmente para um programador eventual como eu que não conseguiu dominar o JavaScript e principalmente o Ajax. Eu tenho uma rotina que dá entrada no estoque, usando o serviço da digitação. Acredito que a grande maioria dos programadores utiliza o serviço de importação do xml para dar entrada no estoque, mas eu não tenho paciência de esperar e assim eu uso uma cópia da confirmação do pedido do fornecedor. No view, eu tenho três entradas: <input wire:model="codfornec">, <input wire:model="qt"> e <input wire:model="total">. Depois que o usuário fornece os dados, o componente procura na tabela de produtos o registro que contém o codfornec que foi digitado, e se encontrar, ele dá a entrada na tabela histórico do produto. O problema é se o componente não conseguir encontrar, aí o componente solta a mensagem "eu não achei" e fica por isso mesmo. O usuário pode abrir uma nova guia e acertar a tabela de produtos, atualizando ou criando um novo registro. Depois ele volta na guia da entrada de produto, e digita tudo de novo. A lei do menor esforço obriga o usuário a reclamar com o programador que não faz sentido digitar tudo de novo, coisa que já foi digitado antes. E ele tem razão. Eu não sei como resolver isso de maneira lógica, mas improvisei essa gambiarra: Eu criei três variáveis públicas: public $codfornec2, $qt2, $total2, e eles foram definidos quando o componente não encontrar o produto, assim: <?php // ... function item() { // ... $aux=tbprod::where('codforn','like',"%$codforn%")->get(); if (count($aux) == 0) { $this->codforn2=$codforn; $this->qt2=$qt; $this->total2=$total; $this->mensagem="Não existe produto com codforn $codforn"; $this->modal=true; return; } A rotina que fecha o modal anula o conteúdo de $codforn, $qt e $total, e assim o usuário vai ver três caixas vazias que ele não quer digitar. Eu mudei a primeira caixa de entrada: <input wire:model="codforn" wire:click="item">, e o método item no componente ficou assim: <?php // ... function item() { if($this->codforn2) { $codforn=$this->codforn2; $qt=$this->qt2; $total=$this->total2; $this->codforn2=$this->qt2=$this->total2=null; } else { if(is_null($this->codforn)) { return; } $codforn = $this->codforn; $qt = $this->qt; $total = deca($this->total); } Essa gambiarra funciona, o problema é como lembrar o usuário de que é possível recuperar a última digitação só com um clique na primeira caixa.
-
O tutorial do Livewire afirma que é fácil fazer upload, mas eu só recebi a mensagem de que o upload falhou, no caso do arquivo zipado. Mas eu vi que o <input type=file> pegou o nome do arquivo selecionado. Com a ajuda do Copilot, consegui pegar o nome do arquivo e mandar para o Livewire: arquivo app > Livewire > Simples.php <?php namespace App\Livewire; use Livewire\Component; class Simples extends Component { protected $listeners=['verArquivo']; public function verArquivo($arquivo) { dd($arquivo); } } arquivo resources > views > livewire > simples.blade.php <flux:input type="file" onchange="arquivo=event.target.files[0].name; Livewire.dispatch('verArquivo',[arquivo])" /> Apesar do código ser bem pequeno, isso é resultado de várias tentativas e erros. Foi muita sorte o código JavaScript funcionar, a lista do Copilot era bem maior. Já o Livewire.dispatch, esse deu muito trabalho, a ideia de colocar colchete em torno da variável que contém o nome do arquivo foi pura tentativa erro, não sei como usar o comando dispatch, mas nesse caso, deu certo. Claro que o nome do arquivo não ajuda muito, mas eu espero explorar o diretório que tem o mesmo nome do arquivo zipado. O PHP, o Laravel e o Livewire não gostam de arquivos zipados, mas para trabalhar com arquivo xml, eles não reclamam.
-
O orçamento é apenas uma equação do primeiro grau, onde orçamento = quantidade x preço. O PHP e o Laravel permitem pegar o valor do <input name=quantidade> e passar para a variável $quantidade através do recurso do <form>. Já o Livewire elimina o transtorno do <form> usando apenas <input wire:model=quantidade>. Isso é bem engenhoso. O problema é o preço. No PHP e no Laravel, eu tive que criar dois módulos, o orçamento e o produto. Para não perder as informações do orçamento eu usei a variável global session(['pedido'=>$pedido]), e assim eu pulava do módulo orçamento para o módulo produto. E no módulo produto, eu usei a variável global session(['codprod'=>$codprod]) e assim voltava para o módulo do orçamento para fazer o resto do serviço. A variável global é uma mão na roda, o problema são os outros módulos, e eu estou enfrentando um monte de problema de lógica. A minha ideia é acabar com a variável global, e usar o Livewire para carregar o orçamento e o produto ao mesmo tempo no navegador, a minha ideia é fazer do produto um modal do orçamento, e assim que o usuário selecionar o produto, ele usa o comando dispatch( ) para enviar o código do produto para o orçamento, e o orçamento usa o recurso do ouvinte ("listener") para pegar o código do produto para terminar a equação. Falar é fácil, codificar são outros quinhentos. Aqui só fiz o esboço.
-
Há muito tempo, eu consegui esse código para criar o arquivo csv no PHP e no Laravel <?php // listagem parcial class Orcamento extends Controller { function bling(Request $request) { // rotina para criar $dados $arquivo = fopen("$request->pBling.csv", "w"); fputcsv($arquivo, $dados[0]); foreach ($dados as $linha) { if ($linha != $dados[0]) { fputcsv($arquivo, $linha); } } fclose($arquivo); if (file_exists("$request->pBling.csv")) { header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . basename("$request->pBling.csv")); header('Content-Length: ' . filesize("$request->pBling.csv")); readfile("$request->pBling.csv"); unlink("$request->pBling.csv"); } } Mas esse código não funciona no Livewire. Depois de pesquisar o Livewire, o Laravel, o Copilot e um monte de tentativa e erro, cheguei nesse código: arquivo app > Livewire > Lorcamento.php <?php namespace App\Livewire; use App\Models\tbhistped; use App\Models\tbpedido; use App\Models\tbpessoa; use App\Models\tbprod; use Livewire\Attributes\Layout; use Livewire\Component; #[Layout('components.layouts.app',['titulo'=>'Orçamento'])] class Lorcamento extends Component { public $bling,$histped,$mensagem,$modal,$modal2; public $pedido,$pessoa,$procPed,$prod,$qt,$vendido,$vr=[]; // listagem parcial function gerarBling() { $this->modal = false; $this->modal2 = false; $pedido = $this->pedido; $pBling = $this->bling; tbpedido::where('ped',$pedido)->update(['bling'=>$pBling]); $contato="Consumidor Final"; $itens=tbhistped::where('ped',$pedido)->get(); $previa=tbhistped::where('ped',$pedido)->where('subtotal','<',0) ->sum('subtotal'); $desconto=$previa ? abs($previa) : 0; $total=tbpedido::where('ped',$pedido)->value('total'); $data=date('d/m/Y',strtotime(tbpedido::where('ped',$pedido)->value('dia'))); $dados = array( array("Número pedido","Nome Comprador","Data","CPF/CNPJ Comprador","Endereço Comprador", "Bairro Comprador","Número Comprador","Complemento Comprador","CEP Comprador","Cidade Comprador", "UF Comprador","Telefone Comprador","Celular Comprador","E-mail Comprador","Produto", "SKU","Un","Quantidade","Valor Unitário","Valor Total", "Total Pedido","Valor Frete Pedido","Valor Desconto Pedido","Outras despesas","Nome Entrega", "Endereço Entrega","Número Entrega","Complemento Entrega","Cidade Entrega","UF Entrega", "CEP Entrega","Bairro Entrega","Transportadora","Serviço","Tipo Frete", "Observações","Qtd Parcela","Data Prevista","Vendedor","Forma Pagamento", "ID Forma Pagamento")); foreach($itens as $item) { if($item->subtotal>0) { $dados[]=array($pBling,$contato,$data,null,null, null,null,null,null,null, null,null,null,null,null, $item->codprod,$item->un,$item->qt,$item->unitario,$item->subtotal, $total,null,$desconto,null,null, null,null,null,null,null, null,null,null,null,null, null,1,$data,null,1, 0); } } $path=storage_path(); $arquivo = fopen($path.$pBling.".csv", "w+"); fputcsv($arquivo, $dados[0]); foreach ($dados as $linha) { if ($linha != $dados[0]) { fputcsv($arquivo, $linha); } } fclose($arquivo); return response()->download($path.$pBling.".csv","$pBling.csv") ->deleteFileAfterSend(true); } } Esse código funciona tanto no Windows quanto no Hostinger. Mas dessa vez eu tive a curiosidade de saber onde exatamente o Laravel cria o arquivo csv. Do jeito que eu fiz, o Laravel cria o arquivo no diretório raíz, e eu chamei o arquivo de 1234.csv, já o Laravel muda o nome para storage1234.csv. Na hora de fazer o download, ele desce com o nome 1234.csv. Eu não sei se posso ou não usar o diretório raiz, mas é assim que estou trabalhando. Aqui no Windows, eu consegui criar o arquivo na pasta Storage, mas lá na Hostinger eu não tenho a menor ideia de como fazer isso.
-
O Livewire não consegue fazer o serviço de impressão. Quem faz isso é o bom e velho JavaScript. O problema é como o JavaScript vai devolver o comando para o Livewire. Há vários tutoriais na internet, recomendando a usar o Livewire.dispatch("voltar") dentro do JavaScript e um protected $listeners=["voltar"=>"voltar"] dentro do componente, mas isso não deu certo comigo, eu tive que apelar para a velha gambiarra, eu pedi para o JavaScript voltar para o orçamento. arquivo app > Livewire > Lcontrolid.php <?php namespace App\Livewire; use App\Models\tbpedido; use Livewire\Attributes\Layout; use Livewire\Component; #[Layout('components.layouts.app',['titulo'=>'Imprimir Pedido'])] class Lcontrolid extends Component { public $itens,$modal,$ped; function mount($pedido) { $this->ped=$pedido; $this->itens=tbpedido::where('tbpedido.ped',$pedido) ->join('tbhistped','tbpedido.ped','=','tbhistped.ped') ->join('tbprod','tbprod.codprod','=','tbhistped.codprod')->get(); $num_rows=count($this->itens); if($num_rows==0) { $this->modal=true; } session(['ocultar'=>true]); } } arquivo resources > views > livewire > lcontrolid.blade.php <div> @if($modal) Não há nada para imprimir @else <table> <tr class=fw-semibold><td colspan=7>Quitanda do Frank Corporation <tr class=fw-semibold><td colspan=7>Pedido {{$itens[0]->ped}} de {{dbr($itens[0]->dia)}} @foreach($itens as $item) <tr><td colspan=7>{{$item->prod}} <tr><td class=text-end>{{$item->qt}} <td class=text-end>{{$item->un}} <td class=px-2>x<td class=text-end>{{dec($item->unitario)}} <td>=<td class=text-end>{{dec($item->subtotal)}} @endforeach <tr class=fw-semibold><td>Total<td><td><td><td><td class=text-end>{{dec($itens[0]->total)}} @endif <script> window.print() window.onafterprint = function() { location.replace('/lorcamento/{{$ped}}') } </script> </div>
-
Lá em 2022 eu vi matéria de como o Laravel passa parâmetros de uma Blade para o Controller, só que eu não entendi nada, e improvisei assim <a href=orcamento?apagar=1>Orçamento</a> Isso deu certo até mesmo com o Livewire. Mas aqui em 2025, eu conto com o Copilot e com ele me aventurei a definir os parâmetros dentro do Route, agora com o paradigma do Livewire: Route::get('lorcamento/{pedido?}/{apagar?}',Lorcamento::class)->name('lorcamento'); Tentei mudar isso, mas o Copilot disse que não dá, essa é a sintaxe do Laravel. O que eu gostei é do ponto de interrogação, ele torna o parâmetro opcional. Eu defini o menu do orçamento, dentro do resources > views > components > layouts > app.blade.php <a class="block px-4 py-2 hover:bg-gray-200" href="{{ route('lorcamento',['apagar'=>1])}}"> Orçamento </a> E finalmente o componente ficou assim: function mount($pedido=null,$apagar=null) { $this->montarPedido($pedido,$apagar); } Note que o nome do parâmetro é exatamente igual ao que foi definido no Route, só que ele usa o prefixo $. O meu sonho é acabar com os parâmetros com a ajuda do Livewire, e definir o Route assim: Route::get('lorcamento',Lorcamento::class)->name('lorcamento'); Mas até esse dia chegar, preciso eliminar um monte de gambiarra que inventei na rotina do orçamento. Todos eles foram para o Liveware, só precisei adaptar aqui e ali. Foi isso que me fez gostar bastante do Liveware, ele é muito mais flexível que o Laravel.
-
Antes de conhecer o Livewire, eu usava o POST para atualizar a tela, o Livewire usa ouvintes ('listeners'), que executam tarefas para mudar as propriedades de um componente e assim mudam as informações que estão na tela, logo depois de ouvir a gritaria do dispatch( ). A seguir tenho um componente chamado razão que executa a mudança da apuração e a apuração aparece na forma de modal e assim que o usuário escolhe a nova apuração, a apuração grita "terminei!" e o razão faz o resto do serviço, e tudo isso sem usar o POST. Eu acredito que o listener é uma forma bem inteligente de executar um método dentro de uma classe. O clássico Laravel usava o Route para cada tarefa que você precisava executar dentro de uma classe, no Livewire o Route só serve para dizer aonde está a classe, ou, mais precisamente, o componente. arquivo resources > views > livewire > lrazao.blade.php <div> <div class="flex bg-gray-200"> <div class="w-[50px] text-right mr-2">Lcto</div> <div class="w-[200px]"> @livewire('lbalanceteApuracao') </div> <div class="w-[500px] -ml-3"> <a href="balanceteInicio" class="text-gray-500 font-semibold">{{$razao->conta}} {{$razao->descricao}}</a> </div> </div> <div class="flex font-semibold"> <div class="w-[240px] text-right mr-2">{{dec($razao->inicio)}}</div> <div>Saldo anterior</div> </div> @foreach($lctos as $lcto) @if($lcto->contad==$razao->conta) <div class="flex even:bg-gray-200"> <div class="w-[50px] text-right"> <a href="ldiarioLcto?docto={{$lcto->docto}}" class="text-gray-500 font-semibold">{{$lcto->lcto}}</a> </div> <div class="w-[40px] text-right">{{$lcto->contac}}</div> <div class="w-[50px] text-right"> <a href="balanceteDiario?dia='{{$lcto->dia}}'" class="text-gray-500 font-semibold"> {{date('d/m',strtotime($lcto->dia))}} </a> </div> <div class="w-[100px] text-right mr-2">{{dec($lcto->valor)}}</div> <div class="w-[350px] whitespace-nowrap overflow-auto">{{$lcto->hist}}</div> </div> @endif @if($lcto->contac==$razao->conta) <div class="flex even:bg-gray-200"> <div class="w-[50px] text-right"> <a href="ldiarioLcto?docto={{$lcto->docto}}" class="text-gray-500 font-semibold"> {{$lcto->lcto}} </a> </div> <div class="w-[40px] text-right text-red-500">{{$lcto->contad}}</div> <div class="w-[50px] text-right"> <a href="balanceteDiario?dia={{$lcto->dia}}" class="text-gray-500 font-semibold"> {{date('d/m',strtotime($lcto->dia))}} </a> </div> <div class="w-[100px] text-right text-red-500 mr-2">{{dec($lcto->valor)}}</div> <div class="w-[350px] whitespace-nowrap overflow-auto">{{$lcto->hist}}</div> </div> @endif @endforeach <div class="flex even:bg-gray-200 font-semibold"> <div class="w-[240px] text-right">{{dec($razao->fim)}}</div> <div class="ml-2"> Saldo atual {{dec($razao->debito)}} <span class="text-red-500">{{dec($razao->credito)}}</span> </div> </div> </div> arquivo resources > views > livewire > lbalancete-apuracao.blade.php <div> <div wire:click=alteraModal class="text-gray-500 font-semibold">{{ $apuracao }}</div> @if($modal) <div class="fixed inset-0 flex items-center justify-center"> <div class='bg-white p-6 rounded shadow-lg border-4 border-gray-500'> <div class="text-nowrap">Selecione o período de apuração</div> <select wire:model="ano"> @foreach($anos as $key => $ano) @if($key == 0) <option value="{{ $ano }}" selected>{{ $ano }}</option> @else <option value="{{ $ano }}">{{ $ano }}</option> @endif @endforeach </select> <div class="mt-3"> @foreach($meses as $posicao => $mes) <button class="ml-1 hover:bg-gray-200 text-gray-500 font-bold py-1 rounded" wire:click="apurada({{ $posicao + 1 }})">{{ $mes }}</button> @endforeach </div> </div> @endif </div> arquivo app > Livewire > Lrazao.php <?php namespace App\Livewire; use App\Models\tbdiario; use Livewire\Attributes\Layout; use Livewire\Component; #[Layout('components.layouts.app',['titulo'=>'Razão'])] class Lrazao extends Component { public $apuracao, $lctos, $razao; protected $listeners=['razaoAtualizar'=>'atualizar']; function atualizar() { $dia=session('apuracao') ?? date('Y-m-d'); $this->apuracao=apuracao($dia); $primeiroDia=$this->apuracao->primeiroDia; $ultimoDia=$this->apuracao->ultimoDia; $this->lctos=tbdiario::whereBetween('dia',[$primeiroDia,$ultimoDia])->get(); } function mount () { $conta=request()->input('conta') ? request()->input('conta') : session('razao'); $balancete=(new Lbalancete)->balancete()->balancete; $this->razao=array_column($balancete, null, 'conta')[$conta] ?? false; $this->atualizar(); } } ?> arquivo app > Livewire > LbalanceteApuracao.php <?php namespace App\Livewire; use App\Models\tbdiario; use Livewire\Component; class LbalanceteApuracao extends Component { public $ano, $anos=[],$apuracao,$mes,$modal; public $meses=['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez']; public $depuracao; function apurada ($mes) { session(['apuracao'=>$this->ano."-".$mes."-01"]); $dia=session('apuracao'); $this->apuracao=apuracao($dia)->apuracao; $this->modal=false; $this->dispatch('razaoAtualizar'); } function alteraModal () { $this->modal = $this->modal ? false : true; } function mount() { $primeiroAno=substr(tbdiario::orderBy('dia')->value('dia'),0,4); $ultimoAno=substr(tbdiario::orderBy('dia','desc')->value('dia'),0,4); for($i=$ultimoAno;$i>=$primeiroAno;$i--) { $this->anos[]=$i; } $dia=session('apuracao'); $this->ano=date('Y',strtotime($dia)); $this->apuracao=apuracao($dia)->apuracao; } } ?>
-
O Copilot disse que o Livewire é baseado no Ajax, assim faz sentido quando você definir <input wire:model="pendencias.{{$index}}.vcto">. No começo achei bem estranho, pois eu estava acostumado com coisa do tipo <input value="{{ $pendencias[$index]->vcto }}">. É muito difícil entender o Livewire no começo, só o tempo é que você se familiarizar com a gramática do PHP e a gramática do Java Script Ajax que vem embutido no Livewire. Eu não tenho a menor ideia de como o Livewire conecta uma variável pública com um wire:model, mas na minha rotina de pendências eu precisei de um monte de wire:model para casar com um monte de pendência. Com a ajuda do Copilot, eu consegui isso: arquivo resources > views > livewire > lpgar.blade.php <div> <input wire:model="doc1" size="5" autocomplete="off" class="border-none rounded p-2 py-0"> <input wire:model="doc2" size="5" autocomplete="off" class="border-none rounded p-2 py-0"> <input type="submit" wire:click="ocultar" value="Ocultar Pendências"> <div class="flex bg-gray-200 mt-2"> <div class="w-[117px] ml-3 text-center">Vencimento</div> <div class="w-[50px] text-right">Docto</div> <div class="w-[110px] text-right">Pendência</div> <div class="w-[346px] px-2 border">Pessoa</div> </div> @foreach($pendencias as $index => $pendencia) <div class="even:bg-gray-200"> <div class="flex"> <div class="w-[117px] ml-3 text-right"> <input type=date wire:model="pendencias.{{$index}}.vcto" onclick=showPicker() wire:change="atualizaVcto({{$pendencia['docto']}},{{$index}})" class="w-[117px] bg-transparent text-gray-500 font-semibold rounded py-0 border-none"> </div> <div class="w-[50px] text-right"> <div wire:click="selecionarDocto({{$pendencia['docto']}})" title="Lçto: {{ $pendencias[$index]['lcto'] }}" class="text-right"> {{ $pendencia['docto'] }} </div> </div> @if($pendencia['debito']) <div class="w-[110px] text-right"> <?=dec($pendencia['debito'])?> </div> @else <div class="w-[110px] text-right text-red-500"> <?=dec($pendencia['credito'])?> </div> @endif <div class="w-[346px] px-2 truncate"> <a class="text-gray-500 font-semibold hover:bg-gray-200" wire:click="selecionarPessoa({{$pendencia['docto']}})" title="Histórico: {!!$pendencia['hist']!!}"> <?=$pendencia['pessoa']?> </a> </div> </div> </div> @endforeach </div> Arquivo app > Livewire > Lpagar.php <?php namespace App\Livewire; use App\Models\tbcontacorrente; use App\Models\tbdiario; use App\Models\tbpessoa; use Livewire\Attributes\Layout; use Livewire\Component; #[Layout('components.layouts.app',['titulo'=>'Pendências'])] class Lpagar extends Component { public $doc1,$doc2,$pendencias=[]; function atualizaVcto($docto,$index) { $vcto=$this->pendencias[$index]['vcto']; tbcontacorrente::where('docto',$docto) ->update(['vcto'=>$vcto]); $this->montaPendencias(); } function montaPendencias() { if(request()->input('docto')) { $docto=request()->input('docto'); $codp=session('codp'); tbcontacorrente::where('docto',$docto)->update(['codp'=>$codp]); } $this->pendencias=[]; $contas=tbcontacorrente::where('pgto',0)->orderBy('vcto')->get(); foreach($contas as $conta) { $doc=tbdiario::where('docto',$conta->docto)->first(); $vcto=$conta->vcto; $docto=$conta->docto; $lcto=$doc->lcto; if($doc->contad==130 || $doc->contad==211) { $debito=$doc->valor; $credito=null; } else { $debito=null; $credito=$doc->valor; } $hist=dbr($doc->dia)." ".$doc->hist; if($conta->codp) { $pessoa=tbpessoa::where('codp',$conta->codp)->value('pessoa'); } else { $pessoa="Selecionar"; } $this->pendencias[]=['vcto'=>$vcto,'docto'=>$docto,'lcto'=>$lcto,'debito'=>$debito, 'credito'=>$credito,'hist'=>$hist,'pessoa'=>$pessoa]; } } function mount() { $pendencias=tbcontacorrente::with('diario')->where('pgto',0)->get(); foreach($pendencias as $p) { $eliminar=($p->diario->contad!==130); $eliminar+=($p->diario->contad!==211); $eliminar+=($p->diario->contac!==130); $eliminar+=($p->diario->contac!==211); if($eliminar==4) { tbcontacorrente::where('docto',$p->docto)->delete(); } } $pendencias=tbcontacorrente::pluck('docto'); $doc1=tbdiario::where('dia','>','2023-12-31')->where('contad',130)->pluck('docto'); $doc2=tbdiario::where('dia','>','2023-12-31')->where('contac',130)->pluck('docto'); $doc3=tbdiario::where('dia','>','2023-12-31')->where('contad',211)->pluck('docto'); $doc4=tbdiario::where('dia','>','2023-12-31')->where('contac',211)->pluck('docto'); $documentos=$doc1->merge($doc2)->merge($doc3)->merge($doc4); $diferenca=$documentos->diff($pendencias); foreach($diferenca as $d) { $lcto=tbdiario::where('docto',$d)->value('lcto'); tbcontacorrente::create(['docto'=>$d,'lcto'=>$lcto,'pgto'=>0]); } $this->montaPendencias(); } function ocultar() { if($this->doc1 !== null) { tbcontacorrente::where('docto',$this->doc1) ->update(['pgto'=>1]); } if($this->doc2 !== null) { tbcontacorrente::where('docto',$this->doc2) ->update(['pgto'=>1]); } $this->doc1=$this->doc2=null; $this->montaPendencias(); } function selecionarDocto($docto) { if($this->doc1==null) { $this->doc1 = $docto; } else { if($this->doc2==null) { $this->doc2 = $docto; } } } function selecionarPessoa($docto) { session(['end'=>"lpagar?docto=$docto"]); redirect()->route("lpessoa"); } }
-
Nessa semana, eu consegui terminar de ver o tutorial gratuito no livewire.laravel.com, são vídeos rápidos falado em inglês. O tutorial gratuito mostra o básico, para recursos mais avançados o portal pede coisa da ordem de R$ 300,00, mesmo assim o tutorial gratuito fala do recurso de validação, confirmação, Alpine.js, e isso ainda não usei aqui. Eu já tinha visto o Livewire antes, mas eu não entendi o propósito dele. Nesse ano, o Laravel lançou a versão 12, o problema é que ele obriga a você escolher uma extensão: o Livewire, o Vue e o React. Eu escolhi o Livewire por achar que era o menos complicado. Eu tive que estudar o Livewire para adaptar o meu código escrito em Laravel. O problema é que eu não consegui adaptar coisa alguma. Assim eu peguei um tutorial e aos poucos fui migrando o meu código em Laravel para o Livewire, e acabei gostando. O Livewire acabou de vez com o mito MVC (modelo, visão e controle) e mostrou que é possível fazer a festa só trabalhando com a variável pública. No tempo do PHP e do Laravel, eu apanhei muito para pegar o valor do <input> para definir o valor da variável lá no Controller, usando uma complicada rotina de <form> e método POST. O Livewire acabou com esse pesadelo, basta você vincular o <input> com a variável através do recurso wire:model. Ele é fantástico! Agora, o Livewire mudou a linguagem, ao invés de Controle e Visão, agora é Componente e Visão; apesar deles serem visualmente diferentes (PHP e HTML), tudo indica que o Livewire conseguiu colocar tudo lá no navegador. O Livewire me deu muita coragem, e agora não tenho medo de mexer com o modal. O modal nada mais é que um código em HTML que você pode esconder e exibir, era necessário você dominar o JavaScript e o CSS para mexer com isso, eu gastei um monte de lenço de papel para fazer o modal funcionar. O Livewire me ensinou a usar um componente como modal, claro que o Copilot me ajudou bastante. O Liveware também me ensinou a fazer depuração. Quando um erro era encontrado no controle do Laravel, o Laravel parava tudo, e mostrava aquela mensagem "você está fazendo a coisa errada". Nem sempre o Liveware faz esse serviço, tudo é diferente. A primeira coisa que o Livewire faz é executar a função mount ( ), e se não tiver nada disso, ele mostra a visão. Se você aperta o botão, e nada acontece, basta usar o web console, e lá vai ter a mensagem 1 erro livewire.js. Eu aprendi que fiz um monte de erro de digitação na view. Mas se essa mensagem não aparece no web console, eu vou lá no componente e crio a variável pública $depuração, vou lá na visão e acrescento o comando {{ $depuração }} e finalmente vou no componente e uso a minha intuição e acrescento o código PHP $this->depuração="O problema pode estar aqui". Nem tudo dá para resolver no Livewire. Nessa semana eu pedi o balancete, mas o Livewire só mostrava o balancete de maio, quando precisava do balancete de abril. Isso é um erro de lógica. Para saber quem estava pedindo o balancete de maio eu usei o VS Code, pedi para ele listar todos os códigos onde havia o comando session(['apuracao'=> pelo comando Find in Files e assim eu cheguei no método tbw, onde ele pega a última data do diário contábil e monta o balancete. Foi fácil consertar, eu só pedi para apagar assim session( )->forget('apuracao') depois que o método conseguiu o que queria.