- Introduced HeaderExample component for header display. - Created StyleGuideOne, StyleGuideTwo, and StyleGuideThree components showcasing various UI elements and layouts. - Added system pages: ComingSoon, Forbidden, Maintenance, and NotFound for better user experience during different states. - Updated index.ts to export new components for easier access.
209 lines
9.3 KiB
TypeScript
209 lines
9.3 KiB
TypeScript
import React from 'react';
|
|
|
|
// --- SHARED SUB-COMPONENTS ---
|
|
const Card = ({
|
|
title,
|
|
children,
|
|
className = '',
|
|
}: {
|
|
title?: string;
|
|
children: React.ReactNode;
|
|
className?: string;
|
|
}) => (
|
|
<div className={`bg-white border border-gray-200 rounded-lg shadow-sm ${className}`}>
|
|
{title && (
|
|
<div className="px-4 py-3 border-b border-gray-100 bg-gray-50/50">
|
|
<h3 className="text-lg font-semibold text-gray-800">{title}</h3>
|
|
</div>
|
|
)}
|
|
<div className="p-5">{children}</div>
|
|
</div>
|
|
);
|
|
|
|
const Badge = ({
|
|
children,
|
|
variant = 'info',
|
|
}: {
|
|
children: React.ReactNode;
|
|
variant?: 'success' | 'error' | 'warning' | 'info';
|
|
}) => {
|
|
const styles = {
|
|
success: 'bg-green-50 text-green-600 border-green-100',
|
|
error: 'bg-red-50 text-red-600 border-red-100',
|
|
warning: 'bg-amber-50 text-amber-600 border-amber-100',
|
|
info: 'bg-brand-50 text-brand-600 border-brand-100',
|
|
};
|
|
return (
|
|
<span className={`px-2 py-0.5 rounded-sm text-xs font-bold border ${styles[variant]} uppercase tracking-wider`}>
|
|
{children}
|
|
</span>
|
|
);
|
|
};
|
|
|
|
// --- MAIN PAGE COMPONENT ---
|
|
export function StyleGuideOne() {
|
|
return (
|
|
<div className="min-h-screen bg-gray-50 text-gray-700 font-sans">
|
|
{/* 1. OBJECT HEADER (SAP Pattern) */}
|
|
<div className="bg-white border-b border-gray-200 px-8 py-6 sticky top-0 z-10 shadow-sm">
|
|
<div className="max-w-7xl mx-auto flex flex-col md:flex-row md:items-center justify-between gap-4">
|
|
<div>
|
|
<nav className="text-xs font-bold text-brand-600 uppercase tracking-widest mb-1">
|
|
Procurement / Purchase Orders
|
|
</nav>
|
|
<h1 className="text-xl font-bold text-gray-900 flex items-center gap-3">
|
|
PO #4500019283
|
|
<Badge variant="success">Released</Badge>
|
|
</h1>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<button className="px-4 py-1.5 border border-gray-300 rounded-md bg-white hover:bg-gray-50 font-medium transition-all shadow-sm">
|
|
Reject
|
|
</button>
|
|
<button className="px-4 py-1.5 bg-brand-500 text-white rounded-md hover:bg-brand-600 font-medium transition-all shadow-sm">
|
|
Approve Order
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="max-w-7xl mx-auto p-6 space-y-8">
|
|
{/* 2. ANALYTICS / KPI SECTION */}
|
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
{[
|
|
{ label: 'Total Value', val: '$12,450.00', color: 'text-gray-900' },
|
|
{ label: 'Items Count', val: '24 SKUs', color: 'text-gray-900' },
|
|
{ label: 'Days Overdue', val: '5 Days', color: 'text-red-500' },
|
|
{ label: 'Vendor Rating', val: '4.8 / 5.0', color: 'text-green-600' },
|
|
].map((kpi, i) => (
|
|
<div key={i} className="bg-white p-4 rounded-lg border border-gray-200 shadow-sm">
|
|
<p className="text-xs font-bold text-gray-500 uppercase tracking-wider">{kpi.label}</p>
|
|
<p className={`text-xl font-bold mt-1 ${kpi.color}`}>{kpi.val}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
|
{/* LEFT: FORM & CONTROLS */}
|
|
<div className="lg:col-span-1 space-y-6">
|
|
<Card title="General Information">
|
|
<div className="space-y-4">
|
|
<div className="flex flex-col gap-1">
|
|
<label className="text-sm font-medium text-gray-500">Vendor Name</label>
|
|
<input
|
|
type="text"
|
|
readOnly
|
|
className="bg-gray-50 border border-gray-200 rounded-md px-3 py-1.5 text-gray-600 outline-none cursor-not-allowed"
|
|
defaultValue="Steel Global Corp"
|
|
/>
|
|
</div>
|
|
<div className="flex flex-col gap-1">
|
|
<label className="text-sm font-medium text-gray-500">Shipping Method</label>
|
|
<select className="border border-gray-300 rounded-md px-3 py-1.5 bg-white focus:ring-1 focus:ring-brand-500 outline-none">
|
|
<option>Sea Freight - Standard</option>
|
|
<option>Air Freight - Express</option>
|
|
</select>
|
|
</div>
|
|
<div className="flex flex-col gap-1">
|
|
<label className="text-sm font-medium text-gray-500">Order Priority</label>
|
|
<div className="flex gap-4 mt-1">
|
|
<label className="flex items-center gap-2 cursor-pointer">
|
|
<input type="radio" name="prio" className="accent-brand-500" />{' '}
|
|
<span className="text-base">Normal</span>
|
|
</label>
|
|
<label className="flex items-center gap-2 cursor-pointer">
|
|
<input type="radio" name="prio" className="accent-brand-500" defaultChecked />{' '}
|
|
<span className="text-base">High</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
|
|
<Card title="Order Status Logs">
|
|
<ul className="space-y-4">
|
|
{[
|
|
{ time: '10:00 AM', msg: 'Order Created', user: 'System' },
|
|
{ time: '11:30 AM', msg: 'Manager Approved', user: 'Budi Santoso' },
|
|
].map((log, i) => (
|
|
<li key={i} className="flex gap-3 border-l-2 border-brand-200 pl-4 relative">
|
|
<div className="absolute w-2.5 h-2.5 bg-brand-500 rounded-full -left-[6px] top-1"></div>
|
|
<div>
|
|
<p className="text-base font-medium text-gray-800">{log.msg}</p>
|
|
<p className="text-xs text-gray-500">
|
|
{log.time} • By {log.user}
|
|
</p>
|
|
</div>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* RIGHT: DATA TABLE (The Core of ERP) */}
|
|
<div className="lg:col-span-2">
|
|
<Card className="!p-0 overflow-hidden">
|
|
<div className="p-4 border-b border-gray-100 flex justify-between items-center">
|
|
<h3 className="text-lg font-semibold text-gray-800">Line Items</h3>
|
|
<div className="flex gap-2">
|
|
<button className="text-xs font-bold text-brand-600 hover:bg-brand-50 px-2 py-1 rounded">
|
|
EXPORT CSV
|
|
</button>
|
|
<button className="text-xs font-bold text-brand-600 hover:bg-brand-50 px-2 py-1 rounded">
|
|
PRINT PO
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full border-collapse">
|
|
<thead>
|
|
<tr className="bg-gray-100/80">
|
|
<th className="px-4 py-2 text-xs font-bold text-gray-500 uppercase">Material</th>
|
|
<th className="px-4 py-2 text-xs font-bold text-gray-500 uppercase">Description</th>
|
|
<th className="px-4 py-2 text-xs font-bold text-gray-500 uppercase text-right">Qty</th>
|
|
<th className="px-4 py-2 text-xs font-bold text-gray-500 uppercase text-right">Price</th>
|
|
<th className="px-4 py-2 text-xs font-bold text-gray-500 uppercase text-right">Total</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-gray-100 text-base">
|
|
{[1, 2, 3, 4, 5].map((item) => (
|
|
<tr key={item} className="hover:bg-brand-50/20 transition-all cursor-pointer group">
|
|
<td className="px-4 py-2 font-mono text-brand-600 group-hover:underline">M-1000{item}</td>
|
|
<td className="px-4 py-2 text-gray-800">
|
|
Industrial Steel Pipe 2.5" - Grade {item === 2 ? 'B' : 'A'}
|
|
</td>
|
|
<td className="px-4 py-2 text-right">100.00</td>
|
|
<td className="px-4 py-2 text-right">150.00</td>
|
|
<td className="px-4 py-2 text-right font-semibold text-gray-900">15,000.00</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
<tfoot className="bg-gray-50/80 font-bold border-t-2 border-gray-200">
|
|
<tr>
|
|
<td colSpan={4} className="px-4 py-3 text-right text-gray-500 uppercase text-xs tracking-widest">
|
|
Grand Total (Net)
|
|
</td>
|
|
<td className="px-4 py-3 text-right text-brand-600 text-lg">$ 75,000.00</td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</Card>
|
|
|
|
<div className="mt-4 bg-amber-50 border border-amber-100 rounded-lg p-4 flex gap-3">
|
|
<span className="text-xl">⚠️</span>
|
|
<div>
|
|
<p className="text-base font-bold text-amber-800">Budget Warning</p>
|
|
<p className="text-sm text-amber-700">
|
|
This purchase order exceeds the quarterly budget for Department "Steel Fabrication" by 12%.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|