From 1c9f6f0330b3b86e7bfe538369707eee5771712b Mon Sep 17 00:00:00 2001 From: Alessandro Costa de Oliveira Date: Thu, 9 Apr 2026 17:06:52 -0300 Subject: [PATCH] =?UTF-8?q?Campo=20data=20input=20com=20m=C3=A1scara?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit campo data input datepicker d/m/Y, salva Y-m-d, exibe d/m/Y campo texto input campo caixa de texto textarea --- app/Http/Controllers/ChamadoController.php | 61 ++++++++++++++++-- app/Utils/JSONForms.php | 64 +++++++++++++++++++ public/js/functions.js | 17 +++++ resources/views/chamados/create.blade.php | 1 + .../chamados/show/dados-formulario.blade.php | 5 +- .../show/editar-formulario-btn.blade.php | 1 + .../show/formulario-dados-atendente.blade.php | 5 +- .../template-btn-novocampo-modal.blade.php | 1 + resources/views/filas/template.blade.php | 1 + tests/Unit/JSONFormsTest.php | 53 +++++++++++++++ 10 files changed, 202 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/ChamadoController.php b/app/Http/Controllers/ChamadoController.php index 37dd29dc..25976dcf 100644 --- a/app/Http/Controllers/ChamadoController.php +++ b/app/Http/Controllers/ChamadoController.php @@ -130,8 +130,10 @@ public function store(ChamadoRequest $request, Fila $fila) # na criação não precisa #$request->validate(JSONForms::buildRules($request, $fila)); + $extras = $this->normalizeExtrasForStorage($request->extras, $fila); + # transaction para não ter problema de inconsistência do DB - $chamado = \DB::transaction(function () use ($request, $fila) { + $chamado = \DB::transaction(function () use ($request, $fila, $extras) { $chamado = new Chamado; $chamado->nro = Chamado::obterProximoNumero(); $chamado->fila_id = $fila->id; @@ -139,7 +141,7 @@ public function store(ChamadoRequest $request, Fila $fila) $chamado->status = 'Triagem'; $chamado->descricao = $request->descricao; - $chamado->extras = json_encode($request->extras); + $chamado->extras = json_encode($extras); // vamos salvar sem evento pois o autor ainda não está cadastrado $chamado->saveQuietly(); @@ -338,6 +340,7 @@ private function grava(Chamado $chamado, Request $request) { $atualizacao = []; $novo_valor = []; + $extras_request = $this->normalizeExtrasForStorage($request->extras, $chamado->fila); # assunto if ($chamado->assunto != $request->assunto && !empty($request->assunto)) { @@ -356,11 +359,10 @@ private function grava(Chamado $chamado, Request $request) } # formulario (extras) - if ($chamado->extras != json_encode($request->extras) && !empty($request->extras)) { + if ($chamado->extras != json_encode($extras_request) && !empty($extras_request)) { /* guardando os dados antigos em log para auditoria */ - Log::info(' - Edição de chamado - Usuário: ' . \Auth::user()->codpes . ' - ' . \Auth::user()->name . ' - Id Chamado: ' . $chamado->id . ' - Extras antigo: ' . $chamado->extras . ' - Novo extras: ' . json_encode($request->extras)); + Log::info(' - Edição de chamado - Usuário: ' . \Auth::user()->codpes . ' - ' . \Auth::user()->name . ' - Id Chamado: ' . $chamado->id . ' - Extras antigo: ' . $chamado->extras . ' - Novo extras: ' . json_encode($extras_request)); $extras_chamados = json_decode($chamado->extras, true); - $extras_request = $request->extras; /* se não for um chamado novo */ $atualiza_extras = false; if ($chamado->extras != "null") { @@ -417,6 +419,55 @@ private function grava(Chamado $chamado, Request $request) return $chamado; } + private function normalizeExtrasForStorage($extras, Fila $fila) + { + if (!is_array($extras)) { + return $extras; + } + + $template = json_decode($fila->template); + if (!$template) { + return $extras; + } + + foreach ($template as $key => $field) { + if (!isset($field->type) || $field->type !== 'date') { + continue; + } + + if (!array_key_exists($key, $extras)) { + continue; + } + + $extras[$key] = $this->normalizeDateToStorage($extras[$key]); + } + + return $extras; + } + + private function normalizeDateToStorage($value) + { + if (!is_string($value) || trim($value) === '') { + return $value; + } + + $value = trim($value); + + if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) { + return $value; + } + + if (preg_match('/^\d{2}\/\d{2}\/\d{4}$/', $value)) { + try { + return \Carbon\Carbon::createFromFormat('d/m/Y', $value)->format('Y-m-d'); + } catch (\Exception $e) { + return $value; + } + } + + return $value; + } + /** * adiciona atendentes. Pode ser mais de um * diff --git a/app/Utils/JSONForms.php b/app/Utils/JSONForms.php index dc329edb..fad8923e 100644 --- a/app/Utils/JSONForms.php +++ b/app/Utils/JSONForms.php @@ -7,6 +7,24 @@ class JSONForms { + private static function formatDateToBrazilian($value) + { + if (empty($value) || !is_string($value)) { + return $value; + } + + if (preg_match('/^\d{2}\/\d{2}\/\d{4}$/', $value)) { + return $value; + } + + if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) { + [$year, $month, $day] = explode('-', $value); + return $day . '/' . $month . '/' . $year; + } + + return $value; + } + /** * Valida os campos do formulário * @@ -59,6 +77,52 @@ protected static function JSON2Form($template, $data, $perfil) $fieldInput = $fieldInput ->required(); } + $input[] = $fieldInput; + break; + case 'date': + $dateValue = self::formatDateToBrazilian($value); + if (empty($dateValue)) { + $dateValue = date('d/m/Y'); + } + + $fieldInput = html()->text("extras[$key]", $dateValue) + ->class('form-control datepicker date-mask') + ->attribute('placeholder', 'dd/mm/aaaa') + ->attribute('maxlength', '10') + ->attribute('inputmode', 'numeric') + ->attribute('autocomplete', 'off'); + + if (isset($json->validate) && strpos($json->validate, 'required') !== false) { + $fieldInput = $fieldInput->required(); + } + + $input[] = $fieldInput; + break; + case 'text': + $fieldInput = html()->text("extras[$key]", $value)->class('form-control'); + + if (isset($json->validate) && strpos($json->validate, 'required') !== false) { + $fieldInput = $fieldInput->required(); + } + + $input[] = $fieldInput; + break; + case 'number': + $fieldInput = html()->number("extras[$key]", $value)->class('form-control'); + + if (isset($json->validate) && strpos($json->validate, 'required') !== false) { + $fieldInput = $fieldInput->required(); + } + + $input[] = $fieldInput; + break; + case 'textarea': + $fieldInput = html()->textarea("extras[$key]", $value)->class('form-control')->rows(3); + + if (isset($json->validate) && strpos($json->validate, 'required') !== false) { + $fieldInput = $fieldInput ->required(); + } + $input[] = $fieldInput; break; diff --git a/public/js/functions.js b/public/js/functions.js index 4bb5dc3f..f1ac8363 100644 --- a/public/js/functions.js +++ b/public/js/functions.js @@ -62,3 +62,20 @@ function mudarCampoInputTextarea(campo) { }); } } + +/* @autor uspdev/alecosta 09/04/2026 +* Aplica máscara de data no formato dd/mm/aaaa. +*/ +function aplicarMascaraData() { + $('.date-mask').each(function () { + $(this).on('input', function () { + var valor = $(this).val().replace(/\D/g, '').slice(0, 8); + if (valor.length > 4) { + valor = valor.replace(/(\d{2})(\d{2})(\d{1,4})/, '$1/$2/$3'); + } else if (valor.length > 2) { + valor = valor.replace(/(\d{2})(\d{1,2})/, '$1/$2'); + } + $(this).val(valor); + }); + }); +} diff --git a/resources/views/chamados/create.blade.php b/resources/views/chamados/create.blade.php index 2d705b74..b831d449 100644 --- a/resources/views/chamados/create.blade.php +++ b/resources/views/chamados/create.blade.php @@ -85,6 +85,7 @@ class="fas fa-times-circle"> Cancelar * Ao carregar a página ordena todos os campos caixa de seleção adicionados na fila */ $(document).ready(function() { + aplicarMascaraData(); // Pega todos os campos extras que são caixa de seleção $('select[name^="extras"]').each(function () { var nameField = $(this).prop('name'); diff --git a/resources/views/chamados/show/dados-formulario.blade.php b/resources/views/chamados/show/dados-formulario.blade.php index 517e56ac..18548d01 100644 --- a/resources/views/chamados/show/dados-formulario.blade.php +++ b/resources/views/chamados/show/dados-formulario.blade.php @@ -5,7 +5,10 @@ {{ $val->label }}: @switch($val->type) @case('date') - {{ Carbon\Carbon::parse($extras->$field)->format('d/m/Y') ?? '' }} + @php + $dateValue = !empty($extras->$field) ? Carbon\Carbon::parse($extras->$field) : null; + @endphp + {{ $dateValue ? ucfirst($dateValue->locale('pt_BR')->translatedFormat('l')) . ', ' . $dateValue->format('d/m/Y') : '' }} @break @default @php diff --git a/resources/views/chamados/show/editar-formulario-btn.blade.php b/resources/views/chamados/show/editar-formulario-btn.blade.php index 2dde27b1..3d83da90 100644 --- a/resources/views/chamados/show/editar-formulario-btn.blade.php +++ b/resources/views/chamados/show/editar-formulario-btn.blade.php @@ -58,6 +58,7 @@ function mostraModal() { * Ao carregar a página ordena todos os campos caixa de seleção adicionados na fila */ $(document).ready(function() { + aplicarMascaraData(); // Pega todos os campos extras que são caixa de seleção $('select[name^="extras"]').each(function () { var nameField = $(this).prop('name'); diff --git a/resources/views/chamados/show/formulario-dados-atendente.blade.php b/resources/views/chamados/show/formulario-dados-atendente.blade.php index 519b6cbe..99278080 100644 --- a/resources/views/chamados/show/formulario-dados-atendente.blade.php +++ b/resources/views/chamados/show/formulario-dados-atendente.blade.php @@ -15,7 +15,10 @@ {{ $val->label }}: @switch($val->type) @case('date') - {{ Carbon\Carbon::parse($extras->$field)->format('d/m/Y') ?? '' }} + @php + $dateValue = !empty($extras->$field) ? Carbon\Carbon::parse($extras->$field) : null; + @endphp + {{ $dateValue ? ucfirst($dateValue->locale('pt_BR')->translatedFormat('l')) . ', ' . $dateValue->format('d/m/Y') : '' }} @break @default {{ $extras->$field ?? '' }} diff --git a/resources/views/filas/partials/template-btn-novocampo-modal.blade.php b/resources/views/filas/partials/template-btn-novocampo-modal.blade.php index f2c2aa9f..d7637430 100644 --- a/resources/views/filas/partials/template-btn-novocampo-modal.blade.php +++ b/resources/views/filas/partials/template-btn-novocampo-modal.blade.php @@ -28,6 +28,7 @@ @case('type') + diff --git a/tests/Unit/JSONFormsTest.php b/tests/Unit/JSONFormsTest.php index 779b8053..890f4c8c 100644 --- a/tests/Unit/JSONFormsTest.php +++ b/tests/Unit/JSONFormsTest.php @@ -61,6 +61,24 @@ public function testGenerateFormTemplate() $this->assertStringContainsString("extras[predio]", $form[0][1]->toHtml()); } + public function testGenerateFormTextFieldRendersTextInput() + { + $template = json_encode($this->template); + $fila = Fila::factory()->make(['template' => $template]); + $form = JSONForms::generateForm($fila); + $this->assertStringContainsString('type="text"', $form[0][1]->toHtml()); + } + + public function testGenerateFormTextareaFieldRendersTextarea() + { + $tmp = $this->template; + $tmp["predio"]["type"] = "textarea"; + $template = json_encode($tmp); + $fila = Fila::factory()->make(['template' => $template]); + $form = JSONForms::generateForm($fila); + $this->assertStringContainsString("toHtml()); + } + public function testGenerateFormChamado() { $template = json_encode($this->template); @@ -128,6 +146,41 @@ public function testGenerateFormSelected() $this->assertStringContainsString('selected">Admin', $form[0][1]->toHtml()); } + public function testGenerateFormDateFieldUsesMask() + { + $tmp = $this->template; + $tmp["predio"]["type"] = "date"; + $template = json_encode($tmp); + $fila = Fila::factory()->make(['template' => $template]); + $form = JSONForms::generateForm($fila); + $this->assertStringContainsString('class="form-control datepicker date-mask"', $form[0][1]->toHtml()); + } + + public function testGenerateFormDateFieldUsesCurrentDateByDefault() + { + $tmp = $this->template; + $tmp["predio"]["type"] = "date"; + $template = json_encode($tmp); + $fila = Fila::factory()->make(['template' => $template]); + $form = JSONForms::generateForm($fila); + $this->assertStringContainsString('value="' . date('d/m/Y') . '"', $form[0][1]->toHtml()); + } + + public function testGenerateFormDateFieldFormatsValue() + { + $tmp = $this->template; + $tmp["predio"]["type"] = "date"; + $template = json_encode($tmp); + $fila = Fila::factory()->create(['template' => $template]); + $chamado = Chamado::factory()->make([ + 'fila_id' => $fila->id, + 'extras' => '{"predio": "2026-04-09"}' + ]); + + $form = JSONForms::generateForm($fila, $chamado); + $this->assertStringContainsString('value="09/04/2026"', $form[0][1]->toHtml()); + } + public function testGenerateFormHelp() { $tmp = $this->template;