Initial commit: HelpDesk ICHN - .NET 10 backend + Next.js 16 frontend

This commit is contained in:
Nurfog committed 2026-09-10 10:20:51 -03:00
commit 359f0caf85
90 files changed
+13395

No files matched your search

+191
View File
@@ -0,0 +1,191 @@
"use client";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { createTicket, getAgents, type User } from "@/lib/api";
import Link from "next/link";
export default function NewTicketPage() {
const router = useRouter();
const [agents, setAgents] = useState<User[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const [subject, setSubject] = useState("");
const [description, setDescription] = useState("");
const [priority, setPriority] = useState("medium");
const [category, setCategory] = useState("");
const [assigneeId, setAssigneeId] = useState("");
useEffect(() => {
getAgents().catch((): User[] => [
{ id: 2, name: "Carlos Méndez", email: "carlos@test.com", role: "agent" as const },
{ id: 4, name: "Ana García", email: "ana@test.com", role: "agent" as const },
]).then((data) => setAgents(data));
}, []);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError("");
setLoading(true);
try {
const ticket = await createTicket({
subject,
description,
priority,
category,
assigneeId: assigneeId ? parseInt(assigneeId) : undefined,
});
router.push(`/tickets/${ticket.id}`);
} catch (err: any) {
setError(err.message || "Error al crear el ticket");
} finally {
setLoading(false);
}
};
return (
<div>
<div className="page-header">
<div>
<Link href="/tickets" className="text-decoration-none text-muted" style={{ fontSize: "0.85rem" }}>
<i className="bi bi-arrow-left me-1"></i>Volver a tickets
</Link>
<h1 className="mt-1">Nuevo Ticket</h1>
</div>
</div>
<div className="row">
<div className="col-lg-8">
<div className="card">
<div className="card-body p-4">
{error && (
<div className="alert alert-danger py-2" role="alert">
<i className="bi bi-exclamation-circle me-2"></i>
{error}
</div>
)}
<form onSubmit={handleSubmit}>
<div className="mb-3">
<label className="form-label fw-semibold">Asunto</label>
<input
type="text"
className="form-control"
placeholder="Describe brevemente el problema o solicitud"
value={subject}
onChange={(e) => setSubject(e.target.value)}
required
autoFocus
/>
</div>
<div className="mb-3">
<label className="form-label fw-semibold">Descripción</label>
<textarea
className="form-control"
rows={6}
placeholder="Proporciona detalles sobre el problema, pasos para reproducir, etc."
value={description}
onChange={(e) => setDescription(e.target.value)}
required
></textarea>
</div>
<div className="row g-3 mb-4">
<div className="col-md-4">
<label className="form-label fw-semibold">Prioridad</label>
<select
className="form-select"
value={priority}
onChange={(e) => setPriority(e.target.value)}
>
<option value="low">Baja</option>
<option value="medium">Media</option>
<option value="high">Alta</option>
<option value="urgent">Urgente</option>
</select>
</div>
<div className="col-md-4">
<label className="form-label fw-semibold">Categoría</label>
<select
className="form-select"
value={category}
onChange={(e) => setCategory(e.target.value)}
required
>
<option value="">Seleccionar categoría</option>
<option value="Software">Software</option>
<option value="Hardware">Hardware</option>
<option value="Red">Red</option>
<option value="Acceso">Acceso</option>
<option value="Correo">Correo</option>
<option value="Otro">Otro</option>
</select>
</div>
<div className="col-md-4">
<label className="form-label fw-semibold">Asignar a</label>
<select
className="form-select"
value={assigneeId}
onChange={(e) => setAssigneeId(e.target.value)}
>
<option value="">Sin asignar</option>
{agents.map((a) => (
<option key={a.id} value={a.id}>{a.name}</option>
))}
</select>
</div>
</div>
<div className="d-flex gap-2">
<button
type="submit"
className="btn btn-primary px-4"
disabled={loading}
>
{loading ? (
<>
<span className="spinner-border spinner-border-sm me-2" role="status"></span>
Creando...
</>
) : (
<>
<i className="bi bi-plus-lg me-2"></i>
Crear Ticket
</>
)}
</button>
<Link href="/tickets" className="btn btn-outline-secondary">
Cancelar
</Link>
</div>
</form>
</div>
</div>
</div>
{/* Tips */}
<div className="col-lg-4">
<div className="card">
<div className="card-body">
<h6 className="d-flex align-items-center gap-2 mb-3">
<i className="bi bi-lightbulb" style={{ color: "#ffc107" }}></i>
Consejos
</h6>
<ul className="mb-0" style={{ fontSize: "0.85rem", lineHeight: 1.7 }}>
<li>Sé específico en el asunto del ticket</li>
<li>Incluye pasos para reproducir el problema</li>
<li>Adjunta capturas de pantalla si es posible</li>
<li>Selecciona la categoría correcta para una atención más rápida</li>
<li>Asigna la prioridad adecuada según el impacto</li>
</ul>
</div>
</div>
</div>
</div>
</div>
);
}