feat: add order views for rescheduling pickups, handover manifests, and damage reporting
This commit is contained in:
parent
00c82b2740
commit
74e44c034e
5 changed files with 1144 additions and 173 deletions
233
src/components/orders/HandoverManifestView.tsx
Normal file
233
src/components/orders/HandoverManifestView.tsx
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
import React, { useState } from 'react';
|
||||
import {
|
||||
ChevronRight,
|
||||
PackageCheck,
|
||||
CheckCircle2,
|
||||
Truck,
|
||||
Calendar,
|
||||
Check,
|
||||
CheckCheck
|
||||
} from 'lucide-react';
|
||||
|
||||
interface HandoverManifestViewProps {
|
||||
onBack: () => void;
|
||||
onTabChange: (tab: string) => void;
|
||||
}
|
||||
|
||||
export const HandoverManifestView: React.FC<HandoverManifestViewProps> = ({ onBack, onTabChange }) => {
|
||||
const [allSelected, setAllSelected] = useState(true);
|
||||
const [isConfirming, setIsConfirming] = useState(false);
|
||||
const [isConfirmed, setIsConfirmed] = useState(false);
|
||||
|
||||
const mockPackages = [
|
||||
{ awb: 'DLV-88491024-IN', item: 'Jaipur Cobalt Ceramic Plates (Set of 4)', orderId: 'TRD-9031', dest: 'Bengaluru, Karnataka', pin: '560001', weight: '2.4 kg' },
|
||||
{ awb: 'DLV-88491025-IN', item: 'Bidriware Silver Inlay Fluted Vase', orderId: 'TRD-9038', dest: 'New Delhi, Delhi', pin: '110001', weight: '1.8 kg' },
|
||||
{ awb: 'DLV-88491026-IN', item: 'Banarasi Katan Silk Saree (Heirloom)', orderId: 'TRD-9042', dest: 'Mumbai, Maharashtra', pin: '400050', weight: '0.9 kg' },
|
||||
{ awb: 'DLV-88491027-IN', item: 'Gorakhpur Terracotta Planters (Pair)', orderId: 'TRD-9049', dest: 'Hyderabad, Telangana', pin: '500034', weight: '4.6 kg' },
|
||||
{ awb: 'DLV-88491028-IN', item: 'Saharanpur Sheesham Carved Bowls (Trio)', orderId: 'TRD-9055', dest: 'Chennai, Tamil Nadu', pin: '600028', weight: '1.7 kg' },
|
||||
];
|
||||
|
||||
const handleConfirm = () => {
|
||||
setIsConfirming(true);
|
||||
setTimeout(() => {
|
||||
setIsConfirming(false);
|
||||
setIsConfirmed(true);
|
||||
}, 1200);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="handover-manifest-view" style={{ maxWidth: '1400px', margin: '0 auto', animation: 'fadeIn 0.2s ease-in-out' }}>
|
||||
{/* Breadcrumb & Top Bar */}
|
||||
<div className="is-flex flex-direction-column sm-flex-row sm-items-center justify-content-between gap-4 pb-5 mb-5" style={{ borderBottom: '1px solid rgba(220, 192, 193, 0.6)' }}>
|
||||
<div className="is-flex flex-direction-column gap-2">
|
||||
<div className="is-flex is-align-items-center gap-2 has-text-weight-semibold is-size-7">
|
||||
<a onClick={onBack} className="has-text-grey hover-text-primary transition-colors">Orders & Dispatch</a>
|
||||
<ChevronRight size={16} className="has-text-grey-light" />
|
||||
<span style={{ color: '#5a0118', fontWeight: 600 }}>Manifest #TRD-2025-MNF-0841</span>
|
||||
</div>
|
||||
<h1 className="title is-size-3 mb-0" style={{ fontWeight: 700, letterSpacing: '-0.02em', color: '#1c1b1b' }}>3PL Courier Handover Manifest</h1>
|
||||
<div className="is-flex is-align-items-center gap-3 is-size-7 mt-1 has-text-grey">
|
||||
<span style={{ color: '#5a0118', fontWeight: 600 }}>Delhivery Express</span>
|
||||
<span style={{ color: '#897172' }}>•</span>
|
||||
<span>Today, Oct 24 • Window: 2:30 PM – 3:30 PM</span>
|
||||
<span style={{ color: '#897172' }}>•</span>
|
||||
<span>Surface & Air Sweep</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Header Tabs */}
|
||||
<div className="is-flex is-align-items-center gap-2 mb-6 overflow-x-auto pb-1">
|
||||
<button onClick={() => onTabChange('overall')} className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 500 }}>
|
||||
<PackageCheck size={16} className="mr-2" />
|
||||
Overall
|
||||
</button>
|
||||
<button onClick={() => onTabChange('ready_for_pickup')} className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 500 }}>
|
||||
Ready for pickup
|
||||
</button>
|
||||
<button className="button is-rounded is-trad-primary is-small px-4" style={{ fontWeight: 600, backgroundColor: '#791b2c', color: '#ffffff' }}>
|
||||
Handover
|
||||
</button>
|
||||
<button className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 500 }}>
|
||||
Reschedule
|
||||
</button>
|
||||
<button className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 500 }}>
|
||||
Report transit damage
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Manifest Summary Bento Cards */}
|
||||
<div className="columns is-variable is-4 mb-6">
|
||||
<div className="column is-4">
|
||||
<div className="card p-5 h-100 is-flex flex-direction-column justify-content-between" style={{ borderRadius: '16px', border: '1px solid rgba(220, 192, 193, 0.4)', boxShadow: '0 1px 3px rgba(0,0,0,0.02)' }}>
|
||||
<span className="is-size-7 has-text-weight-bold has-text-grey is-uppercase" style={{ letterSpacing: '0.04em' }}>Total Parcels</span>
|
||||
<div className="mt-4">
|
||||
<div className="is-size-2 has-text-weight-bold" style={{ color: '#1c1b1b', lineHeight: 1 }}>14</div>
|
||||
<div className="is-size-7 has-text-grey mt-2">All packed & labeled</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="column is-4">
|
||||
<div className="card p-5 h-100 is-flex flex-direction-column justify-content-between" style={{ borderRadius: '16px', border: '1px solid rgba(220, 192, 193, 0.4)', boxShadow: '0 1px 3px rgba(0,0,0,0.02)' }}>
|
||||
<span className="is-size-7 has-text-weight-bold has-text-grey is-uppercase" style={{ letterSpacing: '0.04em' }}>Combined Weight</span>
|
||||
<div className="mt-4">
|
||||
<div className="is-size-2 has-text-weight-bold" style={{ color: '#1c1b1b', lineHeight: 1 }}>
|
||||
18.2 <span className="is-size-4 has-text-weight-medium has-text-grey">kg</span>
|
||||
</div>
|
||||
<div className="is-size-7 has-text-grey mt-2">Volumetric verified</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="column is-4">
|
||||
<div className="card p-5 h-100 is-flex flex-direction-column justify-content-between" style={{ borderRadius: '16px', border: '1px solid rgba(220, 192, 193, 0.4)', boxShadow: '0 1px 3px rgba(0,0,0,0.02)' }}>
|
||||
<span className="is-size-7 has-text-weight-bold has-text-grey is-uppercase" style={{ letterSpacing: '0.04em' }}>Assigned Carrier</span>
|
||||
<div className="mt-4">
|
||||
<div className="is-size-4 has-text-weight-bold" style={{ color: '#5a0118', lineHeight: 1.2 }}>Delhivery Express</div>
|
||||
<div className="is-size-7 has-text-grey mt-2">Priority Pickup Hub #IND-45</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Manifest Table Card */}
|
||||
<div className="card mb-6" style={{ borderRadius: '16px', border: '1px solid rgba(220, 192, 193, 0.4)', boxShadow: '0 1px 3px rgba(0,0,0,0.02)', overflow: 'hidden' }}>
|
||||
<div className="p-4 is-flex flex-direction-column sm-flex-row sm-items-center justify-content-between gap-3" style={{ backgroundColor: '#f6f3f2' }}>
|
||||
<div className="is-flex is-align-items-center gap-3">
|
||||
<h2 className="title is-size-5 mb-0" style={{ fontWeight: 700, color: '#1c1b1b' }}>Package List</h2>
|
||||
<span className="tag is-rounded" style={{ backgroundColor: '#e5e2e1', color: '#564243', fontWeight: 500 }}>14 items</span>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center gap-4 is-size-7 has-text-grey">
|
||||
<span>Mark items verified upon physical sweep</span>
|
||||
<button onClick={() => setAllSelected(!allSelected)} className="button is-ghost is-small has-text-weight-bold" style={{ color: '#5a0118', padding: 0 }}>
|
||||
{allSelected ? 'Deselect All' : 'Select All (14)'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="table-container mb-0">
|
||||
<table className="table is-fullwidth is-hoverable trad-table">
|
||||
<thead>
|
||||
<tr style={{ backgroundColor: 'rgba(246, 243, 242, 0.4)', borderBottom: '1px solid rgba(220, 192, 193, 0.4)' }}>
|
||||
<th className="has-text-centered" style={{ width: '50px' }}>
|
||||
<input type="checkbox" checked={allSelected} onChange={() => setAllSelected(!allSelected)} style={{ width: '16px', height: '16px', accentColor: '#5a0118', cursor: 'pointer' }} />
|
||||
</th>
|
||||
<th className="has-text-grey is-size-7" style={{ textTransform: 'uppercase', letterSpacing: '0.04em' }}>AWB Number</th>
|
||||
<th className="has-text-grey is-size-7" style={{ textTransform: 'uppercase', letterSpacing: '0.04em' }}>Craft Item</th>
|
||||
<th className="has-text-grey is-size-7" style={{ textTransform: 'uppercase', letterSpacing: '0.04em' }}>Destination</th>
|
||||
<th className="has-text-grey is-size-7" style={{ textTransform: 'uppercase', letterSpacing: '0.04em' }}>Weight</th>
|
||||
<th className="has-text-grey is-size-7 has-text-centered" style={{ textTransform: 'uppercase', letterSpacing: '0.04em' }}>Driver Check</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{mockPackages.map((pkg, idx) => (
|
||||
<tr key={idx} style={{ borderBottom: '1px solid rgba(220, 192, 193, 0.3)' }}>
|
||||
<td className="is-vcentered has-text-centered">
|
||||
<input type="checkbox" checked={allSelected} readOnly style={{ width: '16px', height: '16px', accentColor: '#5a0118', cursor: 'pointer' }} />
|
||||
</td>
|
||||
<td className="is-vcentered">
|
||||
<div className="has-text-weight-bold is-size-7" style={{ color: '#5a0118' }}>{pkg.awb}</div>
|
||||
</td>
|
||||
<td className="is-vcentered">
|
||||
<div className="has-text-weight-semibold is-size-7" style={{ color: '#1c1b1b' }}>{pkg.item}</div>
|
||||
<div className="is-size-7 has-text-grey mt-1">Order #{pkg.orderId}</div>
|
||||
</td>
|
||||
<td className="is-vcentered">
|
||||
<div className="has-text-weight-medium is-size-7" style={{ color: '#1c1b1b' }}>{pkg.dest}</div>
|
||||
<div className="is-size-7 has-text-grey mt-1">{pkg.pin}</div>
|
||||
</td>
|
||||
<td className="is-vcentered">
|
||||
<div className="has-text-weight-medium is-size-7" style={{ color: '#1c1b1b' }}>{pkg.weight}</div>
|
||||
</td>
|
||||
<td className="is-vcentered has-text-centered">
|
||||
<div className="is-flex is-align-items-center is-justify-content-center has-text-weight-semibold is-size-7" style={{ color: '#003112' }}>
|
||||
<CheckCircle2 size={16} className="mr-1" /> Verified
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="p-4 is-flex is-align-items-center justify-content-between is-size-7 has-text-grey" style={{ backgroundColor: 'rgba(246, 243, 242, 0.4)', borderTop: '1px solid rgba(220, 192, 193, 0.4)' }}>
|
||||
<span>Showing 5 of 14 verified packages. Batch validated for courier pickup.</span>
|
||||
<span className="has-text-weight-medium" style={{ color: '#1c1b1b' }}>All 14 parcels scanned</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Primary Confirmation Footer & Floating Action */}
|
||||
<div className="card p-5 mb-5 is-flex flex-direction-column sm-flex-row sm-items-center justify-content-between gap-4" style={{ borderRadius: '16px', border: '1px solid rgba(220, 192, 193, 0.4)', boxShadow: '0 1px 3px rgba(0,0,0,0.02)' }}>
|
||||
<div className="is-flex is-align-items-center gap-3">
|
||||
<div className="is-flex is-align-items-center is-justify-content-center flex-shrink-0" style={{ width: '36px', height: '36px', borderRadius: '50%', backgroundColor: '#f6f3f2', color: '#5a0118' }}>
|
||||
<CheckCheck size={20} />
|
||||
</div>
|
||||
<div>
|
||||
<div className="has-text-weight-bold is-size-6" style={{ color: '#1c1b1b' }}>Ready for Dispatch</div>
|
||||
<div className="is-size-7 has-text-grey mt-1">Both signatures recorded. Completing handover sends instant delivery updates.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center gap-3" style={{ width: '100%', maxWidth: '400px' }}>
|
||||
<button className="button is-rounded is-light is-fullwidth" style={{ height: '44px', fontWeight: 600, backgroundColor: '#f6f3f2', color: '#1c1b1b' }}>
|
||||
Report Discrepancy
|
||||
</button>
|
||||
<button
|
||||
onClick={handleConfirm}
|
||||
disabled={isConfirming || isConfirmed}
|
||||
className={`button is-rounded is-fullwidth ${isConfirmed ? 'is-success' : 'is-trad-primary'}`}
|
||||
style={{ height: '44px', fontWeight: 700, backgroundColor: isConfirmed ? '#003112' : '#5a0118', color: '#ffffff', transition: 'all 0.3s ease' }}
|
||||
>
|
||||
{isConfirming ? (
|
||||
<span className="loader" style={{ width: '1em', height: '1em', borderWidth: '2px', marginRight: '8px' }}></span>
|
||||
) : isConfirmed ? (
|
||||
<CheckCircle2 size={18} className="mr-2" />
|
||||
) : (
|
||||
<Check size={18} className="mr-2" />
|
||||
)}
|
||||
{isConfirming ? 'Registering...' : isConfirmed ? 'Handover Complete!' : 'Confirm Handover'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>{`
|
||||
.justify-content-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.flex-direction-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
@media (min-width: 769px) {
|
||||
.sm-flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
.sm-items-center {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -3,13 +3,19 @@ import { OrderItem } from '../../types/seller';
|
|||
import {
|
||||
ChevronRight,
|
||||
Printer,
|
||||
Calendar,
|
||||
Truck,
|
||||
CheckCircle2,
|
||||
Check,
|
||||
Award,
|
||||
PackageCheck,
|
||||
Gift
|
||||
Gift,
|
||||
Grid,
|
||||
RefreshCw,
|
||||
Clock,
|
||||
AlertTriangle,
|
||||
Star,
|
||||
MapPin,
|
||||
Box,
|
||||
Bike,
|
||||
Truck
|
||||
} from 'lucide-react';
|
||||
|
||||
interface OrderDetailViewProps {
|
||||
|
|
@ -17,116 +23,115 @@ interface OrderDetailViewProps {
|
|||
onBack: () => void;
|
||||
onPrintLabel: (order: OrderItem) => void;
|
||||
onReschedule: (order: OrderItem) => void;
|
||||
onTabChange?: (tab: string) => void;
|
||||
}
|
||||
|
||||
export const OrderDetailView: React.FC<OrderDetailViewProps> = ({ order, onBack, onPrintLabel, onReschedule }) => {
|
||||
export const OrderDetailView: React.FC<OrderDetailViewProps> = ({ order, onBack, onPrintLabel, onReschedule, onTabChange }) => {
|
||||
return (
|
||||
<div className="order-detail-view" style={{ maxWidth: '1400px', margin: '0 auto', animation: 'fadeIn 0.2s ease-in-out' }}>
|
||||
|
||||
{/* Top Navigation & Breadcrumbs */}
|
||||
<div className="is-flex is-align-items-center is-justify-content-space-between mb-5 pb-4" style={{ borderBottom: '1px solid rgba(220, 192, 193, 0.6)' }}>
|
||||
<div className="is-flex is-align-items-center gap-2 has-text-weight-semibold is-size-7">
|
||||
<a onClick={onBack} className="has-text-grey hover-text-primary transition-colors">Orders</a>
|
||||
<ChevronRight size={16} className="has-text-grey-light" />
|
||||
<span style={{ color: '#1c1b1b', fontWeight: 600 }}>Order {order.orderNumber}</span>
|
||||
<div className="is-flex is-flex-wrap-wrap is-align-items-center justify-content-between gap-4 py-4 mb-6" style={{ borderBottom: '1px solid rgba(220, 192, 193, 0.6)' }}>
|
||||
<div className="is-flex is-align-items-center gap-2 has-text-weight-medium is-size-7" style={{ color: '#564243' }}>
|
||||
<a onClick={onBack} className="hover-text-primary transition-colors cursor-pointer">Orders</a>
|
||||
<ChevronRight size={16} style={{ color: '#897172' }} />
|
||||
<span className="has-text-weight-semibold" style={{ color: '#1c1b1b' }}>Order #{order.orderNumber}</span>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center gap-3">
|
||||
<span className="tag is-rounded is-light has-text-weight-semibold is-flex is-align-items-center gap-2" style={{ backgroundColor: '#f6f3f2', color: '#564243', padding: '0.4rem 0.8rem' }}>
|
||||
<span style={{ width: '6px', height: '6px', borderRadius: '50%', backgroundColor: '#9d4225' }}></span>
|
||||
<span className="is-inline-flex is-align-items-center gap-2 px-3 py-1 is-size-7 has-text-weight-medium" style={{ borderRadius: '9999px', backgroundColor: '#f6f3f2', color: '#564243' }}>
|
||||
<span style={{ width: '8px', height: '8px', borderRadius: '50%', backgroundColor: '#9d4225' }}></span>
|
||||
{order.courierPartner || 'Delhivery Priority Air'}
|
||||
</span>
|
||||
<span className="has-text-grey is-family-monospace has-text-weight-medium is-size-7">AWB: {order.awbNumber}</span>
|
||||
<span className="is-family-monospace has-text-weight-medium is-size-7" style={{ color: '#897172' }}>AWB: {order.awbNumber}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Header Tabs */}
|
||||
<div className="is-flex is-align-items-center gap-2 mb-5 overflow-x-auto pb-1">
|
||||
<button className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 500 }}>
|
||||
<PackageCheck size={16} className="mr-2" />
|
||||
Overall
|
||||
<div className="is-flex is-align-items-center gap-2 mb-6 overflow-x-auto pb-1">
|
||||
<button onClick={() => onTabChange?.('overall')} className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<Grid size={16} className="mr-2" /> Overall
|
||||
</button>
|
||||
<button className="button is-rounded is-trad-primary is-small px-4" style={{ fontWeight: 600, backgroundColor: '#791b2c', color: '#ffffff' }}>
|
||||
<CheckCircle2 size={16} className="mr-2" />
|
||||
Ready for pickup
|
||||
<button className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<Package size={16} className="mr-2" /> Ready for pickup
|
||||
</button>
|
||||
<button className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 500 }}>
|
||||
<Truck size={16} className="mr-2" />
|
||||
Handover
|
||||
<button onClick={() => onTabChange?.('handover')} className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<RefreshCw size={16} className="mr-2" /> Handover
|
||||
</button>
|
||||
<button className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 500 }}>
|
||||
<Calendar size={16} className="mr-2" />
|
||||
Reschedule
|
||||
<button onClick={() => onReschedule(order)} className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<Clock size={16} className="mr-2" /> Reschedule
|
||||
</button>
|
||||
<button onClick={() => onTabChange?.('report_damage')} className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<AlertTriangle size={16} className="mr-2" /> Report transit damage
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Header Hero Card */}
|
||||
<div className="card p-5 mb-5 is-flex flex-col md-flex-row is-align-items-center is-justify-content-space-between gap-5" style={{ borderRadius: '16px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
|
||||
<div className="card p-6 mb-6 is-flex flex-direction-column md-flex-row is-align-items-flex-start md-items-center justify-content-between gap-6 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(220, 192, 193, 0.4)' }}>
|
||||
<div className="is-flex is-flex-direction-column gap-2">
|
||||
<div className="is-flex is-align-items-center gap-3 is-flex-wrap-wrap">
|
||||
<h1 className="title is-size-3 mb-0" style={{ fontWeight: 700, letterSpacing: '-0.02em', color: '#1c1b1b' }}>Order {order.orderNumber}</h1>
|
||||
<span className="tag is-rounded has-text-weight-bold" style={{ backgroundColor: '#95f8a7', color: '#00210a' }}>
|
||||
<CheckCircle2 size={15} className="mr-1" />
|
||||
Ready for Pickup
|
||||
<span className="is-inline-flex is-align-items-center gap-2 px-3 py-1 has-text-weight-bold is-size-7" style={{ borderRadius: '9999px', backgroundColor: '#95f8a7', color: '#00210a' }}>
|
||||
<CheckCircle2 size={15} /> Ready for Pickup
|
||||
</span>
|
||||
<span className="tag is-rounded is-light" style={{ backgroundColor: '#f0eded', color: '#564243', fontSize: '0.75rem' }}>B2C Retail</span>
|
||||
<span className="px-3 py-1 is-size-7" style={{ borderRadius: '9999px', backgroundColor: '#e5e2e1', color: '#564243' }}>B2C Retail</span>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center gap-3 is-size-7 mt-1 has-text-grey">
|
||||
<div className="is-flex is-align-items-center gap-3 is-size-7 mt-1 is-flex-wrap-wrap" style={{ color: '#564243' }}>
|
||||
<span>Placed yesterday at 4:15 PM</span>
|
||||
<span style={{ width: '4px', height: '4px', borderRadius: '50%', backgroundColor: '#897172' }}></span>
|
||||
<span style={{ color: '#9d4225', fontWeight: 600 }}>Courier pickup window: {order.pickupSlot || 'Today, 2:30 – 3:30 PM'}</span>
|
||||
<span className="has-text-weight-semibold" style={{ color: '#9d4225' }}>Courier pickup window: {order.pickupSlot || 'Today, 2:30 – 3:30 PM'}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center gap-3 is-flex-wrap-wrap">
|
||||
<button onClick={() => onReschedule(order)} className="button is-rounded is-light" style={{ height: '44px', padding: '0 1.25rem', fontWeight: 600, backgroundColor: '#f6f3f2', color: '#1c1b1b' }}>
|
||||
<button onClick={() => onReschedule(order)} className="button is-rounded" style={{ height: '44px', padding: '0 1.25rem', fontWeight: 600, backgroundColor: '#f6f3f2', color: '#1c1b1b', border: 'none', transition: 'all 0.2s' }}>
|
||||
Reschedule Courier
|
||||
</button>
|
||||
<button onClick={() => onPrintLabel(order)} className="button is-rounded is-trad-primary" style={{ height: '44px', padding: '0 1.5rem', fontWeight: 600, backgroundColor: '#5a0118' }}>
|
||||
<Printer size={18} className="mr-2" />
|
||||
Print Shipping Label
|
||||
<button onClick={() => onPrintLabel(order)} className="button is-rounded is-flex is-align-items-center gap-2 shadow-sm" style={{ height: '44px', padding: '0 1.5rem', fontWeight: 600, backgroundColor: '#5a0118', color: '#ffffff', border: 'none', transition: 'all 0.2s' }}>
|
||||
<Printer size={18} /> Print Shipping Label
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Minimal 3-Step Timeline */}
|
||||
<div className="card p-5 mb-5" style={{ borderRadius: '16px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
|
||||
<div className="columns is-variable is-3">
|
||||
<div className="card p-6 mb-6 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(220, 192, 193, 0.4)' }}>
|
||||
<div className="columns is-variable is-4 relative">
|
||||
<div className="column is-4">
|
||||
<div className="p-4 is-flex is-align-items-flex-start gap-3" style={{ borderRadius: '16px', backgroundColor: 'rgba(246, 243, 242, 0.6)' }}>
|
||||
<div className="is-flex is-align-items-flex-start gap-4 p-4" style={{ borderRadius: '16px', backgroundColor: 'rgba(246, 243, 242, 0.6)' }}>
|
||||
<div className="is-flex is-align-items-center is-justify-content-center flex-shrink-0" style={{ width: '36px', height: '36px', borderRadius: '50%', backgroundColor: '#003112', color: '#ffffff' }}>
|
||||
<Check size={18} />
|
||||
</div>
|
||||
<div>
|
||||
<div className="has-text-weight-bold is-size-6" style={{ color: '#1c1b1b' }}>1. Order Placed</div>
|
||||
<div className="is-size-7 has-text-grey mt-1">Yesterday, 4:15 PM</div>
|
||||
<div className="is-size-7 mt-2 has-text-weight-semibold is-flex is-align-items-center" style={{ color: '#003112' }}>
|
||||
<CheckCircle2 size={14} className="mr-2" /> Payment in Escrow
|
||||
<div className="is-size-7 mt-1" style={{ color: '#564243' }}>Yesterday, 4:15 PM</div>
|
||||
<div className="is-flex is-align-items-center gap-1 has-text-weight-semibold mt-2" style={{ color: '#003112', fontSize: '11px' }}>
|
||||
<Award size={13} /> Payment in Escrow
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="column is-4">
|
||||
<div className="p-4 is-flex is-align-items-flex-start gap-3" style={{ borderRadius: '16px', backgroundColor: 'rgba(246, 243, 242, 0.6)' }}>
|
||||
<div className="is-flex is-align-items-flex-start gap-4 p-4" style={{ borderRadius: '16px', backgroundColor: 'rgba(246, 243, 242, 0.6)' }}>
|
||||
<div className="is-flex is-align-items-center is-justify-content-center flex-shrink-0" style={{ width: '36px', height: '36px', borderRadius: '50%', backgroundColor: '#003112', color: '#ffffff' }}>
|
||||
<Check size={18} />
|
||||
</div>
|
||||
<div>
|
||||
<div className="has-text-weight-bold is-size-6" style={{ color: '#1c1b1b' }}>2. Packed & Verified</div>
|
||||
<div className="is-size-7 has-text-grey mt-1">Today, 1:10 PM</div>
|
||||
<div className="is-size-7 mt-2 has-text-weight-semibold is-flex is-align-items-center" style={{ color: '#003112' }}>
|
||||
<PackageCheck size={14} className="mr-2" /> Box Barcode #90814
|
||||
<div className="is-size-7 mt-1" style={{ color: '#564243' }}>Today, 1:10 PM</div>
|
||||
<div className="is-flex is-align-items-center gap-1 has-text-weight-semibold mt-2" style={{ color: '#003112', fontSize: '11px' }}>
|
||||
<Box size={13} /> Box Barcode #90814
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="column is-4">
|
||||
<div className="p-4 is-flex is-align-items-flex-start gap-3" style={{ borderRadius: '16px', backgroundColor: '#ffdadb', color: '#40000e' }}>
|
||||
<div className="is-flex is-align-items-center is-justify-content-center flex-shrink-0 heartbeat" style={{ width: '36px', height: '36px', borderRadius: '50%', backgroundColor: '#5a0118', color: '#ffffff' }}>
|
||||
<div className="is-flex is-align-items-flex-start gap-4 p-4 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffdadb', color: '#40000e' }}>
|
||||
<div className="is-flex is-align-items-center is-justify-content-center flex-shrink-0 animate-pulse" style={{ width: '36px', height: '36px', borderRadius: '50%', backgroundColor: '#5a0118', color: '#ffffff' }}>
|
||||
<Truck size={18} />
|
||||
</div>
|
||||
<div>
|
||||
<div className="has-text-weight-bold is-size-6" style={{ color: '#5a0118' }}>3. Out for Pickup</div>
|
||||
<div className="is-size-7 mt-1 has-text-weight-medium" style={{ color: '#832333' }}>Arriving by 3:30 PM</div>
|
||||
<div className="is-size-7 mt-2 has-text-weight-bold is-flex is-align-items-center" style={{ color: '#5a0118' }}>
|
||||
<span className="material-symbols-outlined mr-2" style={{ fontSize: '15px' }}>pin</span> OTP: 7491
|
||||
<div className="is-flex is-align-items-center gap-1 has-text-weight-bold mt-2" style={{ color: '#5a0118', fontSize: '11px' }}>
|
||||
<MapPin size={13} /> OTP: 7491
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -135,172 +140,186 @@ export const OrderDetailView: React.FC<OrderDetailViewProps> = ({ order, onBack,
|
|||
</div>
|
||||
|
||||
{/* 2-Column Split: Item & Payout + Delivery & Packing Details */}
|
||||
<div className="columns is-variable is-5 mb-5">
|
||||
{/* Left Col: Handcrafted Item & Checklist */}
|
||||
<div className="column is-8">
|
||||
<div className="columns is-variable is-6">
|
||||
{/* Left Col: Handcrafted Item & Payout */}
|
||||
<div className="column is-8 is-flex is-flex-direction-column gap-6">
|
||||
|
||||
{/* Product Card */}
|
||||
<div className="card p-5 mb-5" style={{ borderRadius: '16px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
|
||||
<div className="is-flex is-justify-content-space-between is-align-items-center pb-3 mb-4" style={{ borderBottom: '1px solid rgba(220, 192, 193, 0.5)' }}>
|
||||
<h2 className="title is-size-5 mb-0" style={{ fontWeight: 700, color: '#1c1b1b' }}>Consignment Item</h2>
|
||||
<span className="is-size-7 has-text-grey">1 Box (2.4 kg)</span>
|
||||
<div className="card p-6 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(220, 192, 193, 0.4)' }}>
|
||||
<div className="is-flex is-align-items-center justify-content-between pb-4 mb-5" style={{ borderBottom: '1px solid rgba(220, 192, 193, 0.5)' }}>
|
||||
<h2 className="is-size-5 has-text-weight-bold" style={{ color: '#1c1b1b' }}>Consignment Item</h2>
|
||||
<span className="is-size-7" style={{ color: '#564243' }}>1 Box (2.4 kg)</span>
|
||||
</div>
|
||||
|
||||
<div className="is-flex is-align-items-flex-start gap-5">
|
||||
<div style={{ width: '110px', height: '110px', borderRadius: '16px', backgroundColor: '#f0eded', flexShrink: 0, position: 'relative', overflow: 'hidden' }}>
|
||||
<img src="https://lh3.googleusercontent.com/aida-public/AB6AXuDepeiJK_MZ4VhGgZmIFisTOhinUlBBA0cnBBZHANJwRM7yfzchVuk3jngyBHNSii34_unI6DCsHi6ryk8peXAV-xrlnVRcG7BR05WesCwVn1U4l0D_5R0aWLv1u9LEQBlk-kP0bLVLx12_7yvf4ZSv3Bs3bNajWG5AvLL97bNe173b0631DVZTVfZP8V-Hf4npV7Av-EROfGRmTWfGpufSfvpBFLYUH1KtdLr2FQNXWJDVPc1V76Qclg" style={{ width: '100%', height: '100%', objectFit: 'cover' }} alt="Craft Product" />
|
||||
<span className="tag is-dark is-small" style={{ position: 'absolute', bottom: '6px', left: '6px', backgroundColor: 'rgba(28, 27, 27, 0.8)', fontSize: '10px' }}>Set of 4</span>
|
||||
<div className="is-flex flex-direction-column sm-flex-row is-align-items-flex-start sm-items-center gap-5">
|
||||
<div className="flex-shrink-0 position-relative" style={{ width: '112px', height: '112px', borderRadius: '16px', overflow: 'hidden', backgroundColor: '#f0eded' }}>
|
||||
<img src={order.imageUrl || "https://images.unsplash.com/photo-1610701596007-11502861dcfa?q=80&w=200&auto=format&fit=crop"} alt={order.productName} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
|
||||
<span className="position-absolute px-2 py-1 has-text-weight-medium" style={{ bottom: '6px', left: '6px', borderRadius: '4px', backgroundColor: 'rgba(28, 27, 27, 0.8)', color: '#fcf9f8', fontSize: '10px' }}>Set of 4</span>
|
||||
</div>
|
||||
|
||||
<div className="is-flex-grow-1" style={{ minWidth: 0 }}>
|
||||
<div className="is-flex is-align-items-center gap-2 mb-2">
|
||||
<span className="tag is-small has-text-weight-bold" style={{ backgroundColor: '#95f8a7', color: '#00210a', fontSize: '10px' }}>GI-RAJ-0042</span>
|
||||
<span className="is-family-monospace has-text-grey is-size-7" style={{ fontSize: '11px' }}>SKU: JPR-BLU-084</span>
|
||||
<span className="px-2 py-1 has-text-weight-bold" style={{ borderRadius: '4px', backgroundColor: '#95f8a7', color: '#00210a', fontSize: '10px' }}>GI-RAJ-0042</span>
|
||||
<span className="is-family-monospace" style={{ color: '#897172', fontSize: '11px' }}>SKU: JPR-BLU-084</span>
|
||||
</div>
|
||||
<h3 className="is-size-5 has-text-weight-semibold" style={{ color: '#1c1b1b', lineHeight: 1.3, marginBottom: '6px' }}>
|
||||
{order.productTitle || 'Jaipur Royal Cobalt Ceramic Dinner Plates'}
|
||||
</h3>
|
||||
<p className="is-size-7 has-text-grey mb-3">High-fire quartz terracotta blend with lead-free traditional indigo glaze.</p>
|
||||
<div className="is-size-7 has-text-grey">
|
||||
<span>Quantity: <strong style={{ color: '#1c1b1b' }}>{order.quantity} set</strong></span>
|
||||
<h3 className="is-size-5 has-text-weight-semibold" style={{ color: '#1c1b1b', lineHeight: 1.3 }}>{order.productName}</h3>
|
||||
<p className="is-size-7 mt-2" style={{ color: '#564243' }}>High-fire quartz terracotta blend with lead-free traditional indigo glaze.</p>
|
||||
<div className="mt-3 is-size-7" style={{ color: '#564243' }}>
|
||||
<span>Quantity: <strong style={{ color: '#1c1b1b' }}>1 set</strong></span>
|
||||
<span className="mx-3" style={{ color: '#897172' }}>•</span>
|
||||
<span>Unit Price: <strong style={{ color: '#1c1b1b' }}>₹{(order.amount / (order.quantity || 1)).toLocaleString()}</strong></span>
|
||||
<span>Unit Price: <strong style={{ color: '#1c1b1b' }}>{order.orderValue}</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Clean Financial Summary */}
|
||||
<div className="mt-5 pt-4 columns is-variable is-3" style={{ borderTop: '1px solid rgba(220, 192, 193, 0.5)' }}>
|
||||
<div className="column">
|
||||
<div className="p-3" style={{ borderRadius: '16px', backgroundColor: '#f6f3f2' }}>
|
||||
<div className="is-size-7 has-text-grey mb-1">Order Value</div>
|
||||
<div className="is-size-4 has-text-weight-bold" style={{ color: '#1c1b1b' }}>₹{order.amount.toLocaleString()}.00</div>
|
||||
<div className="mt-6 pt-5 columns is-mobile is-variable is-4" style={{ borderTop: '1px solid rgba(220, 192, 193, 0.5)' }}>
|
||||
<div className="column is-4-tablet is-6-mobile">
|
||||
<div className="p-4 is-flex is-flex-direction-column" style={{ borderRadius: '16px', backgroundColor: '#f6f3f2' }}>
|
||||
<span className="is-size-7" style={{ color: '#564243' }}>Order Value</span>
|
||||
<span className="is-size-5 has-text-weight-bold mt-1" style={{ color: '#1c1b1b' }}>{order.orderValue}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="column">
|
||||
<div className="p-3" style={{ borderRadius: '16px', backgroundColor: '#f6f3f2' }}>
|
||||
<div className="is-size-7 has-text-grey mb-1">TradHox Commission</div>
|
||||
<div className="is-size-4 has-text-weight-bold" style={{ color: '#003112' }}>₹0.00 <span className="is-size-7 has-text-weight-normal">(0%)</span></div>
|
||||
<div className="column is-4-tablet is-6-mobile">
|
||||
<div className="p-4 is-flex is-flex-direction-column" style={{ borderRadius: '16px', backgroundColor: '#f6f3f2' }}>
|
||||
<span className="is-size-7" style={{ color: '#564243' }}>TradHox Commission</span>
|
||||
<span className="is-size-5 has-text-weight-bold mt-1" style={{ color: '#003112' }}>₹0.00 <span className="has-text-weight-normal" style={{ fontSize: '11px' }}>(0%)</span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="column">
|
||||
<div className="p-3" style={{ borderRadius: '16px', backgroundColor: 'rgba(255, 219, 208, 0.3)' }}>
|
||||
<div className="is-size-7 has-text-weight-bold" style={{ color: '#7e2c10', marginBottom: '4px' }}>Net Maker Payout</div>
|
||||
<div className="is-size-4 has-text-weight-bold" style={{ color: '#5a0118' }}>₹{order.amount.toLocaleString()}.00</div>
|
||||
<div className="column is-4-tablet is-12-mobile">
|
||||
<div className="p-4 is-flex is-flex-direction-column h-100 justify-content-center" style={{ borderRadius: '16px', backgroundColor: 'rgba(255, 219, 208, 0.3)' }}>
|
||||
<span className="is-size-7 has-text-weight-bold" style={{ color: '#7e2c10' }}>Net Maker Payout</span>
|
||||
<span className="is-size-5 has-text-weight-bold mt-1" style={{ color: '#5a0118' }}>{order.orderValue}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Simplified 3-Item Packing Checklist */}
|
||||
<div className="card p-5" style={{ borderRadius: '16px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
|
||||
<div className="is-flex is-align-items-center justify-content-between mb-4">
|
||||
<div className="is-flex-grow-1">
|
||||
<h2 className="title is-size-5 mb-1" style={{ fontWeight: 700, color: '#1c1b1b' }}>Pre-Dispatch Checklist</h2>
|
||||
<p className="is-size-7 has-text-grey">Artisanal packing safety verified for transit.</p>
|
||||
<div className="card p-6 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(220, 192, 193, 0.4)' }}>
|
||||
<div className="is-flex is-align-items-center justify-content-between mb-5">
|
||||
<div>
|
||||
<h2 className="is-size-5 has-text-weight-bold" style={{ color: '#1c1b1b' }}>Pre-Dispatch Checklist</h2>
|
||||
<p className="is-size-7 mt-1" style={{ color: '#564243' }}>Artisanal packing safety verified for transit.</p>
|
||||
</div>
|
||||
<span className="tag is-rounded has-text-weight-bold" style={{ backgroundColor: '#95f8a7', color: '#00210a' }}>3 of 3 Verified</span>
|
||||
<span className="px-3 py-1 has-text-weight-bold is-size-7" style={{ borderRadius: '9999px', backgroundColor: '#95f8a7', color: '#00210a' }}>3 of 3 Verified</span>
|
||||
</div>
|
||||
|
||||
<div className="is-flex flex-direction-column">
|
||||
<div className="is-flex is-align-items-center justify-content-between p-3 mb-3" style={{ borderRadius: '16px', backgroundColor: '#f6f3f2' }}>
|
||||
<div className="is-flex is-align-items-center">
|
||||
<CheckCircle2 size={20} className="mr-3" style={{ color: '#003112' }} />
|
||||
<span className="has-text-weight-medium is-size-6" style={{ color: '#1c1b1b' }}>Acoustic tap test passed (zero micro-cracks)</span>
|
||||
<div className="is-flex is-flex-direction-column gap-3">
|
||||
<div className="is-flex is-align-items-center justify-content-between p-3" style={{ borderRadius: '16px', backgroundColor: '#f6f3f2' }}>
|
||||
<div className="is-flex is-align-items-center gap-3">
|
||||
<CheckCircle2 size={20} style={{ color: '#003112', fill: '#003112', stroke: '#fff' }} />
|
||||
<span className="has-text-weight-medium is-size-7" style={{ color: '#1c1b1b' }}>Acoustic tap test passed (zero micro-cracks)</span>
|
||||
</div>
|
||||
<span className="is-family-monospace is-size-7 has-text-grey ml-2">Glaze OK</span>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center justify-content-between p-3 mb-3" style={{ borderRadius: '16px', backgroundColor: '#f6f3f2' }}>
|
||||
<div className="is-flex is-align-items-center">
|
||||
<CheckCircle2 size={20} className="mr-3" style={{ color: '#003112' }} />
|
||||
<span className="has-text-weight-medium is-size-6" style={{ color: '#1c1b1b' }}>Double honeycomb craft cushioning applied</span>
|
||||
</div>
|
||||
<span className="is-family-monospace is-size-7 has-text-grey ml-2">Protected</span>
|
||||
<span className="is-family-monospace" style={{ fontSize: '11px', color: '#897172' }}>Glaze OK</span>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center justify-content-between p-3" style={{ borderRadius: '16px', backgroundColor: '#f6f3f2' }}>
|
||||
<div className="is-flex is-align-items-center">
|
||||
<CheckCircle2 size={20} className="mr-3" style={{ color: '#003112' }} />
|
||||
<span className="has-text-weight-medium is-size-6" style={{ color: '#1c1b1b' }}>GI authenticity hologram and fragile sticker attached</span>
|
||||
<div className="is-flex is-align-items-center gap-3">
|
||||
<CheckCircle2 size={20} style={{ color: '#003112', fill: '#003112', stroke: '#fff' }} />
|
||||
<span className="has-text-weight-medium is-size-7" style={{ color: '#1c1b1b' }}>Double honeycomb craft cushioning applied</span>
|
||||
</div>
|
||||
<span className="is-family-monospace is-size-7 has-text-grey ml-2">Holo #9912</span>
|
||||
<span className="is-family-monospace" style={{ fontSize: '11px', color: '#897172' }}>Protected</span>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center justify-content-between p-3" style={{ borderRadius: '16px', backgroundColor: '#f6f3f2' }}>
|
||||
<div className="is-flex is-align-items-center gap-3">
|
||||
<CheckCircle2 size={20} style={{ color: '#003112', fill: '#003112', stroke: '#fff' }} />
|
||||
<span className="has-text-weight-medium is-size-7" style={{ color: '#1c1b1b' }}>GI authenticity hologram and fragile sticker attached</span>
|
||||
</div>
|
||||
<span className="is-family-monospace" style={{ fontSize: '11px', color: '#897172' }}>Holo #9912</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Right Col: Customer, Gift Note & Courier Handshake */}
|
||||
<div className="column is-4">
|
||||
<div className="is-flex flex-direction-column gap-5 h-100">
|
||||
{/* Delivery & Patron */}
|
||||
<div className="card p-5" style={{ borderRadius: '16px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
|
||||
<div className="is-flex is-align-items-center justify-content-between mb-4">
|
||||
<span className="is-size-7 has-text-weight-bold has-text-grey is-uppercase" style={{ letterSpacing: '0.04em' }}>Recipient</span>
|
||||
<span className="is-size-7 has-text-weight-semibold is-flex is-align-items-center" style={{ color: '#003112' }}>
|
||||
<Award size={14} className="mr-1" /> 5th Order Patron
|
||||
</span>
|
||||
</div>
|
||||
<div className="title is-size-5 mb-2" style={{ fontWeight: 700, color: '#1c1b1b' }}>{order.customerName}</div>
|
||||
<div className="is-size-7 has-text-grey" style={{ lineHeight: 1.5 }}>
|
||||
#402, Samriddhi Enclave, 14th Main, 4th Block, Koramangala, {order.customerCity}, {order.customerState} – 560034
|
||||
</div>
|
||||
<div className="mt-4 pt-3 is-flex is-align-items-center justify-content-between" style={{ borderTop: '1px solid rgba(220, 192, 193, 0.5)' }}>
|
||||
<span className="is-family-monospace has-text-weight-medium" style={{ color: '#1c1b1b', fontSize: '0.9rem' }}>+91 98450 XXXXX</span>
|
||||
<span className="tag is-small is-light" style={{ backgroundColor: '#f0eded' }}>Masked</span>
|
||||
</div>
|
||||
<div className="column is-4 is-flex is-flex-direction-column gap-6">
|
||||
|
||||
{/* Delivery & Patron */}
|
||||
<div className="card p-6 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(220, 192, 193, 0.4)' }}>
|
||||
<div className="is-flex is-align-items-center justify-content-between mb-4">
|
||||
<span className="is-size-7 has-text-weight-bold is-uppercase" style={{ letterSpacing: '0.04em', color: '#564243' }}>Recipient</span>
|
||||
<span className="is-flex is-align-items-center gap-1 has-text-weight-semibold" style={{ fontSize: '11px', color: '#003112' }}>
|
||||
<Star size={13} /> 5th Order Patron
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Customer Gift Note Card */}
|
||||
<div className="card p-4 mb-5" style={{ borderRadius: '16px', backgroundColor: 'rgba(255, 219, 208, 0.2)', boxShadow: 'none' }}>
|
||||
<div className="is-flex is-align-items-center mb-2 has-text-weight-bold is-size-7" style={{ color: '#9d4225' }}>
|
||||
<Gift size={20} className="mr-2" />
|
||||
Customer Gift Note
|
||||
</div>
|
||||
<p className="is-size-6 is-italic mb-3" style={{ color: '#3a0b00', lineHeight: 1.4 }}>
|
||||
“Please handle with care, this is an anniversary present!”
|
||||
</p>
|
||||
<div className="is-size-7 is-flex is-align-items-center" style={{ color: '#7e2c10' }}>
|
||||
<Check size={14} className="mr-2" /> Gift note printed on dispatch card
|
||||
</div>
|
||||
<div className="is-size-5 has-text-weight-bold" style={{ color: '#1c1b1b' }}>{order.customerName}</div>
|
||||
<div className="is-size-7 mt-2" style={{ color: '#564243', lineHeight: 1.6 }}>
|
||||
{order.shippingAddress || '#402, Samriddhi Enclave, 14th Main, 4th Block, Koramangala, Bengaluru, Karnataka – 560034'}
|
||||
</div>
|
||||
|
||||
{/* Courier Handshake */}
|
||||
<div className="card p-5 is-flex-grow-1" style={{ borderRadius: '16px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
|
||||
<div className="is-size-7 has-text-weight-bold has-text-grey is-uppercase mb-4" style={{ letterSpacing: '0.04em' }}>Courier Handover</div>
|
||||
<div className="is-flex is-align-items-center justify-content-between mb-4">
|
||||
<div>
|
||||
<div className="has-text-weight-bold is-size-6" style={{ color: '#1c1b1b' }}>Ramesh Kumar</div>
|
||||
<div className="is-size-7 has-text-grey">Delhivery Express • KA-01-MJ-4192</div>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center is-justify-content-center flex-shrink-0" style={{ width: '36px', height: '36px', borderRadius: '50%', backgroundColor: '#f6f3f2', color: '#5a0118' }}>
|
||||
<Truck size={18} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-3 is-flex is-align-items-center justify-content-between mb-2" style={{ borderRadius: '16px', backgroundColor: '#f6f3f2' }}>
|
||||
<span className="has-text-weight-medium is-size-7 has-text-grey">Verification OTP:</span>
|
||||
<span className="is-family-monospace has-text-weight-bold is-size-4" style={{ color: '#5a0118', letterSpacing: '0.1em' }}>7491</span>
|
||||
</div>
|
||||
<p className="is-size-7 has-text-centered has-text-grey" style={{ fontSize: '11px' }}>Share OTP only after parcel barcode is scanned</p>
|
||||
<div className="mt-4 pt-4 is-flex is-align-items-center justify-content-between is-size-7" style={{ borderTop: '1px solid rgba(220, 192, 193, 0.5)' }}>
|
||||
<span className="is-family-monospace has-text-weight-medium" style={{ color: '#1c1b1b' }}>+91 98450 XXXXX</span>
|
||||
<span className="px-2 py-1" style={{ fontSize: '11px', borderRadius: '4px', backgroundColor: '#f0eded', color: '#564243' }}>Masked</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Customer Gift Note Card */}
|
||||
<div className="card p-5 shadow-sm" style={{ borderRadius: '16px', backgroundColor: 'rgba(255, 219, 208, 0.2)', border: 'none' }}>
|
||||
<div className="is-flex is-align-items-center gap-2 mb-3 has-text-weight-bold is-size-7" style={{ color: '#9d4225' }}>
|
||||
<Gift size={18} />
|
||||
<span>Customer Gift Note</span>
|
||||
</div>
|
||||
<p className="is-italic is-size-6" style={{ color: '#3a0b00', lineHeight: 1.4 }}>
|
||||
“Please handle with care, this is an anniversary present!”
|
||||
</p>
|
||||
<div className="mt-4 is-flex is-align-items-center gap-2 has-text-weight-medium" style={{ fontSize: '11px', color: '#7e2c10' }}>
|
||||
<Check size={15} /> Gift note printed on dispatch card
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Courier Handshake */}
|
||||
<div className="card p-6 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(220, 192, 193, 0.4)' }}>
|
||||
<div className="is-size-7 has-text-weight-bold is-uppercase mb-4" style={{ letterSpacing: '0.04em', color: '#564243' }}>Courier Handover</div>
|
||||
<div className="is-flex is-align-items-center justify-content-between mb-5">
|
||||
<div>
|
||||
<div className="has-text-weight-bold is-size-7" style={{ color: '#1c1b1b' }}>Ramesh Kumar</div>
|
||||
<div className="is-size-7 mt-1" style={{ color: '#564243' }}>Delhivery Express • KA-01-MJ-4192</div>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center is-justify-content-center flex-shrink-0" style={{ width: '36px', height: '36px', borderRadius: '50%', backgroundColor: '#f6f3f2', color: '#5a0118' }}>
|
||||
<Bike size={20} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4 is-flex is-align-items-center justify-content-between" style={{ borderRadius: '16px', backgroundColor: '#f6f3f2' }}>
|
||||
<span className="has-text-weight-medium is-size-7" style={{ color: '#564243' }}>Verification OTP:</span>
|
||||
<span className="is-family-monospace is-size-4 has-text-weight-bold" style={{ color: '#5a0118', letterSpacing: '0.1em' }}>7491</span>
|
||||
</div>
|
||||
<p className="has-text-centered mt-3" style={{ fontSize: '12px', color: '#897172' }}>Share OTP only after parcel barcode is scanned</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<style>{`
|
||||
.justify-content-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.justify-content-center {
|
||||
justify-content: center;
|
||||
}
|
||||
.flex-direction-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
.heartbeat {
|
||||
animation: heartbeat 2s infinite ease-in-out;
|
||||
.position-relative {
|
||||
position: relative;
|
||||
}
|
||||
@keyframes heartbeat {
|
||||
0% { transform: scale(1); }
|
||||
14% { transform: scale(1.1); }
|
||||
28% { transform: scale(1); }
|
||||
42% { transform: scale(1.1); }
|
||||
70% { transform: scale(1); }
|
||||
.position-absolute {
|
||||
position: absolute;
|
||||
}
|
||||
.h-100 {
|
||||
height: 100%;
|
||||
}
|
||||
@media (min-width: 769px) {
|
||||
.sm-flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
.sm-items-center {
|
||||
align-items: center;
|
||||
}
|
||||
.md-flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
.md-items-center {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
|
|
|
|||
334
src/components/orders/ReportDamageView.tsx
Normal file
334
src/components/orders/ReportDamageView.tsx
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
import React, { useState } from 'react';
|
||||
import {
|
||||
ChevronRight,
|
||||
Clock,
|
||||
ShieldCheck,
|
||||
Grid,
|
||||
Package,
|
||||
RefreshCw,
|
||||
Calendar,
|
||||
AlertTriangle,
|
||||
Archive,
|
||||
HeartCrack,
|
||||
Unlock,
|
||||
ImagePlus,
|
||||
Landmark,
|
||||
Zap,
|
||||
ArrowLeft,
|
||||
Send,
|
||||
Loader2,
|
||||
CheckCircle2
|
||||
} from 'lucide-react';
|
||||
import { OrderItem } from '../../types/seller';
|
||||
|
||||
interface ReportDamageViewProps {
|
||||
onBack: () => void;
|
||||
onTabChange?: (tab: string) => void;
|
||||
order?: OrderItem | null;
|
||||
}
|
||||
|
||||
export const ReportDamageView: React.FC<ReportDamageViewProps> = ({ onBack, onTabChange, order }) => {
|
||||
const [damageType, setDamageType] = useState('outer_crushed');
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [isSubmitted, setIsSubmitted] = useState(false);
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setIsSubmitting(true);
|
||||
setTimeout(() => {
|
||||
setIsSubmitting(false);
|
||||
setIsSubmitted(true);
|
||||
}, 1200);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="report-damage-view" style={{ maxWidth: '1400px', margin: '0 auto', animation: 'fadeIn 0.2s ease-in-out' }}>
|
||||
|
||||
{/* Breadcrumb & Top Indicator Bar */}
|
||||
<div className="is-flex is-flex-wrap-wrap is-align-items-center justify-content-between gap-4 pt-4 mb-5">
|
||||
<nav className="is-flex is-align-items-center gap-2 has-text-weight-medium is-size-7" style={{ color: '#564243' }}>
|
||||
<a onClick={onBack} className="hover-text-primary transition-colors cursor-pointer" style={{ color: '#564243' }}>Returns & Claims</a>
|
||||
<ChevronRight size={16} style={{ color: '#897172' }} />
|
||||
<span className="has-text-weight-semibold" style={{ color: '#5a0118' }}>File Transit Damage Claim</span>
|
||||
</nav>
|
||||
<div className="is-inline-flex is-align-items-center gap-2 px-3 py-2" style={{ borderRadius: '9999px', backgroundColor: 'rgba(253, 140, 104, 0.2)', color: '#742508', fontSize: '11px', fontWeight: 600 }}>
|
||||
<Clock size={16} />
|
||||
<span>Claim Window: <strong className="has-text-weight-bold">31h remaining</strong> (Delivered 24 Oct, 11:30 AM)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Editorial Header Block */}
|
||||
<div className="is-flex is-flex-direction-column gap-2 pb-4">
|
||||
<div className="is-flex is-align-items-center gap-2" style={{ color: '#5a0118' }}>
|
||||
<ShieldCheck size={20} />
|
||||
<span className="has-text-weight-bold is-uppercase" style={{ fontSize: '11px', letterSpacing: '0.04em' }}>24-Hour Damage Protection</span>
|
||||
</div>
|
||||
<h1 className="title is-size-2 mb-1" style={{ letterSpacing: '-0.02em', color: '#1c1b1b', fontWeight: 700 }}>Report Transit Damage</h1>
|
||||
<p className="is-size-6" style={{ color: '#564243', maxWidth: '42rem' }}>We take care of transit issues so you don't have to. Tell us what happened below and receive reimbursement directly to your account within 24 hours.</p>
|
||||
</div>
|
||||
|
||||
{/* Bento Grid Context & Main Claim Form */}
|
||||
<div className="is-flex is-align-items-center gap-2 pb-4 mb-6 overflow-x-auto" style={{ borderBottom: '1px solid rgba(234, 231, 231, 0.6)' }}>
|
||||
<button onClick={() => onTabChange?.('overall')} className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: 'transparent', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<Grid size={18} className="mr-2" /> Overall
|
||||
</button>
|
||||
<button onClick={() => onTabChange?.('ready_for_pickup')} className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: 'transparent', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<Package size={18} className="mr-2" /> Ready for pickup
|
||||
</button>
|
||||
<button onClick={() => onTabChange?.('handover')} className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: 'transparent', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<RefreshCw size={18} className="mr-2" /> Handover
|
||||
</button>
|
||||
<button onClick={() => onTabChange?.('reschedule')} className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: 'transparent', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<Calendar size={18} className="mr-2" /> Reschedule
|
||||
</button>
|
||||
<button className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center shadow-sm" style={{ backgroundColor: '#791b2c', color: '#ffffff', fontWeight: 600, border: 'none' }}>
|
||||
<AlertTriangle size={18} className="mr-2" /> Report transit damage
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div style={{ maxWidth: '48rem', display: 'flex', flexDirection: 'column', gap: '1.5rem', marginBottom: '3rem' }}>
|
||||
|
||||
{/* Top Product Summary Card */}
|
||||
<div className="card p-5 is-flex is-align-items-center justify-content-between gap-4 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(234, 231, 231, 0.6)' }}>
|
||||
<div className="is-flex is-align-items-center gap-4">
|
||||
<div className="flex-shrink-0" style={{ width: '64px', height: '64px', borderRadius: '12px', overflow: 'hidden', backgroundColor: '#f0eded' }}>
|
||||
<img
|
||||
src={order?.imageUrl || "https://images.unsplash.com/photo-1578309139682-990522c00cc7?q=80&w=200&auto=format&fit=crop"}
|
||||
alt="Product"
|
||||
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className="is-size-5 has-text-weight-semibold" style={{ color: '#1c1b1b' }}>{order?.productTitle || 'Bidriware Silver Inlay Floral Vase'}</div>
|
||||
<div className="is-size-7 mt-1" style={{ color: '#564243' }}>
|
||||
Order <span className="is-family-monospace has-text-weight-medium" style={{ color: '#1c1b1b' }}>#{order?.orderNumber || 'TDX-90650'}</span> · Blue Dart AWB {order?.awbNumber || 'BD-98214820'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="has-text-right flex-shrink-0">
|
||||
<div className="is-size-7 has-text-weight-bold is-uppercase" style={{ color: '#564243', letterSpacing: '0.04em' }}>Declared Value</div>
|
||||
<div className="is-size-4 has-text-weight-bold" style={{ color: '#5a0118' }}>₹{order?.amount?.toLocaleString() || '6,400'}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Simple Form */}
|
||||
<form onSubmit={handleSubmit} className="card p-6 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(234, 231, 231, 0.6)', display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
||||
|
||||
{/* Step 1: Damage Type */}
|
||||
<div className="is-flex is-flex-direction-column gap-3">
|
||||
<div className="is-flex is-align-items-center justify-content-between">
|
||||
<label className="is-size-5 has-text-weight-semibold" style={{ color: '#1c1b1b' }}>Step 1 · What kind of damage occurred?</label>
|
||||
<span className="is-size-7 has-text-weight-semibold" style={{ color: '#5a0118' }}>Select one</span>
|
||||
</div>
|
||||
<div className="columns is-mobile is-multiline is-variable is-3 mt-1">
|
||||
|
||||
<div className="column is-4-tablet is-12-mobile">
|
||||
<label
|
||||
className="is-flex is-flex-direction-column gap-2 p-4 cursor-pointer transition-all h-100"
|
||||
style={{
|
||||
borderRadius: '12px',
|
||||
backgroundColor: damageType === 'outer_crushed' ? 'rgba(255, 218, 219, 0.2)' : '#f6f3f2',
|
||||
border: damageType === 'outer_crushed' ? '2px solid #791b2c' : '1px solid transparent'
|
||||
}}
|
||||
onClick={() => setDamageType('outer_crushed')}
|
||||
>
|
||||
<div className="is-flex is-align-items-center justify-content-between">
|
||||
<Archive size={22} style={{ color: '#5a0118' }} />
|
||||
<div style={{ color: '#791b2c' }}>
|
||||
{damageType === 'outer_crushed' ? <CheckCircle2 size={16} style={{ fill: '#791b2c', color: '#fff' }} /> : <div style={{ width: '16px', height: '16px', borderRadius: '50%', border: '1px solid #897172' }}></div>}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="is-block has-text-weight-semibold mb-1" style={{ color: '#1c1b1b', fontSize: '13px' }}>Crushed outer box</span>
|
||||
<span className="is-block is-size-7" style={{ color: '#564243' }}>Carton impact or crushed packaging</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="column is-4-tablet is-12-mobile">
|
||||
<label
|
||||
className="is-flex is-flex-direction-column gap-2 p-4 cursor-pointer transition-all h-100"
|
||||
style={{
|
||||
borderRadius: '12px',
|
||||
backgroundColor: damageType === 'item_broken' ? 'rgba(255, 218, 219, 0.2)' : '#f6f3f2',
|
||||
border: damageType === 'item_broken' ? '2px solid #791b2c' : '1px solid transparent'
|
||||
}}
|
||||
onClick={() => setDamageType('item_broken')}
|
||||
>
|
||||
<div className="is-flex is-align-items-center justify-content-between">
|
||||
<HeartCrack size={22} style={{ color: '#5a0118' }} />
|
||||
<div style={{ color: '#791b2c' }}>
|
||||
{damageType === 'item_broken' ? <CheckCircle2 size={16} style={{ fill: '#791b2c', color: '#fff' }} /> : <div style={{ width: '16px', height: '16px', borderRadius: '50%', border: '1px solid #897172' }}></div>}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="is-block has-text-weight-semibold mb-1" style={{ color: '#1c1b1b', fontSize: '13px' }}>Broken handcrafted item</span>
|
||||
<span className="is-block is-size-7" style={{ color: '#564243' }}>Fractured craft body, silver work loose</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="column is-4-tablet is-12-mobile">
|
||||
<label
|
||||
className="is-flex is-flex-direction-column gap-2 p-4 cursor-pointer transition-all h-100"
|
||||
style={{
|
||||
borderRadius: '12px',
|
||||
backgroundColor: damageType === 'seal_opened' ? 'rgba(255, 218, 219, 0.2)' : '#f6f3f2',
|
||||
border: damageType === 'seal_opened' ? '2px solid #791b2c' : '1px solid transparent'
|
||||
}}
|
||||
onClick={() => setDamageType('seal_opened')}
|
||||
>
|
||||
<div className="is-flex is-align-items-center justify-content-between">
|
||||
<Unlock size={22} style={{ color: '#5a0118' }} />
|
||||
<div style={{ color: '#791b2c' }}>
|
||||
{damageType === 'seal_opened' ? <CheckCircle2 size={16} style={{ fill: '#791b2c', color: '#fff' }} /> : <div style={{ width: '16px', height: '16px', borderRadius: '50%', border: '1px solid #897172' }}></div>}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="is-block has-text-weight-semibold mb-1" style={{ color: '#1c1b1b', fontSize: '13px' }}>Seal opened / missing</span>
|
||||
<span className="is-block is-size-7" style={{ color: '#564243' }}>Tampered tape or missing contents</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Step 2: Clean Photo Upload Zone */}
|
||||
<div className="is-flex is-flex-direction-column gap-3">
|
||||
<div className="is-flex is-align-items-center justify-content-between">
|
||||
<label className="is-size-5 has-text-weight-semibold" style={{ color: '#1c1b1b' }}>Step 2 · Unboxing photos</label>
|
||||
<span className="is-size-7" style={{ color: '#564243' }}>Clear photos speed up 24h approval</span>
|
||||
</div>
|
||||
<div className="columns is-mobile is-variable is-3 mt-1" style={{ overflowX: 'auto', flexWrap: 'nowrap' }}>
|
||||
|
||||
<div className="column is-4-tablet is-5-mobile" style={{ minWidth: '160px' }}>
|
||||
<div className="position-relative" style={{ borderRadius: '12px', overflow: 'hidden', aspectRatio: '1', backgroundColor: '#eae7e7' }}>
|
||||
<img src="https://images.unsplash.com/photo-1580674285054-bed31e145f59?q=80&w=300&auto=format&fit=crop" alt="Outer Box Damage" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
|
||||
<div className="position-absolute px-2 py-1 has-text-centered" style={{ bottom: '6px', left: '6px', right: '6px', borderRadius: '4px', backgroundColor: 'rgba(255, 255, 255, 0.9)', backdropFilter: 'blur(4px)', color: '#1c1b1b', fontSize: '11px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
|
||||
Box Condition
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="column is-4-tablet is-5-mobile" style={{ minWidth: '160px' }}>
|
||||
<div className="position-relative" style={{ borderRadius: '12px', overflow: 'hidden', aspectRatio: '1', backgroundColor: '#eae7e7' }}>
|
||||
<img src="https://images.unsplash.com/photo-1596547611090-e22a46c306d1?q=80&w=300&auto=format&fit=crop" alt="Damaged Craft Item" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
|
||||
<div className="position-absolute px-2 py-1 has-text-centered" style={{ bottom: '6px', left: '6px', right: '6px', borderRadius: '4px', backgroundColor: 'rgba(255, 255, 255, 0.9)', backdropFilter: 'blur(4px)', color: '#1c1b1b', fontSize: '11px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
|
||||
Broken Area
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="column is-4-tablet is-5-mobile" style={{ minWidth: '160px' }}>
|
||||
<label className="is-flex is-flex-direction-column is-align-items-center justify-content-center p-4 cursor-pointer transition-all" style={{ borderRadius: '12px', backgroundColor: '#f6f3f2', aspectRatio: '1', textAlign: 'center' }}>
|
||||
<div className="is-flex is-align-items-center justify-content-center mb-2" style={{ width: '40px', height: '40px', borderRadius: '50%', backgroundColor: '#eae7e7', color: '#5a0118' }}>
|
||||
<ImagePlus size={20} />
|
||||
</div>
|
||||
<span className="has-text-weight-semibold" style={{ color: '#1c1b1b', fontSize: '13px' }}>Add Photo</span>
|
||||
<span className="is-size-7 mt-1" style={{ color: '#564243' }}>e.g. Shipping label</span>
|
||||
<input type="file" className="is-hidden" accept="image/*" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Step 3: Payout Settlement Confirmation */}
|
||||
<div className="is-flex is-flex-direction-column gap-3">
|
||||
<label className="is-size-5 has-text-weight-semibold" style={{ color: '#1c1b1b' }}>Step 3 · Settlement destination</label>
|
||||
<div className="p-4 is-flex is-align-items-center justify-content-between" style={{ borderRadius: '12px', backgroundColor: '#f6f3f2' }}>
|
||||
<div className="is-flex is-align-items-center gap-3">
|
||||
<div className="is-flex is-align-items-center justify-content-center flex-shrink-0" style={{ width: '40px', height: '40px', borderRadius: '50%', backgroundColor: 'rgba(90, 1, 24, 0.1)', color: '#5a0118' }}>
|
||||
<Landmark size={20} />
|
||||
</div>
|
||||
<div>
|
||||
<div className="has-text-weight-semibold" style={{ color: '#1c1b1b', fontSize: '13px' }}>State Bank of India · ending in 4019</div>
|
||||
<div className="is-size-7 mt-1" style={{ color: '#564243' }}>Full ₹{order?.amount?.toLocaleString() || '6,400'} payout credited directly via instant NEFT</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center gap-2 px-3 py-1 has-text-weight-semibold" style={{ borderRadius: '9999px', backgroundColor: 'rgba(0, 74, 30, 0.1)', color: '#003112', fontSize: '11px' }}>
|
||||
<Zap size={14} /> 24h Guarantee
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom Actions */}
|
||||
<div className="pt-2 is-flex is-align-items-center justify-content-between gap-4">
|
||||
<button onClick={onBack} type="button" className="button is-rounded is-light" style={{ height: '44px', padding: '0 1.5rem', fontWeight: 600, color: '#1c1b1b', backgroundColor: '#f6f3f2', border: 'none' }}>
|
||||
<ArrowLeft size={18} className="mr-2" /> Back
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="button is-rounded shadow-sm"
|
||||
style={{
|
||||
height: '44px',
|
||||
padding: '0 2rem',
|
||||
fontWeight: 600,
|
||||
backgroundColor: isSubmitted ? '#004a1e' : '#5a0118',
|
||||
color: '#ffffff',
|
||||
border: 'none',
|
||||
transition: 'all 0.2s'
|
||||
}}
|
||||
disabled={isSubmitting || isSubmitted}
|
||||
>
|
||||
{isSubmitting ? (
|
||||
<>
|
||||
<Loader2 size={18} className="mr-2 spin" /> Securing Claim Dossier...
|
||||
</>
|
||||
) : isSubmitted ? (
|
||||
<>
|
||||
<CheckCircle2 size={18} className="mr-2" /> Claim #CLM-8921 Dispatched
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Send size={18} className="mr-2" /> Submit Claim
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<style>{`
|
||||
.justify-content-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.justify-content-center {
|
||||
justify-content: center;
|
||||
}
|
||||
.flex-direction-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
.position-relative {
|
||||
position: relative;
|
||||
}
|
||||
.position-absolute {
|
||||
position: absolute;
|
||||
}
|
||||
.h-100 {
|
||||
height: 100%;
|
||||
}
|
||||
.spin {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
@media (min-width: 769px) {
|
||||
.sm-flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
.sm-items-center {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
303
src/components/orders/ReschedulePickupView.tsx
Normal file
303
src/components/orders/ReschedulePickupView.tsx
Normal file
|
|
@ -0,0 +1,303 @@
|
|||
import React, { useState } from 'react';
|
||||
import {
|
||||
ArrowLeft,
|
||||
Grid,
|
||||
RefreshCw,
|
||||
Clock,
|
||||
AlertTriangle,
|
||||
Package,
|
||||
CheckCircle2,
|
||||
Calendar,
|
||||
Truck,
|
||||
Edit
|
||||
} from 'lucide-react';
|
||||
import { OrderItem } from '../../types/seller';
|
||||
|
||||
interface ReschedulePickupViewProps {
|
||||
onBack: () => void;
|
||||
onTabChange?: (tab: string) => void;
|
||||
order?: OrderItem | null; // Optional: if provided, reschedule for single order, else batch
|
||||
}
|
||||
|
||||
export const ReschedulePickupView: React.FC<ReschedulePickupViewProps> = ({ onBack, onTabChange, order }) => {
|
||||
const [reason, setReason] = useState('curing');
|
||||
const [slot, setSlot] = useState('morning');
|
||||
const [dateType, setDateType] = useState('tomorrow');
|
||||
|
||||
const reasons = [
|
||||
{ id: 'curing', label: 'Handcrafts Still Drying / Finishing', desc: 'Extra time needed for kiln curing or natural dye drying.' },
|
||||
{ id: 'adding_orders', label: 'Adding More Orders to Batch', desc: 'Packing more finished crafts to ship together.' },
|
||||
{ id: 'closed', label: 'Workshop Temporarily Closed', desc: 'Artisan master or team unavailable today.' },
|
||||
{ id: 'weather', label: 'Weather / Heavy Rain in Cluster', desc: 'Protecting consignments from humidity or rain.' },
|
||||
{ id: 'inaccessible', label: 'Workshop Inaccessible', desc: 'Local craft corridor or market temporarily blocked.' },
|
||||
{ id: 'other', label: 'Other Reason', desc: 'Briefly let the logistics team know what changed.' }
|
||||
];
|
||||
|
||||
const slots = [
|
||||
{ id: 'morning', label: 'Morning (10:00 AM – 1:00 PM)', desc: 'Delhivery Express & Air Linehaul', tag: 'Fastest Delivery' },
|
||||
{ id: 'afternoon', label: 'Afternoon (2:00 PM – 5:00 PM)', desc: 'Standard ground carrier sweep', tag: 'Standard', tagBg: 'transparent' },
|
||||
{ id: 'evening', label: 'Evening (5:00 PM – 7:00 PM)', desc: 'Regional depot consolidation run', tag: 'Evening Run', tagBg: 'transparent' }
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="reschedule-view" style={{ maxWidth: '1400px', margin: '0 auto', animation: 'fadeIn 0.2s ease-in-out' }}>
|
||||
|
||||
{/* Top Context Navigation Strip */}
|
||||
<section className="px-8 pt-6 pb-5 mb-6" style={{ backgroundColor: '#fcf9f8', borderBottom: '1px solid rgba(220, 192, 193, 0.6)' }}>
|
||||
<div style={{ maxWidth: '1152px', margin: '0 auto' }}>
|
||||
<div className="is-flex is-align-items-center gap-2 is-size-7 mb-3" style={{ color: '#564243' }}>
|
||||
<a onClick={onBack} className="is-inline-flex is-align-items-center gap-2 has-text-weight-semibold cursor-pointer transition-colors" style={{ color: '#5a0118' }}>
|
||||
<ArrowLeft size={16} /> Back to Orders & Shipping
|
||||
</a>
|
||||
<span style={{ color: '#dcd9d9' }}>/</span>
|
||||
<span className="has-text-weight-semibold" style={{ color: '#1c1b1b' }}>Jaipur Pottery & Handloom Cluster</span>
|
||||
</div>
|
||||
|
||||
<div className="is-flex flex-direction-column md-flex-row md-items-center justify-content-between gap-4 pt-1 mb-4">
|
||||
<div>
|
||||
<h1 className="title is-size-2 mb-1" style={{ letterSpacing: '-0.02em', color: '#1c1b1b' }}>Reschedule Courier Pickup</h1>
|
||||
<p className="is-size-6" style={{ color: '#564243', maxWidth: '42rem' }}>Choose a new pickup date and time that fits your workshop schedule.</p>
|
||||
</div>
|
||||
<div className="is-inline-flex is-align-items-center gap-3 px-4 py-2 shadow-sm" style={{ backgroundColor: '#ffffff', borderRadius: '9999px', border: '1px solid #eae7e7', color: '#1c1b1b', fontSize: '13px' }}>
|
||||
<Package size={18} style={{ color: '#9d4225' }} />
|
||||
<span>Batch of <strong className="has-text-weight-semibold">14 Orders</strong> ready</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav className="is-flex is-align-items-center gap-2 overflow-x-auto pb-1" aria-label="Orders & Dispatch tabs">
|
||||
<button onClick={() => onTabChange?.('overall')} className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: 'transparent', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<Grid size={16} className="mr-2" /> Overall
|
||||
</button>
|
||||
<button onClick={() => onTabChange?.('ready_for_pickup')} className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: 'transparent', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<Package size={16} className="mr-2" /> Ready for pickup
|
||||
</button>
|
||||
<button onClick={() => onTabChange?.('handover')} className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: 'transparent', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<RefreshCw size={16} className="mr-2" /> Handover
|
||||
</button>
|
||||
<button className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center shadow-sm" style={{ backgroundColor: '#791b2c', color: '#ffffff', fontWeight: 600, border: 'none' }}>
|
||||
<Clock size={16} className="mr-2" /> Reschedule
|
||||
</button>
|
||||
<button onClick={() => onTabChange?.('report_damage')} className="button is-rounded is-small px-4 transition-all is-flex is-align-items-center" style={{ backgroundColor: 'transparent', color: '#564243', fontWeight: 500, border: 'none' }}>
|
||||
<AlertTriangle size={16} className="mr-2" /> Report transit damage
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Main Workspace: 2-Column Desktop Grid */}
|
||||
<div className="px-8 pb-8" style={{ backgroundColor: '#fcf9f8' }}>
|
||||
<div className="columns is-variable is-6" style={{ maxWidth: '1152px', margin: '0 auto' }}>
|
||||
|
||||
<div className="column is-8 is-flex is-flex-direction-column gap-6">
|
||||
|
||||
{/* Current Booking */}
|
||||
<div className="card p-5 is-flex is-flex-direction-column sm-flex-row is-align-items-flex-start sm-items-center justify-content-between gap-4 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(234, 231, 231, 0.6)' }}>
|
||||
<div className="is-flex is-align-items-center gap-4">
|
||||
<div className="is-flex is-align-items-center is-justify-content-center shrink-0" style={{ width: '40px', height: '40px', borderRadius: '12px', backgroundColor: '#ffdbd0', color: '#3a0b00' }}>
|
||||
<Clock size={22} />
|
||||
</div>
|
||||
<div className="is-flex is-flex-direction-column">
|
||||
<span className="is-size-7 has-text-weight-bold is-uppercase" style={{ letterSpacing: '0.04em', color: '#9d4225' }}>Current Booking</span>
|
||||
<span className="is-size-5 has-text-weight-semibold" style={{ color: '#1c1b1b' }}>Today, 2:30 PM – 3:30 PM</span>
|
||||
<span className="is-size-7" style={{ color: '#564243' }}>14 orders ready for Delhivery collection</span>
|
||||
</div>
|
||||
</div>
|
||||
<span className="is-inline-flex is-align-items-center gap-2 px-3 py-1 has-text-weight-semibold" style={{ borderRadius: '9999px', backgroundColor: '#f0eded', color: '#564243', fontSize: '11px' }}>
|
||||
<span style={{ width: '8px', height: '8px', borderRadius: '50%', backgroundColor: '#9d4225' }}></span>
|
||||
Active Pickup
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Step 1 */}
|
||||
<div className="card p-6 is-flex is-flex-direction-column gap-4 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(234, 231, 231, 0.6)' }}>
|
||||
<div className="is-flex is-flex-direction-column gap-1">
|
||||
<span className="is-size-7 has-text-weight-bold is-uppercase" style={{ letterSpacing: '0.04em', color: '#5a0118' }}>Step 1</span>
|
||||
<h2 className="is-size-5 has-text-weight-semibold" style={{ color: '#1c1b1b' }}>1. Why do you need to reschedule?</h2>
|
||||
</div>
|
||||
|
||||
<div className="columns is-multiline is-variable is-3 mt-1">
|
||||
{reasons.map((r) => {
|
||||
const isSelected = reason === r.id;
|
||||
return (
|
||||
<div className="column is-6" key={r.id}>
|
||||
<label
|
||||
className="is-flex is-align-items-flex-start gap-3 p-4 cursor-pointer transition-all h-100"
|
||||
style={{
|
||||
borderRadius: '12px',
|
||||
backgroundColor: isSelected ? 'rgba(255, 218, 219, 0.2)' : 'rgba(246, 243, 242, 0.5)',
|
||||
border: isSelected ? '2px solid #791b2c' : '1px solid transparent'
|
||||
}}
|
||||
onClick={() => setReason(r.id)}
|
||||
>
|
||||
<div style={{ marginTop: '2px', color: '#791b2c' }}>
|
||||
{isSelected ? <CheckCircle2 size={18} style={{ fill: '#791b2c', color: '#fff' }} /> : <div style={{ width: '16px', height: '16px', borderRadius: '50%', border: '1px solid #897172', margin: '1px' }}></div>}
|
||||
</div>
|
||||
<div className="is-flex is-flex-direction-column">
|
||||
<span className="has-text-weight-semibold" style={{ color: '#1c1b1b', fontSize: '15px' }}>{r.label}</span>
|
||||
<p className="is-size-7 mt-1" style={{ color: '#564243' }}>{r.desc}</p>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Step 2 */}
|
||||
<div className="card p-6 is-flex is-flex-direction-column gap-4 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(234, 231, 231, 0.6)' }}>
|
||||
<div className="is-flex is-align-items-center justify-content-between">
|
||||
<div className="is-flex is-flex-direction-column gap-1">
|
||||
<span className="is-size-7 has-text-weight-bold is-uppercase" style={{ letterSpacing: '0.04em', color: '#5a0118' }}>Step 2</span>
|
||||
<h2 className="is-size-5 has-text-weight-semibold" style={{ color: '#1c1b1b' }}>2. When should the courier come?</h2>
|
||||
</div>
|
||||
<span className="has-text-weight-semibold px-3 py-1" style={{ borderRadius: '9999px', backgroundColor: 'rgba(149, 248, 167, 0.3)', color: '#004a1e', fontSize: '11px' }}>Free Doorstep Pickup</span>
|
||||
</div>
|
||||
|
||||
<div className="is-flex is-align-items-center gap-2 pb-3 mb-1 overflow-x-auto" style={{ borderBottom: '1px solid rgba(234, 231, 231, 0.6)' }}>
|
||||
<button onClick={() => setDateType('tomorrow')} className={`button is-rounded ${dateType === 'tomorrow' ? 'shadow-sm' : ''}`} style={{ fontWeight: 600, backgroundColor: dateType === 'tomorrow' ? '#791b2c' : '#f6f3f2', color: dateType === 'tomorrow' ? '#ffffff' : '#564243', border: 'none' }}>Tomorrow (Recommended)</button>
|
||||
<button onClick={() => setDateType('day_after')} className="button is-rounded" style={{ fontWeight: 500, backgroundColor: dateType === 'day_after' ? '#791b2c' : '#f6f3f2', color: dateType === 'day_after' ? '#ffffff' : '#564243', border: 'none' }}>Day After Tomorrow</button>
|
||||
<button onClick={() => setDateType('custom')} className="button is-rounded" style={{ fontWeight: 500, backgroundColor: dateType === 'custom' ? '#791b2c' : '#f6f3f2', color: dateType === 'custom' ? '#ffffff' : '#564243', border: 'none' }}>Custom Date</button>
|
||||
</div>
|
||||
|
||||
<div className="is-flex is-flex-direction-column gap-3">
|
||||
{slots.map((s) => {
|
||||
const isSelected = slot === s.id;
|
||||
return (
|
||||
<label
|
||||
key={s.id}
|
||||
className="is-flex is-align-items-center justify-content-between p-4 cursor-pointer transition-all"
|
||||
style={{
|
||||
borderRadius: '12px',
|
||||
backgroundColor: isSelected ? 'rgba(255, 218, 219, 0.2)' : 'rgba(246, 243, 242, 0.5)',
|
||||
border: isSelected ? '2px solid #791b2c' : '1px solid transparent'
|
||||
}}
|
||||
onClick={() => setSlot(s.id)}
|
||||
>
|
||||
<div className="is-flex is-align-items-center gap-4">
|
||||
<div style={{ color: '#791b2c' }}>
|
||||
{isSelected ? <CheckCircle2 size={18} style={{ fill: '#791b2c', color: '#fff' }} /> : <div style={{ width: '16px', height: '16px', borderRadius: '50%', border: '1px solid #897172' }}></div>}
|
||||
</div>
|
||||
<div className="is-flex is-flex-direction-column">
|
||||
<span className="has-text-weight-semibold" style={{ color: '#1c1b1b', fontSize: '15px' }}>{s.label}</span>
|
||||
<span className="is-size-7 mt-1" style={{ color: '#564243' }}>{s.desc}</span>
|
||||
</div>
|
||||
</div>
|
||||
<span className="px-3 py-1 has-text-weight-semibold" style={{ borderRadius: '9999px', backgroundColor: s.tagBg || '#5a0118', color: s.tagBg ? '#564243' : '#ffffff', fontSize: '11px' }}>
|
||||
{s.tag}
|
||||
</span>
|
||||
</label>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="is-flex is-align-items-center gap-2 pt-1" style={{ color: '#004a1e', fontSize: '11px', fontWeight: 600 }}>
|
||||
<CheckCircle2 size={16} /> Free doorstep pickup · No penalty or cancellation fees
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Step 3 */}
|
||||
<div className="card p-6 is-flex is-flex-direction-column gap-3 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(234, 231, 231, 0.6)' }}>
|
||||
<div className="is-flex is-flex-direction-column gap-1">
|
||||
<span className="is-size-7 has-text-weight-bold is-uppercase" style={{ letterSpacing: '0.04em', color: '#5a0118' }}>Step 3</span>
|
||||
<h2 className="is-size-5 has-text-weight-semibold" style={{ color: '#1c1b1b' }}>3. Instructions for Driver (Optional)</h2>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center gap-3 px-4 py-3 mt-2" style={{ borderRadius: '12px', backgroundColor: '#f6f3f2' }}>
|
||||
<Edit size={18} style={{ color: '#564243' }} />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Any notes for the driver? (e.g. Call before arrival, use side gate)"
|
||||
style={{ background: 'transparent', border: 'none', outline: 'none', width: '100%', color: '#1c1b1b', fontSize: '13px' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="column is-4">
|
||||
<div className="is-flex is-flex-direction-column gap-5 sticky-top">
|
||||
<div className="card p-6 is-flex is-flex-direction-column gap-4 shadow-sm" style={{ borderRadius: '16px', backgroundColor: '#ffffff', border: '1px solid rgba(234, 231, 231, 0.6)' }}>
|
||||
<div className="is-flex is-align-items-center justify-content-between pb-3" style={{ borderBottom: '1px solid rgba(234, 231, 231, 0.6)' }}>
|
||||
<span className="is-size-5 has-text-weight-semibold" style={{ color: '#1c1b1b' }}>Reschedule Summary</span>
|
||||
<Truck size={20} style={{ color: '#5a0118' }} />
|
||||
</div>
|
||||
|
||||
<div className="is-flex is-flex-direction-column gap-3 is-size-7">
|
||||
<div className="is-flex is-align-items-center justify-content-between">
|
||||
<span style={{ color: '#564243' }}>Consignment</span>
|
||||
<span className="has-text-weight-semibold" style={{ color: '#1c1b1b' }}>{order ? '1 Package' : '14 Packages'}</span>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center justify-content-between">
|
||||
<span style={{ color: '#564243' }}>Pickup Location</span>
|
||||
<span className="has-text-weight-semibold" style={{ color: '#1c1b1b' }}>Jaipur Pottery Hub</span>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center justify-content-between">
|
||||
<span style={{ color: '#564243' }}>Selected New Slot</span>
|
||||
<span className="has-text-weight-semibold" style={{ color: '#5a0118' }}>
|
||||
{dateType === 'tomorrow' ? 'Tomorrow' : 'Custom'}, {slot === 'morning' ? '10:00 AM – 1:00 PM' : slot === 'afternoon' ? '2:00 PM – 5:00 PM' : '5:00 PM – 7:00 PM'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-4 mt-2 is-flex is-align-items-flex-start gap-3" style={{ borderRadius: '12px', backgroundColor: 'rgba(255, 218, 219, 0.2)' }}>
|
||||
<CheckCircle2 size={20} style={{ color: '#5a0118', flexShrink: 0, marginTop: '2px' }} />
|
||||
<div className="is-flex is-flex-direction-column">
|
||||
<span className="is-size-7 has-text-weight-bold is-uppercase" style={{ letterSpacing: '0.04em', color: '#5a0118' }}>Tradhox Artisan Promise</span>
|
||||
<p className="is-size-7 mt-1" style={{ color: '#1c1b1b' }}>100% protection on courier adjustments. No penalties for handmade delays.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="is-flex is-flex-direction-column gap-3 pt-3">
|
||||
<button onClick={onBack} className="button is-rounded shadow-sm" style={{ height: '48px', backgroundColor: '#791b2c', color: '#ffffff', fontWeight: 600, border: 'none', transition: 'all 0.2s' }}>
|
||||
Confirm Rescheduled Pickup
|
||||
</button>
|
||||
<button onClick={onBack} className="button is-rounded" style={{ height: '44px', backgroundColor: '#f6f3f2', color: '#564243', fontWeight: 600, border: 'none', transition: 'all 0.2s' }}>
|
||||
Keep Original Today 2:30 PM Pickup
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p className="has-text-centered pt-2" style={{ fontSize: '13px', color: '#564243', lineHeight: 1.4 }}>
|
||||
Buyer notifications will be automatically updated with the revised dispatch schedule.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>{`
|
||||
.justify-content-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.flex-direction-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
.h-100 {
|
||||
height: 100%;
|
||||
}
|
||||
.sticky-top {
|
||||
position: sticky;
|
||||
top: 5rem;
|
||||
}
|
||||
@media (min-width: 769px) {
|
||||
.sm-flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
.sm-items-center {
|
||||
align-items: center;
|
||||
}
|
||||
.md-flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
.md-items-center {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
import { ReschedulePickupView } from "../../components/orders/ReschedulePickupView";
|
||||
import { ReportDamageView } from "../../components/orders/ReportDamageView";
|
||||
import React, { useState } from 'react';
|
||||
import { useSeller } from '../../context/SellerContext';
|
||||
import { OrderItem } from '../../types/seller';
|
||||
import { OrderDetailView } from '../../components/orders/OrderDetailView';
|
||||
import { HandoverManifestView } from '../../components/orders/HandoverManifestView';
|
||||
import {
|
||||
Printer,
|
||||
Calendar,
|
||||
|
|
@ -19,6 +22,9 @@ export const OrdersPage: React.FC = () => {
|
|||
const { orders, reschedulePickup } = useSeller();
|
||||
const [activeTab, setActiveTab] = useState<'all' | OrderItem['status']>('all');
|
||||
const [activeOrder, setActiveOrder] = useState<OrderItem | null>(null);
|
||||
const [showManifest, setShowManifest] = useState(false);
|
||||
const [showReschedule, setShowReschedule] = useState(false);
|
||||
const [showReportDamage, setShowReportDamage] = useState(false);
|
||||
|
||||
// Modals state
|
||||
const [selectedOrderForLabel, setSelectedOrderForLabel] = useState<OrderItem | null>(null);
|
||||
|
|
@ -43,13 +49,89 @@ export const OrdersPage: React.FC = () => {
|
|||
alert('Generating combined PDF batch shipping manifest for 14 ready orders.');
|
||||
};
|
||||
|
||||
if (showManifest) {
|
||||
return (
|
||||
<HandoverManifestView
|
||||
onBack={() => setShowManifest(false)}
|
||||
onTabChange={(tab) => {
|
||||
if (tab === 'overall') {
|
||||
setShowManifest(false);
|
||||
setActiveTab('all');
|
||||
} else if (tab === 'ready_for_pickup') {
|
||||
setShowManifest(false);
|
||||
setActiveTab('ready_to_ship');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (showReschedule) {
|
||||
return (
|
||||
<ReschedulePickupView
|
||||
onBack={() => setShowReschedule(false)}
|
||||
onTabChange={(tab) => {
|
||||
if (tab === 'overall') {
|
||||
setShowReschedule(false);
|
||||
setActiveTab('all');
|
||||
} else if (tab === 'ready_for_pickup') {
|
||||
setShowReschedule(false);
|
||||
setActiveTab('ready_to_ship');
|
||||
} else if (tab === 'handover') {
|
||||
setShowReschedule(false);
|
||||
setShowManifest(true);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (showReportDamage) {
|
||||
return (
|
||||
<ReportDamageView
|
||||
order={orders[0]} // using first order as sample since the mockup shows a specific item
|
||||
onBack={() => setShowReportDamage(false)}
|
||||
onTabChange={(tab) => {
|
||||
if (tab === 'overall') {
|
||||
setShowReportDamage(false);
|
||||
setActiveTab('all');
|
||||
} else if (tab === 'ready_for_pickup') {
|
||||
setShowReportDamage(false);
|
||||
setActiveTab('ready_to_ship');
|
||||
} else if (tab === 'handover') {
|
||||
setShowReportDamage(false);
|
||||
setShowManifest(true);
|
||||
} else if (tab === 'reschedule') {
|
||||
setShowReportDamage(false);
|
||||
setShowReschedule(true);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (activeOrder) {
|
||||
return (
|
||||
<OrderDetailView
|
||||
order={activeOrder}
|
||||
onBack={() => setActiveOrder(null)}
|
||||
onPrintLabel={setSelectedOrderForLabel}
|
||||
onReschedule={setRescheduleOrder}
|
||||
onReschedule={() => {
|
||||
setActiveOrder(null);
|
||||
setShowReschedule(true);
|
||||
}}
|
||||
onTabChange={(tab) => {
|
||||
if (tab === 'handover') {
|
||||
setActiveOrder(null);
|
||||
setShowManifest(true);
|
||||
} else if (tab === 'overall') {
|
||||
setActiveOrder(null);
|
||||
setActiveTab('all');
|
||||
} else if (tab === 'report_damage') {
|
||||
setActiveOrder(null);
|
||||
setShowReportDamage(true);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -70,7 +152,7 @@ export const OrdersPage: React.FC = () => {
|
|||
</p>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center gap-3">
|
||||
<button className="button is-rounded is-light" style={{ height: '40px', fontWeight: 600, fontSize: '0.85rem' }}>
|
||||
<button onClick={() => setShowReschedule(true)} className="button is-rounded is-light" style={{ height: '40px', fontWeight: 600, fontSize: '0.85rem' }}>
|
||||
<Calendar size={16} className="mr-2 has-text-warning-dark" />
|
||||
Reschedule Pickup
|
||||
</button>
|
||||
|
|
@ -91,15 +173,15 @@ export const OrdersPage: React.FC = () => {
|
|||
<Inbox size={16} className="mr-2" />
|
||||
Ready for pickup
|
||||
</button>
|
||||
<button className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#F6F3F2', color: '#564243', fontWeight: 600 }}>
|
||||
<button onClick={() => setShowManifest(true)} className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#F6F3F2', color: '#564243', fontWeight: 600 }}>
|
||||
<CheckCircle2 size={16} className="mr-2" />
|
||||
Handover
|
||||
</button>
|
||||
<button className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#F6F3F2', color: '#564243', fontWeight: 600 }}>
|
||||
<button onClick={() => setShowReschedule(true)} className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#F6F3F2', color: '#564243', fontWeight: 600 }}>
|
||||
<Calendar size={16} className="mr-2" />
|
||||
Reschedule
|
||||
</button>
|
||||
<button className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#F6F3F2', color: '#564243', fontWeight: 600 }}>
|
||||
<button onClick={() => setShowReportDamage(true)} className="button is-rounded is-light is-small px-4" style={{ backgroundColor: '#F6F3F2', color: '#564243', fontWeight: 600 }}>
|
||||
<Truck size={16} className="mr-2" />
|
||||
Report transit damage
|
||||
</button>
|
||||
|
|
@ -126,7 +208,7 @@ export const OrdersPage: React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
<div className="is-flex is-align-items-center gap-2 w-100 w-auto-tablet">
|
||||
<button className="button is-ghost has-text-weight-bold" style={{ color: 'var(--trad-maroon)', fontSize: '0.85rem' }}>Reschedule</button>
|
||||
<button onClick={() => setShowReschedule(true)} className="button is-ghost has-text-weight-bold" style={{ color: 'var(--trad-maroon)', fontSize: '0.85rem' }}>Reschedule</button>
|
||||
<a href="tel:+919829014820" className="button is-rounded is-white is-small px-4" style={{ fontSize: '0.85rem', fontWeight: 600 }}>
|
||||
<PhoneCall size={14} className="mr-2 has-text-primary" style={{ color: 'var(--trad-maroon)' }} />
|
||||
Call Driver
|
||||
|
|
|
|||
Loading…
Reference in a new issue