Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import RootLayout from './layouts/RootLayout';
import { BuyerSidebar, SellerSidebar, AdminSidebar } from './components/RoleBasedSidebar';
import WorkspaceView from './components/WorkspaceView';


import { CartProvider } from './context/CartContext';

// Auth Pages
Expand All @@ -25,7 +26,36 @@ import BuyerProfile from './pages/buyer/BuyerProfile';
import Dashboard from './pages/seller/dashboard';
import Catalog from './pages/seller/catalog';

// Admin Pages
import Overview from './pages/admin/overview';
import Verify from './pages/admin/verify';
import Moderate from './pages/admin/moderate';
import Users from './pages/admin/users';
import Logs from './pages/admin/logs';
import Disputes from './pages/admin/disputes';

const App = () => (
<BrowserRouter>
<Routes>
<Route path="/admin/*" element={<RootLayout sidebarContent={<AdminSidebar />} />} >
<Route path="" element={<Overview />} />
<Route path="verify" element={<Verify />} />
<Route path="moderate" element={<Moderate />} />
<Route path="users" element={<Users />} />
<Route path="logs" element={<Logs />} />
<Route path="disputes" element={<Disputes />} />
<Route path="*" element={<WorkspaceView />} />
</Route>

<Route path="/seller/*" element={<RootLayout sidebarContent={<SellerSidebar />} />}>
<Route path="*" element={<WorkspaceView />} />
</Route>

<Route path="/*" element={<RootLayout sidebarContent={<BuyerSidebar />} />}>
<Route path="*" element={<WorkspaceView />} />
</Route>
</Routes>
</BrowserRouter>
<CartProvider>
<BrowserRouter>
<Routes>
Expand Down
103 changes: 103 additions & 0 deletions frontend/src/components/admin/ActiveDisputeQueue.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import React from 'react';

Check failure on line 1 in frontend/src/components/admin/ActiveDisputeQueue.jsx

View workflow job for this annotation

GitHub Actions / Frontend Build & Lint

'React' is defined but never used

Check failure on line 1 in frontend/src/components/admin/ActiveDisputeQueue.jsx

View workflow job for this annotation

GitHub Actions / Frontend Build & Lint

'React' is defined but never used
import { ArrowUpDown, SlidersHorizontal } from 'lucide-react';
import Pagination from './Pagination';

const ReasonBadge = ({ reason }) => {
return (
<span className="inline-flex px-3 py-1 rounded-full bg-[#EBE5D9] text-[#8C5233] text-[9px] font-bold tracking-widest uppercase">
{reason}
</span>
);
};

const ActiveDisputeQueue = ({ data, onRowClick, onFilterClick, onSortClick }) => {
return (
<div className="card-custom !p-0 overflow-hidden flex flex-col h-full group hover:card-custom-hover">
{/* Header */}
<div className="flex flex-col md:flex-row justify-between items-start md:items-center p-6 border-b border-neutral-dark/10 gap-4">
<h2 className="text-lg font-headline font-bold text-neutral-dark">Active Dispute Queue</h2>
<div className="flex items-center gap-4 text-neutral-dark/60">
<button
onClick={onSortClick}
className="text-neutral-dark/40 hover:text-neutral-dark transition-colors outline-none focus-visible:ring-2 focus-visible:ring-primary rounded-sm"
>
<ArrowUpDown className="w-4 h-4" />
</button>
<button
onClick={onFilterClick}
className="text-neutral-dark/40 hover:text-neutral-dark transition-colors outline-none focus-visible:ring-2 focus-visible:ring-primary rounded-sm"
>
<SlidersHorizontal className="w-4 h-4" />
</button>
<div className="w-px h-5 bg-neutral-dark/10 mx-2"></div>
<span className="text-[11px] font-sans text-neutral-dark/60">
1-4 of 24
</span>
</div>
</div>

{/* Table Content */}
<div className="overflow-x-auto flex-1">
<table className="w-full text-left border-collapse min-w-[700px]">
<thead>
<tr className="bg-neutral-dark/5 border-b border-neutral-dark/10">
<th className="py-4 px-6 text-[10px] font-sans font-bold tracking-widest text-neutral-dark/60 uppercase">Dispute ID</th>
<th className="py-4 px-4 text-[10px] font-sans font-bold tracking-widest text-neutral-dark/60 uppercase">Artisan / Shop</th>
<th className="py-4 px-4 text-[10px] font-sans font-bold tracking-widest text-neutral-dark/60 uppercase">Customer</th>
<th className="py-4 px-4 text-[10px] font-sans font-bold tracking-widest text-neutral-dark/60 uppercase">Reason</th>
<th className="py-4 px-6 text-[10px] font-sans font-bold tracking-widest text-neutral-dark/60 uppercase text-right">Amount</th>
</tr>
</thead>
<tbody>
{data.map((row, i) => (
<tr
key={i}
onClick={() => onRowClick(row.id)}
className={`border-b border-neutral-dark/5 hover:bg-neutral-dark/5 transition-colors cursor-pointer group/row ${i === data.length - 1 ? 'border-b-0' : ''}`}
>
<td className="py-5 px-6">
<span className="text-[10px] font-sans font-bold text-[#8C5233] uppercase tracking-widest">
{row.id}
</span>
</td>
<td className="py-5 px-4 flex items-center gap-3">
<div className="w-8 h-8 rounded-md overflow-hidden shrink-0 bg-neutral-dark/10">
<img src={row.shopImg} alt={row.shopName} className="w-full h-full object-cover" />
</div>
<span className="text-[13px] font-sans font-bold text-neutral-dark">
{row.shopName}
</span>
</td>
<td className="py-5 px-4">
<span className="text-[13px] font-sans text-neutral-dark/80">
{row.customerName}
</span>
</td>
<td className="py-5 px-4">
<ReasonBadge reason={row.reason} />
</td>
<td className="py-5 px-6 text-right">
<span className="text-[13px] font-headline font-bold text-neutral-dark">
{row.amount}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>

{/* Footer / Pagination */}
<div className="border-t border-neutral-dark/10 p-4 px-6 flex items-center justify-between bg-neutral-dark/5">
<div className="text-[11px] font-sans text-neutral-dark/60">
Showing <span className="font-bold text-neutral-dark">1-4</span> of <span className="font-bold text-neutral-dark">24</span> open disputes
</div>
<div className="scale-90 origin-right">
<Pagination />
</div>
</div>
</div>
);
};

export default ActiveDisputeQueue;
63 changes: 63 additions & 0 deletions frontend/src/components/admin/AdminActionModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { useEffect } from 'react';

Check failure on line 1 in frontend/src/components/admin/AdminActionModal.jsx

View workflow job for this annotation

GitHub Actions / Frontend Build & Lint

'React' is defined but never used

Check failure on line 1 in frontend/src/components/admin/AdminActionModal.jsx

View workflow job for this annotation

GitHub Actions / Frontend Build & Lint

'React' is defined but never used
import { X, Info } from 'lucide-react';

const AdminActionModal = ({ isOpen, onClose, title, message }) => {
useEffect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = 'unset';
}
return () => {
document.body.style.overflow = 'unset';
};
}, [isOpen]);

if (!isOpen) return null;

return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 sm:p-6">
{/* Backdrop */}
<div
className="absolute inset-0 bg-neutral-dark/40 backdrop-blur-sm transition-opacity"
onClick={onClose}
/>

{/* Modal Dialog */}
<div className="relative bg-background rounded-2xl shadow-xl w-full max-w-md overflow-hidden transform transition-all">
{/* Header */}
<div className="flex items-center justify-between p-6 border-b border-neutral-dark/10">
<h3 className="text-lg font-headline font-bold text-neutral-dark flex items-center gap-2">
<Info className="w-5 h-5 text-[#8C5233]" />
{title}
</h3>
<button
onClick={onClose}
className="text-neutral-dark/50 hover:text-neutral-dark hover:bg-neutral-dark/5 rounded-full p-2 transition-colors focus:outline-none focus:ring-2 focus:ring-[#8C5233]"
>
<X className="w-5 h-5" />
</button>
</div>

{/* Content */}
<div className="p-6">
<p className="text-[14px] font-sans text-neutral-dark/70 leading-relaxed">
{message || "This feature is currently under development for the Admin Portal. Check back later!"}
</p>
</div>

{/* Footer */}
<div className="flex justify-end p-6 bg-neutral-dark/5 border-t border-neutral-dark/10">
<button
onClick={onClose}
className="px-6 py-2.5 rounded-md bg-[#8C5233] hover:bg-[#7E4A2E] text-white text-[13px] font-sans font-bold tracking-wide transition-colors shadow-sm"
>
Got it
</button>
</div>
</div>
</div>
);
};

export default AdminActionModal;
55 changes: 55 additions & 0 deletions frontend/src/components/admin/AdminHeader.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';

Check failure on line 1 in frontend/src/components/admin/AdminHeader.jsx

View workflow job for this annotation

GitHub Actions / Frontend Build & Lint

'React' is defined but never used

Check failure on line 1 in frontend/src/components/admin/AdminHeader.jsx

View workflow job for this annotation

GitHub Actions / Frontend Build & Lint

'React' is defined but never used
import { Search, Bell, HelpCircle } from 'lucide-react';

const AdminHeader = ({
searchPlaceholder = "Search for shops, orders, or reports...",
primaryActionText = "Export Report",
onPrimaryActionClick,
secondaryActionText,
secondaryActionIcon: SecondaryActionIcon,
onSecondaryActionClick
}) => {
return (
<header className="flex justify-between items-center py-6">
{/* Search Bar */}
<div className="relative w-full max-w-md">
<Search className="absolute left-4 top-1/2 -translate-y-1/2 w-4 h-4 text-neutral-dark/40" />
<input
type="text"
placeholder={searchPlaceholder}
className="w-full pl-11 pr-4 py-3 bg-neutral border border-neutral-dark/10 rounded-full text-[13px] font-sans placeholder:text-neutral-dark/40 focus:outline-none focus:ring-2 focus:ring-[#8C5233]/20 transition-all shadow-sm"
/>
</div>

{/* Right Controls */}
<div className="flex items-center gap-6">
<div className="flex items-center gap-3">
{secondaryActionText && (
<button
onClick={onSecondaryActionClick}
className="flex items-center gap-2 px-6 py-2.5 rounded-md border border-[#8C5233] text-[#8C5233] hover:bg-[#8C5233]/5 text-[13px] font-sans font-bold transition-colors"
>
{SecondaryActionIcon && <SecondaryActionIcon className="w-4 h-4" />}
{secondaryActionText}
</button>
)}
<button
onClick={onPrimaryActionClick}
className="px-6 py-2.5 rounded-md bg-[#8C5233] hover:bg-[#7E4A2E] text-white text-[13px] font-sans font-bold transition-colors shadow-sm"
>
{primaryActionText}
</button>
</div>
<button className="relative text-neutral-dark/60 hover:text-neutral-dark transition-colors outline-none focus-visible:ring-2 focus-visible:ring-[#8C5233] rounded-full p-1">
<Bell className="w-5 h-5" />
<span className="absolute top-1 right-1 w-2 h-2 bg-destructive rounded-full border border-background"></span>
</button>
<button className="text-neutral-dark/60 hover:text-neutral-dark transition-colors outline-none focus-visible:ring-2 focus-visible:ring-[#8C5233] rounded-full p-1">
<HelpCircle className="w-5 h-5" />
</button>
</div>
</header>
);
};

export default AdminHeader;
28 changes: 28 additions & 0 deletions frontend/src/components/admin/AdminStatCard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';

Check failure on line 1 in frontend/src/components/admin/AdminStatCard.jsx

View workflow job for this annotation

GitHub Actions / Frontend Build & Lint

'React' is defined but never used

Check failure on line 1 in frontend/src/components/admin/AdminStatCard.jsx

View workflow job for this annotation

GitHub Actions / Frontend Build & Lint

'React' is defined but never used

const AdminStatCard = ({ title, value, subtext, subtextColor = 'text-neutral-dark/60', icon: Icon, iconBgClass = 'bg-[#F5EDE8]', iconColorClass = 'text-primary', accentClass = '' }) => {
return (
<div className={`card-custom !p-6 flex flex-col justify-between h-40 group hover:card-custom-hover ${accentClass}`}>
<div className="flex justify-between items-start">
<h3 className="text-[11px] font-sans font-bold tracking-widest text-neutral-dark/60 uppercase max-w-[70%] leading-relaxed">
{title}
</h3>
{Icon && (
<div className={`w-8 h-8 rounded-full flex items-center justify-center ${iconBgClass} shrink-0`}>
<Icon className={`w-4 h-4 ${iconColorClass}`} />
</div>
)}
</div>

<div className="mt-4">
<div className="text-3xl font-headline font-bold text-neutral-dark mb-1">
{value}
</div>
<div className={`text-[10px] font-sans font-medium ${subtextColor}`}>
{subtext}
</div>
</div>
</div>
);
};
export default AdminStatCard;
Loading
Loading