Files
trackgo-fe/packages/ui/src/components/examples/style-guide-1.tsx
T
Firman Ramdhani 23c869e574 feat: add example components and system pages for UI showcase
- 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.
2026-01-19 16:04:07 +07:00

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>
);
}