OrderManagement.tsx
Golden-Hour-backend-layer-2/pages/OrderManagement.tsx
import React, { useState } from 'react';
interface OrderManagementProps {
view?: 'maisons' | 'experiences' | 'services' | 'products' | 'returns';
}
interface LogEntry {
time: string;
event: string;
officer: string;
}
interface OrderDetail {
id: string;
customer: string;
phone: string;
email: string;
orderName: string;
status: string;
statusTime: string;
payment: string;
details: Record<string, string>;
logs: LogEntry[];
}
const ProtocolBar: React.FC = () => (
<div className="fixed bottom-12 left-1/2 -translate-x-1/2 bg-white/90 backdrop-blur-md border border-[#c5a059]/20 px-10 py-5 rounded-full gallery-shadow flex items-center space-x-12 z-50 transition-all hover:border-[#c5a059]/40 group">
<button className="flex items-center space-x-3 text-slate-400 hover:text-slate-900 transition-all">
<i className="fa-solid fa-magnifying-glass text-[9px] text-[#c5a059]"></i>
<span className="text-[8px] font-bold uppercase tracking-[0.3em]">Search</span>
</button>
<div className="w-[0.5px] h-4 bg-[#c5a059]/20"></div>
<button className="flex items-center space-x-3 text-slate-400 hover:text-slate-900 transition-all">
<i className="fa-solid fa-plus text-[9px] text-[#c5a059]"></i>
<span className="text-[8px] font-bold uppercase tracking-[0.3em]">Create</span>
</button>
</div>
);
const BookingLogModal: React.FC<{ order: OrderDetail | null; onClose: () => void }> = ({ order, onClose }) => {
if (!order) return null;
return (
<div className="fixed inset-0 z-[110] flex items-center justify-center p-4 bg-slate-900/40 backdrop-blur-sm fade-in-section">
<div className="bg-white rounded-[2rem] gallery-shadow w-full max-w-md overflow-hidden border border-[#c5a059]/20 flex flex-col">
<div className="p-8 border-b border-[#c5a059]/10 flex items-center justify-between bg-[#fdfcf9]">
<div>
<span className="text-[7px] font-black uppercase tracking-[0.4em] text-[#c5a059] block mb-1 font-serif italic">Protocol Registry</span>
<h3 className="font-serif italic text-2xl text-slate-900">Timeline: {order.id}</h3>
</div>
<button onClick={onClose} className="w-8 h-8 rounded-full border border-[#c5a059]/10 flex items-center justify-center text-slate-300 hover:text-slate-900 transition-all">
<i className="fa-solid fa-xmark text-xs"></i>
</button>
</div>
<div className="p-8 space-y-6 max-h-[60vh] overflow-y-auto no-scrollbar">
{order.logs.map((log, i) => (
<div key={i} className="flex group/log">
<div className="w-16 flex-shrink-0 pt-1 text-right pr-6">
<p className="serif-numeral text-[10px] text-slate-300 group-hover/log:text-[#c5a059] transition-colors">{log.time}</p>
</div>
<div className="flex-1 pb-6 border-l border-[#c5a059]/10 pl-6 relative">
<div className="absolute -left-[3.5px] top-2 w-1.5 h-1.5 rounded-full bg-[#c5a059]/30 group-hover/log:bg-[#c5a059] transition-all"></div>
<p className="text-[9px] font-black uppercase tracking-widest text-slate-800 leading-none mb-1.5">{log.event}</p>
<p className="text-[8px] font-serif italic text-slate-400">Authorized by Officer {log.officer}</p>
</div>
</div>
))}
</div>
<div className="p-6 bg-[#fdfcf9] border-t border-[#c5a059]/10 flex justify-end">
<button onClick={onClose} className="text-[8px] font-bold uppercase tracking-[0.2em] text-slate-400 hover:text-slate-900 transition-all">Close Registry</button>
</div>
</div>
</div>
);
};
const OrderDetailModal: React.FC<{ order: OrderDetail | null; onClose: () => void }> = ({ order, onClose }) => {
if (!order) return null;
return (
<div className="fixed inset-0 z-[100] flex items-center justify-center p-4 bg-slate-900/60 backdrop-blur-md fade-in-section">
<div className="bg-white rounded-[3rem] gallery-shadow w-full max-w-2xl overflow-hidden border border-[#c5a059]/20 flex flex-col">
<div className="p-10 border-b border-[#c5a059]/10 flex items-center justify-between bg-[#fdfcf9]">
<div>
<span className="text-[8px] font-bold uppercase tracking-[0.5em] text-[#c5a059] block mb-2 font-serif italic">Transaction Dossier</span>
<h3 className="font-serif italic text-3xl text-slate-900">Order {order.id}</h3>
</div>
<button onClick={onClose} className="w-10 h-10 rounded-full border border-[#c5a059]/10 flex items-center justify-center text-slate-400 hover:text-slate-900 transition-all">
<i className="fa-solid fa-xmark"></i>
</button>
</div>
<div className="p-10 grid grid-cols-2 gap-10">
<div className="space-y-6">
<section>
<h4 className="text-[8px] font-bold uppercase tracking-[0.3em] text-slate-300 mb-3">Client Information</h4>
<p className="font-serif italic text-2xl text-slate-900 leading-tight">{order.customer}</p>
<div className="mt-3 space-y-1">
<p className="text-[10px] text-slate-500 font-medium uppercase tracking-widest flex items-center">
<i className="fa-solid fa-phone text-[8px] mr-3 text-[#c5a059]/40"></i> {order.phone}
</p>
<p className="text-[10px] text-slate-500 font-medium uppercase tracking-widest flex items-center">
<i className="fa-solid fa-envelope text-[8px] mr-3 text-[#c5a059]/40"></i> {order.email}
</p>
</div>
</section>
<section>
<h4 className="text-[8px] font-bold uppercase tracking-[0.3em] text-slate-300 mb-3">Provision Details</h4>
<p className="font-serif italic text-xl text-[#c5a059]">{order.orderName}</p>
<div className="mt-4 space-y-3">
{Object.entries(order.details).map(([key, val]) => (
<div key={key} className="flex justify-between border-b border-[#c5a059]/5 pb-1">
<span className="text-[8px] font-bold uppercase tracking-widest text-slate-400">{key}</span>
<span className="text-[10px] font-medium text-slate-800">{val}</span>
</div>
))}
</div>
</section>
</div>
<div className="bg-[#fdfcf9] rounded-[2rem] p-8 border border-[#c5a059]/5 flex flex-col justify-between">
<section>
<h4 className="text-[8px] font-bold uppercase tracking-[0.3em] text-slate-300 mb-6">Execution Status</h4>
<div className="flex items-center space-x-4 mb-4">
<div className="w-2 h-2 rounded-full bg-emerald-400 shadow-[0_0_10px_rgba(52,211,153,0.4)]"></div>
<div>
<p className="text-[10px] font-black uppercase tracking-widest text-slate-900">{order.status}</p>
<p className="text-[8px] font-serif italic text-slate-400 mt-1">Logged: {order.statusTime}</p>
</div>
</div>
</section>
<section className="pt-8 border-t border-[#c5a059]/10 text-right">
<h4 className="text-[8px] font-bold uppercase tracking-[0.3em] text-slate-300 mb-2">Total Acquisition</h4>
<p className="font-serif italic text-5xl text-slate-900 tracking-tighter">{order.payment}</p>
</section>
</div>
</div>
<div className="p-8 bg-[#fdfcf9]/80 border-t border-[#c5a059]/10 flex justify-between">
<button className="text-[8px] font-bold uppercase tracking-[0.2em] text-[#c5a059] hover:text-slate-900 transition-all">Download Receipt PDF</button>
<button onClick={onClose} className="bg-black text-white px-8 py-3 rounded-full text-[8px] font-bold uppercase tracking-[0.3em] hover:bg-[#c5a059] transition-all">Close Entry</button>
</div>
</div>
</div>
);
};
const ActionButtons: React.FC = () => (
<div className="flex justify-center items-center space-x-6">
<button className="text-slate-300 hover:text-[#c5a059] transition-all" title="Modify Details">
<i className="fa-solid fa-pen-nib text-sm"></i>
</button>
<button className="text-slate-300 hover:text-[#c5a059] transition-all" title="Send Email Protocol">
<i className="fa-solid fa-envelope text-sm"></i>
</button>
<button className="text-slate-300 hover:text-rose-600 transition-all" title="Delete Transaction">
<i className="fa-solid fa-trash-can text-sm"></i>
</button>
</div>
);
const OrderManagement: React.FC<OrderManagementProps> = ({ view = 'maisons' }) => {
const [selectedOrder, setSelectedOrder] = useState<OrderDetail | null>(null);
const [selectedLogOrder, setSelectedLogOrder] = useState<OrderDetail | null>(null);
const mockData: Record<string, OrderDetail[]> = {
maisons: [
{ id: '#M-2025-01', customer: 'Alice Wong', phone: '+33 6 12 34 56 78', email: 'alice@example.com', orderName: 'Villa Golden Hour', status: 'Confirmed', statusTime: 'Today, 10:24 AM', payment: '€2,500.00', details: { 'Check In': '12/05/2025', 'Check Out': '15/05/2025', 'Guests': '4 Adults' }, logs: [{time: '08:00', event: 'Draft Initialized', officer: 'AD-01'}, {time: '10:24', event: 'Payment Secured', officer: 'FIN-2'}, {time: '10:30', event: 'Confirmed Protocol', officer: 'GH-MGR'}] },
{ id: '#M-2025-02', customer: 'David Miller', phone: '+44 7700 900123', email: 'd.miller@uk.co', orderName: 'Azure Suite 4B', status: 'Draft', statusTime: 'Yesterday, 04:15 PM', payment: '€1,800.00', details: { 'Check In': '18/06/2025', 'Check Out': '20/06/2025', 'Guests': '2 Adults' }, logs: [{time: '16:15', event: 'Draft Initialized', officer: 'CL-04'}] },
],
experiences: [
{ id: '#E-2025-01', customer: 'Bob Chen', phone: '+44 7700 900000', email: 'bob.c@web.com', orderName: 'Wine Masterclass', status: 'Pending', statusTime: 'Yesterday, 4:15 PM', payment: '€45.00', details: { 'Time Slot': '14:00 - 16:30', 'Location': 'Tuscan Vineyard', 'Participants': '2' }, logs: [{time: '15:00', event: 'Inquiry Logged', officer: 'EX-01'}] },
],
services: [
{ id: '#S-2025-01', customer: 'Sarah Miller', phone: '+1 202 555 0123', email: 'sm@agency.com', orderName: 'Luxury Shuttle', status: 'Dispatched', statusTime: '2h ago', payment: '€120.00', details: { 'Pickup Time': '09:00 AM', 'Route': 'Station to Villa', 'Type': 'Mercedes V-Class' }, logs: [{time: '07:00', event: 'Driver Assigned', officer: 'OPS-01'}, {time: '09:00', event: 'Dispatched', officer: 'OPS-01'}] },
],
products: [
{ id: '#P-2025-01', customer: 'Mark Ross', phone: '+33 1 45 67 89 10', email: 'mark@ross.co', orderName: 'Huile d\'Olive Set', status: 'Shipped', statusTime: 'Yesterday, 11:30 AM', payment: '€298.47', details: { 'Amount': 'x 3 Units', 'Address': '123 Rue de Rivoli, Paris', 'Courier': 'DHL Express' }, logs: [{time: '10:00', event: 'Order Picked', officer: 'WH-01'}, {time: '11:30', event: 'Shipped Protocol', officer: 'WH-01'}] },
],
returns: [
{ id: '#R-2025-01', customer: 'David Smith', phone: '+44 20 7946 0000', email: 'd.smith@mail.com', orderName: 'Gourmet Box', status: 'Processing', statusTime: 'Today, 09:45 AM', payment: '€85.00', details: { 'Reason': 'Damaged in transit', 'Return Method': 'Pick-up', 'Request Date': '10/05/2025' }, logs: [{time: '09:45', event: 'Claim Logged', officer: 'CS-01'}] },
]
};
const currentData = mockData[view] || [];
return (
<div className="relative pb-32">
<div className="space-y-12 fade-in-section">
<div className="flex justify-between items-end border-b border-[#c5a059]/10 pb-10">
<div>
<h2 className="text-[#c5a059] font-black text-[10px] uppercase tracking-[0.5em] mb-4">Transaction Protocol</h2>
<h3 className="text-4xl font-serif italic text-slate-900">
{view === 'returns' ? 'Returns & Refunds' : `${view.charAt(0).toUpperCase() + view.slice(1)} Orders`}
</h3>
</div>
<div className="flex space-x-4">
<button className="bg-white border border-[#c5a059]/10 text-slate-400 px-8 py-3 rounded-full text-[8px] font-bold uppercase tracking-[0.3em] hover:text-black transition-all">
<i className="fa-solid fa-file-export mr-3"></i> Export Ledger
</button>
</div>
</div>
<div className="bg-white rounded-xl border border-[#c5a059]/5 overflow-hidden gallery-shadow">
<table className="w-full text-left">
<thead className="text-stone-300 text-[8px] font-bold uppercase tracking-[0.2em] border-b border-[#c5a059]/5 font-serif italic">
<tr>
<th className="px-8 py-5">ID</th>
<th className="px-8 py-5">Customer</th>
<th className="px-8 py-5">Contact</th>
<th className="px-8 py-5">Order</th>
{view === 'maisons' && (
<>
<th className="px-8 py-5">Check in</th>
<th className="px-8 py-5">Check out</th>
</>
)}
{view === 'experiences' && (
<>
<th className="px-8 py-5">Time Slot</th>
</>
)}
{view === 'services' && (
<>
<th className="px-8 py-5">Time</th>
</>
)}
{view === 'products' && (
<>
<th className="px-8 py-5">Amount</th>
<th className="px-8 py-5">Address</th>
</>
)}
{view !== 'returns' && <th className="px-8 py-5">Payment</th>}
<th className="px-8 py-5">Booking Status</th>
<th className="px-8 py-5 text-center">Action</th>
</tr>
</thead>
<tbody className="divide-y divide-[#c5a059]/5">
{currentData.map((order) => (
<tr key={order.id} className="hover:bg-[#fdfcf9] transition-all group">
<td className="px-8 py-7 serif-numeral text-sm text-[#c5a059]">{order.id}</td>
<td className="px-8 py-7">
<p className="font-serif italic text-lg text-slate-900 leading-none">{order.customer}</p>
</td>
<td className="px-8 py-7">
<div className="space-y-1">
<p className="text-[9px] text-slate-500 uppercase tracking-wider flex items-center">
<i className="fa-solid fa-phone text-[7px] mr-2 opacity-30"></i> {order.phone}
</p>
<p className="text-[9px] text-slate-400 uppercase tracking-wider flex items-center">
<i className="fa-solid fa-envelope text-[7px] mr-2 opacity-30"></i> {order.email}
</p>
</div>
</td>
<td className="px-8 py-7">
<button
onClick={() => setSelectedOrder(order)}
className="text-[10px] font-bold uppercase tracking-[0.15em] text-[#c5a059] hover:text-slate-900 transition-all text-left decoration-[#c5a059]/20 hover:underline underline-offset-4 font-serif italic"
>
{order.orderName}
</button>
</td>
{view === 'maisons' && (
<>
<td className="px-8 py-7 serif-numeral text-sm text-stone-500">{order.details['Check In']}</td>
<td className="px-8 py-7 serif-numeral text-sm text-stone-500">{order.details['Check Out']}</td>
</>
)}
{view === 'experiences' && (
<td className="px-8 py-7 serif-numeral text-sm text-stone-500">{order.details['Time Slot']}</td>
)}
{view === 'services' && (
<td className="px-8 py-7 serif-numeral text-sm text-stone-500">{order.details['Pickup Time']}</td>
)}
{view === 'products' && (
<>
<td className="px-8 py-7 serif-numeral text-sm text-stone-500">{order.details['Amount']}</td>
<td className="px-8 py-7 text-[10px] text-slate-400 uppercase tracking-widest font-medium truncate max-w-[150px]">{order.details['Address']}</td>
</>
)}
{view !== 'returns' && (
<td className="px-8 py-7 font-serif italic text-lg text-slate-900 tracking-tighter">{order.payment}</td>
)}
<td className="px-8 py-7">
<div className="flex items-center space-x-3">
<div>
<span className={`text-[7px] font-bold uppercase tracking-widest px-2 py-0.5 rounded-full border ${
order.status === 'Confirmed' ? 'border-emerald-100 text-emerald-600 bg-emerald-50/5' :
order.status === 'Dispatched' ? 'border-sky-100 text-sky-600 bg-sky-50/5' :
'border-slate-100 text-slate-400'
}`}>{order.status}</span>
<p className="text-[6px] uppercase tracking-widest text-slate-300 mt-1 font-medium">{order.statusTime}</p>
</div>
<button
onClick={() => setSelectedLogOrder(order)}
className="w-5 h-5 rounded-full border border-[#c5a059]/10 flex items-center justify-center text-slate-300 hover:text-[#c5a059] transition-all"
title="View Protocol Log"
>
<i className="fa-solid fa-clock-rotate-left text-[8px]"></i>
</button>
</div>
</td>
<td className="px-8 py-7">
<ActionButtons />
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
<OrderDetailModal order={selectedOrder} onClose={() => setSelectedOrder(null)} />
<BookingLogModal order={selectedLogOrder} onClose={() => setSelectedLogOrder(null)} />
<ProtocolBar />
</div>
);
};
export default OrderManagement;
Related articles
App.tsx
App.tsx — typescript source code from the Golden-Hour-backend-layer-2 learning materials (Golden-Hour-backend-layer-2/App.tsx).
Read article →Header.tsx
Header.tsx — typescript source code from the Golden-Hour-backend-layer-2 learning materials (Golden-Hour-backend-layer-2/components/Header.tsx).
Read article →Sidebar.tsx
Sidebar.tsx — typescript source code from the Golden-Hour-backend-layer-2 learning materials (Golden-Hour-backend-layer-2/components/Sidebar.tsx).
Read article →index.tsx
index.tsx — typescript source code from the Golden-Hour-backend-layer-2 learning materials (Golden-Hour-backend-layer-2/index.tsx).
Read article →ContentManagement.tsx
ContentManagement.tsx — typescript source code from the Golden-Hour-backend-layer-2 learning materials (Golden-Hour-backend-layer-2/pages/ContentManagement.tsx).
Read article →CustomerManagement.tsx
CustomerManagement.tsx — typescript source code from the Golden-Hour-backend-layer-2 learning materials (Golden-Hour-backend-layer-2/pages/CustomerManagement.tsx).
Read article →