Compare commits

...

2 Commits

Author SHA1 Message Date
lukidev 8dc2c82cc1
feat: Edição de clientes
Funcionalidade para edição de clientes.
2025-11-19 19:51:59 -03:00
lukibeg 692378d0cd feat: Edição de clientes 2025-11-19 19:49:43 -03:00
7 changed files with 46 additions and 44 deletions

View File

@ -34,7 +34,7 @@ public function save(ClientService $clientService)
$client = $clientService->addClient($data);
$this->dispatch('client-added');
$this->dispatch('notify', message: $client->name . ' Cliente adicionado com sucesso!');
$this->dispatch('notify', message: $client->name . ' adicionado com sucesso!');
} catch (\Exception $e) {
$this->dispatch('notify', message: 'Ocorreu um erro inesperado ao salvar.', type: 'error');
}

View File

@ -12,14 +12,14 @@ class CreateUser extends Component
public string $email = '';
public string $password = '';
public string $password_confirm = '';
public bool $permissions = false;
public string $permissions = '';
protected $rules = [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|string|min:8',
'password_confirm' => 'required|string|same:password',
'permissions' => 'required|boolean'
'permissions' => 'required|string|in:user,admin'
];
protected $messages = [
@ -28,7 +28,7 @@ class CreateUser extends Component
'email.unique' => 'O email informado já foi cadastrado anteriormente.',
'password' => 'A senha precisa ter 8 ou mais caracteres.',
'password_confirm' => 'As senhas não coincidem.',
'permissions' => 'Defina o nível de autorização do usuário.',
'permissions' => 'Escolha o nível de autorização do usuário.'
];
public function createUser(UserService $userService)
@ -36,12 +36,6 @@ public function createUser(UserService $userService)
$validated = $this->validate($this->rules, $this->messages);
if ($validated['permissions'] === true) {
$validated['permissions'] = array('admin');
} else {
$validated['permissions'] = array('user');
}
try {
$this->authorize('createUser', Auth::user());

View File

@ -4,6 +4,7 @@
use App\Livewire\Forms\ClientForm;
use App\Models\Client;
use App\Services\ClientService;
use Livewire\Attributes\On;
use Livewire\Component;
use Exception;
@ -13,8 +14,11 @@ class EditClient extends Component
public Client $client;
public ClientForm $clientForm;
// public ClientService $clientService;
#[On('update-client')]
public function loadClient($id)
{
try {
@ -27,15 +31,19 @@ public function loadClient($id)
$this->dispatch('notify', message: 'Ocorreu um erro inesperado ao editar o cliente. ' + $e);
}
}
public function edit($clientId)
public function edit(ClientService $clientService)
{
$this->clientForm->validate();
$data = $this->clientForm->validate();
try {
$this->clientForm->updateClient($this->client);
$this->dispatch('notify', message: $this->client->client_name + ' atualizado com sucesso!');
if (!$clientService->updateClient($this->client, $data)) {
throw new Exception('O serviço não confirmou a atualização.');
}
$this->dispatch('client-updated');
$this->dispatch('notify', message: $this->clientForm->client_name . ' atualizado com sucesso!');
} catch (Exception $e) {
$this->dispatch('notify', message: 'Ocorreu um erro inesperado ao tentar confirmar edição do cliente. ' + $e);
$this->dispatch('notify', message: 'Falha na edição: ' . $e->getMessage(), type: 'error');
}
}
public function render()

View File

@ -2,7 +2,6 @@
namespace App\Livewire\Forms;
use App\Services\ClientService;
use Exception;
use Livewire\Attributes\Validate;
use Livewire\Form;
@ -26,8 +25,6 @@ class ClientForm extends Form
public $modules = '';
public $whatsapp_number = '';
public $whatsapp_activation_date;
public ClientService $clientService;
// Método para preencher o formulário (para edição futura)
public function addClient(Client $client)
{
@ -40,14 +37,6 @@ public function addClient(Client $client)
$this->fill($data);
}
public function updateClient(Client $client)
{
if(!$this->clientService->updateClient($client)){
throw new Exception('Ocorreu um erro.');
}
}
// 4. ADICIONADO: Método de Regras
/**
* Define as regras de validação para o formulário.
@ -57,7 +46,11 @@ public function rules()
return [
'client_name' => 'required|string|max:255',
'legal_name' => 'required|string|max:255',
'cnpj' => 'required|string|max:20|unique:clients,cnpj',
'cnpj' => [
'required',
'string',
'max:18',
],
'profile_image_path' => 'nullable|file|mimes:jpeg,png,bmp,gif,svg,webp|max:2048',
'activation_date' => 'nullable|date',
'carrier' => 'nullable|string|max:255',
@ -83,6 +76,9 @@ public function messages()
'client_name.required' => 'O campo Nome Fantasia é obrigatório.',
'client_name.max' => 'O Nome Fantasia não pode ter mais que 255 caracteres.',
'cnpj.required' => 'O CNPJ é obrigatório.',
'cnpj.max' => 'O CNPJ deve ter no máximo 18 caracteres (incluindo pontuação).',
'cnpj.min' => 'O CNPJ está muito curto. Por favor, insira um CNPJ válido.',
'cnpj.unique' => 'Este CNPJ já está cadastrado em outro cliente.',
'profile_image_path.image' => 'O arquivo deve ser uma imagem válida (jpg, png, etc.).',

View File

@ -20,5 +20,9 @@ public function addClient(array $client)
return Client::create($client);
}
public function updateClient($client) {}
public function updateClient(Client $client, $data)
{
$data['name'] = $data['client_name'];
return $client->update($data);
}
}

View File

@ -47,7 +47,7 @@
<div x-data="{
open: false,
selected: @entangle('permissions'),
options: { '0': 'Usuário', '1': 'Admin' }
options: { 'user': 'Usuário', 'admin': 'Admin' }
}" x-on:click.outside="open = false" class="select-wrapper">
<button type="button" x-on:click="open = true" class="select-button">
@ -63,10 +63,10 @@
</button>
<div x-show="open" x-transition style="display: none;" class="select-options">
<div x-on:click="selected = '0'; open = false" class="select-option"
:class="{ 'selected-option': selected == '0' }">
<span class="option-label" :class="{ 'font-semibold': selected == '0' }">Usuário</span>
<span x-show="selected == '0'"
<div x-on:click="selected = 'user'; open = false" class="select-option"
:class="{ 'selected-option': selected == 'user' }">
<span class="option-label" :class="{ 'font-semibold': selected == 'user' }">Usuário</span>
<span x-show="selected == 'user'"
class="absolute inset-y-0 left-0 flex items-center pl-3 text-blue-600">
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"
fill="currentColor">
@ -77,10 +77,10 @@ class="absolute inset-y-0 left-0 flex items-center pl-3 text-blue-600">
</span>
</div>
<div x-on:click="selected = '1'; open = false" class="select-option"
:class="{ 'selected-option': selected == '1' }">
<span class="option-label" :class="{ 'font-semibold': selected == '1' }">Admin</span>
<span x-show="selected == '1'"
<div x-on:click="selected = 'admin'; open = false" class="select-option"
:class="{ 'selected-option': selected == 'admin' }">
<span class="option-label" :class="{ 'font-semibold': selected == 'admin' }">Admin</span>
<span x-show="selected == 'admin'"
class="absolute inset-y-0 left-0 flex items-center pl-3 text-blue-600">
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"
fill="currentColor">

View File

@ -14,7 +14,7 @@ class="fixed inset-0 bg-white/50 transition-opacity"></div>
class="fixed inset-y-0 right-0 flex max-w-full pl-10" @click.away="showEditClientModal = false">
<div class="w-screen max-w-3xl">
<form wire:submit="edit(clientId)" class="flex h-full flex-col overflow-y-scroll bg-white shadow-xl">
<form wire:submit.prevent="edit" class="flex h-full flex-col overflow-y-scroll bg-white shadow-xl">
<div class="bg-white px-4 py-6 sm:px-6">
<div class="flex items-center justify-between">
@ -45,7 +45,7 @@ class="rounded-md text-blue-200 hover:text-white cursor-pointer focus:outline-no
<label for="client_name" class="form-label">Nome Fantasia *</label>
<input type="text" wire:model="clientForm.client_name" id="client_name"
class="form-input">
@error('form.client_name') <span
@error('clientForm.client_name') <span
class="text-red-500 text-sm">{{ $message }}</span>
@enderror
</div>
@ -53,14 +53,14 @@ class="text-red-500 text-sm">{{ $message }}</span>
<label for="legal_name" class="form-label">Razão Social *</label>
<input type="text" wire:model="clientForm.legal_name" id="legal_name"
class="form-input">
@error('form.legal_name') <span
@error('clientForm.legal_name') <span
class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
</div>
<div class="mt-4">
<label for="cnpj" class="form-label">CNPJ *</label>
<input type="text" wire:model="clientForm.cnpj" id="cnpj" class="form-input">
@error('form.cnpj') <span class="text-red-500 text-sm">{{ $message }}</span>
@error('clientForm.cnpj') <span class="text-red-500 text-sm">{{ $message }}</span>
@enderror
</div>
<div class="mt-4">
@ -72,7 +72,7 @@ class="form-file-input">
class="text-sm text-blue-600 mt-1">
Enviando...
</div>
@error('form.profile_image_path') <span
@error('clientForm.profile_image_path') <span
class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
</div>
@ -105,7 +105,7 @@ class.="form-input" placeholder="Ex: SSH, AnyDesk, VPN">
<label for="server_ip" class="form-label">IP do Servidor</label>
<input type="text" wire:model="clientForm.server_ip" id="server_ip"
class="form-input">
@error('form.server_ip') <span
@error('clientForm.server_ip') <span
class="text-red-500 text-sm">{{ $message }}</span> @enderror
</div>
<div>
@ -159,7 +159,7 @@ class="form-checkbox">
<label for="modules" class="form-label">Módulos Adicionais (JSON)</label>
<textarea wire:model="clientForm.modules" id="modules" rows="3" class="form-input"
placeholder="Ex: {&quot;bi&quot;: true}"></textarea>
@error('form.modules') <span class="text-red-500 text-sm">{{ $message }}</span>
@error('clientForm.modules') <span class="text-red-500 text-sm">{{ $message }}</span>
@enderror
</div>
</div>