From f498624eff07b85ec6cc7568fd7ea4d82aa3ac1a Mon Sep 17 00:00:00 2001
From: NotII <46204250+NotII@users.noreply.github.com>
Date: Tue, 25 Feb 2025 13:12:20 +0000
Subject: [PATCH] Cleanup
---
app/dashboard/orders/[id]/page.tsx | 539 +++++++++++++++++------------
components/tables/order-table.tsx | 55 ++-
2 files changed, 357 insertions(+), 237 deletions(-)
diff --git a/app/dashboard/orders/[id]/page.tsx b/app/dashboard/orders/[id]/page.tsx
index 3a18e62..6d199e5 100644
--- a/app/dashboard/orders/[id]/page.tsx
+++ b/app/dashboard/orders/[id]/page.tsx
@@ -24,7 +24,7 @@ import {
CardTitle,
} from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
-import { Clipboard, Truck, Package, ArrowRight } from "lucide-react";
+import { Clipboard, Truck, Package, ArrowRight, ChevronDown } from "lucide-react";
import { useRouter } from "next/navigation";
import { toast } from "sonner";
import {
@@ -38,6 +38,12 @@ import {
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
+import Layout from "@/components/layout/layout";
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+} from "@/components/ui/collapsible";
interface Order {
orderId: string;
@@ -58,16 +64,20 @@ interface Order {
const getStatusVariant = (status: string) => {
switch (status) {
+ case 'acknowledged':
+ return 'secondary';
case 'paid':
- return 'paid';
+ return 'default';
case 'shipped':
- return 'shipped';
+ return 'default';
case 'completed':
- return 'completed';
+ return 'default';
case 'cancelled':
return 'destructive';
+ case 'unpaid':
+ return 'secondary';
default:
- return 'unpaid';
+ return 'secondary';
}
};
@@ -87,6 +97,7 @@ export default function OrderDetailsPage() {
const [currentOrderNumber, setCurrentOrderNumber] = useState(0);
const [totalPages, setTotalPages] = useState(1);
const [currentPage, setCurrentPage] = useState(1);
+ const [isAcknowledging, setIsAcknowledging] = useState(false);
const router = useRouter();
const params = useParams();
@@ -177,9 +188,9 @@ export default function OrderDetailsPage() {
}
};
- const handleDiscardOrder = async () => {
+ const handleMarkAsAcknowledged = async () => {
try {
- setIsDiscarding(true);
+ setIsAcknowledging(true);
const authToken = document.cookie.split("Authorization=")[1];
const response = await fetchData(
`${process.env.NEXT_PUBLIC_API_URL}/orders/${orderId}`,
@@ -189,19 +200,47 @@ export default function OrderDetailsPage() {
"Content-Type": "application/json",
Authorization: `Bearer ${authToken}`,
},
- body: JSON.stringify({ status: "cancelled" }),
+ body: JSON.stringify({ status: "acknowledged" }),
}
);
if (response && response.message === "Order status updated successfully") {
- setOrder((prevOrder) => prevOrder ? { ...prevOrder, status: "cancelled" } : null);
- toast.success("Order discarded successfully!");
+ setOrder((prevOrder) => prevOrder ? { ...prevOrder, status: "acknowledged" } : null);
+ toast.success("Order marked as acknowledged!");
} else {
- throw new Error(response.error || "Failed to discard order");
+ throw new Error(response.error || "Failed to mark order as acknowledged");
}
} catch (error: any) {
- console.error("Failed to discard order:", error);
- toast.error(error.message || "Failed to discard order");
+ console.error("Failed to mark order as acknowledged:", error);
+ toast.error(error.message || "Failed to mark order as acknowledged");
+ } finally {
+ setIsAcknowledging(false);
+ }
+ };
+
+ const handleDiscardOrder = async () => {
+ try {
+ setIsDiscarding(true);
+ const authToken = document.cookie.split("Authorization=")[1];
+ const response = await fetchData(
+ `${process.env.NEXT_PUBLIC_API_URL}/orders/${orderId}`,
+ {
+ method: "DELETE",
+ headers: {
+ Authorization: `Bearer ${authToken}`,
+ },
+ }
+ );
+
+ if (response && response.message === "Order deleted successfully") {
+ toast.success("Order deleted successfully!");
+ router.push('/dashboard/orders');
+ } else {
+ throw new Error(response.error || "Failed to delete order");
+ }
+ } catch (error: any) {
+ console.error("Failed to delete order:", error);
+ toast.error(error.message || "Failed to delete order");
} finally {
setIsDiscarding(false);
}
@@ -345,235 +384,281 @@ export default function OrderDetailsPage() {
};
if (loading)
- return
Loading order details...
;
+ return (
+
+ Loading order details...
+
+ );
if (error)
- return Error: {error}
;
+ return (
+
+ Error: {error}
+
+ );
return (
-
-
-
-
-
Order Details: {order?.orderId}
+
+
+
+
+
+
Order Details: {order?.orderId}
+
+
+
+ {order?.status}
+
+
+
+
+ {/* Order Navigation - Moved to top */}
+
+
+ {nextOrderId && (
+ {
+ setLoading(true);
+ router.push(`/dashboard/orders/${nextOrderId}`);
+ }}
+ className="flex items-center"
+ >
+ ←
+ Older
+
+ )}
+
+
+ Navigate Orders
+
+
+ {prevOrderId && (
+ {
+ setLoading(true);
+ router.push(`/dashboard/orders/${prevOrderId}`);
+ }}
+ className="flex items-center"
+ >
+ Newer
+ →
+
+ )}
+
+
+
+
+
+
+ PGP Encrypted Address
+
+ Securely encrypted delivery address
+
+
+
+
+
+
+ copyToClipboard(order?.pgpAddress || "")}
+ >
+
+ Copy to Clipboard
+
+
+
+
+
+
+ Shipping Information
+
+ Shipping method and tracking details
+
+
+
+
+
Shipping Method
+
+ {order?.shippingMethod.type} - £
+ {order?.shippingMethod.price.toFixed(2)}
+
+
+
+ Tracking Number
+ setTrackingNumber(e.target.value)}
+ placeholder="Enter tracking number"
+ />
+
+
+
+
+
+ {isSending ? "Updating..." : "Update Tracking"}
+
+
+
-
-
- {order?.status}
-
-
-
-
- PGP Encrypted Address
-
- Securely encrypted delivery address
-
+ Order Items
-
-
-
- copyToClipboard(order?.pgpAddress || "")}
- >
-
- Copy to Clipboard
-
-
-
-
-
-
- Shipping Information
-
- Shipping method and tracking details
-
-
-
-
-
Shipping Method
-
- {order?.shippingMethod.type} - £
- {order?.shippingMethod.price.toFixed(2)}
-
-
-
- Tracking Number
- setTrackingNumber(e.target.value)}
- placeholder="Enter tracking number"
- />
-
-
-
-
-
- {isSending ? "Updating..." : "Update Tracking"}
-
-
-
-
-
-
-
- Order Items
-
-
-
-
-
- Item
- Quantity
- Price
- Total
-
-
-
- {order?.products.map((product) => (
-
-
- {productNames[product.productId] || "Loading..."}
-
- {product.quantity}
- £{product.pricePerUnit.toFixed(2)}
- £{product.totalItemPrice.toFixed(2)}
+
+
+
+ Item
+ Quantity
+ Price
+ Total
- ))}
-
-
- Total:
-
-
- £{order?.totalPrice.toFixed(2)}
-
-
-
-
-
-
+
+
+ {order?.products.map((product) => (
+
+
+ {productNames[product.productId] || "Loading..."}
+
+ {product.quantity}
+ £{product.pricePerUnit.toFixed(2)}
+ £{product.totalItemPrice.toFixed(2)}
+
+ ))}
+
+
+ Total:
+
+
+ £{order?.totalPrice.toFixed(2)}
+
+
+
+
+
+
- {/* Add Crypto Transaction Details */}
-
-
-
Crypto Transactions
- {order?.txid && order.txid.length > 0 ? (
-
- {order.txid.slice(order.txid.length > 2 ? 1 : 0).map((txid: string, index: number) => (
-
- {txid}
-
- ))}
-
- ) : (
-
No crypto transactions associated with this order
- )}
-
-
+ {/* Add Crypto Transaction Details */}
+
+
+
+
+
Crypto Transactions
+
+
+
+
+
+ {order?.txid && order.txid.length > 0 ? (
+
+ {order.txid.slice(order.txid.length > 2 ? 1 : 0).map((txid: string, index: number) => (
+
+ {txid}
+
+ ))}
+
+ ) : (
+
No crypto transactions associated with this order
+ )}
+
+
+
+
-
-
- {order?.status !== "cancelled" && (
-
-
-
- {isDiscarding ? "Discarding..." : "Discard Order"}
-
-
-
-
- Are you sure?
-
- This action will discard the order and cannot be undone.
-
-
-
- Cancel
-
- Discard Order
-
-
-
-
- )}
-
-
- {order?.status === "unpaid" && (
-
- {isPaid ? "Order Marked as Paid" : "Mark Order as Paid"}
-
- )}
-
- {order?.status === "paid" && (
-
-
- {isMarkingShipped ? "Updating..." : "Mark as Shipped"}
-
- )}
-
-
+
+
+ {order?.status !== "cancelled" && (
+
+
+
+ {isDiscarding ? "Deleting..." : "Delete Order"}
+
+
+
+
+ Are you sure?
+
+ This action will permanently delete the order and cannot be undone.
+
+
+
+ Cancel
+
+ Delete Order
+
+
+
+
+ )}
+
+
+ {(order?.status === "unpaid" || order?.status === "paid") && (
+
+ {isAcknowledging ? "Updating..." : "Mark as Acknowledged"}
+
+ )}
- {/* Order Navigation */}
-
-
- {prevOrderId && (
- {
- setLoading(true);
- router.push(`/dashboard/orders/${prevOrderId}`);
- }}
- className="flex items-center"
- >
- ←
- Newer
-
- )}
-
-
- {nextOrderId && (
- {
- setLoading(true);
- router.push(`/dashboard/orders/${nextOrderId}`);
- }}
- className="flex items-center"
- >
- Older
- →
-
- )}
+ {(order?.status === "unpaid" || order?.status === "acknowledged") && (
+
+ {isPaid ? "Order Marked as Paid" : "Mark Order as Paid"}
+
+ )}
+
+ {order?.status === "paid" && (
+
+
+ {isMarkingShipped ? "Updating..." : "Mark as Shipped"}
+
+ )}
+
-
+
);
}
\ No newline at end of file
diff --git a/components/tables/order-table.tsx b/components/tables/order-table.tsx
index 63ece16..2af22e9 100644
--- a/components/tables/order-table.tsx
+++ b/components/tables/order-table.tsx
@@ -1,6 +1,7 @@
"use client";
import { useState, useEffect, useCallback } from "react";
+import React from "react";
import {
Table,
TableBody,
@@ -57,10 +58,11 @@ type SortableColumns = "orderId" | "totalPrice" | "status" | "orderDate";
interface StatusConfig {
icon: React.ElementType;
color: string;
+ bgColor: string;
animate?: string;
}
-type OrderStatus = "paid" | "unpaid" | "confirming" | "shipped" | "completed" | "disputed" | "cancelled";
+type OrderStatus = "paid" | "unpaid" | "acknowledged" | "shipped" | "completed" | "cancelled" | "confirming";
export default function OrderTable() {
const [orders, setOrders] = useState
([]);
@@ -208,13 +210,42 @@ export default function OrderTable() {
};
const statusConfig: Record = {
- paid: { icon: CheckCircle2, color: "text-green-500" },
- unpaid: { icon: XCircle, color: "text-red-500" },
- confirming: { icon: Loader2, color: "text-yellow-500", animate: "animate-spin" },
- shipped: { icon: Truck, color: "text-blue-500" },
- completed: { icon: CheckCircle2, color: "text-gray-500" },
- disputed: { icon: XCircle, color: "text-orange-500" },
- cancelled: { icon: XCircle, color: "text-gray-400" }
+ acknowledged: {
+ icon: CheckCircle2,
+ color: "text-white",
+ bgColor: "bg-purple-600"
+ },
+ paid: {
+ icon: CheckCircle2,
+ color: "text-white",
+ bgColor: "bg-emerald-600"
+ },
+ unpaid: {
+ icon: XCircle,
+ color: "text-white",
+ bgColor: "bg-red-500"
+ },
+ confirming: {
+ icon: Loader2,
+ color: "text-white",
+ bgColor: "bg-yellow-500",
+ animate: "animate-spin"
+ },
+ shipped: {
+ icon: Truck,
+ color: "text-white",
+ bgColor: "bg-blue-600"
+ },
+ completed: {
+ icon: CheckCircle2,
+ color: "text-white",
+ bgColor: "bg-green-600"
+ },
+ cancelled: {
+ icon: XCircle,
+ color: "text-white",
+ bgColor: "bg-gray-500"
+ }
};
return (
@@ -317,8 +348,12 @@ export default function OrderTable() {
#{order.orderId}
£{order.totalPrice.toFixed(2)}
-
-
+
+ {React.createElement(statusConfig[order.status as OrderStatus]?.icon || XCircle, {
+ className: `h-4 w-4 ${statusConfig[order.status as OrderStatus]?.animate || ""}`
+ })}
{order.status.charAt(0).toUpperCase() + order.status.slice(1)}