Ir para conteúdo
Fórum Script Brasil

Frank K Hosaka

Membros
  • Total de itens

    1.622
  • Registro em

  • Última visita

Tudo que Frank K Hosaka postou

  1. O código que eu publiquei não funcionou na Hostinger, há muito erro de lógica que o Copilot encontrou. Ele disse que eu não posso executar a função mount( ) mais de uma vez. Para emparelhar a variável array( ) do Livewire com wire:model no blade, você precisa ter cereteza que o array( ) não está vazio, senão não vai aparecer nada no Blade. arquivo app > Livewire > lprevisao.php <?php namespace App\Livewire; use App\Models\tbdiario; use App\Models\tbmercado; use App\Models\tbprevisao; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Livewire\Component; use Livewire\Attributes\Layout; #[Layout('components.layouts.app',['title'=>'Previsão'])] class Lprevisao extends Component { public $mercado,$painel,$total; public $inputs=[]; public function atualizar($index,$conta) { $valor=deca($this->inputs[$index]); tbprevisao::where('conta',$conta)->update(['valor'=>$valor]); $this->painel=DB::table('tbprevisao')->join('tbw', 'tbprevisao.conta', '=', 'tbw.conta') ->orderBy('tbprevisao.conta')->get(); $this->inputs=[]; foreach($this->painel as $p) { $this->inputs[] = dec($p->valor); } } public function mount() { $balancete = new Lbalancete(); $balancete->tbw(new Request(['opcao'=>1])); $this->mercado=tbmercado::all(); $this->total = DB::table('tbmercado')->select( DB::raw('SUM(venda) as tvenda'), DB::raw('SUM(tarifa) as ttarifa'), DB::raw('SUM(conta) as tconta'))->first(); $this->painel=DB::table('tbprevisao')->join('tbw', 'tbprevisao.conta', '=', 'tbw.conta') ->orderBy('tbprevisao.conta')->get(); foreach($this->painel as $p) { $this->inputs[] = dec($p->valor); } } } arquivo lprevisao.blade.php div> <div class="flex"> <a href=diarioInicio class="w-[100px] text-blue-700">Diario</a> <a href=previsaoPoupanca class="w-[100px] text-blue-700">Poupança</a> </div> <div class="flex"> <div class="w-[50px] text-right">Conta</div> <div class="w-[130px] px-2">Descricao</div> <div class="w-[150px] text-right">Previsão</div> <div class="w-[150px] text-right">Contábil</div> <div class="w-[150px] text-right">Divergência</div> </div> <?php foreach($painel as $key => $p): ?> <div class=flex> <div class="w-[50px] text-right"><?=$p->conta?></div> <div class="w-[188px] ml-2 truncate"><?=$p->descricao?></div> <div class="w-[130px] py-0"> <input class="w-[130px] text-right py-0 border-none" wire:model.defer="inputs.{{$key}}" wire:change="atualizar({{$key}},{{$p->conta}})"> </div> <div class="w-[130px] text-right"><?=dec($p->fim)?></div> <div class="w-[130px] text-right"> <?=dec(abs(round($p->valor - $p->fim,2)))?> </div> </div> <?php endforeach;?> </div>
  2. arquivo app > Liveware > Lprevisao.php <?php namespace App\Livewire; use App\Models\tbdiario; use App\Models\tbmercado; use App\Models\tbprevisao; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Livewire\Component; use Livewire\Attributes\Layout; #[Layout('components.layouts.app',['title'=>'Previsão'])] class Lprevisao extends Component { public $conta,$mercado,$painel,$total,$valor=[]; public function alterar($index,$conta) { $valor=deca($this->valor[$index]); tbprevisao::where('conta',$conta)->update( ['valor'=>$valor]); return $this->mount(); } public function mount() { $balancete = new Lbalancete(); $balancete->tbw(new Request(['opcao'=>1])); $this->mercado=tbmercado::all(); $this->total = DB::table('tbmercado')->select( DB::raw('SUM(venda) as tvenda'), DB::raw('SUM(tarifa) as ttarifa'), DB::raw('SUM(conta) as tconta'))->first(); $this->painel=DB::table('tbprevisao')->join('tbw', 'tbprevisao.conta', '=', 'tbw.conta') ->orderBy('tbprevisao.conta')->get(); } } arquivo resources > views > livewire > lprevisao.blade.php <div> <div class="flex"> <div class="w-[50px] text-right">Conta</div> <div class="w-[130px] px-2">Descricao</div> <div class="w-[150px] text-right">Previsão</div> <div class="w-[150px] text-right">Contábil</div> <div class="w-[150px] text-right">Divergência</div> </div> <?php foreach($painel as $index => $p): ?> <div class=flex> <div class="w-[50px] text-right"><?=$p->conta?></div> <div class="w-[188px] ml-2 truncate"><?=$p->descricao?></div> <div class="w-[130px] py-0"> <input class="w-[130px] text-right py-0 border-none" wire:model="valor.{{$index}}" wire:change="alterar({{$index}},{{$p->conta}})" value=<?=dec($p->valor)?>> </div> <div class="w-[130px] text-right"><?=dec($p->fim)?></div> <div class="w-[130px] text-right"> <?=dec(abs(round($p->valor - $p->fim,2)))?> </div> </div> <?php endforeach;?> </div>
  3. Ontem, eu gastei o dia todo só para mudar a data do lançamento contábil. Foram várias tentativas e erros, tem muitas dicas do Copilot e do portal do Livewire que não funcionam, até eu conseguir isso: arquivo app > Livewire > Ldiario.php <?php namespace App\Livewire; use App\Models\tbdiario; use Livewire\Component; use Livewire\Attributes\Layout; #[Layout('components.layouts.app',['title'=>'Diário'])] class Ldiario extends Component { public $dia, $mensagem, $dataAtual, $lctos, $somaDebito, $somaCredito; public function mount() { $this->dia=(session()->has('dia')) ? session('dia') : date('Y-m-d'); session(['dia'=>$this->dia]); $this->mensagem=""; $this->dataAtual=date('Y-m-d'); if($this->dataAtual!==$this->dia) { $this->mensagem="Hoje é " . dbr($this->dataAtual) . " "; } $this->lctos=tbdiario::where('dia',$this->dia)->orderBy('lcto')->get(); $this->somaDebito=tbdiario::where('contad','>',0)->where('dia',$this->dia)->sum('valor'); $this->somaCredito=tbdiario::where('contac','>',0)->where('dia',$this->dia)->sum('valor'); } public function ldiarioData() { session(['dia'=>$this->dia]); return $this->mount(); } } arquivo resources > views > components > layouts > app.blade.php <!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{ $title ?? 'Page Title' }}</title> </head> @vite(['resources/css/app.css', 'resources/js/app.js']) <body class="w-[630px] m-0 m-auto"> <div> <nav class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div class="flex items-center justify-between h-16"> <div class="flex items-center"> <a href="#" class="text-sm font-medium">Laravel 12</a> <div class="ml-10 flex items-baseline space-x-4"> <div class="relative group"> <button class="px-3 py-2 rounded-md text-sm font-medium"> {{ $title }} </button> <div class="hidden group-hover:block absolute bg-white text-gray-800 rounded-md shadow-lg w-40" > <a href="ldiario" class="block px-4 py-2 text-sm hover:bg-gray-200">Diário</a> <a href="#" class="block px-4 py-2 text-sm hover:bg-gray-200">Opção 2</a> <a href="#" class="block px-4 py-2 text-sm hover:bg-gray-200">Opção 3</a> </div> </div> <div class="relative group"> <button class="px-3 py-2 rounded-md text-sm font-medium"> {{ auth()->user()->nome}} </button> <div class="hidden group-hover:block absolute bg-white text-gray-800 rounded-md shadow-lg w-40" > <a href="#" class="block px-4 py-2 text-sm hover:bg-gray-200">Sair</a> <a href="#" class="block px-4 py-2 text-sm hover:bg-gray-200">Mudar Senha</a> </div> </div> </div> </div> </div> </nav> </div> {{ $slot }} </body> </html> arquivo resources > views > livewire > ldiario.blade.php (parcial) <div> <input type="date" wire:model="dia" id="dia" value='<?=$dia?>' wire:change="ldiarioData" class="border-none font-semibold py-1 px-2 w-[130px] hover:bg-gray-200 rounded text-gray-500"> </div> O mais importante é que consegui rodar na Hostinger (claro que precisei rodar npm install - onde recebi várias mensagens, bem como o npm run build pelo ssh do terminal VS Code). O que eu gostei é que não tem <form>, não tem @csrf e também não tem web.php para funcionar o método ldiarioData, e lá no controlador não tem nenhum Request, tudo é bem mágico mesmo. A variável $dia no controlador está amarrado com o <input wire:model="dia">, mas eu não consegui fazer funcionar o método updatedDia( ), eu desisti e improvisei, definindo mais um serviço no mesmo input, o wire:change="ldiarioData", e isso deu certo.
  4. Eu pensei que bastava definir a variável na classe Liveware para ela mostrar o conteúdo dela no navegador. O Copilot explicou que o Liveware não é nada disso, primeiro ela carrega o layout (onde está a variável que você quer mostrar), depois ela lê a classe (onde você define a variável) e finalmente ela carrega o resto do HTML. Ou seja, ela sempre vai reclamar que a variável não está definida. Para resolver esse contratempo, o Copilot sugeriu isso: public function render() { return view('sua-visao-componente') ->layout('layouts.app', ['menu' => $this->menu]); } O Copilot é muito bacana, mas aí eu lembrei do código do login que vem embutido na hora de instalar o Laravel 12 com Liveware, e tentei usar no meu aplicativo: <?php namespace App\Livewire; use Livewire\Component; use Livewire\Attributes\Layout; #[Layout('components.layouts.app',['menu'=>'Laranja'])] class Lmenu extends Component { } E deu certo! O único problema é que o arquivo lmenu.blade.php (note que o nome da classe está em maiúsculo e o do blade em minúsculo) tem que estar no diretório resources.views.liveware, eu não posso mais colocar no diretório raiz do resources.views. Note que nessa classe, não existe nenhum comando; o arquivo blade também não tem nada. Tudo o que ele faz é botar a barra de navegação no topo da tela, mas ele precisa da variável $menu já definida.
  5. O Laravel 12 não dá suporte para o Breeze com Blade, logo a opção menos ruim para mim foi escolher o Laravel 12 com Livewire para eu ter o código de autenticação. Para fazer o novo pacote funcionar na Hostinger, eu tive que usar o php artisan vendor:publish e lá eu encontrei três publicações do Livewire que conseguiram fazer o Laravel funcionar na Hostinger, mas não consegui instalar o novo pacote do Livewire que se chama flux. Eu tive que estudar o Liveware, para contorná-lo e fazer os meus códigos funcionarem. Uma gambiarra aqui e outra ali, e finalmente eu consegui fazer o meu código funcionar. Só que eu tenho um pequeno programa em JavaScript que não conseguiu rodar: <script> function atualizar(custoAtual, custoAnterior, codprod) { confirma = confirm("Atualizar?\ncusto atual: " + custoAtual + "\ncusto anterior: " + custoAnterior); if (confirma) { xmlhttp = new XMLHttpRequest() url = "nfCusto" formData = new FormData() formData.append('custoAtual', custoAtual) formData.append('codprod', codprod) xmlhttp.open("POST", url, true) xmlhttp.send(formData) location.replace("nfAtualiza") } } </script> Esse é o melhor código que eu já inventei, mas não consegui rodar dentro do Laravel 12, mesmo tentando implantar a rotina csrf dentro dele. Tenho que reconhecer que o meu código não é seguro e o Laravel 12 está de parabéns por bloquear o XMLHttpRequest do JavaScript. O núcleo do Liveware é a função render( ), mas eu encontrei a diretiva #[Layout('components.layouts.auth')] que também faz a mesma coisa, mas eu não consegui usá-lo. Pelo que eu pude entender, o Livewire pega o layout e tenta encaixar dentro dele o controlador e a página principal. Existe um pequeno tutorial chamado "counter" que eu consegui executar, e ao invés de ficar incrementando ou decrementando o contador, eu mudei tudo para alterar um registro no MySQL, isso foi sopa. O duro vai ser na hora que eu precisar trabalhar com um monte de registros do MySQL. arquivo app > Livewire > Counter.php <?php namespace App\Livewire; use App\Models\tbprevisao; use Livewire\Component; class Counter extends Component { public $teste = "olá mundo"; function __construct() { $this->teste=tbprevisao::where('conta',101)->value('valor'); } function atualiza() { tbprevisao::where('conta',101)->update(['valor'=>$this->teste]); } function render() { return view('livewire.counter'); } } arquivo resources > views > components > layouts > app.blade.php // isso é minha gambiarra, faça um backup do arquivo original para você não se arrepender {{ $slot }} arquivo resources > views > livewire > counter.blade.php <div> <form wire:submit="atualiza"> <input wire:model="teste" /> <button type="submit">Atualizar</button> </form> </div> arquivo routes > web.php use App\Livewire\Counter; use App\Livewire\Settings\Appearance; use App\Livewire\Settings\Password; use App\Livewire\Settings\Profile; use Illuminate\Support\Facades\Route; Route::get('counter',Counter::class);
  6. Foi uma semana bem difícil, tentei fazer o Laravel 12 funcionar no VPS do Hostinger, usando o tutorial do Livewire e do Flux no Nginx. Foram várias tentativas e nada deu certo, é possível que tenha usado o comando Linux de maneira errada ou configurado o Nginx de maneira errada. Antes de jogar a toalha no chão, eu aprendi um novo comando do Laravel: php artisan list, ele lista todos os comandos do Laravel pela linha de comando, e uma delas é o vendor:publish. Executei php artisan vendor:publish e encontrei três tópicos que mencionam o Livewire, pedi para publicar todos eles, selecionando um de cada vez. E assim consegui cadastrar a minha conta e chegar no dashboard. Eu acho estranho o flux ter funcionado no login.blade.php e não funcionar no dashboard, mas enfim estou contente com o Laravel 12, eu só precisava mesmo é da rotina de autenticação. O resto continua tudo igual, ou seja, eu vou continuar usando o JavaScript ao invés do Liveware.
  7. Tanto no notebook quanto no Hostinger, o Livewire consegue colocar o login.blade.php no monitor. Para eu conseguir um negócio desses, eu usaria o comando return view('login'), mas o controlador Login do Livewire não usa nada disso. Ele usa: #[Layout('components.layouts.auth')] Fazendo auditoria, o máximo que eu consegui foram duas camadas de códigos que preparam para receber um { $slot }, a minha dúvida é como colocar o login.blade.php dentro desse $slot. A minha precária imaginação acredita que a diretriz #[Layout('components.layouts.auth')] vai buscar o nome do arquivo blade correspondente à classe que for definida depois dele. Isso não é óbvio e não encontrei nenhum tutorial para corroborar a minha tese. Mas, enfim, o login funciona no meu notebook, mas não funciona na Hostinger. O web console reclama que faltam dois arquivos: o livewire.js e o flux.js. Para eu resolver o problema do livewire.js, eu usei php artisan vendor:publish, e assim consegui chegar na tela do dashboard. Só que nada funciona lá, o web console reclama que falta o arquivo flux.js.
  8. Eu ainda não consegui fazer o Laravel 12 com Liveware funcionar na Hostinger com Nginx, mesmo assim estou fazendo testes aqui no meu notebook com Windows e Apache, e descobri que ele suporta o JavaScript, onde montei um modal para o lançamento contábil. Ele só não suporta esse código <script>document.title="Menu";menu.innerHTML="Menu"</script> O erro estava no segundo comando, não existe nenhum objeto com o nome de menu. No Laravel 11 não dava para perceber nenhum erro no código JavaScript, a não ser que você consultasse o web console, já no Laravel 12, qualquer erro no JavaScript é fatal.
  9. Eu usei o arquivo .env para definir o banco de dados Diario hospedado no Hostinger (lá o Linux não autoriza o nome do banco de dados em minúsculo). Eu usei o arquivo .env.local para definir o bando de dados diario hospedado no meu notebook (aqui o Windows não autoriza o nome do banco de dados em maiúsculo). Por muito tempo, eu queria que esses dois arquivos fossem iguais tanto no Hostinger quanto no meu notebook. Graças a ajuda do Copilot, consegui alcançar o meu objetivo com esse código: arquivo bootstrap > app.php <?php use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; $basePath = dirname(__DIR__); $envFile = file_exists($basePath . '/.env.local') && getenv('APP_ENV') === 'local' ? '.env.local' : '.env'; // Força o carregamento do arquivo `.env` ou `.env.local` $dotenv = Dotenv\Dotenv::createImmutable($basePath, $envFile); $dotenv->load(); return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { // }) ->withExceptions(function (Exceptions $exceptions) { // })->create();
  10. Encontrei matéria que fala do Livewire e o servidor nginx, aqui: https://benjamincrozat.com/livewire-js-404-not-found#using-nginx Linux não é a minha praia, pedi ajuda para o Copilot. Entrei no Hostinger VPS Web Terminal, e lá usei cd .. cd etc cd nginx nano nginx.conf dentro do bloco http, acrescentei o bloco server http { server { location = /livewire/livewire.js { expires off; try_files $uri $uri/ /index.php?$query_string; } } } Usando CTRL-X e ENTER, salvei as alterações Para saber se a sintaxe está correta, usei sudo nginx -t Para reiniciar o nginx, vou usar o comando sudo systemctl restart nginx mas vou fazer a noite para não atrapalhar o meu irmão.
  11. Ele pára na rotina de login, tudo indica que não há conexão entre a classe Login do Livewire com o formulário. É uma pena.
  12. Como não é possível trabalhar com o JavaScript e Livewire ao mesmo tempo no Laravel 12 Livewire, fui obrigado a usar o método da tentativa e erro para simular o modal: arquivo app > Livewire > Modal.php <?php namespace App\Livewire; use Livewire\Component; class Modal extends Component { public $usernamePlaceholder="Olá mundo"; public $showModal = false; public $conta = null; public $contaDevedora = null; public $contaCredora = null; public $inputEscolhido = null; public function setConta($conta) { if($this->inputEscolhido=="Devedora") { $this->contaDevedora=$conta; } else { $this->contaCredora=$conta; } return $this->closeModal(); } public function openModalDevedora() { $this->showModal = true; $this->inputEscolhido = 'Devedora'; } public function openModalCredora() { $this->showModal = true; $this->inputEscolhido = 'Credora'; } public function closeModal() { $this->showModal = false; } public function render() { return view('livewire.modal'); } } arquivo resources > views > livewire > modal.blade.php <div class="w-[500px] m-0 m-auto"> <form method=post action=logout>@csrf<button type="submit">Sair</button></form> <flux:input value={{$contaDevedora}} wire:click=openModalDevedora class="border p-2 rounded" label="Conta Devedora" /> <flux:input value={{$contaCredora}} wire:click=openModalCredora class="border p-2 rounded" label="Conta Credora" /> @if ($showModal) <div class="fixed inset-0 flex items-center justify-center z-50"> <div class="bg-white p-5 rounded shadow-md"> <h2 class="text-lg font-bold">Plano de Contas</h2> <div wire:click="setConta('Ativo')">Ativo</div> <div wire:click="setConta('Passivo')">Passivo</div> <div wire:click="setConta('Despesa')">Despesa</div> <div wire:click="setConta('Receita')">Receita</div> <button wire:click="closeModal" class="btn btn-danger">Fechar</button> </div> </div> <div class="fixed inset-0 bg-black opacity-50"></div> @endif </div> arquivo resources > views > menuView.blade.php <livewire:scripts /> <livewire:styles /> <livewire:modal />
  13. Ontem, o Copilot tentou me ensinar como criar uma barra de navegação, usando o Liveware. Eu achei muito complicado e fiquei apavorado! Mas eu encontrei o arquivo resources > views > components > layouts > app > sider.blade.php, eu gostei a beça dele, e consultando a internet eu consegui montar o meu arquivo resources > views > components > layouts > app > navbar.blade.php <flux:header> <flux:navbar> <flux:navbar.item>Laravel 12</flux:navbar.item> <flux:dropdown> <flux:navbar.item icon-trailing="chevron-down">Menu</flux:navbar.item> <flux:navmenu> @if(auth()->user()->id==1) <flux:navmenu.item href="diarioInicio">Diário</flux:navmenu.item> @endif <flux:navmenu.item href="orcamentoMenu">Orçamento</flux:navmenu.item> <flux:navmenu.item href="vendaInicio">Relatório de Venda</flux:navmenu.item> </flux:navmenu> </flux:dropdown> <flux:dropdown> <flux:navbar.item icon-trailing="chevron-down">{{ auth()->user()->nome }}</flux:navbar.item> <flux:navmenu> <form method="POST" action="{{ route('logout') }}" class="w-full"> @csrf <flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full"> {{ __('Sair') }} </flux:menu.item> </form> <form method="POST" action="{{ route('logout') }}" class="w-full"> @csrf <flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full"> {{ __('Mudar a senha') }} </flux:menu.item> </form> </flux:navmenu> </flux:dropdown> </flux:navbar> {{$slot}} @fluxScripts </flux:header> O meu arquivo menuView.blade.php não funciona no Laravel 12, só funciona se você atualizar o navegador. Ele usava JavaScript, e acredito que o paradigma do LiveWare é trocar o JavaScript pelo PHP. E assim, o meu arquivo resources > views > menuView.blade.php ficou assim: @vite(['resources/css/app.css', 'resources/js/app.js']) <div class="w-[500px] m-auto m-0"> <x-layouts.app.navbar /> </div> Por enquanto, tudo é tentativa e erro. Para o diarioView.blade.php funcionar, eu fiz assim: @include('appView') <div class="w-[500px] m-0 m-auto"> <x-layouts.app.navbar /> <input type=submit value='Lançamentos' class="hover:bg-gray-200 py-1 px-2 font-semibold rounded text-gray-500" onclick="location.replace('diarioCria')" /> do dia <input type=date value=<?=$dia?> class="border-none font-semibold py-1 px-2 w-[110px] hover:bg-gray-200 rounded text-gray-500" onclick=this.showPicker() onchange="location.replace('diarioNovaData?data='+this.value)"> <?=$mensagem?> <a href=previsaoInicio class=text-blue-700>Previsão</a> <div class="py-1"></div> <div class="shadow-sm"> <div class="bg-gray-100"> <div class="flex bg-gray-200 py-1"> <div class='w-[40px] whitespace-nowrap px-2'>Lçto</div> <div class='w-[60px] whitespace-nowrap text-right'>Ctad</div> <div class='w-[60px] whitespace-nowrap text-right'>Ctac</div> <div class="w-[100px] whitespace-nowrap text-right">Valor</div> <div> <form action=diarioHistorico method=post> @csrf <input name=hist placeholder="Procurar no Histórico" onchange=submit() class="rounded py-0 ml-2 border-none bg-transparent text-black font-semibold" autocomplete=off> </form> </div> </div> <?php foreach ($lctos as $index => $lcto): ?> <div class="flex odd:bg-gray-200 even:bg-white"> <div class="w-[40px] px-2"> <a href="diarioEdita?docto=<?=$lcto->docto?>" class="text-gray-500 font-semibold"><?=$lcto->lcto?></a> </div> <div class="w-[60px] text-right"><?= $lcto->contad ?></div> <div class="w-[60px] text-right"><?= $lcto->contac ?></div> <div class="w-[100px] text-right"><?= dec($lcto->valor) ?></div> <div class="w-[370px] truncate px-2"><?= $lcto->hist ?></div> </div> <?php endforeach; ?> <div class="flex font-semibold odd:bg-gray-200 even:bg-white"> <div style="width:260px" class="text-right font-semibold"> {{dec($somaDebito)}} </div> <div class='whitespace-nowrap px-2 text-red-500'> @if($somaDebito!==$somaCredito) {{"Soma de Crédito ".dec($somaCredito)}} @endif </div> </div> </div> </div> </div> Tudo isso é gambiarra, não existe nenhum tutorial afirmando que essa é forma correta de usar o <flux>.
  14. Depois de atualizar o Laravel Installer fica bem mais fácil colocar o Laravel 12 no notebook, o problema é que ele pede para escolher uma extensão (React, Vue, LiveWire) ou nenhum. O problema do Laravel puro é que ele não tem uma rotina para o login, assim eu não tive outra escolha senão selecionar uma extensão, no meu caso foi o LiveWire. Após terminar a instalação, o Laravel manda você direto para a tela do 'dashboard' se passar pela rotina do login, é uma tela bonita, mas eu não tenho a menor ideia de como trabalhar com ela. Eu só sei trabalhar com texto, e assim eu tenho o meu 'menuView'. Eu encontrei a rotina do login, e eu alterei assim: arquivo app > Livewire > Auth > Login.php (listagem parcial) <?php //... class Login extends Component { //... public function login(): void { $this->validate(); $this->ensureIsNotRateLimited(); if (! Auth::attempt(['email' => $this->email, 'password' => $this->password], $this->remember)) { RateLimiter::hit($this->throttleKey()); throw ValidationException::withMessages(['email' => __('auth.failed'),]); } RateLimiter::clear($this->throttleKey()); Session::regenerate(); $this->redirectIntended(default: route('menuView', absolute: false), navigate: true); } //... } Fiz logoff, entrei de novo, mas acabei de cara com o 'dashboard'. Então, decidi fechar o navegador, e pedi para o VS Code executar composer dump-autoload, e só assim é que consegui chegar no menuView, depois da rotina do login.
  15. Criei um novo projeto para conhecer o Laravel 12, e acabei me perdendo. A tela de boas vindas mudou, só tem dois botões. Um fala sobre a documentação do Laravel 12 e outro é Deploy, e ele me mandou para o Laravel Cloud, onde eu abri a minha conta, e depois fiquei sem saber o que fazer. Procurei o YouTube, e ele não me ajudou em nada, o vídeo falava da época em que o pessoa pretendia atualizar o Laravel. Assim, eu tive que improvisar. Procurei o Laravel 11, e de lá eu instalei o Breeze Blade (isso não existe no Laravel 12); e assim eu consegui colocar a opção de login na tela de boas vindas e cheguei no painel de controle. Pelo que pude deduzir o Laravel 12 é para quem tem o código hospedado no Github, mas por enquanto vou continuar usando o meu notebook. Na minha opinião, o pessoal precisa colocar um tutorial de como usar o Laravel 12, não adianta mandar eu ler os conceitos básicos do Laravel que eu vou acabar dormindo. ============================================== No fórum do Laracasts encontrei a solução: https://laracasts.com/discuss/channels/laravel/add-livewire-starter-kit-to-existing-base-laravel-12-installation A primeira tarefa é atualizar o instalador do Laravel assim: composer global remove laravel/installer composer global require laravel/installer Em seguida, você usa o comando: laravel new novoProjeto Ele vai fazer uma série de perguntas, uma delas é starter kit, eu escolhi o LiveWire, apesar de não ter a menor ideia de como usar isso, e também tem um outro tanto de perguntas que fui respondendo de acordo com o meu nariz, e assim ele já embutiu a rotina de login no projeto. Como eu trabalho com mysql, eu alterei o arquivo .env. Durante dois dias fiquei batendo a cabeça na parede, mas hoje eu vi que o Laravel 12 é muito mais fácil de instalar. Eles mudaram o script para executar o código no computador local, você não precisa mais ter dois terminais, um para ativar o servidor e outro para ativar o vite, agora faz as duas tarefas com o comando composer run dev
  16. Nessa semana, eu consegui fazer o cálculo do Simples Nacional no meu notebook, mas eu não consegui fazer o valor do imposto ser igual ao que foi calculado pela Contabilidade, a diferença é de alguns centavos, mas eu posso usar o meu programa como uma estimativa. O problema foi na hora de copiar o meu código PHP na Hostinger, lá o PHP reclamou que o comando scandir não encontrou o diretório que mandei procurar. Levei um tempão para entender porque o scandir não funciona: o que funciona no notebook nem sempre vai funcionar na Hostinger. Na base da tentativa e erro, fui procurar a solução no HTML, no <input type="file" multiple>, mas o máximo que eu consegui foi obter uma lista de 20 arquivos, quando precisava ver coisa da ordem de 700 arquivos. O Copilot explicou que o navegador e o servidor podem definir restrição para o <input type="file" multiple>, e o Copilot disse que eu preciso estudar mais, ir além do PHP e aprender como fazer a Hostinger ter acesso remoto ao meu notebook, e assim calcular o Simples Nacional na internet. A minha primeira tentativa de calcular o Simples foi pelo comando zipArchive do PHP, e eu consegui fazer funcionar uma vez ou outra. O Windows sempre consegue abrir o arquivo .zip, já o comando zipArchive do PHP sempre reclamava que encontrou erro no arquivo, assim eu desisti dele. Conclusão: eu não sei se é possível calcular o Simples Nacional na internet, mas eu consegui calcular aqui no notebook com o PHP. Mas para calcular o Simples aqui no notebook, eu preciso da venda dos doze últimos meses que está no MySQL que está hospedado lá na Hostinger. Isso é constrangedor, mas pelo menos eu posso chorar a vontade, isso é o que dá para fazer quando estou num beco sem saída. bling.php (parcial) <?php class Bling { static function simplesSelecionado() { $diretorio="C:/Users/Frank/Downloads/".substr($_FILES['pasta']['full_path'],0,-4); $contaArquivos = count(scandir($diretorio)) - 2 - 2 ; $notasFiscais = []; $nfCanceladas = []; $nfces = scandir($diretorio); $notasCanceladas=0; $somaTotal=0; $comST=0; $semST=0; foreach($nfces as $nfce) { if($nfce !== '.' && $nfce !=='..' ) { if(strpos($nfce,'-can') !== false) { $nfCanceladas[] = intval(substr($nfce,28,6)); $notasCanceladas++; continue; } $numeroNota=intval(substr($nfce,28,6)); if(in_array($numeroNota,$nfCanceladas)) { continue; } $notasFiscais[]=$numeroNota; $dom = new DOMDocument(); $dom->load("$diretorio/$nfce"); $nfe=$dom->documentElement; if($nfe->getElementsByTagName('vNF')->item(0)) { $somaNF=$nfe->getElementsByTagName('vNF')->item(0)->nodeValue; $somaTotal+=$somaNF; $produtos=$nfe->getElementsByTagName('prod'); foreach($produtos as $p) { $cfop=$p->getElementsByTagName('CFOP')->item(0)->nodeValue; $vProd=$p->getElementsByTagName('vProd')->item(0)->nodeValue; $vDesc=0; if($p->getElementsByTagName('vDesc')->item(0)) { $vDesc=$p->getElementsByTagName('vDesc')->item(0)->nodeValue; } if($cfop==5405) { $comST += $vProd - $vDesc; } else { $semST += $vProd - $vDesc; } } } } } sort($notasFiscais); $primeiraNota=intval($notasFiscais[0]); $ultimaNota=intval($notasFiscais[$contaArquivos-1]); $totalDeNotas=count($notasFiscais); $rendas=bd::x('select * from tbrendabruta order by id desc limit 13')->get(); $renda=0; foreach($rendas as $key=>$r) { if($key>0) { $renda += $r->renda; } } // indices da primeira faixa da tabela do Simples Nacional 2025 no comércio $aliqICMS=1.36; $ICMS=round($semST*$aliqICMS/100,2); $aliqIRPJ=0.22; $IRPJ=round($somaTotal*$aliqIRPJ/100,2); $aliqCSLL=0.14; $CSLL=round($somaTotal*$aliqCSLL/100,2); $aliqCOFINS=0.5096; $COFINS=round($somaTotal*$aliqCOFINS/100,2); $aliqPIS=0.1105; $PIS=round($somaTotal*$aliqPIS/100,2); $aliqINSS=1.66; $INSS=intval($somaTotal*$aliqINSS)/100; $aliqSimples=4; $Simples=$ICMS+$IRPJ+$CSLL+$COFINS+$PIS+$INSS; view('blingSimples',['primeiraNota'=>$primeiraNota,'ultimaNota'=>$ultimaNota, 'notasFiscais'=>$notasFiscais,'somaTotal'=>$somaTotal, 'contaArquivos'=>$contaArquivos,'notasCanceladas'=>$notasCanceladas, 'totalDeNotas'=>$totalDeNotas,'nfCanceladas'=>$nfCanceladas, 'comST'=>$comST,'semST'=>$semST,'renda'=>$renda, 'aliqICMS'=>$aliqICMS,'ICMS'=>$ICMS, 'aliqIRPJ'=>$aliqIRPJ,'IRPJ'=>$IRPJ, 'aliqCSLL'=>$aliqCSLL,'CSLL'=>$CSLL, 'aliqCOFINS'=>$aliqCOFINS,'COFINS'=>$COFINS, 'aliqPIS'=>$aliqPIS,'PIS'=>$PIS, 'aliqINSS'=>$aliqINSS,'INSS'=>$INSS, 'aliqSimples'=>$aliqSimples,'Simples'=>$Simples, 'rendas'=>$rendas]); } } arquivo blingSimples.php (ele usa o CSS https://cdn.tailwindcss.com) <?php include 'menuView.php'; ?> <script>btMenu.innerHTML="Simples";document.title="Simples"</script> <div class=flex> <div>Total de Notas</div> <div class="ml-2"><?=$totalDeNotas?></div> </div> <div class=flex> <div>Notas Canceladas</div> <div class="ml-2 text-right mr-2"><?=$notasCanceladas.": ";?></div> <?php foreach($nfCanceladas as $n): echo $n."<br>"; endforeach; ?> </div> <div class=flex> <div>Total das Notas Fiscais</div> <div class="text-right ml-2"><?=dec($somaTotal)?></div> </div> <div class=flex> <div>Primeira Nota</div> <div class="text-right ml-2"><?=$primeiraNota?></div> </div> <div class=flex> <div>Última Nota</div> <div class="text-right ml-5"><?=$ultimaNota?></div> </div> <div class=flex> <div class="w-[120px]">Renda 12 Meses</div> <div class="w-[100px] text-right"><?=dec($renda)?></div> </div> <div class="flex"> <?php $contador = 0; foreach($rendas as $key=>$r): if($key>0): if ($contador % 4 === 0 && $contador !== 0): ?> </div><div class="flex"> <?php endif; ?> <div class="w-[50px]"><?php echo $r->apuracao; ?></div> <div class="w-[80px] text-right font-semibold mr-2"><?php echo dec($r->renda); ?></div> <?php $contador++; endif; endforeach; ?> </div> <div class=flex> <div class="w-[120px]">Com ST</div> <div class="w-[100px] text-right"><?=dec($comST)?></div> </div> <div class=flex> <div class="w-[120px]">Sem ST ICMS</div> <div class="w-[100px] text-right"><?=dec($semST)?></div> <div class="w-[100px] text-right"><?=dec($aliqICMS)."%"?></div> <div class="w-[100px] text-right"><?=dec($ICMS)?></div> </div> <div class=flex> <div class="w-[120px]">IRPJ</div> <div class="w-[100px] text-right"><?=dec($somaTotal)?></div> <div class="w-[100px] text-right"><?=dec($aliqIRPJ)."%"?></div> <div class="w-[100px] text-right"><?=dec($IRPJ)?></div> </div> <div class=flex> <div class="w-[120px]">CSLL</div> <div class="w-[100px] text-right"><?=dec($somaTotal)?></div> <div class="w-[100px] text-right"><?=dec($aliqCSLL)."%"?></div> <div class="w-[100px] text-right"><?=dec($CSLL)?></div> </div> <div class=flex> <div class="w-[120px]">COFINS</div> <div class="w-[100px] text-right"><?=dec($somaTotal)?></div> <div class="w-[100px] text-right"><?=dec($aliqCOFINS)."%"?></div> <div class="w-[100px] text-right"><?=dec($COFINS)?></div> </div> <div class=flex> <div class="w-[120px]">PIS</div> <div class="w-[100px] text-right"><?=dec($somaTotal)?></div> <div class="w-[100px] text-right"><?=dec($aliqPIS)."%"?></div> <div class="w-[100px] text-right"><?=dec($PIS)?></div> </div> <div class=flex> <div class="w-[120px]">INSS</div> <div class="w-[100px] text-right"><?=dec($somaTotal)?></div> <div class="w-[100px] text-right"><?=dec($aliqINSS)."%"?></div> <div class="w-[100px] text-right"><?=dec($INSS)?></div> </div> <div class=flex> <div class="w-[120px]">Simples</div> <div class="w-[100px] text-right">Estimativa</div> <div class="w-[100px] text-right"><?=dec($aliqSimples)."%"?></div> <div class="w-[100px] text-right font-semibold"><?=dec($Simples)?></div> </div>
  17. Frank K Hosaka

    PHP: continue

    Comecei a estudar o cálculo do Simples Nacional, começando com um arquivo zipado da Bling, onde tem um monte de NFCE. O problema é a nota cancelada. A nota comum tem o formato 35...123-nfe.xml, já a nota cancelada tem o formato 35...123-can.xml. No Windows Explorer, o arquivo -can aparece antes do -nfe. Usei o famoso método da tentativa e erro e presumi que o comando PHP scandir($diretorio) seguisse o mesmo formato do Windows Explorer. O problema é como desconsiderar o arquivo -can e o arquivo -nfe correspondente. E assim o Copilot me ensinou a usar um novo comando do PHP, o continue. Eu achei esse comando muito esperto, digno de receber uma nota aqui no fórum, o comando continue simplesmente faz o ciclo foreach pular para o item seguinte: <?php class Bling { function faltanteSelecionado() { $diretorio="C:/Users/Frank/Downloads/".substr($_FILES['pasta']['full_path'],0,-4); $contaArquivos = count(scandir($diretorio)) - 2 - 2 ; $notasFiscais = []; $nfCanceladas = []; $nfces = scandir($diretorio); $notasCanceladas=0; $somaTotal=0; $comST=0; $semST=0; foreach($nfces as $nfce) { if($nfce !== '.' && $nfce !=='..' ) { if(strpos($nfce,'-can') !== false) { $nfCanceladas[] = intval(substr($nfce,28,6)); $notasCanceladas++; continue; } $numeroNota=intval(substr($nfce,28,6)); if(in_array($numeroNota,$nfCanceladas)) { continue; } $notasFiscais[]=$numeroNota; $dom = new DOMDocument(); $dom->load("$diretorio/$nfce"); $nfe=$dom->documentElement; if($nfe->getElementsByTagName('vNF')->item(0)) { $somaNF=$nfe->getElementsByTagName('vNF')->item(0)->nodeValue; $somaTotal+=$somaNF; $produtos=$nfe->getElementsByTagName('prod'); foreach($produtos as $p) { $cfop=$p->getElementsByTagName('CFOP')->item(0)->nodeValue; $vProd=$p->getElementsByTagName('vProd')->item(0)->nodeValue; $vDesc=0; if($p->getElementsByTagName('vDesc')->item(0)) { $vDesc=$p->getElementsByTagName('vDesc')->item(0)->nodeValue; } if($cfop==5405) { $comST += $vProd - $vDesc; } else { $semST += $vProd - $vDesc; } } } } } sort($notasFiscais); $primeiraNota=intval($notasFiscais[0]); $ultimaNota=intval($notasFiscais[$contaArquivos-1]); $totalDeNotas=count($notasFiscais); view('blingFaltante',['primeiraNota'=>$primeiraNota,'ultimaNota'=>$ultimaNota, 'notasFiscais'=>$notasFiscais,'somaTotal'=>$somaTotal, 'contaArquivos'=>$contaArquivos,'notasCanceladas'=>$notasCanceladas, 'totalDeNotas'=>$totalDeNotas,'nfCanceladas'=>$nfCanceladas, 'comST'=>$comST,'semST'=>$semST]); } }
  18. Ao invés de usar uma caixa de texto, usei uma célula do lado. Se a célula estiver vazia, isso gera erro. Para contornar esse contratempo, o melhor é pedir para o VBA não considerar se a célula estiver vazia, tipo: Sub Teste() If Not IsEmpty(Range("L5").Value) Then Range("K5").Value = Format(Range("L5").Value, "dd,mm,yyyy") Else MsgBox "A célula L5 está vazia. Por favor, insira um valor antes de executar a macro.", vbExclamation, "Aviso" End If End Sub
  19. Tentei fazer do seu jeito, insert into meus_contatos (id_contatos,sobrenome) values (null,'frank') e deu certo. Acredito que o problema estava nas aspas, eu tive que mudar um monte de aspas curvas com aspas simples '
  20. CREATE TABLE meus_contatos ( id_contatos INT NOT NULL AUTO_INCREMENT PRIMARY KEY, sobrenome VARCHAR(30), primeiro_nome VARCHAR(20), sexo CHAR(1), email VARCHAR(50) UNIQUE, aniversario DATE, profissao VARCHAR(50), locall VARCHAR(50), estado_civil VARCHAR(20), interesses VARCHAR(100), procura VARCHAR(100) ); INSERT INTO meus_contatos (sobrenome, primeiro_nome, sexo, email, aniversario, profissao, locall, estado_civil, interesses, procura) VALUES ('Almeida', 'Jose', 'M', 'jose@gmail.com', '1970-02-02', 'pedreiro', 'brazlandia', 'casado', 'cinema', 'emprego'), ('Prado', 'Joao', 'M', 'joao@gmail.com', '1971-02-02', 'marceneiro', 'brazlandia', 'casado', 'jogos', 'relacionamento'), ('Oliveira Souza', 'Jonas', 'M', 'jonas@gmail.com', '1973-02-02', 'empresario', 'brazlandia', 'casado', 'futebol', 'emprego'), ('Gomes', 'Sergio', 'M', 'sergio@gmail.com', '1979-02-02', 'marceneiro', 'brazlandia', 'solteiro', 'voleibol', 'relacionamento'), ('Gomes', 'Joana', 'F', 'joana@gmail.com', '1980-02-02', 'marceneiro', 'brazlandia', 'casada', 'educacao', 'viagens');
  21. Mais uma tentativa: Criei um gráfico e copiei três vezes o mesmo gráfico; criei um userform,um ListBox com nomem lstCharts e um botão com nome cmdApplyBorder, e o código no ambiente do UserForm ficou assim: Private Sub UserForm_Initialize() Dim ws As Worksheet Set ws = ThisWorkbook.Sheets("gráficos") Dim cht As ChartObject For Each cht In ws.ChartObjects lstCharts.AddItem cht.Name Next cht ' Define o tamanho da fonte da ListBox lstCharts.Font.Size = 14 End Sub Private Sub cmdApplyBorder_Click() Dim ws As Worksheet Set ws = ThisWorkbook.Sheets("gráficos") Dim selectedChart As String selectedChart = lstCharts.Value If selectedChart <> "" Then Dim cht As ChartObject ' Define a borda preta fina para todos os gráficos For Each cht In ws.ChartObjects cht.Border.Color = RGB(0, 0, 0) cht.Border.Weight = xlThin Next cht ' Desenha a borda vermelha mais grossa no gráfico correspondente Set cht = ws.ChartObjects(selectedChart) cht.Border.Color = RGB(255, 0, 0) cht.Border.Weight = xlThick ' Fecha o UserForm Unload Me Else MsgBox "Por favor, selecione um gráfico.", vbExclamation End If End Sub No ambiente de código da planilha gráfico, criei o seguinte comando: Sub ShowUserForm() UserForm1.Show End Sub
  22. Não sei se isso vai ajudar, mas eu descobri que fiz uma enorme confusão entre imagem e gráfico, o Copilot me ensinou a criar um gráfico. Primeiro criei uma planilha chamada gráficos, na coluna A1 coloquei Ano, e abaixo dela coloquei 20, 21, 22, 23, 24, 25; na coluna B1 coloquei Popularidade, e abaixo dela coloquei 5, 4, 3, 2, 1, 0. Pedi para o Copilot criar um código VBA (no ambiente da planilha gráficos) e em seguida salvar o arquivo. Isso está longe de resolver o seu problema, mas acredito que ele pode ajudar a conhecer melhor o VBA: Sub CriarEGerarGrafico() Dim ws As Worksheet Dim grafico As ChartObject Dim pastanome As String Dim currentchart As Chart ' Define a planilha onde os dados estão localizados Set ws = Worksheets("gráficos") ' Verifica se já existe um gráfico na planilha e o remove For Each grafico In ws.ChartObjects grafico.Delete Next grafico ' Adiciona um novo gráfico Set grafico = ws.ChartObjects.Add(Left:=100, Width:=375, Top:=50, Height:=225) ' Define a origem dos dados para o gráfico With grafico.Chart .SetSourceData Source:=ws.Range("A1:B6") .ChartType = xlLineMarkers ' Define o tipo de gráfico como linha com marcadores ' Define os títulos do gráfico e dos eixos .HasTitle = True .ChartTitle.Text = "Popularidade ao Longo dos Anos" .Axes(xlCategory, xlPrimary).HasTitle = True .Axes(xlCategory, xlPrimary).AxisTitle.Text = "Ano" .Axes(xlValue, xlPrimary).HasTitle = True .Axes(xlValue, xlPrimary).AxisTitle.Text = "Popularidade" End With ' Salva o gráfico como imagem no mesmo diretório da pasta de trabalho Set currentchart = grafico.Chart pastanome = ThisWorkbook.Path & Application.PathSeparator & "grafico1.gif" currentchart.Export Filename:=pastanome, filtername:="gif" MsgBox "Gráfico criado e salvo com sucesso em: " & pastanome End Sub
  23. Hoje, apareceu outro problema, a soma das vendas na Bling deu R$ 15.448,23 mas no PHP deu R$ 15.448,22, ou mais precisamente R$ 15.448,224999. Todas as soluções anteriores não deram certo, hoje tentei uma nova gambiarra: function aint($valor) { return ceil($valor*100)/100; }
  24. Copilot: Sim, você pode criar um código VBA para copiar o login e a senha da tabela e colar onde for necessário. Vou fornecer um exemplo de como você pode fazer isso no Excel: ```vba Sub CopiarLoginSenha() Dim ws As Worksheet Dim login As String Dim senha As String Dim link As String Dim destino As Worksheet ' Definir a planilha de origem e a planilha de destino Set ws = ThisWorkbook.Sheets("Planilha1") ' Planilha de origem com os dados Set destino = ThisWorkbook.Sheets("Planilha2") ' Planilha de destino onde os dados serão colados ' Loop através da tabela de dados na Planilha1 For i = 2 To ws.Cells(ws.Rows.Count, 1).End(xlUp).Row link = ws.Cells(i, 1).Value login = ws.Cells(i, 2).Value senha = ws.Cells(i, 3).Value ' Exemplo de uso dos dados copiados ' Você pode modificar esta parte para colar os dados onde precisar destino.Cells(i, 1).Value = link destino.Cells(i, 2).Value = login destino.Cells(i, 3).Value = senha ' Mensagem de confirmação MsgBox "Dados do link: " & link & ", login: " & login & " e senha: " & senha & " copiados com sucesso!", vbInformation Next i End Sub ``` Neste exemplo, o código VBA percorre a tabela de dados na "Planilha1" e copia o link, o login e a senha para a "Planilha2". Você pode modificar este exemplo para colar os dados onde for conveniente para o seu caso específico. Para adicionar este código ao seu projeto do Excel: 1. Pressione `Alt + F11` para abrir o Editor do VBA. 2. Clique em `Inserir` > `Módulo` para criar um novo módulo. 3. Copie e cole o código acima no módulo. 4. Feche o Editor do VBA. 5. No Excel, pressione `Alt + F8` para abrir a janela de macros, selecione `CopiarLoginSenha` e clique em `Executar`. Espero que isso ajude! Se precisar de mais alguma coisa, estou aqui para ajudar. 😊
  25. Na pasta Controller, eu tenho uma classe chamada Outros, e dentro dele criei o seguinte método: function teste() { return "olá mundo!"; } Na pasta Routes, eu criei uma nova rota no web.php: Route::get('teste',[Outros::class,'teste']); E, finalmente, testei no navegador com o comando localhost:8000/teste e a resposta foi 409 not found. Conversei com o Copilot, e ele disse que 99% dos problemas acontecem por erro de digitação, ele pediu para reiniciar o servidor ("php artisan serve"), e muitas instruções estranhas que decidi não seguir. Usei o velho motor de busca do Google "409 not found" e por sorte o primeiro tópico falava do Laravel. O rapaz disse para usar o comando php artisan route:clear e em seguinda php artisan route:list, e verificar se o novo método está na lista. O Laravel é bacana, mas tem hora que ele me tira do sério.
×
×
  • Criar Novo...