Skip to content

Commit

Permalink
admin_ticket_page
Browse files Browse the repository at this point in the history
  • Loading branch information
IkkiOcean committed Nov 10, 2024
1 parent ccb3461 commit 61f92c9
Show file tree
Hide file tree
Showing 6 changed files with 330 additions and 1 deletion.
124 changes: 124 additions & 0 deletions frontend/src/AgroShopAI/components/Pages/AdminTicket.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import React, { useState } from "react";
import Header from "./THeader";
import SearchAndFilter from "./TSearchAndFilter";
import TicketList from "./AdminTicketList";
import TicketDetails from "./AdminTicketDetails";

const dummyTickets = [
{
id: 1,
subject: "Order not received",
status: "Open",
agent: "John Doe",
createdAt: "2023-05-15",
priority: "High",
description:
"I placed an order for fertilizer 5 days ago and haven't received it yet.",
user: "farmer@example.com",
},
{
id: 2,
subject: "Wrong seeds delivered",
status: "In-Progress",
agent: "Jane Smith",
createdAt: "2023-05-14",
priority: "Medium",
description: "I ordered tomato seeds but received cucumber seeds instead.",
user: "gardener@example.com",
},
{
id: 3,
subject: "Pesticide information needed",
status: "Open",
agent: "Unassigned",
createdAt: "2023-05-13",
priority: "Low",
description:
"I need more information about the organic pesticides you offer.",
user: "organic@example.com",
},
{
id: 4,
subject: "Billing discrepancy",
status: "Open",
agent: "Bob Johnson",
createdAt: "2023-05-12",
priority: "High",
description: "I was charged twice for my last order of plant pots.",
user: "plantlover@example.com",
},
{
id: 5,
subject: "Product quality issue",
status: "In-Progress",
agent: "Jane Smith",
createdAt: "2023-05-11",
priority: "Medium",
description:
"The soil I received seems to be of lower quality than advertised.",
user: "gardenexpert@example.com",
},
];

const TicketManagement = () => {
const [tickets, setTickets] = useState(dummyTickets);
const [selectedTicket, setSelectedTicket] = useState(null);
const [searchTerm, setSearchTerm] = useState("");
const [statusFilter, setStatusFilter] = useState("All");
const [priorityFilter, setPriorityFilter] = useState("All");

const filteredTickets = tickets.filter((ticket) => {
return (
ticket.subject.toLowerCase().includes(searchTerm.toLowerCase()) &&
(statusFilter === "All" || ticket.status === statusFilter) &&
(priorityFilter === "All" || ticket.priority === priorityFilter)
);
});

const updateTicketStatus = (id, newStatus) => {
setTickets(
tickets.map((ticket) =>
ticket.id === id ? { ...ticket, status: newStatus } : ticket
)
);
};

const assignTicket = (id, agent) => {
setTickets(
tickets.map((ticket) =>
ticket.id === id ? { ...ticket, agent } : ticket
)
);
};

return (
<div className="container mx-auto">
<Header />
<SearchAndFilter
searchTerm={searchTerm}
setSearchTerm={setSearchTerm}
statusFilter={statusFilter}
setStatusFilter={setStatusFilter}
priorityFilter={priorityFilter}
setPriorityFilter={setPriorityFilter}
/>
<div className="flex">
<div className="w-1/2 pr-4">
<TicketList
filteredTickets={filteredTickets}
setSelectedTicket={setSelectedTicket}
/>
</div>
<div className="w-1/2 pl-4">
<TicketDetails
selectedTicket={selectedTicket}
updateTicketStatus={updateTicketStatus}
assignTicket={assignTicket}
/>
</div>
</div>
</div>
);
};

export default TicketManagement;
92 changes: 92 additions & 0 deletions frontend/src/AgroShopAI/components/Pages/AdminTicketDetails.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
const TicketDetails = ({
selectedTicket,
updateTicketStatus,
assignTicket,
}) => {
if (!selectedTicket)
return <p className="text-gray-600">Select a ticket to view details</p>;

return (
<div>
<h3 className="text-lg font-semibold mb-2">
#{selectedTicket.id} - {selectedTicket.subject}
</h3>
<div className="grid grid-cols-2 gap-4 mb-4">
<div>
<p className="font-medium">User:</p>
<p>{selectedTicket.user}</p>
</div>
<div>
<p className="font-medium">Status:</p>
<p
className={`${
selectedTicket.status === "Open"
? "text-red-500"
: selectedTicket.status === "In-Progress"
? "text-yellow-500"
: "text-green-500"
}`}
>
{selectedTicket.status}
</p>
</div>
<div>
<p className="font-medium">Priority:</p>
<p>{selectedTicket.priority}</p>
</div>
<div>
<p className="font-medium">Agent:</p>
<p>{selectedTicket.agent}</p>
</div>
<div>
<p className="font-medium">Created:</p>
<p>{selectedTicket.createdAt}</p>
</div>
</div>
<div className="mb-4">
<p className="font-medium">Description:</p>
<p className="mt-1 text-gray-600">{selectedTicket.description}</p>
</div>

<div className="mb-4">
<h4 className="font-semibold mb-2">Update Status:</h4>
<div className="flex space-x-2">
<button
className="px-3 py-1 bg-red-500 text-white rounded hover:bg-red-600 transition duration-150 ease-in-out"
onClick={() => updateTicketStatus(selectedTicket.id, "Open")}
>
Open
</button>
<button
className="px-3 py-1 bg-yellow-500 text-white rounded hover:bg-yellow-600 transition duration-150 ease-in-out"
onClick={() => updateTicketStatus(selectedTicket.id, "In-Progress")}
>
In-Progress
</button>
<button
className="px-3 py-1 bg-green-500 text-white rounded hover:bg-green-600 transition duration-150 ease-in-out"
onClick={() => updateTicketStatus(selectedTicket.id, "Resolved")}
>
Resolved
</button>
</div>
</div>

<div>
<h4 className="font-semibold mb-2">Assign Agent:</h4>
<select
className="w-full p-2 border border-gray-300 rounded"
value={selectedTicket.agent}
onChange={(e) => assignTicket(selectedTicket.id, e.target.value)}
>
<option value="Unassigned">Unassigned</option>
<option value="John Doe">John Doe</option>
<option value="Jane Smith">Jane Smith</option>
<option value="Bob Johnson">Bob Johnson</option>
</select>
</div>
</div>
);
};

export default TicketDetails;
38 changes: 38 additions & 0 deletions frontend/src/AgroShopAI/components/Pages/AdminTicketList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const TicketList = ({ filteredTickets, setSelectedTicket }) => (
<div className="bg-white rounded-lg shadow-md p-6">
<h2 className="text-xl font-semibold mb-4">Ticket List</h2>
<div className="space-y-4">
{filteredTickets.map((ticket) => (
<div
key={ticket.id}
className="p-4 border border-gray-200 rounded-lg cursor-pointer hover:bg-gray-50 transition duration-150 ease-in-out"
onClick={() => setSelectedTicket(ticket)}
>
<h3 className="font-semibold text-lg">
#{ticket.id} - {ticket.subject}
</h3>
<div className="mt-2 flex flex-wrap items-center text-sm text-gray-600">
<span className="mr-4">
Status:{" "}
<span
className={`font-medium ${
ticket.status === "Open"
? "text-red-500"
: ticket.status === "In-Progress"
? "text-yellow-500"
: "text-green-500"
}`}
>
{ticket.status}
</span>
</span>
<span className="mr-4">Agent: {ticket.agent}</span>
<span>Created: {ticket.createdAt}</span>
</div>
</div>
))}
</div>
</div>
);

export default TicketList;
31 changes: 31 additions & 0 deletions frontend/src/AgroShopAI/components/Pages/THeader.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useEffect, useState } from "react";

const Header = () => {
const [isHovering, setIsHovering] = useState(false);

// Hover effect to create visual interaction
const handleMouseEnter = () => setIsHovering(true);
const handleMouseLeave = () => setIsHovering(false);

return (
<header
className={`
bg-gradient-to-r from-green-400 to-blue-500 shadow-xl
text-white p-6 rounded-lg shadow-md mt-20 mb-5 pt-12 transition-all duration-500 ease-in-out`}


>
<div className="container mx-auto text-center">
<h1 className="text-4xl font-extrabold tracking-wide mb-2 transform hover:scale-105 transition-transform duration-500">
AgroShop Admin - Ticket Management
</h1>
<p className="text-lg font-medium tracking-wide opacity-90">
Manage tickets efficiently and provide exceptional service.
</p>
</div>
</header>
);
};

export default Header;
43 changes: 43 additions & 0 deletions frontend/src/AgroShopAI/components/Pages/TSearchAndFilter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const SearchAndFilter = ({
searchTerm,
setSearchTerm,
statusFilter,
setStatusFilter,
priorityFilter,
setPriorityFilter,
}) => (
<div className="bg-white rounded-lg shadow-md p-6 mb-6">
<h2 className="text-xl font-semibold mb-4">Search and Filter</h2>
<div className="flex flex-wrap items-center space-x-4">
<input
type="text"
placeholder="Search tickets..."
className="p-2 border border-gray-300 rounded flex-grow"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<select
className="p-2 border border-gray-300 rounded"
value={statusFilter}
onChange={(e) => setStatusFilter(e.target.value)}
>
<option value="All">All Statuses</option>
<option value="Open">Open</option>
<option value="In-Progress">In-Progress</option>
<option value="Resolved">Resolved</option>
</select>
<select
className="p-2 border border-gray-300 rounded"
value={priorityFilter}
onChange={(e) => setPriorityFilter(e.target.value)}
>
<option value="All">All Priorities</option>
<option value="High">High</option>
<option value="Medium">Medium</option>
<option value="Low">Low</option>
</select>
</div>
</div>
);

export default SearchAndFilter;
3 changes: 2 additions & 1 deletion frontend/src/MainContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ import BundledProducts from './AgroShopAI/components/Pages/BulkPage';
import TrendingProductsPage from './AgroShopAI/components/Pages/Trending';

import AffiliateProgramPage from './AgroShopAI/components/Pages/Affiliate';
import TicketManagement from './AgroShopAI/components/Pages/AdminTicket';



Expand Down Expand Up @@ -221,7 +222,7 @@ const MainContent = () => {
<Route path="/agri/bulk" element={<BundledProducts/>} />

<Route path="/agri/trend" element={<TrendingProductsPage/>} />

<Route path="/agri/adminTicket" element={<TicketManagement/>} />

</Routes>
{checkShop ? <ShopFooter /> : <Footer />}
Expand Down

0 comments on commit 61f92c9

Please sign in to comment.