detail view polished
This commit is contained in:
parent
9575cd060e
commit
a8807155a2
@ -2,7 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/x-icon" href="/src/assets/favicon.ico" />
|
<link rel="icon" type="image/png" href="/src/assets/logo.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Krishna Sales</title>
|
<title>Krishna Sales</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
@ -21,6 +21,38 @@ import {
|
|||||||
ArrowLeft,
|
ArrowLeft,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
|
|
||||||
|
const SafeImage = ({ src, alt, type, text, className }: { src: string, alt: string, type: 'store' | 'proof', text?: string, className?: string }) => {
|
||||||
|
const [error, setError] = useState(false);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
if (type === 'store') {
|
||||||
|
return (
|
||||||
|
<div className="h-40 bg-[#E8FBF0] p-6 flex flex-col items-center justify-center text-center gap-2 border border-emerald-200 w-full">
|
||||||
|
<div className="w-12 h-12 rounded-full bg-[var(--tiles-card-bg)] shadow-sm flex items-center justify-center text-emerald-500">
|
||||||
|
<ImageIcon size={22} />
|
||||||
|
</div>
|
||||||
|
<span className="text-xs font-bold text-emerald-700 uppercase tracking-wider">{text || 'Image not available'}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="rounded-xl border border-emerald-200 bg-[#E8FBF0] p-6 flex flex-col items-center justify-center text-center gap-2 w-full h-full min-h-[160px]">
|
||||||
|
<Camera className="text-emerald-500" size={24} />
|
||||||
|
<span className="text-xs font-semibold text-emerald-700">{text || 'No proof image uploaded'}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={src}
|
||||||
|
alt={alt}
|
||||||
|
className={className}
|
||||||
|
onError={() => setError(true)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export interface CallDetailProps {
|
export interface CallDetailProps {
|
||||||
instanceId: number | string;
|
instanceId: number | string;
|
||||||
selectedRow?: Record<string, any>;
|
selectedRow?: Record<string, any>;
|
||||||
@ -347,6 +379,7 @@ export function CallDetail({
|
|||||||
const channel = String(rowSrc.order_received_channel
|
const channel = String(rowSrc.order_received_channel
|
||||||
|| rowSrc.channel || data?.order_received_channel || 'No data');
|
|| rowSrc.channel || data?.order_received_channel || 'No data');
|
||||||
const storeNotes = selectStore.notes || 'No notes available.';
|
const storeNotes = selectStore.notes || 'No notes available.';
|
||||||
|
const visitNotes = String(rowSrc.notes || data?.notes || rowSrc.remarks || data?.remarks || rowSrc.remark || data?.remark || '');
|
||||||
const currentStateName = String(rowSrc.current_state_name || data?.current_state_name || 'No data');
|
const currentStateName = String(rowSrc.current_state_name || data?.current_state_name || 'No data');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -406,19 +439,19 @@ export function CallDetail({
|
|||||||
|
|
||||||
{/* Top Right KPI Grid */}
|
{/* Top Right KPI Grid */}
|
||||||
<div className="flex flex-nowrap items-center gap-3 w-full lg:w-auto overflow-x-auto pb-2 min-w-0">
|
<div className="flex flex-nowrap items-center gap-3 w-full lg:w-auto overflow-x-auto pb-2 min-w-0">
|
||||||
<div className="bg-slate-50 border border-slate-200/60 rounded-xl p-3 text-center min-w-[100px] flex-1">
|
<div className="bg-[#E8FBF0] border border-emerald-200 rounded-xl p-3 text-center min-w-[100px] flex-1">
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">TOTAL BAGS</div>
|
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">TOTAL BAGS</div>
|
||||||
<div className="text-xl font-bold text-slate-900">{totalBags.toLocaleString()}</div>
|
<div className="text-xl font-bold text-slate-900">{totalBags.toLocaleString()}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-slate-50 border border-slate-200/60 rounded-xl p-3 text-center min-w-[100px] flex-1">
|
<div className="bg-[#E8FBF0] border border-emerald-200 rounded-xl p-3 text-center min-w-[100px] flex-1">
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">TOTAL KGS</div>
|
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">TOTAL KGS</div>
|
||||||
<div className="text-xl font-bold text-slate-900">{totalKgs.toLocaleString()}</div>
|
<div className="text-xl font-bold text-slate-900">{totalKgs.toLocaleString()}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-slate-50 border border-slate-200/60 rounded-xl p-3 text-center min-w-[100px] flex-1">
|
<div className="bg-[#E8FBF0] border border-emerald-200 rounded-xl p-3 text-center min-w-[100px] flex-1">
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">LINE ITEMS</div>
|
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">ORDER ITEMS</div>
|
||||||
<div className="text-xl font-bold text-slate-900">{lineItemsCount}</div>
|
<div className="text-xl font-bold text-slate-900">{lineItemsCount}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-slate-50 border border-slate-200/60 rounded-xl p-3 text-center min-w-[110px] flex-1">
|
<div className="bg-[#E8FBF0] border border-emerald-200 rounded-xl p-3 text-center min-w-[110px] flex-1">
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">SALES OFFICER</div>
|
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">SALES OFFICER</div>
|
||||||
<div className="text-sm font-bold text-slate-900 truncate mt-1">{salesOfficer}</div>
|
<div className="text-sm font-bold text-slate-900 truncate mt-1">{salesOfficer}</div>
|
||||||
</div>
|
</div>
|
||||||
@ -728,9 +761,21 @@ export function CallDetail({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right Store Proof Photo */}
|
{/* Right Store Proof Photo */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
{visitNotes && visitNotes.trim() !== '' && visitNotes.toLowerCase() !== 'undefined' && visitNotes.toLowerCase() !== 'null' && (
|
||||||
|
<div className="space-y-2">
|
||||||
|
<div className="text-[11px] font-bold text-emerald-600 uppercase tracking-wider flex items-center gap-1">
|
||||||
|
<FileText size={12} className="text-emerald-500" /> VISIT NOTES
|
||||||
|
</div>
|
||||||
|
<div className="bg-[#E8FBF0] border border-emerald-200 rounded-xl p-3.5 text-xs text-slate-700 leading-relaxed font-medium">
|
||||||
|
{visitNotes}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="text-[11px] font-bold text-slate-400 uppercase tracking-wider flex items-center gap-1">
|
<div className="text-[11px] font-bold text-slate-400 uppercase tracking-wider flex items-center gap-1">
|
||||||
<FileText size={12} /> UPLOADED PROOF
|
<Camera size={12} /> UPLOADED PROOF
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{uploadedImages.length > 0 ? (
|
{uploadedImages.length > 0 ? (
|
||||||
@ -739,14 +784,11 @@ export function CallDetail({
|
|||||||
const previewUrl = `${orderBookingClient.baseUrl}/app/${APP_ID}/view/files/${file.uuid}/preview`;
|
const previewUrl = `${orderBookingClient.baseUrl}/app/${APP_ID}/view/files/${file.uuid}/preview`;
|
||||||
return (
|
return (
|
||||||
<div key={file.uuid || idx} className="relative w-full rounded-xl overflow-hidden border border-slate-200 bg-slate-100 flex items-center justify-center group shadow-sm">
|
<div key={file.uuid || idx} className="relative w-full rounded-xl overflow-hidden border border-slate-200 bg-slate-100 flex items-center justify-center group shadow-sm">
|
||||||
<img
|
<SafeImage
|
||||||
src={previewUrl}
|
src={previewUrl}
|
||||||
alt={file.original_name || 'Uploaded Proof'}
|
alt={file.original_name || 'Uploaded Proof'}
|
||||||
|
type="proof"
|
||||||
className="w-full h-auto max-h-[300px] object-cover transition-transform group-hover:scale-[1.01]"
|
className="w-full h-auto max-h-[300px] object-cover transition-transform group-hover:scale-[1.01]"
|
||||||
onError={(e) => {
|
|
||||||
(e.target as HTMLImageElement).style.display = 'none';
|
|
||||||
(e.target as HTMLImageElement).parentElement!.innerHTML = `<div class="p-6 text-center text-xs text-slate-400 font-mono">${file.original_name || 'Proof Image'}</div>`;
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<a href={previewUrl} target="_blank" rel="noopener noreferrer" className="absolute inset-0 z-10" aria-label="View Full Image" />
|
<a href={previewUrl} target="_blank" rel="noopener noreferrer" className="absolute inset-0 z-10" aria-label="View Full Image" />
|
||||||
</div>
|
</div>
|
||||||
@ -754,14 +796,15 @@ export function CallDetail({
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="rounded-xl border border-slate-200/80 bg-slate-50 p-6 flex flex-col items-center justify-center text-center gap-2">
|
<div className="rounded-xl border border-emerald-200 bg-[#E8FBF0] p-6 flex flex-col items-center justify-center text-center gap-2">
|
||||||
<Camera className="text-slate-400" size={24} />
|
<Camera className="text-emerald-500" size={24} />
|
||||||
<span className="text-xs font-semibold text-slate-500">No proof image uploaded</span>
|
<span className="text-xs font-semibold text-emerald-700">No proof image uploaded</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -772,21 +815,20 @@ export function CallDetail({
|
|||||||
<div className="bg-[var(--tiles-card-bg)] rounded-2xl border border-slate-200/80 overflow-hidden shadow-sm">
|
<div className="bg-[var(--tiles-card-bg)] rounded-2xl border border-slate-200/80 overflow-hidden shadow-sm">
|
||||||
{storeImages.length > 0 ? (
|
{storeImages.length > 0 ? (
|
||||||
<div className="relative w-full h-44 bg-slate-100 flex items-center justify-center overflow-hidden">
|
<div className="relative w-full h-44 bg-slate-100 flex items-center justify-center overflow-hidden">
|
||||||
<img
|
<SafeImage
|
||||||
src={`${orderBookingClient.baseUrl}/app/${APP_ID}/view/files/${storeImages[0].uuid}/preview`}
|
src={`${orderBookingClient.baseUrl}/app/${APP_ID}/view/files/${storeImages[0].uuid}/preview`}
|
||||||
alt="Store Front"
|
alt="Store Front"
|
||||||
|
type="store"
|
||||||
|
text={storeName}
|
||||||
className="w-full h-full object-cover"
|
className="w-full h-full object-cover"
|
||||||
onError={(e) => {
|
|
||||||
(e.target as HTMLImageElement).style.display = 'none';
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="h-40 bg-gradient-to-br from-slate-100 to-slate-200/70 p-6 flex flex-col items-center justify-center text-center gap-2 border-b border-slate-200/50">
|
<div className="h-40 bg-[#E8FBF0] p-6 flex flex-col items-center justify-center text-center gap-2 border-b border-emerald-200">
|
||||||
<div className="w-12 h-12 rounded-full bg-[var(--tiles-card-bg)] shadow-sm flex items-center justify-center text-slate-500">
|
<div className="w-12 h-12 rounded-full bg-[var(--tiles-card-bg)] shadow-sm flex items-center justify-center text-emerald-500">
|
||||||
<ImageIcon size={22} />
|
<ImageIcon size={22} />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-xs font-bold text-slate-600 uppercase tracking-wider">{storeName}</span>
|
<span className="text-xs font-bold text-emerald-700 uppercase tracking-wider">{storeName}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -845,9 +887,9 @@ export function CallDetail({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Notes Container */}
|
{/* Notes Container */}
|
||||||
<div className="bg-slate-50/80 border border-slate-200/80 rounded-xl p-3.5 space-y-1.5 text-xs">
|
<div className="bg-[#E8FBF0] border border-emerald-200 rounded-xl p-3.5 space-y-1.5 text-xs">
|
||||||
<div className="font-bold text-slate-600 flex items-center gap-1.5 text-[11px] uppercase tracking-wider">
|
<div className="font-bold text-emerald-600 flex items-center gap-1.5 text-[11px] uppercase tracking-wider">
|
||||||
<FileText size={12} /> NOTES
|
<FileText size={12} className="text-emerald-500" /> NOTES
|
||||||
</div>
|
</div>
|
||||||
<p className="text-slate-700 leading-relaxed font-medium">
|
<p className="text-slate-700 leading-relaxed font-medium">
|
||||||
{storeNotes}
|
{storeNotes}
|
||||||
|
|||||||
@ -284,12 +284,12 @@ export function DailyLogDetail({ instanceId, refreshKey, onPunchOut, onBack }: D
|
|||||||
<Map size={14} className="text-slate-500" /> Route Assignment
|
<Map size={14} className="text-slate-500" /> Route Assignment
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div className="border border-slate-100 rounded-xl p-4 bg-slate-50 flex flex-col justify-between">
|
<div className="border border-emerald-200 rounded-xl p-4 bg-[#E8FBF0] flex flex-col justify-between">
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-3">Route Code</div>
|
<div className="text-[10px] font-bold text-emerald-600 uppercase tracking-wider mb-3">Route Code</div>
|
||||||
<div className="text-lg font-bold text-slate-900">{String(routeCode)}</div>
|
<div className="text-lg font-bold text-slate-900">{String(routeCode)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="border border-slate-100 rounded-xl p-4 bg-slate-50 flex flex-col justify-between">
|
<div className="border border-emerald-200 rounded-xl p-4 bg-[#E8FBF0] flex flex-col justify-between">
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-3">Sub Route</div>
|
<div className="text-[10px] font-bold text-emerald-600 uppercase tracking-wider mb-3">Sub Route</div>
|
||||||
<div className="text-lg font-bold text-slate-900">{String(subRoute)}</div>
|
<div className="text-lg font-bold text-slate-900">{String(subRoute)}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -312,9 +312,9 @@ export function DailyLogDetail({ instanceId, refreshKey, onPunchOut, onBack }: D
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}) : (
|
}) : (
|
||||||
<div className="w-full h-32 rounded-lg bg-slate-50 border border-dashed border-slate-200 flex flex-col items-center justify-center text-slate-400">
|
<div className="w-full h-32 rounded-lg bg-[#E8FBF0] border border-emerald-200 flex flex-col items-center justify-center text-emerald-700">
|
||||||
<Camera size={24} className="mb-2 opacity-50" />
|
<Camera size={24} className="mb-2 text-emerald-500" />
|
||||||
<span className="text-xs">No image uploaded</span>
|
<span className="text-xs font-semibold">No image uploaded</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="text-[10px] text-slate-400 mt-2">Uploaded at punch in.</div>
|
<div className="text-[10px] text-slate-400 mt-2">Uploaded at punch in.</div>
|
||||||
@ -329,8 +329,8 @@ export function DailyLogDetail({ instanceId, refreshKey, onPunchOut, onBack }: D
|
|||||||
|
|
||||||
<div className="flex flex-col gap-5">
|
<div className="flex flex-col gap-5">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-8 h-8 rounded-full bg-slate-50 border border-slate-100 flex items-center justify-center shrink-0">
|
<div className="w-8 h-8 rounded-full bg-[#E8FBF0] border border-emerald-200 flex items-center justify-center shrink-0">
|
||||||
<User size={12} className="text-slate-500" />
|
<User size={12} className="text-emerald-500" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">Name</div>
|
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">Name</div>
|
||||||
@ -338,8 +338,8 @@ export function DailyLogDetail({ instanceId, refreshKey, onPunchOut, onBack }: D
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-8 h-8 rounded-full bg-slate-50 border border-slate-100 flex items-center justify-center shrink-0">
|
<div className="w-8 h-8 rounded-full bg-[#E8FBF0] border border-emerald-200 flex items-center justify-center shrink-0">
|
||||||
<Mail size={12} className="text-slate-500" />
|
<Mail size={12} className="text-emerald-500" />
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-hidden">
|
<div className="overflow-hidden">
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">Email</div>
|
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">Email</div>
|
||||||
@ -347,8 +347,8 @@ export function DailyLogDetail({ instanceId, refreshKey, onPunchOut, onBack }: D
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-8 h-8 rounded-full bg-slate-50 border border-slate-100 flex items-center justify-center shrink-0">
|
<div className="w-8 h-8 rounded-full bg-[#E8FBF0] border border-emerald-200 flex items-center justify-center shrink-0">
|
||||||
<Hash size={12} className="text-slate-500" />
|
<Hash size={12} className="text-emerald-500" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">User ID</div>
|
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">User ID</div>
|
||||||
|
|||||||
@ -127,9 +127,9 @@ export function OrderDetail({ instanceId }: WiredDetailViewProps) {
|
|||||||
<span className="flex items-center gap-1.5"><Hash size={14} /> Instance #{instanceId}</span>
|
<span className="flex items-center gap-1.5"><Hash size={14} /> Instance #{instanceId}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="border border-slate-100 bg-slate-50 rounded-xl p-4 flex flex-col gap-1 min-w-[200px]">
|
<div className="border border-emerald-200 bg-[#E8FBF0] rounded-xl p-4 flex flex-col gap-1 min-w-[200px]">
|
||||||
<div className="flex items-center gap-1.5 text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-1">
|
<div className="flex items-center gap-1.5 text-[10px] font-bold text-emerald-600 uppercase tracking-wider mb-1">
|
||||||
<Store size={12} /> Store
|
<Store size={12} className="text-emerald-500" /> Store
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm font-bold text-slate-900">{String(storeName)}</div>
|
<div className="text-sm font-bold text-slate-900">{String(storeName)}</div>
|
||||||
<div className="flex items-center gap-2 text-[10px] text-slate-500 mt-1">
|
<div className="flex items-center gap-2 text-[10px] text-slate-500 mt-1">
|
||||||
@ -157,7 +157,7 @@ export function OrderDetail({ instanceId }: WiredDetailViewProps) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="border border-slate-200 rounded-xl p-5 bg-[var(--tiles-card-bg)] shadow-sm flex flex-col justify-between">
|
<div className="border border-slate-200 rounded-xl p-5 bg-[var(--tiles-card-bg)] shadow-sm flex flex-col justify-between">
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-3">
|
<div className="flex items-center gap-2 text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-3">
|
||||||
<List size={14} className="text-slate-500" /> Line Items
|
<List size={14} className="text-slate-500" /> Order Items
|
||||||
</div>
|
</div>
|
||||||
<div className="text-2xl font-bold text-slate-900">{itemsArray.length}</div>
|
<div className="text-2xl font-bold text-slate-900">{itemsArray.length}</div>
|
||||||
</div>
|
</div>
|
||||||
@ -167,18 +167,18 @@ export function OrderDetail({ instanceId }: WiredDetailViewProps) {
|
|||||||
<div className="flex flex-col lg:flex-row gap-4">
|
<div className="flex flex-col lg:flex-row gap-4">
|
||||||
{/* Left Table */}
|
{/* Left Table */}
|
||||||
<div className="flex-[2] border border-slate-200 rounded-xl bg-[var(--tiles-card-bg)] shadow-sm overflow-hidden flex flex-col min-w-0">
|
<div className="flex-[2] border border-slate-200 rounded-xl bg-[var(--tiles-card-bg)] shadow-sm overflow-hidden flex flex-col min-w-0">
|
||||||
<div className="p-4 border-b border-slate-100 flex items-center gap-2 bg-slate-50">
|
<div className="p-4 border-b border-emerald-200 flex items-center gap-2 bg-[#E8FBF0]">
|
||||||
<Package size={14} className="text-slate-500" />
|
<Package size={14} className="text-emerald-500" />
|
||||||
<span className="text-xs font-bold text-slate-500 uppercase tracking-wider">Order Items</span>
|
<span className="text-xs font-bold text-emerald-600 uppercase tracking-wider">Order Items</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-x-auto flex-1">
|
<div className="overflow-x-auto flex-1">
|
||||||
<table className="w-full text-sm text-left">
|
<table className="w-full text-sm text-left">
|
||||||
<thead className="bg-slate-50/50 text-[10px] font-bold text-slate-400 uppercase tracking-wider">
|
<thead className="bg-[#E8FBF0]/50 text-[10px] font-bold text-slate-400 uppercase tracking-wider">
|
||||||
<tr>
|
<tr>
|
||||||
<th className="px-5 py-3 border-b border-slate-100">Product</th>
|
<th className="px-5 py-3 border-b border-emerald-200">Product</th>
|
||||||
<th className="px-5 py-3 border-b border-slate-100">Category</th>
|
<th className="px-5 py-3 border-b border-emerald-200">Category</th>
|
||||||
<th className="px-5 py-3 border-b border-slate-100">SKU</th>
|
<th className="px-5 py-3 border-b border-emerald-200">SKU</th>
|
||||||
<th className="px-5 py-3 border-b border-slate-100 text-right">Bags</th>
|
<th className="px-5 py-3 border-b border-emerald-200 text-right">Bags</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="divide-y divide-slate-100">
|
<tbody className="divide-y divide-slate-100">
|
||||||
@ -191,7 +191,7 @@ export function OrderDetail({ instanceId }: WiredDetailViewProps) {
|
|||||||
const weight = item.sku_3 ? `${item.sku_3} kg` : '-';
|
const weight = item.sku_3 ? `${item.sku_3} kg` : '-';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr key={idx} className="hover:bg-slate-50/50 transition-colors">
|
<tr key={idx} className="hover:bg-[#E8FBF0]/50 transition-colors">
|
||||||
<td className="px-5 py-3">
|
<td className="px-5 py-3">
|
||||||
<div className="font-bold text-slate-900 text-xs mb-0.5 whitespace-nowrap">{String(product)}</div>
|
<div className="font-bold text-slate-900 text-xs mb-0.5 whitespace-nowrap">{String(product)}</div>
|
||||||
<div className="text-[10px] text-slate-500">BR Code {String(brCode)}</div>
|
<div className="text-[10px] text-slate-500">BR Code {String(brCode)}</div>
|
||||||
@ -205,7 +205,7 @@ export function OrderDetail({ instanceId }: WiredDetailViewProps) {
|
|||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<tr className="bg-slate-50 font-bold">
|
<tr className="bg-[#E8FBF0] font-bold">
|
||||||
<td colSpan={3} className="px-5 py-3 text-slate-900 text-xs">Total</td>
|
<td colSpan={3} className="px-5 py-3 text-slate-900 text-xs">Total</td>
|
||||||
<td className="px-5 py-3 text-right text-slate-900 text-xs">{String(totalBags)}</td>
|
<td className="px-5 py-3 text-right text-slate-900 text-xs">{String(totalBags)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -232,8 +232,8 @@ export function OrderDetail({ instanceId }: WiredDetailViewProps) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-8 h-8 rounded-full bg-slate-50 border border-slate-100 flex items-center justify-center shrink-0">
|
<div className="w-8 h-8 rounded-full bg-[#E8FBF0] border border-emerald-200 flex items-center justify-center shrink-0">
|
||||||
<Mail size={12} className="text-slate-500" />
|
<Mail size={12} className="text-emerald-500" />
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-hidden">
|
<div className="overflow-hidden">
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">Email</div>
|
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">Email</div>
|
||||||
@ -241,8 +241,8 @@ export function OrderDetail({ instanceId }: WiredDetailViewProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-8 h-8 rounded-full bg-slate-50 border border-slate-100 flex items-center justify-center shrink-0">
|
<div className="w-8 h-8 rounded-full bg-[#E8FBF0] border border-emerald-200 flex items-center justify-center shrink-0">
|
||||||
<Hash size={12} className="text-slate-500" />
|
<Hash size={12} className="text-emerald-500" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">User ID</div>
|
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-0.5">User ID</div>
|
||||||
|
|||||||
@ -301,16 +301,16 @@ export function StoreDetail({ instanceId, onBack, onEdit }: StoreDetailProps) {
|
|||||||
<h3 className="text-xs font-bold text-slate-500 uppercase tracking-wider m-0">Route Assignment</h3>
|
<h3 className="text-xs font-bold text-slate-500 uppercase tracking-wider m-0">Route Assignment</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-5 grid grid-cols-1 sm:grid-cols-3 gap-4 bg-[var(--tiles-card-bg)]">
|
<div className="p-5 grid grid-cols-1 sm:grid-cols-3 gap-4 bg-[var(--tiles-card-bg)]">
|
||||||
<div className="p-4 rounded-xl border border-slate-100 bg-slate-50">
|
<div className="p-4 rounded-xl border border-emerald-100 bg-emerald-50">
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-1">Route</div>
|
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-1">Route</div>
|
||||||
<div className="text-base font-bold text-slate-900">{routeName ? String(routeName) : '-'}</div>
|
<div className="text-base font-bold text-slate-900">{routeName ? String(routeName) : '-'}</div>
|
||||||
<div className="text-xs text-slate-500 mt-1">Code {routeCode ? String(routeCode) : '-'}</div>
|
<div className="text-xs text-slate-500 mt-1">Code {routeCode ? String(routeCode) : '-'}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-4 rounded-xl border border-slate-100 bg-slate-50">
|
<div className="p-4 rounded-xl border border-emerald-100 bg-emerald-50">
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-1">Sub Route</div>
|
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-1">Sub Route</div>
|
||||||
<div className="text-base font-bold text-slate-900">{subRoute ? String(subRoute) : '-'}</div>
|
<div className="text-base font-bold text-slate-900">{subRoute ? String(subRoute) : '-'}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-4 rounded-xl border border-slate-100 bg-slate-50">
|
<div className="p-4 rounded-xl border border-emerald-100 bg-emerald-50">
|
||||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-1">Area</div>
|
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-1">Area</div>
|
||||||
<div className="text-base font-bold text-slate-900">{area ? String(area) : '-'}</div>
|
<div className="text-base font-bold text-slate-900">{area ? String(area) : '-'}</div>
|
||||||
<div className="text-xs text-slate-500 mt-1">PIN {pinCode ? String(pinCode) : '-'}</div>
|
<div className="text-xs text-slate-500 mt-1">PIN {pinCode ? String(pinCode) : '-'}</div>
|
||||||
@ -360,7 +360,7 @@ export function StoreDetail({ instanceId, onBack, onEdit }: StoreDetailProps) {
|
|||||||
<h3 className="text-xs font-bold text-slate-500 uppercase tracking-wider m-0">Distributor</h3>
|
<h3 className="text-xs font-bold text-slate-500 uppercase tracking-wider m-0">Distributor</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-5 bg-[var(--tiles-card-bg)]">
|
<div className="p-5 bg-[var(--tiles-card-bg)]">
|
||||||
<div className="p-4 rounded-xl border border-slate-100 bg-slate-50">
|
<div className="p-4 rounded-xl border border-emerald-100 bg-emerald-50">
|
||||||
<div className="text-sm font-bold text-slate-900 mb-1">{distributorName ? String(distributorName) : '-'}</div>
|
<div className="text-sm font-bold text-slate-900 mb-1">{distributorName ? String(distributorName) : '-'}</div>
|
||||||
<div className="text-xs text-slate-500 mb-4">Owner · {distributorOwnerName ? String(distributorOwnerName) : '-'}</div>
|
<div className="text-xs text-slate-500 mb-4">Owner · {distributorOwnerName ? String(distributorOwnerName) : '-'}</div>
|
||||||
|
|
||||||
|
|||||||
@ -36,18 +36,18 @@ export function LoginPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen flex items-center justify-center p-4 bg-app">
|
<div className="min-h-screen flex items-center justify-center p-4 bg-[#E8FBF0]">
|
||||||
<Card className="w-full max-w-[400px]">
|
<Card className="w-full max-w-[400px]">
|
||||||
<div className="flex flex-col gap-1 mb-6 items-center text-center">
|
<div className="flex flex-col gap-1 mb-6 items-center text-center">
|
||||||
<img src={logo} alt="Logo" className="h-20 w-auto object-contain mb-2" />
|
<img src={logo} alt="Logo" className="h-20 w-auto object-contain mb-2" />
|
||||||
<h1 className="m-0 text-2xl font-extrabold text-strong tracking-[-0.02em]">Krishna Sales</h1>
|
<h1 className="m-0 text-2xl font-extrabold text-strong tracking-[-0.02em]">Krishna Sales</h1>
|
||||||
</div>
|
</div>
|
||||||
<form onSubmit={submit} className="flex flex-col gap-4">
|
<form onSubmit={submit} className="flex flex-col gap-4">
|
||||||
<Input label="Email" type="email" value={email} onChange={(e) => setEmail(e.target.value)} required autoFocus />
|
<Input label="Email" type="email" value={email} onChange={(e) => setEmail(e.target.value)} required autoFocus className="[&>div]:rounded-full [&>div:focus-within]:!border-emerald-500 [&>div:focus-within]:!shadow-[0_0_0_3px_rgba(16,185,129,0.3)]" />
|
||||||
<Input label="Password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} required />
|
<Input label="Password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} required className="[&>div]:rounded-full [&>div:focus-within]:!border-emerald-500 [&>div:focus-within]:!shadow-[0_0_0_3px_rgba(16,185,129,0.3)]" />
|
||||||
|
|
||||||
{error && <div className="text-xs text-ruby-600 font-medium">{error}</div>}
|
{error && <div className="text-xs text-ruby-600 font-medium">{error}</div>}
|
||||||
<Button type="submit" full disabled={busy}>
|
<Button type="submit" full disabled={busy} className="rounded-full bg-emerald-600 hover:bg-emerald-700 text-white border-transparent">
|
||||||
{busy ? 'Signing in…' : 'Sign in'}
|
{busy ? 'Signing in…' : 'Sign in'}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user