feat(admin): edit order status with dropdown and notify partner by email
Some checks failed
Staging Build / build (push) Has been cancelled

This commit is contained in:
DanielS
2026-06-26 09:04:06 +02:00
parent c9ae185fdf
commit fbab22506b
2 changed files with 148 additions and 6 deletions

View File

@@ -1,11 +1,18 @@
"use client";
import { useState } from "react";
import { useState, useEffect } from "react";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Download, ExternalLink, Search } from "lucide-react";
import { Download, ExternalLink, Search, Loader2 } from "lucide-react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { updateOrderStatus } from "@/lib/actions/orders";
interface OrdersTableProps {
initialOrders: any[];
@@ -26,10 +33,29 @@ const statusClass: Record<string, string> = {
};
export function OrdersTable({ initialOrders }: OrdersTableProps) {
const [orders, setOrders] = useState(initialOrders);
const [search, setSearch] = useState("");
const [statusFilter, setStatusFilter] = useState<string>("all");
const [updatingId, setUpdatingId] = useState<string | null>(null);
const filteredOrders = initialOrders.filter((order) => {
useEffect(() => {
setOrders(initialOrders);
}, [initialOrders]);
const handleStatusChange = async (orderId: string, newStatus: 'pending' | 'active' | 'completed' | 'cancelled') => {
setUpdatingId(orderId);
try {
await updateOrderStatus(orderId, newStatus);
setOrders(prev => prev.map(o => o.id === orderId ? { ...o, status: newStatus } : o));
} catch (error) {
console.error(error);
alert("Fehler beim Ändern des Status.");
} finally {
setUpdatingId(null);
}
};
const filteredOrders = orders.filter((order) => {
const orderNum = (order.order_number || "").toLowerCase();
const company = (order.customer_data?.company_name || "").toLowerCase();
const contact = `${order.customer_data?.first_name || ""} ${order.customer_data?.last_name || ""}`.toLowerCase();
@@ -163,9 +189,31 @@ export function OrdersTable({ initialOrders }: OrdersTableProps) {
{new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(order.total_price)}
</TableCell>
<TableCell>
<Badge className={`text-xs px-2 py-0.5 rounded ${statusClass[order.status] ?? 'bg-slate-500/20 text-slate-300'}`}>
{statusLabel[order.status] ?? order.status}
</Badge>
<DropdownMenu>
<DropdownMenuTrigger asChild disabled={updatingId === order.id}>
<button className="focus:outline-none focus:ring-0 active:scale-95 disabled:pointer-events-none transition-transform duration-100">
<Badge className={`text-xs px-2 py-0.5 rounded cursor-pointer transition-all duration-200 hover:opacity-85 flex items-center gap-1.5 ${statusClass[order.status] ?? 'bg-slate-500/20 text-slate-300'}`}>
{updatingId === order.id ? (
<Loader2 className="w-3 h-3 animate-spin mr-1" />
) : null}
{statusLabel[order.status] ?? order.status}
<span className="text-[9px] opacity-70"></span>
</Badge>
</button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="bg-slate-900 border-white/10 text-white min-w-[140px]">
{Object.entries(statusLabel).map(([key, label]) => (
<DropdownMenuItem
key={key}
disabled={updatingId === order.id}
onClick={() => handleStatusChange(order.id, key as any)}
className={`text-xs cursor-pointer hover:bg-white/10 transition-colors focus:bg-white/10 focus:text-white ${order.status === key ? 'font-bold text-primary' : ''}`}
>
{label}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</TableCell>
<TableCell className="text-right">
{order.pdf_url ? (