diff --git a/app/Http/Controllers/Api/AmiEventController.php b/app/Http/Controllers/Api/AmiEventController.php index 91094f9..69da686 100644 --- a/app/Http/Controllers/Api/AmiEventController.php +++ b/app/Http/Controllers/Api/AmiEventController.php @@ -24,20 +24,23 @@ public function handle(Request $request) $data = $request->all(); $eventName = $data['Event'] ?? null; - $queueName = $data['Queue'] ?? null; + $queueNumber = $data['Queue'] ?? null; - if (!$eventName || !$queueName) { + $this->saveQueues($queueNumber, $tenant); + + if (!$eventName || !$queueNumber) { return response()->json(['status' => 'ignored']); } $queue = Queue::where('tenant_id', $tenant->id) - ->where('source_id', $queueName) // Procura "08000" na coluna source_id + ->where('source_id', $queueNumber) ->first();; if (!$queue) { return response()->json(['error' => 'Fila não encontrada'], 404); } + switch ($eventName) { case 'QueueCallerJoin': $this->handleJoin($queue, $data); @@ -60,7 +63,7 @@ public function handle(Request $request) private function handleJoin($queue, $data) { WaitingList::create([ - 'tenant_id' => $queue->tenant_id, // <--- ADICIONE ESTA LINHA + 'tenant_id' => $queue->tenant_id, 'queue_id' => $queue->id, 'caller_number' => $data['CallerIDNum'], 'caller_name' => $data['CallerIDName'] ?? 'Desconhecido', @@ -132,9 +135,19 @@ private function updateMetric($queue, $field, $value) $metric = $this->getTodayMetric($queue); $metric->increment($field, $value); } + + private function saveQueues($queue, $tenant) + { + $existingQueues = Queue::where('source_id', $queue)->exists(); + + if (!$existingQueues) { + Queue::create(['tenant_id' => $tenant->id, 'type' => 'voice', 'source_id' => $queue]); + exit; + } + + } private function broadcastUpdate($queue) { - // Dispara o evento apenas para o Tenant dono da fila broadcast(new DashboardUpdate($queue->tenant_id)); } } diff --git a/app/Http/Controllers/QueueController.php b/app/Http/Controllers/QueueController.php new file mode 100644 index 0000000..10327bd --- /dev/null +++ b/app/Http/Controllers/QueueController.php @@ -0,0 +1,30 @@ +validate([ + 'queue_number' => 'required|numeric', + 'friendly_name' => 'required|string|max:255' + ]); + + Queue::updateOrCreate( + [ + 'tenant_id' => Auth::user()->tenant_id, + 'source_id' => $validated['queue_number'], + ], + [ + 'name' => $validated['friendly_name'] + ] + ); + + return back()->with('message', 'Nome da fila atualizado com sucesso!'); + } +} diff --git a/database/migrations/2025_12_15_134836_create_omniboard_schema.php b/database/migrations/2025_12_15_134836_create_omniboard_schema.php index cbcfee4..a19a993 100644 --- a/database/migrations/2025_12_15_134836_create_omniboard_schema.php +++ b/database/migrations/2025_12_15_134836_create_omniboard_schema.php @@ -21,7 +21,7 @@ public function up() Schema::create('queues', function (Blueprint $table) { $table->id(); $table->foreignId('tenant_id')->constrained()->cascadeOnDelete(); - $table->string('name'); + $table->string('name')->nullable(); $table->string('type')->default('voice'); // voice, whatsapp $table->string('source_id')->nullable(); // ID no Asterisk/Helena $table->integer('sla_threshold')->default(20); // Meta de SLA em segundos @@ -59,7 +59,7 @@ public function up() $table->id(); $table->foreignId('queue_id')->constrained()->cascadeOnDelete(); $table->date('date'); - + // Métricas visíveis na imagem $table->integer('received_count')->default(0); $table->integer('answered_count')->default(0); @@ -69,9 +69,9 @@ public function up() $table->integer('avg_talk_time')->default(0); // Em segundos $table->integer('max_wait_time')->default(0); // Em segundos $table->integer('transferred_count')->default(0); - + $table->timestamps(); - + // Garante uma métrica por fila por dia $table->unique(['queue_id', 'date']); }); @@ -97,4 +97,4 @@ public function down() Schema::dropIfExists('queues'); Schema::dropIfExists('tenants'); } -}; \ No newline at end of file +}; diff --git a/resources/js/Components/SetQueueNameForm.vue b/resources/js/Components/SetQueueNameForm.vue new file mode 100644 index 0000000..ca07992 --- /dev/null +++ b/resources/js/Components/SetQueueNameForm.vue @@ -0,0 +1,107 @@ + + + \ No newline at end of file diff --git a/resources/js/Layouts/AuthenticatedLayout.vue b/resources/js/Layouts/AuthenticatedLayout.vue index 48ad96d..57bdb42 100644 --- a/resources/js/Layouts/AuthenticatedLayout.vue +++ b/resources/js/Layouts/AuthenticatedLayout.vue @@ -4,16 +4,15 @@ import ApplicationLogo from '@/Components/ApplicationLogo.vue'; import Dropdown from '@/Components/Dropdown.vue'; import DropdownLink from '@/Components/DropdownLink.vue'; import { Link } from '@inertiajs/vue3'; +import SetQueueNameForm from '@/Components/SetQueueNameForm.vue'; const showingSidebar = ref(false); const menuItems = [ { name: 'Dashboard', route: 'dashboard', icon: 'M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z' }, { name: 'Monitoramento', route: '#', icon: 'M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z' }, - { name: 'Relatórios', route: '#', icon: 'M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z' }, { name: 'Filas', route: '#', icon: 'M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10' }, { name: 'Agentes', route: '#', icon: 'M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z' }, - { name: 'Configurações', route: '#', icon: 'M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z' }, ]; @@ -115,12 +114,15 @@ const menuItems = [ + +
diff --git a/resources/views/app.blade.php b/resources/views/app.blade.php index 334627a..693b530 100644 --- a/resources/views/app.blade.php +++ b/resources/views/app.blade.php @@ -1,21 +1,26 @@ - - - - {{ config('app.name', 'Laravel') }} + + + - - - + + + {{ config('app.name', 'Laravel') }} - - @routes - @vite(['resources/js/app.js', "resources/js/Pages/{$page['component']}.vue"]) - @inertiaHead - - - @inertia - - + + + + + + @routes + @vite(['resources/js/app.js', "resources/js/Pages/{$page['component']}.vue"]) + @inertiaHead + + + + @inertia + + + \ No newline at end of file diff --git a/routes/auth.php b/routes/auth.php index 3926ecf..2750481 100644 --- a/routes/auth.php +++ b/routes/auth.php @@ -12,47 +12,43 @@ use Illuminate\Support\Facades\Route; Route::middleware('guest')->group(function () { - Route::get('register', [RegisteredUserController::class, 'create']) - ->name('register'); - - Route::post('register', [RegisteredUserController::class, 'store']); Route::get('login', [AuthenticatedSessionController::class, 'create']) ->name('login'); Route::post('login', [AuthenticatedSessionController::class, 'store']); - Route::get('forgot-password', [PasswordResetLinkController::class, 'create']) - ->name('password.request'); + // Route::get('forgot-password', [PasswordResetLinkController::class, 'create']) + // ->name('password.request'); - Route::post('forgot-password', [PasswordResetLinkController::class, 'store']) - ->name('password.email'); + // Route::post('forgot-password', [PasswordResetLinkController::class, 'store']) + // ->name('password.email'); - Route::get('reset-password/{token}', [NewPasswordController::class, 'create']) - ->name('password.reset'); + // Route::get('reset-password/{token}', [NewPasswordController::class, 'create']) + // ->name('password.reset'); - Route::post('reset-password', [NewPasswordController::class, 'store']) - ->name('password.store'); + // Route::post('reset-password', [NewPasswordController::class, 'store']) + // ->name('password.store'); }); Route::middleware('auth')->group(function () { - Route::get('verify-email', EmailVerificationPromptController::class) - ->name('verification.notice'); + // Route::get('verify-email', EmailVerificationPromptController::class) + // ->name('verification.notice'); - Route::get('verify-email/{id}/{hash}', VerifyEmailController::class) - ->middleware(['signed', 'throttle:6,1']) - ->name('verification.verify'); + // Route::get('verify-email/{id}/{hash}', VerifyEmailController::class) + // ->middleware(['signed', 'throttle:6,1']) + // ->name('verification.verify'); - Route::post('email/verification-notification', [EmailVerificationNotificationController::class, 'store']) - ->middleware('throttle:6,1') - ->name('verification.send'); + // Route::post('email/verification-notification', [EmailVerificationNotificationController::class, 'store']) + // ->middleware('throttle:6,1') + // ->name('verification.send'); - Route::get('confirm-password', [ConfirmablePasswordController::class, 'show']) - ->name('password.confirm'); + // Route::get('confirm-password', [ConfirmablePasswordController::class, 'show']) + // ->name('password.confirm'); - Route::post('confirm-password', [ConfirmablePasswordController::class, 'store']); + // Route::post('confirm-password', [ConfirmablePasswordController::class, 'store']); - Route::put('password', [PasswordController::class, 'update'])->name('password.update'); + // Route::put('password', [PasswordController::class, 'update'])->name('password.update'); Route::post('logout', [AuthenticatedSessionController::class, 'destroy']) ->name('logout'); diff --git a/routes/web.php b/routes/web.php index 96604b2..73a3376 100644 --- a/routes/web.php +++ b/routes/web.php @@ -5,6 +5,7 @@ use Illuminate\Foundation\Application; use Illuminate\Support\Facades\Route; use Inertia\Inertia; +use App\Http\Controllers\QueueController; Route::get('/', function () { return Inertia::render('Welcome', [ @@ -15,7 +16,9 @@ ]); }); -Route::get('/dashboard', [DashboardController::class, 'index'])->middleware(['auth', 'verified'])->name('dashboard'); +Route::post('/queues', [QueueController::class, 'setQueueName'])->middleware(['auth'])->name('queues.store'); + +Route::get('/dashboard', [DashboardController::class, 'index'])->middleware(['auth'])->name('dashboard'); Route::middleware('auth')->group(function () { Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');