feat: Implement smart back navigation with fallback across all detail/edit pages
Implemented context-aware back button that respects user's navigation path:
Pattern:
```typescript
const handleBack = () => {
if (window.history.state?.idx > 0) {
navigate(-1); // Go back in history
} else {
navigate('/fallback'); // Safe fallback
}
};
```
Updated Pages:
✅ Orders/Detail.tsx → Fallback: /orders
✅ Orders/Edit.tsx → Fallback: /orders/:id
✅ Customers/Detail.tsx → Fallback: /customers
✅ Customers/Edit.tsx → Fallback: /customers
✅ Products/Edit.tsx → Fallback: /products
✅ Coupons/Edit.tsx → Fallback: /coupons
User Flow Examples:
1. Normal Navigation (History Available):
Customers Index → Customer Detail → Orders Tab → Order Detail
→ Click Back → Returns to Customer Detail ✅
2. Direct Access (No History):
User opens /orders/360 directly
→ Click Back → Goes to /orders (fallback) ✅
3. New Tab (No History):
User opens order in new tab
→ Click Back → Goes to /orders (fallback) ✅
4. Page Refresh (History Cleared):
User refreshes page
→ Click Back → Goes to fallback ✅
Benefits:
✅ Respects user's navigation path when possible
✅ Never breaks or leaves the app
✅ Predictable behavior in all scenarios
✅ Professional UX (like Gmail, Shopify, etc.)
✅ Works with deep links and bookmarks
Technical:
- Uses window.history.state.idx to detect history
- Falls back to safe default when no history
- Consistent pattern across all pages
- No URL parameters needed
Result: Back button now works intelligently based on context!
This commit is contained in:
@@ -43,11 +43,20 @@ export default function CouponEdit() {
|
||||
},
|
||||
});
|
||||
|
||||
// Smart back handler: go back in history if available, otherwise fallback to /coupons
|
||||
const handleBack = () => {
|
||||
if (window.history.state?.idx > 0) {
|
||||
navigate(-1); // Go back in history
|
||||
} else {
|
||||
navigate('/coupons'); // Fallback to coupons index
|
||||
}
|
||||
};
|
||||
|
||||
// Set contextual header
|
||||
useEffect(() => {
|
||||
const actions = (
|
||||
<div className="flex gap-2">
|
||||
<Button size="sm" variant="ghost" onClick={() => navigate('/coupons')}>
|
||||
<Button size="sm" variant="ghost" onClick={handleBack}>
|
||||
{__('Back')}
|
||||
</Button>
|
||||
<Button
|
||||
|
||||
@@ -37,6 +37,15 @@ export default function CustomerDetail() {
|
||||
const orders = ordersQuery.data?.rows || [];
|
||||
const { setPageHeader, clearPageHeader } = usePageHeader();
|
||||
|
||||
// Smart back handler: go back in history if available, otherwise fallback to /customers
|
||||
const handleBack = () => {
|
||||
if (window.history.state?.idx > 0) {
|
||||
navigate(-1); // Go back in history
|
||||
} else {
|
||||
navigate('/customers'); // Fallback to customers index
|
||||
}
|
||||
};
|
||||
|
||||
// Page header
|
||||
React.useEffect(() => {
|
||||
if (!customer) {
|
||||
@@ -46,7 +55,7 @@ export default function CustomerDetail() {
|
||||
|
||||
const actions = (
|
||||
<div className="flex gap-2">
|
||||
<Button size="sm" variant="ghost" onClick={() => navigate('/customers')}>
|
||||
<Button size="sm" variant="ghost" onClick={handleBack}>
|
||||
{__('Back')}
|
||||
</Button>
|
||||
<Button size="sm" onClick={() => navigate(`/customers/${customerId}/edit`)}>
|
||||
|
||||
@@ -46,11 +46,20 @@ export default function CustomerEdit() {
|
||||
await updateMutation.mutateAsync(data);
|
||||
};
|
||||
|
||||
// Smart back handler: go back in history if available, otherwise fallback to /customers
|
||||
const handleBack = () => {
|
||||
if (window.history.state?.idx > 0) {
|
||||
navigate(-1); // Go back in history
|
||||
} else {
|
||||
navigate('/customers'); // Fallback to customers index
|
||||
}
|
||||
};
|
||||
|
||||
// Set page header with back button and save button
|
||||
useEffect(() => {
|
||||
const actions = (
|
||||
<div className="flex gap-2">
|
||||
<Button size="sm" variant="ghost" onClick={() => navigate('/customers')}>
|
||||
<Button size="sm" variant="ghost" onClick={handleBack}>
|
||||
{__('Back')}
|
||||
</Button>
|
||||
<Button
|
||||
|
||||
@@ -143,6 +143,15 @@ export default function OrderShow() {
|
||||
retryPaymentMutation.mutate();
|
||||
}
|
||||
|
||||
// Smart back handler: go back in history if available, otherwise fallback to /orders
|
||||
const handleBack = () => {
|
||||
if (window.history.state?.idx > 0) {
|
||||
nav(-1); // Go back in history
|
||||
} else {
|
||||
nav('/orders'); // Fallback to orders index
|
||||
}
|
||||
};
|
||||
|
||||
// Set contextual header with Back button and Edit action
|
||||
useEffect(() => {
|
||||
if (!order || isPrintMode) {
|
||||
@@ -152,7 +161,7 @@ export default function OrderShow() {
|
||||
|
||||
const actions = (
|
||||
<div className="flex gap-2">
|
||||
<Button size="sm" variant="ghost" onClick={() => nav('/orders')}>
|
||||
<Button size="sm" variant="ghost" onClick={handleBack}>
|
||||
{__('Back')}
|
||||
</Button>
|
||||
<Link to={`/orders/${id}/edit`}>
|
||||
|
||||
@@ -60,11 +60,20 @@ export default function OrdersEdit() {
|
||||
}
|
||||
}, [order.meta]);
|
||||
|
||||
// Smart back handler: go back in history if available, otherwise fallback to order detail
|
||||
const handleBack = () => {
|
||||
if (window.history.state?.idx > 0) {
|
||||
nav(-1); // Go back in history
|
||||
} else {
|
||||
nav(`/orders/${orderId}`); // Fallback to order detail
|
||||
}
|
||||
};
|
||||
|
||||
// Set page header with back button and save button
|
||||
useEffect(() => {
|
||||
const actions = (
|
||||
<div className="flex gap-2">
|
||||
<Button size="sm" variant="ghost" onClick={() => nav(`/orders/${orderId}`)}>
|
||||
<Button size="sm" variant="ghost" onClick={handleBack}>
|
||||
{__('Back')}
|
||||
</Button>
|
||||
<Button
|
||||
|
||||
@@ -66,11 +66,20 @@ export default function ProductEdit() {
|
||||
}
|
||||
}, [productQ.data?.meta]);
|
||||
|
||||
// Smart back handler: go back in history if available, otherwise fallback to /products
|
||||
const handleBack = () => {
|
||||
if (window.history.state?.idx > 0) {
|
||||
navigate(-1); // Go back in history
|
||||
} else {
|
||||
navigate('/products'); // Fallback to products index
|
||||
}
|
||||
};
|
||||
|
||||
// Set page header with back button and save button
|
||||
useEffect(() => {
|
||||
const actions = (
|
||||
<div className="flex gap-2">
|
||||
<Button size="sm" variant="ghost" onClick={() => navigate('/products')}>
|
||||
<Button size="sm" variant="ghost" onClick={handleBack}>
|
||||
{__('Back')}
|
||||
</Button>
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user