Compare commits

..

11 Commits

Author SHA1 Message Date
lukibeg 0dc2c8d88c feat: Lista os clientes dinâmicos. 2025-11-16 21:55:17 -03:00
lukibeg b1207b3ed9 Revert "feat: Lista os clientes din"
This reverts commit aa4d6d2ccb.
2025-11-16 21:51:40 -03:00
lukibeg aa4d6d2ccb feat: Lista os clientes din 2025-11-16 21:50:40 -03:00
lukibeg 3363e9eede feat: Carrega clientes dinâmicamente. 2025-11-16 21:50:15 -03:00
lukibeg 5451f5c9ab feat: Deleta clientes. 2025-11-16 21:49:50 -03:00
lukibeg 6abd11dce7 refactor: Apenas carrega componentes dinâmicos. 2025-11-16 21:49:18 -03:00
lukibeg 4afc2b4e0a refactor|feat: Aprimora transições e apaga cliente de forma permanente. 2025-11-16 21:48:26 -03:00
lukibeg c788a80d03 feat: Agora verifica se o usuário está logado antes de concluir uma ação. 2025-11-16 21:47:22 -03:00
lukibeg a7b0de06f1 Sem mudanças. 2025-11-16 21:45:54 -03:00
lukibeg 73bc359885 Sem mudanças. 2025-11-16 21:45:29 -03:00
lukibeg 16b3e0dd17 refactor: Renderiza o dashboard geral. 2025-11-16 21:42:45 -03:00
9 changed files with 124 additions and 164 deletions

View File

@ -13,7 +13,6 @@ class ClientController extends Controller
public function __construct(ClientService $userService) {} public function __construct(ClientService $userService) {}
public function dashboard(Request $request): View public function dashboard(Request $request): View
{ {
$clients = Client::all(); return view('dashboard');
return view('dashboard', ['clients' => $clients]);
} }
} }

View File

@ -5,6 +5,7 @@
use App\Models\Client; use App\Models\Client;
use App\Services\ClientService; use App\Services\ClientService;
use App\Livewire\Forms\ClientForm; // 1. Importa seu Form Object use App\Livewire\Forms\ClientForm; // 1. Importa seu Form Object
use Illuminate\Support\Facades\Auth;
use Livewire\Component; use Livewire\Component;
use Livewire\WithFileUploads; use Livewire\WithFileUploads;
use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\Crypt;

View File

@ -0,0 +1,30 @@
<?php
namespace App\Livewire\Admin;
use Livewire\Component;
use Livewire\Attributes\On;
use App\Models\Client;
class DeleteClient extends Component
{
#[On('confirm-delete')]
public function deleteClient($payload)
{
$deletedClient = Client::findOrFail($payload);
if ($deletedClient) {
$deletedClient->delete();
}
$this->dispatch('clientDeleted');
// (Opcional) Envia uma notificação de sucesso
$this->dispatch('notify', message: 'Cliente excluído com sucesso!');
}
public function render()
{
return '<div></div>';
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace App\Livewire\Admin;
use App\Models\Client;
use Livewire\Component;
use Livewire\Attributes\On;
class ShowClient extends Component
{
#[On('clientDeleted')]
public function refreshClientList() {}
public function render()
{
$clients = Client::all();
return view('livewire.admin.show-client', [
'clients' => $clients
]);
}
}

View File

@ -8,7 +8,6 @@
class ClientForm extends Form class ClientForm extends Form
{ {
// 2. ATRIBUTOS REMOVIDOS: Os #[Rule(...)] foram removidos daqui
public $client_name = ''; public $client_name = '';
public $legal_name = ''; public $legal_name = '';
public $cnpj = ''; public $cnpj = '';

View File

@ -4,6 +4,7 @@
use App\Models\Client; use App\Models\Client;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
class ClientService class ClientService
@ -12,6 +13,10 @@ class ClientService
public function __construct(protected Client $client) {} public function __construct(protected Client $client) {}
public function addClient(array $client) public function addClient(array $client)
{ {
if (!Auth::check()) {
return redirect()->to('/login');
}
return Client::create($client); return Client::create($client);
} }
} }

View File

@ -3,42 +3,35 @@
- 'showQuestion' controla a visibilidade. - 'showQuestion' controla a visibilidade.
- '@sure.window' é o evento que dispara a abertura. - '@sure.window' é o evento que dispara a abertura.
--> -->
<div x-data="{showQuestion: false}" <div x-data="{showQuestion: false, clientId: null}" @sure.window="showQuestion = true; clientId = $event.detail.id"
@sure.window="showQuestion = true" x-cloak {{-- x-cloak é bom para evitar "piscadas" na tela --}}>
x-cloak {{-- x-cloak é bom para evitar "piscadas" na tela --}}
>
<!-- <!--
1. O OVERLAY (Fundo) 1. O OVERLAY (Fundo)
Copiado 1-para-1 do seu 'create-user' Copiado 1-para-1 do seu 'create-user'
--> -->
<div x-show="showQuestion" <div x-show="showQuestion" class="modal-overlay" x-transition:enter.duration.300ms
class="modal-overlay" x-transition:leave.duration.300ms>
x-transition:enter.duration.300ms
x-transition:leave.duration.300ms
>
<!-- <!--
2. O CONTAINER (Card) 2. O CONTAINER (Card)
Copiado 1-para-1 do seu 'create-user' Copiado 1-para-1 do seu 'create-user'
--> -->
<div x-on:click.outside="showQuestion = false" <div x-on:click.outside="showQuestion = false" x-show="showQuestion" x-transition:enter="transition-enter"
x-show="showQuestion" x-transition:enter-start="transition-enter-start" x-transition:enter-end="transition-enter-end"
x-transition:enter="transition-enter" x-transition:leave="transition-leave" x-transition:leave-start="transition-leave-start"
x-transition:enter-start="transition-enter-start" x-transition:leave-end="transition-leave-end" class="modal-container max-w-sm" {{-- Adicionei 'max-w-sm'
x-transition:enter-end="transition-enter-end" para um modal de alerta menor --}}>
x-transition:leave="transition-leave"
x-transition:leave-start="transition-leave-start"
x-transition:leave-end="transition-leave-end"
class="modal-container max-w-sm" {{-- Adicionei 'max-w-sm' para um modal de alerta menor --}}
>
<!-- 3. O NOVO CONTEÚDO (Confirmação) --> <!-- 3. O NOVO CONTEÚDO (Confirmação) -->
<!-- Ícone de Alerta --> <!-- Ícone de Alerta -->
<div class="mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10"> <div
<svg class="h-6 w-6 text-red-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> class="mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" /> <svg class="h-6 w-6 text-red-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round"
d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
</svg> </svg>
</div> </div>
@ -47,12 +40,12 @@ class="modal-container max-w-sm" {{-- Adicionei 'max-w-sm' para um modal de aler
<h3 class="modal-title" id="modal-title"> <h3 class="modal-title" id="modal-title">
Confirmar Exclusão Confirmar Exclusão
</h3> </h3>
<!-- Descrição --> <!-- Descrição -->
<div class="mt-2"> <div class="mt-2">
<p class="text-sm text-gray-500"> <p class="text-sm text-gray-500">
Você tem certeza que deseja excluir este cliente? Você tem certeza que deseja excluir este cliente?
Todos os seus dados serão removidos permanentemente. Todos os seus dados serão removidos permanentemente.
Esta ação não pode ser desfeita. Esta ação não pode ser desfeita.
</p> </p>
</div> </div>
@ -60,24 +53,17 @@ class="modal-container max-w-sm" {{-- Adicionei 'max-w-sm' para um modal de aler
<!-- Botões (usando a estrutura do 'create-user') --> <!-- Botões (usando a estrutura do 'create-user') -->
<div class="form-footer mt-5 sm:mt-4 sm:flex sm:flex-row-reverse"> <div class="form-footer mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
<!-- <!--
O botão "Sim, Excluir" deve vir primeiro no HTML O botão "Sim, Excluir" deve vir primeiro no HTML
para o 'flex-row-reverse' funcionar. para o 'flex-row-reverse' funcionar.
--> -->
<button type="button" <button type="button" @click="$dispatch('confirm-delete', [clientId]); showQuestion = false"
{{-- class="btn-submit bg-red-600 hover:bg-red-700 focus:ring-red-500 w-full sm:w-auto">
Aqui, ele dispara o evento 'confirm-delete'
(que seu Livewire pode ouvir) e fecha o modal.
--}}
@click="$dispatch('confirm-delete'); showQuestion = false"
class="btn-submit bg-red-600 hover:bg-red-700 focus:ring-red-500 w-full sm:w-auto">
Sim, Excluir Sim, Excluir
</button> </button>
<button type="button" <button type="button" @click="showQuestion = false" class="btn-cancel mt-3 sm:mt-0 w-full sm:w-auto">
@click="showQuestion = false"
class="btn-cancel mt-3 sm:mt-0 w-full sm:w-auto">
Cancelar Cancelar
</button> </button>
</div> </div>

View File

@ -5,128 +5,7 @@
<livewire:admin.create-user /> <livewire:admin.create-user />
<livewire:admin.add-client /> <livewire:admin.add-client />
<livewire:admin.show-users /> <livewire:admin.show-users />
<livewire:admin.delete-client />
<x-are-you-sure /> <x-are-you-sure />
<livewire:admin.show-client />
<div class="container grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
@foreach ($clients as $client)
<div class="client-card">
<div class="client-card-header">
<div class="client-avatar">
<img src="{{ Vite::asset('resources/images/mr-distribuidora.svg') }}" alt="Avatar do Cliente"
class="w-32 h-32 rounded-full object-cover">
</div>
<div x-data="{ open: false }" @click.outside="open = false" class="client-options-menu">
<button @click="open = !open" class="client-options-button">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-400 hover:text-gray-700"
viewBox="0 0 20 20" fill="currentColor">
<path
d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" />
</svg>
</button>
<ul x-show="open" class="client-options-list" x-transition>
<li><a href="#" class="client-option-item">Ver Detalhes</a></li>
<li><a href="#" class="client-option-item">Editar Cliente</a></li>
<li>
<a href="#" class="client-option-item text-red-600" x-on:click.prevent="$dispatch('sure')">
Excluir Cliente
</a>
</li>
</ul>
</div>
</div>
<div class="client-card-name">
{{ $client->name }}
</div>
</div>
@endforeach
<div class="client-card">
<div class="client-card-header">
<div class="client-avatar">
<img src="{{ Vite::asset('resources/images/maissaude.svg') }}" alt="Avatar do Cliente"
class="w-32 h-32 rounded-full object-cover">
</div>
<div x-data="{ open: false }" @click.outside="open = false" class="client-options-menu">
<button @click="open = !open" class="client-options-button">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-400 hover:text-gray-700"
viewBox="0 0 20 20" fill="currentColor">
<path
d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" />
</svg>
</button>
<ul x-show="open" class="client-options-list" x-transition>
<li><a href="#" class="client-option-item">Ver Detalhes</a></li>
<li><a href="#" class="client-option-item">Editar Cliente</a></li>
<li><a href="#" class="client-option-item text-red-600">Excluir Cliente</a></li>
</ul>
</div>
</div>
<div class="client-card-name">
Cliente 2
</div>
</div>
<div class="client-card">
<div class="client-card-header">
<div class="client-avatar">
<img src="{{ Vite::asset('resources/images/logo.png') }}" alt="Avatar do Cliente"
class="w-32 h-32 rounded-full object-cover">
</div>
<div x-data="{ open: false }" @click.outside="open = false" class="client-options-menu">
<button @click="open = !open" class="client-options-button">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-400 hover:text-gray-700"
viewBox="0 0 20 20" fill="currentColor">
<path
d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" />
</svg>
</button>
<ul x-show="open" class="client-options-list" x-transition>
<li><a href="#" class="client-option-item">Ver Detalhes</a></li>
<li><a href="#" class="client-option-item">Editar Cliente</a></li>
<li><a href="#" class="client-option-item text-red-600">Excluir Cliente</a></li>
</ul>
</div>
</div>
<div class="client-card-name">
Cliente 3
</div>
</div>
<div class="client-card">
<div class="client-card-header">
<div class="client-avatar">
<img src="{{ Vite::asset('resources/images/logo.png') }}" alt="Avatar do Cliente"
class="w-32 h-32 rounded-full object-cover">
</div>
<div x-data="{ open: false }" @click.outside="open = false" class="client-options-menu">
<button @click="open = !open" class="client-options-button">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-400 hover:text-gray-700"
viewBox="0 0 20 20" fill="currentColor">
<path
d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" />
</svg>
</button>
<ul x-show="open" class="client-options-list" x-transition>
<li><a href="#" class="client-option-item">Ver Detalhes</a></li>
<li><a href="#" class="client-option-item">Editar Cliente</a></li>
<li><a href="#" class="client-option-item text-red-600">Excluir Cliente</a></li>
</ul>
</div>
</div>
<div class="client-card-name">
Cliente 4
</div>
</div>
</div>
@endsection @endsection

View File

@ -0,0 +1,38 @@
<div class="container grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
@foreach ($clients as $client)
<div class="client-card">
<div class="client-card-header">
<div class="client-avatar">
<img src="{{ Vite::asset('resources/images/mr-distribuidora.svg') }}" alt="Avatar do Cliente"
class="w-32 h-32 rounded-full object-cover">
</div>
<div x-data="{ open: false }" @click.outside="open = false" class="client-options-menu">
<button @click="open = !open" class="client-options-button">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-400 hover:text-gray-700"
viewBox="0 0 20 20" fill="currentColor">
<path
d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" />
</svg>
</button>
<ul x-show="open" class="client-options-list" x-transition>
<li><a href="#" class="client-option-item">Ver Detalhes</a></li>
<li><a href="#" class="client-option-item">Editar Cliente</a></li>
<li>
<a href="#" class="client-option-item text-red-600"
x-on:click.prevent="$dispatch('sure', { id: '{{ $client->id }}' })">
Excluir Cliente
</a>
</li>
</ul>
</div>
</div>
<div class="client-card-name">
{{ $client->name }}
</div>
</div>
@endforeach
</div>