This commit is contained in:
95
app/dashboard/admin/vendors/page.tsx
vendored
95
app/dashboard/admin/vendors/page.tsx
vendored
@@ -6,7 +6,9 @@ import { Badge } from "@/components/ui/badge";
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
||||||
import { Search, MoreHorizontal, UserCheck, UserX, Mail, Loader2, Store, Shield, ShieldAlert, Clock, Calendar } from "lucide-react";
|
import { Search, MoreHorizontal, UserCheck, UserX, Mail, Loader2, Store, Shield, ShieldAlert, Clock, Calendar, Pencil, Plus } from "lucide-react";
|
||||||
|
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api-client";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
@@ -41,6 +43,43 @@ export default function AdminVendorsPage() {
|
|||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [pagination, setPagination] = useState<PaginationResponse['pagination'] | null>(null);
|
const [pagination, setPagination] = useState<PaginationResponse['pagination'] | null>(null);
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
|
const [isEditStoreOpen, setIsEditStoreOpen] = useState(false);
|
||||||
|
const [editingVendor, setEditingVendor] = useState<Vendor | null>(null);
|
||||||
|
const [newStoreId, setNewStoreId] = useState("");
|
||||||
|
const [updating, setUpdating] = useState(false);
|
||||||
|
|
||||||
|
const handleEditStore = (vendor: Vendor) => {
|
||||||
|
setEditingVendor(vendor);
|
||||||
|
setNewStoreId(vendor.storeId || "");
|
||||||
|
setIsEditStoreOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveStoreId = async () => {
|
||||||
|
if (!editingVendor) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
setUpdating(true);
|
||||||
|
await fetchClient(`/admin/vendors/${editingVendor._id}/store-id`, {
|
||||||
|
method: 'PUT',
|
||||||
|
body: JSON.stringify({ storeId: newStoreId })
|
||||||
|
});
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: "Success",
|
||||||
|
description: "Store ID updated successfully",
|
||||||
|
});
|
||||||
|
setIsEditStoreOpen(false);
|
||||||
|
fetchVendors(); // Refresh list
|
||||||
|
} catch (error: any) {
|
||||||
|
toast({
|
||||||
|
title: "Error",
|
||||||
|
description: error.message || "Failed to update store ID",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setUpdating(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const fetchVendors = useCallback(async () => {
|
const fetchVendors = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
@@ -209,9 +248,29 @@ export default function AdminVendorsPage() {
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
{vendor.storeId ? (
|
{vendor.storeId ? (
|
||||||
|
<div className="flex items-center gap-2 group/store">
|
||||||
<span className="font-mono text-xs">{vendor.storeId}</span>
|
<span className="font-mono text-xs">{vendor.storeId}</span>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="h-6 w-6 opacity-0 group-hover/store:opacity-100 transition-opacity"
|
||||||
|
onClick={() => handleEditStore(vendor)}
|
||||||
|
>
|
||||||
|
<Pencil className="h-3 w-3" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-muted-foreground italic text-xs">No store</span>
|
<span className="text-muted-foreground italic text-xs">No store</span>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="h-6 w-6 text-muted-foreground hover:text-primary"
|
||||||
|
onClick={() => handleEditStore(vendor)}
|
||||||
|
>
|
||||||
|
<Plus className="h-3 w-3" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
@@ -291,6 +350,40 @@ export default function AdminVendorsPage() {
|
|||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Dialog open={isEditStoreOpen} onOpenChange={setIsEditStoreOpen}>
|
||||||
|
<DialogContent className="sm:max-w-[425px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Update Vendor Store</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Enter the Store ID to assign to vendor <span className="font-semibold text-foreground">{editingVendor?.username}</span>.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="grid gap-4 py-4">
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="storeId">Store ID</Label>
|
||||||
|
<Input
|
||||||
|
id="storeId"
|
||||||
|
value={newStoreId}
|
||||||
|
onChange={(e) => setNewStoreId(e.target.value)}
|
||||||
|
placeholder="Enter 24-character Store ID"
|
||||||
|
className="col-span-3 font-mono"
|
||||||
|
/>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
Ensure the Store ID corresponds to an existing store in the system.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="outline" onClick={() => setIsEditStoreOpen(false)} disabled={updating}>Cancel</Button>
|
||||||
|
<Button onClick={saveStoreId} disabled={updating || !newStoreId || newStoreId.length < 24}>
|
||||||
|
{updating && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||||
|
Save Changes
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</div >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user