18. Crear Chatbots

 

Tutorial 18: Crear Chatbots

En este tutorial, implementaremos la funcionalidad para crear nuevos chatbots desde cero. Aprenderemos a añadir el botón de creación, configurar la vista, manejar el formulario y procesar la creación en el controlador.


1. Agregar el Botón de Creación en el Listado

Primero, debemos añadir un botón en la vista de listado (index) que nos permita navegar a la página de creación.

Modificar la Vista Index

resources/views/chatbots/index.blade.php (o su equivalente en Inertia/Vue)

blade
<div>
    {{-- Contenedor con flex para alinear título y botón --}}
    <div class="flex items-center justify-between mb-4">
        <h1 class="text-2xl font-bold">Listado de Chatbots</h1>
        
        {{-- Botón para crear nuevo chatbot --}}
        <a href="{{ route('chatbots.create') }}" 
           class="inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition">
            <span class="mr-2">
                <svg xmlns="http://www.w3.org/2000/svg" 
                     class="h-5 w-5" 
                     fill="none" 
                     viewBox="0 0 24 24" 
                     stroke="currentColor">
                    <path stroke-linecap="round" 
                          stroke-linejoin="round" 
                          stroke-width="2" 
                          d="M12 4v16m8-8H4" />
                </svg>
            </span>
            Crear Chatbot
        </a>
    </div>

    {{-- Resto del contenido del listado --}}
</div>

Si usas Livewire o Blade puro:

blade
<div class="flex items-center justify-between mb-6">
    <h1 class="text-2xl font-semibold">Mis Chatbots</h1>
    <a href="{{ route('chatbots.create') }}" 
       class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded flex items-center">
        <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
        </svg>
        Crear Chatbot
    </a>
</div>

2. Configurar el Controlador - Método create

En el ChatbotController, debemos agregar la lógica para mostrar el formulario de creación.

app/Http/Controllers/ChatbotController.php

php
use Inertia\Inertia;
use App\Models\Chatbot;

public function create()
{
    // Pasamos un chatbot vacío a la vista
    return Inertia::render('Chatbots/Create', [
        'chatbot' => new Chatbot()
    ]);
}

Si usas Livewire o Blade tradicional:

php
public function create()
{
    return view('chatbots.create', [
        'chatbot' => new Chatbot()
    ]);
}

Crear la Vista de Creación

Para ahorrar tiempo y mantener consistencia, podemos duplicar la vista de edición y adaptarla para creación.

resources/views/chatbots/create.blade.php (Blade)
o
resources/js/Pages/Chatbots/Create.vue (Inertia/Vue)


3. Adaptar el Formulario para Creación

La vista de creación será muy similar a la de edición, pero con algunas diferencias clave:

Estructura del Formulario

blade
{{-- resources/views/chatbots/create.blade.php --}}

@extends('layouts.app')

@section('content')
<div class="container mx-auto px-4 py-8">
    <div class="max-w-2xl mx-auto">
        <h1 class="text-2xl font-bold mb-6">Crear Nuevo Chatbot</h1>
        
        {{-- Formulario --}}
        <form action="{{ route('chatbots.store') }}" method="POST">
            @csrf
            
            {{-- Campo: Nombre --}}
            <div class="mb-4">
                <label for="name" class="block text-sm font-medium text-gray-700 mb-2">
                    Nombre del Chatbot
                </label>
                <input type="text" 
                       id="name" 
                       name="name" 
                       value="{{ old('name') }}"
                       class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                       placeholder="Ej: Asistente de Ventas">
                @error('name')
                    <p class="mt-1 text-sm text-red-600">{{ $message }}</p>
                @enderror
            </div>
            
            {{-- Campo: Descripción --}}
            <div class="mb-4">
                <label for="description" class="block text-sm font-medium text-gray-700 mb-2">
                    Descripción
                </label>
                <textarea id="description" 
                          name="description" 
                          rows="4"
                          class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                          placeholder="Describe el propósito de este chatbot...">{{ old('description') }}</textarea>
                @error('description')
                    <p class="mt-1 text-sm text-red-600">{{ $message }}</p>
                @enderror
            </div>
            
            {{-- Botón de envío --}}
            <div class="flex items-center justify-end">
                <a href="{{ route('chatbots.index') }}" 
                   class="px-4 py-2 text-sm text-gray-600 hover:text-gray-800 mr-2">
                    Cancelar
                </a>
                <button type="submit" 
                        class="px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition">
                    Crear Chatbot
                </button>
            </div>
        </form>
    </div>
</div>
@endsection

Para Inertia.js (Vue)

vue
<template>
    <div class="container mx-auto px-4 py-8">
        <div class="max-w-2xl mx-auto">
            <h1 class="text-2xl font-bold mb-6">Crear Nuevo Chatbot</h1>
            
            <form @submit.prevent="handleSubmit">
                <div class="mb-4">
                    <label for="name" class="block text-sm font-medium text-gray-700 mb-2">
                        Nombre del Chatbot
                    </label>
                    <input type="text" 
                           id="name" 
                           v-model="form.name"
                           class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                           placeholder="Ej: Asistente de Ventas">
                    <p v-if="form.errors.name" class="mt-1 text-sm text-red-600">
                        {{ form.errors.name }}
                    </p>
                </div>
                
                <div class="mb-4">
                    <label for="description" class="block text-sm font-medium text-gray-700 mb-2">
                        Descripción
                    </label>
                    <textarea id="description" 
                              v-model="form.description"
                              rows="4"
                              class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                              placeholder="Describe el propósito de este chatbot..."></textarea>
                    <p v-if="form.errors.description" class="mt-1 text-sm text-red-600">
                        {{ form.errors.description }}
                    </p>
                </div>
                
                <div class="flex items-center justify-end">
                    <Link :href="route('chatbots.index')" 
                          class="px-4 py-2 text-sm text-gray-600 hover:text-gray-800 mr-2">
                        Cancelar
                    </Link>
                    <button type="submit" 
                            class="px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition">
                        Crear Chatbot
                    </button>
                </div>
            </form>
        </div>
    </div>
</template>

<script setup>
import { useForm } from '@inertiajs/vue3';
import { Link } from '@inertiajs/vue3';

const form = useForm({
    name: '',
    description: '',
});

const handleSubmit = () => {
    form.post(route('chatbots.store'));
};
</script>

4. Procesar la Creación - Método store

En el controlador, implementamos la lógica para guardar el nuevo chatbot.

app/Http/Controllers/ChatbotController.php

php
use Illuminate\Http\Request;
use App\Models\Chatbot;
use App\Http\Requests\ChatbotRequest; // Usando FormRequest para validación

public function store(ChatbotRequest $request)
{
    // Crear el chatbot asociado al usuario autenticado
    $chatbot = $request->user()->chatbots()->create($request->validated());
    
    // Redireccionar a la página de detalles o al listado
    // Opción 1: Redirigir al listado
    return redirect()->route('chatbots.index')
                     ->with('success', '¡Chatbot creado exitosamente!');
    
    // Opción 2: Redirigir a la página de detalles del nuevo chatbot
    // return redirect()->route('chatbots.show', $chatbot)
    //                  ->with('success', '¡Chatbot creado exitosamente!');
}

Validación con FormRequest

Creamos un FormRequest para manejar la validación de manera limpia:

app/Http/Requests/ChatbotRequest.php

php
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class ChatbotRequest extends FormRequest
{
    public function authorize()
    {
        return true; // O verificar permisos aquí
    }

    public function rules()
    {
        return [
            'name' => 'required|string|max:255|unique:chatbots,name',
            'description' => 'nullable|string|max:1000',
        ];
    }
    
    public function messages()
    {
        return [
            'name.required' => 'El nombre del chatbot es obligatorio',
            'name.unique' => 'Ya existe un chatbot con este nombre',
            'name.max' => 'El nombre no puede tener más de 255 caracteres',
            'description.max' => 'La descripción no puede tener más de 1000 caracteres',
        ];
    }
}

5. Resumen del Flujo de Creación

  1. Usuario hace clic en "Crear Chatbot" desde el listado.

  2. Navegación a la ruta chatbots.create.

  3. Controlador create() retorna la vista con un modelo vacío.

  4. Usuario completa el formulario y hace clic en "Crear".

  5. Envío POST a la ruta chatbots.store.

  6. Validación a través del ChatbotRequest.

  7. Creación del nuevo chatbot asociado al usuario autenticado.

  8. Redirección al listado o a la página de detalles.

  9. Feedback con mensaje de éxito.


6. Estructura de Rutas Completa

routes/web.php

php
use App\Http\Controllers\ChatbotController;

Route::resource('chatbots', ChatbotController::class)
    ->middleware(['auth']);

Esto generará automáticamente todas las rutas RESTful:

  • GET /chatbots → index

  • GET /chatbots/create → create

  • POST /chatbots → store

  • GET /chatbots/{chatbot} → show

  • GET /chatbots/{chatbot}/edit → edit

  • PUT/PATCH /chatbots/{chatbot} → update

  • DELETE /chatbots/{chatbot} → destroy


7. Código Completo del Controlador

app/Http/Controllers/ChatbotController.php

php
<?php

namespace App\Http\Controllers;

use App\Models\Chatbot;
use App\Http\Requests\ChatbotRequest;
use Illuminate\Http\Request;
use Inertia\Inertia;

class ChatbotController extends Controller
{
    public function index()
    {
        $chatbots = auth()->user()->chatbots()->paginate(10);
        
        if (request()->wantsJson()) {
            return response()->json($chatbots);
        }
        
        return Inertia::render('Chatbots/Index', [
            'chatbots' => $chatbots
        ]);
    }

    public function create()
    {
        return Inertia::render('Chatbots/Create', [
            'chatbot' => new Chatbot()
        ]);
    }

    public function store(ChatbotRequest $request)
    {
        $chatbot = $request->user()->chatbots()->create($request->validated());
        
        return redirect()->route('chatbots.index')
                         ->with('success', '¡Chatbot creado exitosamente!');
    }

    public function show(Chatbot $chatbot)
    {
        $this->authorize('view', $chatbot);
        
        return Inertia::render('Chatbots/Show', [
            'chatbot' => $chatbot
        ]);
    }

    public function edit(Chatbot $chatbot)
    {
        $this->authorize('update', $chatbot);
        
        return Inertia::render('Chatbots/Edit', [
            'chatbot' => $chatbot
        ]);
    }

    public function update(ChatbotRequest $request, Chatbot $chatbot)
    {
        $this->authorize('update', $chatbot);
        
        $chatbot->update($request->validated());
        
        return redirect()->back()
                         ->with('success', '¡Chatbot actualizado exitosamente!');
    }

    public function destroy(Chatbot $chatbot)
    {
        $this->authorize('delete', $chatbot);
        
        $chatbot->delete();
        
        return redirect()->route('chatbots.index')
                         ->with('success', '¡Chatbot eliminado exitosamente!');
    }
}

8. Mejoras Adicionales

Agregar Políticas de Autorización

app/Policies/ChatbotPolicy.php

php
namespace App\Policies;

use App\Models\User;
use App\Models\Chatbot;

class ChatbotPolicy
{
    public function view(User $user, Chatbot $chatbot)
    {
        return $user->id === $chatbot->user_id;
    }

    public function create(User $user)
    {
        return true; // Todos los usuarios autenticados pueden crear
    }

    public function update(User $user, Chatbot $chatbot)
    {
        return $user->id === $chatbot->user_id;
    }

    public function delete(User $user, Chatbot $chatbot)
    {
        return $user->id === $chatbot->user_id;
    }
}

Estilos CSS para el Botón

css
.btn-create {
    @apply inline-flex items-center px-4 py-2 bg-blue-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-blue-700 active:bg-blue-800 focus:outline-none focus:border-blue-800 focus:ring focus:ring-blue-200 disabled:opacity-25 transition;
}

Notificaciones con Toast

javascript
// En tu layout principal
Livewire.on('chatbot-created', () => {
    toast.success('¡Chatbot creado exitosamente!');
});

9. Verificación Final

Al completar este tutorial, deberías tener:

✅ Botón "Crear Chatbot" visible en el listado
✅ Página de creación con formulario funcional
✅ Validación de datos en el servidor
✅ Asociación automática del chatbot al usuario autenticado
✅ Redirección después de la creación
✅ Mensaje de éxito para el usuario
✅ Código limpio y organizado


Conclusión

¡Has implementado exitosamente la funcionalidad de creación de chatbots! Ahora los usuarios pueden:

  1. Ver el listado de sus chatbots

  2. Hacer clic en "Crear Chatbot"

  3. Completar el formulario con nombre y descripción

  4. Guardar el nuevo chatbot que automáticamente se asocia a su cuenta

Este flujo sigue las mejores prácticas de Laravel, usando:

  • FormRequest para validación

  • Relaciones Eloquent para asociación de usuarios

  • Inertia.js para SPA moderno (o Blade para tradicional)

  • Políticas para autorización

¡Ya puedes crear chatbots fácilmente desde tu aplicación

Comentarios

Entradas más populares de este blog

1. Introducción al curso de Chatbots personalizados con Laravel & OpenAI

2. Prerequisitos para el Curso de Chatbots con Laravel y OpenAI

4. Herramientas de Calidad