A
Anonymous

Ticket Page - Copy this React, Tailwind Component to your project

import-{-useState-}-from-"react";-import-{-FaHome,-FaSignOutAlt,-FaPlus,-FaFilter-}-from-"react-icons/fa";-const-TicketPage-=-()-=>-{-const-[tickets,-setTickets]-=-useState([-{-id:-1,-title:-"Server-Down-Issue",-description:-"Main-server-is-not-responding",-priority:-"High",-status:-"Open",-createdAt:-"2024-01-20"-},-{-id:-2,-title:-"UI-Enhancement-Request",-description:-"Update-dashboard-layout",-priority:-"Medium",-status:-"In-Progress",-createdAt:-"2024-01-19"-},-{-id:-3,-title:-"Database-Optimization",-description:-"Improve-query-performance",-priority:-"Low",-status:-"Resolved",-createdAt:-"2024-01-18"-}-]);-const-[filters,-setFilters]-=-useState({-status:-"all",-priority:-"all"-});-const-[showCreateModal,-setShowCreateModal]-=-useState(false);-const-[selectedTicket,-setSelectedTicket]-=-useState(null);-const-[newTicket,-setNewTicket]-=-useState({-title:-"",-description:-"",-priority:-"Low"-});-const-[errors,-setErrors]-=-useState({});-const-validateForm-=-()-=>-{-const-errors-=-{};-if-(!newTicket.title.trim())-{-errors.title-=-"Title-is-required";-}-if-(!newTicket.description.trim())-{-errors.description-=-"Description-is-required";-}-return-errors;-};-const-handleSubmit-=-()-=>-{-const-formErrors-=-validateForm();-if-(Object.keys(formErrors).length->-0)-{-setErrors(formErrors);-return;-}-const-ticket-=-{-id:-tickets.length-+-1,-...newTicket,-status:-"Open",-createdAt:-new-Date().toISOString().split("T")[0]-};-setTickets([...tickets,-ticket]);-setShowCreateModal(false);-setNewTicket({-title:-"",-description:-"",-priority:-"Low"-});-setErrors({});-};-const-filteredTickets-=-tickets.filter(ticket-=>-{-return-(-(filters.status-===-"all"-||-ticket.status-===-filters.status)-&&-(filters.priority-===-"all"-||-ticket.priority-===-filters.priority)-);-});-const-handleCreateTicket-=-()-=>-{-setShowCreateModal(true);-};-const-handleTicketClick-=-(ticket)-=>-{-setSelectedTicket(ticket);-};-const-getPriorityColor-=-(priority)-=>-{-switch-(priority)-{-case-"High":-return-"text-destructive";-case-"Medium":-return-"text-orange-500";-case-"Low":-return-"text-green-500";-default:-return-"text-accent";-}-};-return-(-<div-className="min-h-screen-bg-background">-{/*-Header-*/}-<header-className="bg-card-shadow-sm">-<div-className="max-w-7xl-mx-auto-px-4-sm:px-6-lg:px-8-py-4">-<div-className="flex-items-center-justify-between">-<div-className="flex-items-center-space-x-4">-<h1-className="text-2xl-font-heading-text-foreground">Ticket-Management</h1>-<nav-className="flex-space-x-4">-<button-className="flex-items-center-space-x-2-text-accent-hover:text-foreground">-<FaHome-className="h-5-w-5"-/>-<span>Dashboard</span>-</button>-</nav>-</div>-<div-className="flex-items-center-space-x-4">-<span-className="text-foreground">Welcome,-John-Doe</span>-<button-className="flex-items-center-space-x-2-text-accent-hover:text-foreground">-<FaSignOutAlt-className="h-5-w-5"-/>-<span>Logout</span>-</button>-</div>-</div>-</div>-</header>-{/*-Main-Content-*/}-<main-className="max-w-7xl-mx-auto-px-4-sm:px-6-lg:px-8-py-8">-{/*-Filters-and-Actions-*/}-<div-className="mb-6-flex-flex-wrap-items-center-justify-between-gap-4">-<div-className="flex-flex-wrap-items-center-gap-4">-<div-className="flex-items-center-space-x-2">-<FaFilter-className="text-accent"-/>-<select-value={filters.status}-onChange={(e)-=>-setFilters({-...filters,-status:-e.target.value-})}-className="border-border-input-rounded-md-px-3-py-2-bg-card-text-foreground-focus:outline-none-focus:ring-2-focus:ring-ring"->-<option-value="all">All-Status</option>-<option-value="Open">Open</option>-<option-value="In-Progress">In-Progress</option>-<option-value="Resolved">Resolved</option>-</select>-</div>-<div-className="flex-items-center-space-x-2">-<FaFilter-className="text-accent"-/>-<select-value={filters.priority}-onChange={(e)-=>-setFilters({-...filters,-priority:-e.target.value-})}-className="border-border-input-rounded-md-px-3-py-2-bg-card-text-foreground-focus:outline-none-focus:ring-2-focus:ring-ring"->-<option-value="all">All-Priority</option>-<option-value="High">High</option>-<option-value="Medium">Medium</option>-<option-value="Low">Low</option>-</select>-</div>-</div>-<button-onClick={handleCreateTicket}-className="flex-items-center-space-x-2-bg-primary-text-primary-foreground-px-4-py-2-rounded-md-hover:bg-blue-600-transition-colors"->-<FaPlus-className="h-5-w-5"-/>-<span>Create-Ticket</span>-</button>-</div>-{/*-Ticket-List-*/}-<div-className="bg-card-rounded-lg-shadow-sm-overflow-hidden">-<div-className="overflow-x-auto">-<table-className="w-full">-<thead-className="bg-muted">-<tr>-<th-className="px-6-py-3-text-left-text-sm-font-body-text-foreground">Title</th>-<th-className="px-6-py-3-text-left-text-sm-font-body-text-foreground">Priority</th>-<th-className="px-6-py-3-text-left-text-sm-font-body-text-foreground">Status</th>-<th-className="px-6-py-3-text-left-text-sm-font-body-text-foreground">Created-At</th>-</tr>-</thead>-<tbody-className="divide-y-divide-border">-{filteredTickets.map((ticket)-=>-(-<tr-key={ticket.id}-onClick={()-=>-handleTicketClick(ticket)}-className="hover:bg-muted-cursor-pointer"->-<td-className="px-6-py-4-text-sm-text-foreground">{ticket.title}</td>-<td-className="px-6-py-4-text-sm">-<span-className={`font-body-${getPriorityColor(ticket.priority)}`}>-{ticket.priority}-</span>-</td>-<td-className="px-6-py-4-text-sm-text-foreground">{ticket.status}</td>-<td-className="px-6-py-4-text-sm-text-foreground">{ticket.createdAt}</td>-</tr>-))}-</tbody>-</table>-</div>-</div>-</main>-{/*-Create-Ticket-Modal-*/}-{showCreateModal-&&-(-<div-className="fixed-inset-0-bg-background/80-backdrop-blur-sm-flex-items-center-justify-center-p-4">-<div-className="bg-card-p-6-rounded-lg-shadow-lg-max-w-md-w-full">-<h2-className="text-xl-font-heading-text-foreground-mb-6">Create-New-Ticket</h2>-<form-className="space-y-4">-<div>-<label-className="block-text-sm-font-body-text-foreground-mb-1">Title</label>-<input-type="text"-value={newTicket.title}-onChange={(e)-=>-setNewTicket({-...newTicket,-title:-e.target.value-})}-className="w-full-border-border-input-rounded-md-px-3-py-2-bg-card-text-foreground-focus:outline-none-focus:ring-2-focus:ring-ring"-placeholder="Enter-ticket-title"-/>-{errors.title-&&-(-<p-className="text-destructive-text-sm-mt-1">{errors.title}</p>-)}-</div>-<div>-<label-className="block-text-sm-font-body-text-foreground-mb-1">Description</label>-<textarea-value={newTicket.description}-onChange={(e)-=>-setNewTicket({-...newTicket,-description:-e.target.value-})}-className="w-full-border-border-input-rounded-md-px-3-py-2-bg-card-text-foreground-focus:outline-none-focus:ring-2-focus:ring-ring-min-h-[100px]"-placeholder="Enter-ticket-description"-/>-{errors.description-&&-(-<p-className="text-destructive-text-sm-mt-1">{errors.description}</p>-)}-</div>-<div>-<label-className="block-text-sm-font-body-text-foreground-mb-1">Priority</label>-<select-value={newTicket.priority}-onChange={(e)-=>-setNewTicket({-...newTicket,-priority:-e.target.value-})}-className="w-full-border-border-input-rounded-md-px-3-py-2-bg-card-text-foreground-focus:outline-none-focus:ring-2-focus:ring-ring"->-<option-value="Low">Low</option>-<option-value="Medium">Medium</option>-<option-value="High">High</option>-</select>-</div>-<div-className="flex-justify-end-space-x-4-mt-6">-<button-type="button"-onClick={()-=>-{-setShowCreateModal(false);-setNewTicket({-title:-"",-description:-"",-priority:-"Low"-});-setErrors({});-}}-className="px-4-py-2-text-accent-hover:text-foreground"->-Cancel-</button>-<button-type="button"-onClick={handleSubmit}-className="px-4-py-2-bg-primary-text-primary-foreground-rounded-md-hover:bg-blue-600"->-Create-</button>-</div>-</form>-</div>-</div>-)}-{/*-Ticket-Details-Modal-*/}-{selectedTicket-&&-(-<div-className="fixed-inset-0-bg-background/80-backdrop-blur-sm-flex-items-center-justify-center-p-4">-<div-className="bg-card-p-6-rounded-lg-shadow-lg-max-w-md-w-full">-<h2-className="text-xl-font-heading-text-foreground-mb-4">{selectedTicket.title}</h2>-<div-className="space-y-4">-<div>-<span-className="text-accent">Description:</span>-<p-className="mt-1-text-foreground">{selectedTicket.description}</p>-</div>-<div>-<span-className="text-accent">Priority:</span>-<span-className={`ml-2-font-body-${getPriorityColor(selectedTicket.priority)}`}>-{selectedTicket.priority}-</span>-</div>-<div>-<span-className="text-accent">Status:</span>-<span-className="ml-2-text-foreground">{selectedTicket.status}</span>-</div>-<div>-<span-className="text-accent">Created-At:</span>-<span-className="ml-2-text-foreground">{selectedTicket.createdAt}</span>-</div>-</div>-<div-className="mt-6-flex-justify-end">-<button-onClick={()-=>-setSelectedTicket(null)}-className="px-4-py-2-bg-primary-text-primary-foreground-rounded-md-hover:bg-blue-600"->-Close-</button>-</div>-</div>-</div>-)}-</div>-);-};-export-default-TicketPage;

Prompt
Component Preview

About

TicketPage - Manage tickets with filters for status and priority, create new tickets, and view details. Built with React and Tailwind. Get code instantly!

Share

Last updated 1 month ago