Feature: Royal Mail tracking integration (hybrid approach)
Add ability to sync shipment tracking data from Royal Mail API: - Create Royal Mail API service (src/lib/royalmail.ts) to fetch tracking status - Add sync-tracking endpoint to pull latest status from Royal Mail - Create SyncRoyalMailButton component for admin panel - Add 'Sync from Royal Mail' button on order detail page - Auto-update order status based on Royal Mail tracking status Admin workflow: 1. Create shipping label in Royal Mail Click & Drop 2. Copy tracking number into tracking form 3. Click 'Sync from Royal Mail' to fetch and update status 4. System maps Royal Mail status to our order status (SHIPPED, DELIVERED, etc) Uses Royal Mail's public tracking API - no special credentials required. Supports manual label creation workflow (hybrid approach).
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
interface SyncRoyalMailButtonProps {
|
||||
orderId: string;
|
||||
trackingNumber?: string | null;
|
||||
onSuccess?: () => void;
|
||||
}
|
||||
|
||||
export default function SyncRoyalMailButton({ orderId, trackingNumber, onSuccess }: SyncRoyalMailButtonProps) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
|
||||
|
||||
const handleSync = async () => {
|
||||
if (!trackingNumber) {
|
||||
setMessage({ type: 'error', text: 'Please enter a tracking number first' });
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
setMessage(null);
|
||||
|
||||
try {
|
||||
const res = await fetch(`/api/orders/${orderId}/sync-tracking`, {
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (!res.ok) {
|
||||
setMessage({ type: 'error', text: data.error || 'Failed to sync tracking' });
|
||||
return;
|
||||
}
|
||||
|
||||
setMessage({
|
||||
type: 'success',
|
||||
text: `Tracking synced! Status: ${data.trackingData.status}`,
|
||||
});
|
||||
|
||||
onSuccess?.();
|
||||
} catch (err) {
|
||||
setMessage({ type: 'error', text: 'Error syncing with Royal Mail' });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleSync}
|
||||
disabled={loading || !trackingNumber}
|
||||
className="bg-splash-blue px-4 py-2 text-sm font-medium text-paper hover:bg-splash-blue/90 disabled:opacity-60"
|
||||
>
|
||||
{loading ? 'Syncing...' : '🔄 Sync from Royal Mail'}
|
||||
</button>
|
||||
|
||||
{message && (
|
||||
<p
|
||||
className={`text-sm ${
|
||||
message.type === 'success' ? 'text-splash-blue' : 'text-splash-pink'
|
||||
}`}
|
||||
>
|
||||
{message.text}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user