192 lines
7.2 KiB
Svelte
192 lines
7.2 KiB
Svelte
<script lang="ts">
|
|
import { onMount } from 'svelte';
|
|
import { auth } from '$lib/stores/auth.js';
|
|
import { tickets } from '$lib/stores/tickets.js';
|
|
import { goto } from '$app/navigation';
|
|
import Icon from '$lib/components/Icon.svelte';
|
|
|
|
onMount(() => {
|
|
// Redirect if not authenticated
|
|
if (!$auth.isAuthenticated) {
|
|
goto('/login');
|
|
return;
|
|
}
|
|
|
|
// Load user's tickets
|
|
tickets.loadTickets();
|
|
});
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>ServiceManager - Mesa de Ayuda</title>
|
|
</svelte:head>
|
|
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
<!-- Welcome Section -->
|
|
<div class="bg-gradient-to-r from-primary-500 to-primary-600 rounded-lg p-8 text-white mb-8">
|
|
<div class="max-w-3xl">
|
|
<h1 class="text-3xl font-bold mb-2">
|
|
Bienvenido, {$auth.user?.first_name}
|
|
{$auth.user?.last_name}
|
|
</h1>
|
|
<p class="text-primary-100 text-lg">
|
|
Gestiona tus tickets de soporte de manera eficiente. Crea nuevos tickets, da seguimiento a
|
|
los existentes y mantente actualizado con el estado de tus solicitudes.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quick Actions -->
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
|
|
<a href="/tickets/new" class="card hover:shadow-lg transition-shadow group cursor-pointer">
|
|
<div class="card-content text-center">
|
|
<div
|
|
class="w-12 h-12 bg-primary-100 rounded-lg flex items-center justify-center mx-auto mb-4 group-hover:bg-primary-200 transition-colors"
|
|
>
|
|
<Icon name="plus" size="w-6 h-6" className="text-primary-600" />
|
|
</div>
|
|
<h3 class="text-lg font-medium text-gray-900 mb-2">Crear Ticket</h3>
|
|
<p class="text-gray-600 text-sm">Reporta un problema o solicita soporte técnico</p>
|
|
</div>
|
|
</a>
|
|
|
|
<a href="/tickets" class="card hover:shadow-lg transition-shadow group cursor-pointer">
|
|
<div class="card-content text-center">
|
|
<div
|
|
class="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center mx-auto mb-4 group-hover:bg-blue-200 transition-colors"
|
|
>
|
|
<Icon name="ticket" size="w-6 h-6" className="text-blue-600" />
|
|
</div>
|
|
<h3 class="text-lg font-medium text-gray-900 mb-2">Mis Tickets</h3>
|
|
<p class="text-gray-600 text-sm">Consulta el estado de todos tus tickets</p>
|
|
</div>
|
|
</a>
|
|
|
|
<a href="/profile" class="card hover:shadow-lg transition-shadow group cursor-pointer">
|
|
<div class="card-content text-center">
|
|
<div
|
|
class="w-12 h-12 bg-green-100 rounded-lg flex items-center justify-center mx-auto mb-4 group-hover:bg-green-200 transition-colors"
|
|
>
|
|
<Icon name="user" size="w-6 h-6" className="text-green-600" />
|
|
</div>
|
|
<h3 class="text-lg font-medium text-gray-900 mb-2">Mi Perfil</h3>
|
|
<p class="text-gray-600 text-sm">Actualiza tu información personal</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Recent Tickets -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h2 class="text-xl font-semibold text-gray-900">Tickets Recientes</h2>
|
|
<p class="text-gray-600 mt-1">Últimos tickets que has creado o actualizado</p>
|
|
</div>
|
|
|
|
<div class="card-content">
|
|
{#if $tickets.isLoading}
|
|
<div class="text-center py-8">
|
|
<div class="spinner w-8 h-8 mx-auto mb-4" />
|
|
<p class="text-gray-600">Cargando tickets...</p>
|
|
</div>
|
|
{:else if $tickets.error}
|
|
<div class="text-center py-8">
|
|
<div
|
|
class="w-12 h-12 bg-red-100 rounded-lg flex items-center justify-center mx-auto mb-4"
|
|
>
|
|
<svg class="w-6 h-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<p class="text-gray-600 mb-4">Error al cargar los tickets</p>
|
|
<button on:click={() => tickets.loadTickets()} class="btn-primary px-4 py-2">
|
|
Reintentar
|
|
</button>
|
|
</div>
|
|
{:else if $tickets.tickets.length === 0}
|
|
<div class="text-center py-8">
|
|
<div
|
|
class="w-12 h-12 bg-gray-100 rounded-lg flex items-center justify-center mx-auto mb-4"
|
|
>
|
|
<svg
|
|
class="w-6 h-6 text-gray-400"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<p class="text-gray-600 mb-4">No tienes tickets creados</p>
|
|
<a href="/tickets/new" class="btn-primary px-4 py-2"> Crear tu primer ticket </a>
|
|
</div>
|
|
{:else}
|
|
<div class="space-y-4">
|
|
{#each $tickets.tickets.slice(0, 5) as ticket (ticket.id)}
|
|
<div class="border border-gray-200 rounded-lg p-4 hover:bg-gray-50 transition-colors">
|
|
<div class="flex justify-between items-start">
|
|
<div class="flex-1">
|
|
<h3 class="font-medium text-gray-900 mb-1">
|
|
<a href="/tickets/{ticket.id}" class="hover:text-primary-600">
|
|
{ticket.title}
|
|
</a>
|
|
</h3>
|
|
<p class="text-gray-600 text-sm line-clamp-2 mb-2">
|
|
{ticket.description}
|
|
</p>
|
|
<div class="flex items-center space-x-4 text-xs text-gray-500">
|
|
<span>#{ticket.id.substring(0, 8)}</span>
|
|
<span>{new Date(ticket.created_at).toLocaleDateString('es-ES')}</span>
|
|
</div>
|
|
</div>
|
|
<div class="ml-4">
|
|
<span class="badge-{ticket.status.toLowerCase().replace('_', '-')}">
|
|
{ticket.status === 'NEW'
|
|
? 'Nuevo'
|
|
: ticket.status === 'IN_PROGRESS'
|
|
? 'En Progreso'
|
|
: ticket.status === 'WAITING_FOR_CLIENT'
|
|
? 'Esperando Cliente'
|
|
: ticket.status === 'RESOLVED'
|
|
? 'Resuelto'
|
|
: ticket.status === 'CLOSED'
|
|
? 'Cerrado'
|
|
: 'Reabierto'}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/each}
|
|
|
|
{#if $tickets.tickets.length > 5}
|
|
<div class="text-center pt-4 border-t border-gray-200">
|
|
<a href="/tickets" class="btn-secondary px-4 py-2">
|
|
Ver todos los tickets ({$tickets.tickets.length})
|
|
</a>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.line-clamp-2 {
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
line-clamp: 2; /* Propiedad estándar para compatibilidad */
|
|
}
|
|
</style>
|