vue- Laravel con Inertia.js-app:TaskList

 Laravel con Inertia.js

Aquí tienes el tutorial completamente corregido, especialmente la parte de rutas y controladores:

📁 ESTRUCTURA DE ARCHIVOS CORREGIDA

text
📁 taskList/
   📁 app/
      📁 Http/
         📁 Controllers/
            📄 TareaController.php
   📁 resources/
      📁 js/
         📁 Components/
            📄 TaskList.vue
            📄 Boton.vue
         📁 Pages/
            📄 Tarea.vue
      📁 views/
   📁 routes/
      📄 web.php

🎯 RUTAS CORREGIDAS

routes/web.php

php
<?php

use App\Http\Controllers\TareaController;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
*/

Route::get('/', function () {
    return inertia('Welcome');
});

// ✅ RUTAS CORREGIDAS PARA TAREAS
Route::get('/tareas', [TareaController::class, 'index'])->name('tareas.index');
Route::post('/tareas', [TareaController::class, 'store'])->name('tareas.store');
Route::put('/tareas/{id}', [TareaController::class, 'update'])->name('tareas.update');
Route::delete('/tareas/{id}', [TareaController::class, 'destroy'])->name('tareas.destroy');

// ⚠️ IMPORTANTE: ¡Las rutas deben coincidir con el nombre del controlador!
// ❌ ERROR COMÚN: Route::get('/tarea', [TareaController::class, 'index'])
// ✅ CORRECTO:   Route::get('/tareas', [TareaController::class, 'index'])

🎯 CONTROLADOR CORREGIDO

app/Http/Controllers/TareaController.php

php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Inertia\Inertia; // 🔥 ¡OBLIGATORIO!

class TareaController extends Controller
{
    // 📋 Mostrar todas las tareas
    public function index()
    {
        // Recuperar tareas de sesión o base de datos
        $tareas = session('tareas', []);
        
        return Inertia::render('Tareas', [
            'tareas' => $tareas
        ]);
    }

    // ➕ Crear nueva tarea
    public function store(Request $request)
    {
        // Validar
        $request->validate([
            'titulo' => 'required|string|max:255'
        ]);

        // Obtener tareas existentes
        $tareas = session('tareas', []);
        
        // Agregar nueva tarea
        $tareas[] = [
            'id' => time(),
            'titulo' => $request->titulo,
            'completada' => false
        ];

        // Guardar en sesión
        session(['tareas' => $tareas]);

        // Redirigir (Inertia maneja la respuesta)
        return redirect()->route('tareas.index');
    }

    // ✏️ Actualizar tarea
    public function update(Request $request, $id)
    {
        $tareas = session('tareas', []);
        
        foreach ($tareas as &$tarea) {
            if ($tarea['id'] == $id) {
                $tarea['completada'] = $request->completada ?? false;
                $tarea['titulo'] = $request->titulo ?? $tarea['titulo'];
            }
        }

        session(['tareas' => $tareas]);
        
        return redirect()->route('tareas.index');
    }

    // 🗑️ Eliminar tarea
    public function destroy($id)
    {
        $tareas = session('tareas', []);
        
        $tareas = array_filter($tareas, function($tarea) use ($id) {
            return $tarea['id'] != $id;
        });

        session(['tareas' => array_values($tareas)]);
        
        return redirect()->route('tareas.index');
    }
}

🎯 COMPONENTE CORREGIDO

resources/js/Pages/Tareas.vue (Página principal)

vue
<template>
    <div class="max-w-2xl mx-auto p-6">
        <h1 class="text-2xl font-bold mb-6">📝 Lista de Tareas</h1>

        <!-- ✅ USO DEL COMPONENTE -->
        <TaskList :tareas="tareas" @actualizar="refrescar" />

        <!-- Formulario para agregar tareas -->
        <form @submit.prevent="agregarTarea" class="mt-6">
            <div class="flex gap-4">
                <input 
                    v-model="nuevaTarea"
                    type="text"
                    placeholder="Nueva tarea..."
                    class="flex-1 px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
                >
                <button 
                    type="submit"
                    class="px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600"
                >
                    Agregar
                </button>
            </div>
        </form>
    </div>
</template>

<script setup>
import { ref } from 'vue';
import { router } from '@inertiajs/vue3';
import TaskList from '@/Components/TaskList.vue'; // ✅ REGISTRO LOCAL

// Props recibidas del controlador
const props = defineProps({
    tareas: Array
});

// Estado local
const nuevaTarea = ref('');

// Métodos
const agregarTarea = () => {
    if (!nuevaTarea.value.trim()) return;
    
    router.post('/tareas', {
        titulo: nuevaTarea.value
    }, {
        onSuccess: () => {
            nuevaTarea.value = '';
        }
    });
};

const refrescar = () => {
    router.get('/tareas');
};
</script>

🎯 COMPONENTE REUTILIZABLE

resources/js/Components/TaskList.vue

vue
<template>
    <div class="space-y-3">
        <div 
            v-for="tarea in tareas" 
            :key="tarea.id"
            class="flex items-center justify-between p-4 bg-white rounded-lg shadow"
        >
            <div class="flex items-center gap-3">
                <input 
                    type="checkbox"
                    :checked="tarea.completada"
                    @change="toggleTarea(tarea)"
                    class="w-5 h-5"
                >
                <span :class="{ 'line-through text-gray-400': tarea.completada }">
                    {{ tarea.titulo }}
                </span>
            </div>
            
            <button 
                @click="eliminarTarea(tarea.id)"
                class="text-red-500 hover:text-red-700"
            >
                🗑️
            </button>
        </div>

        <p v-if="!tareas.length" class="text-gray-500 text-center py-8">
            No hay tareas aún. ¡Agrega una! ✨
        </p>
    </div>
</template>

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

defineProps({
    tareas: Array
});

const emit = defineEmits(['actualizar']);

const toggleTarea = (tarea) => {
    router.put(`/tareas/${tarea.id}`, {
        completada: !tarea.completada
    }, {
        onSuccess: () => emit('actualizar')
    });
};

const eliminarTarea = (id) => {
    if (confirm('¿Eliminar esta tarea?')) {
        router.delete(`/tareas/${id}`, {
            onSuccess: () => emit('actualizar')
        });
    }
};
</script>

🔥 REGISTRO GLOBAL EN app.js

resources/js/app.js

javascript
import './bootstrap';
import '../css/app.css';

import { createApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy';

// ✅ IMPORTAR COMPONENTES
import TaskList from './Components/TaskList.vue';
import Boton from './Components/Boton.vue';

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
    setup({ el, App, props, plugin }) {
        const app = createApp({ render: () => h(App, props) })
            .use(plugin)
            .use(ZiggyVue);
        
        // ✅ REGISTRO GLOBAL
        app.component('task-list', TaskList);
        app.component('boton', Boton);
        
        return app.mount(el);
    },
    progress: {
        color: '#4B5563',
    },
});

📝 RESUMEN DE CORRECCIONES

❌ Error✅ Corrección
Route::get('/tarea', ...)Route::get('/tareas', ...)
return Inertia::render('Tarea', ...)return Inertia::render('Tareas', ...)
session('tarea', '')session('tareas', [])
'tarea' => $request->tarea'titulo' => $request->titulo
Solo método storeAñadir métodos update y destroy

🚀 COMANDOS ÚTILES

bash
#si esta la carpeta creada
composer create-project laravel/laravel .

# Crear proyecto
composer create-project laravel/laravel taskList # Instalar Jetstream con Inertia composer require laravel/jetstream php artisan jetstream:install inertia # Crear controlador php artisan make:controller TareaController # Instalar dependencias npm install # Ejecutar desarrollo npm run dev # Migrar base de datos php artisan migrate

✅ VERIFICACIÓN RÁPIDA

  1. Rutas: Todas usan /tareas (plural)

  2. Controlador: Importa Inertia\Inertia

  3. Vista: Inertia::render('Tareas', $data)

  4. Componente: Archivo Tareas.vue en Pages

  5. Registro: En app.js con app.component()

¡Ahora sí está todo corregido! ¿Necesitas alguna aclaración adicional?

Comentarios

Entradas más populares de este blog

Laravel + Inertia - ejemplo app:inertia-sesion

Tareas con Laravel + Inertia + Jetstream-tareas-app