import { useState, useEffect } from "react"; import { useLocation } from "wouter"; import { useAuth } from "@/hooks/use-auth"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { adminApi, categoriesApi, productsApi } from "@/lib/api"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Separator } from "@/components/ui/separator"; import { Skeleton } from "@/components/ui/skeleton"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { useToast } from "@/hooks/use-toast"; import { Users, Store, Package, Settings, Plus, Trash2, Edit, Eye, ShoppingCart, MapPin, ExternalLink } from "lucide-react"; const sellerSchema = z.object({ username: z.string().min(3, "Username must be at least 3 characters"), password: z.string().min(6, "Password must be at least 6 characters"), }); const categorySchema = z.object({ name: z.string().min(1, "Category name is required"), icon: z.string().optional(), imageUrl: z.string().url().optional().or(z.literal("")), }); const productSchema = z.object({ title: z.string().min(1, "Product title is required"), description: z.string().min(1, "Product description is required"), price: z.string().min(1, "Price is required"), originalPrice: z.string().optional(), stock: z.string().min(1, "Stock is required"), categoryId: z.string().min(1, "Category is required"), isActive: z.boolean().default(true), }); type SellerFormData = z.infer; type CategoryFormData = z.infer; type ProductFormData = z.infer; export default function AdminDev() { const [, setLocation] = useLocation(); const { userType, adminLogin } = useAuth(); const { toast } = useToast(); const queryClient = useQueryClient(); const [isSellerDialogOpen, setIsSellerDialogOpen] = useState(false); const [isCategoryDialogOpen, setIsCategoryDialogOpen] = useState(false); const [editingCategory, setEditingCategory] = useState(null); const [editingProduct, setEditingProduct] = useState(null); const [isProductDialogOpen, setIsProductDialogOpen] = useState(false); // Auto-login as admin if not already useEffect(() => { if (userType !== 'admin') { adminLogin(); } }, [userType, adminLogin]); const { data: sellers = [], isLoading: sellersLoading } = useQuery({ queryKey: ['/api/admin/sellers'], queryFn: () => adminApi.getSellers(), }); const { data: categories = [], isLoading: categoriesLoading } = useQuery({ queryKey: ['/api/categories'], queryFn: () => categoriesApi.getAll(), }); const { data: products = [], isLoading: productsLoading } = useQuery({ queryKey: ['/api/products'], queryFn: () => productsApi.getAll(), }); const { data: orders = [], isLoading: ordersLoading } = useQuery({ queryKey: ['/api/admin/orders'], queryFn: () => adminApi.getOrders(), }); const { data: users = [], isLoading: usersLoading } = useQuery({ queryKey: ['/api/admin/users'], queryFn: async () => { const response = await fetch('/api/admin/users'); return response.json(); }, }); const sellerForm = useForm({ resolver: zodResolver(sellerSchema), defaultValues: { username: "", password: "", }, }); const categoryForm = useForm({ resolver: zodResolver(categorySchema), defaultValues: { name: "", icon: "", imageUrl: "", }, }); const productForm = useForm({ resolver: zodResolver(productSchema), defaultValues: { title: "", description: "", price: "", originalPrice: "", stock: "", categoryId: "", isActive: true, }, }); const createSellerMutation = useMutation({ mutationFn: (data: SellerFormData) => adminApi.createSeller(data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/api/admin/sellers'] }); setIsSellerDialogOpen(false); sellerForm.reset(); toast({ title: "Seller created", description: "New seller account has been created successfully.", }); }, onError: () => { toast({ variant: "destructive", title: "Error", description: "Failed to create seller account.", }); }, }); const deleteSellerMutation = useMutation({ mutationFn: (id: string) => adminApi.deleteSeller(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/api/admin/sellers'] }); toast({ title: "Seller deleted", description: "Seller account and all associated products have been deleted.", }); }, onError: () => { toast({ variant: "destructive", title: "Error", description: "Failed to delete seller account.", }); }, }); const createCategoryMutation = useMutation({ mutationFn: (data: CategoryFormData) => categoriesApi.create(data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/api/categories'] }); setIsCategoryDialogOpen(false); categoryForm.reset(); toast({ title: "Category created", description: "New category has been created successfully.", }); }, onError: () => { toast({ variant: "destructive", title: "Error", description: "Failed to create category.", }); }, }); const deleteCategoryMutation = useMutation({ mutationFn: (id: string) => categoriesApi.delete(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/api/categories'] }); toast({ title: "Category deleted", description: "Category has been deleted successfully.", }); }, onError: () => { toast({ variant: "destructive", title: "Error", description: "Failed to delete category.", }); }, }); const updateCategoryMutation = useMutation({ mutationFn: ({ id, data }: { id: string; data: CategoryFormData }) => categoriesApi.update(id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/api/categories'] }); setEditingCategory(null); setIsCategoryDialogOpen(false); categoryForm.reset(); toast({ title: "Category updated", description: "Category has been updated successfully.", }); }, onError: () => { toast({ variant: "destructive", title: "Error", description: "Failed to update category.", }); }, }); const updateProductMutation = useMutation({ mutationFn: ({ id, data }: { id: string; data: ProductFormData }) => adminApi.updateProduct(id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/api/products'] }); setEditingProduct(null); setIsProductDialogOpen(false); productForm.reset(); toast({ title: "Product updated", description: "Product has been updated successfully.", }); }, onError: () => { toast({ variant: "destructive", title: "Error", description: "Failed to update product.", }); }, }); const deleteProductMutation = useMutation({ mutationFn: (id: string) => adminApi.deleteProduct(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/api/products'] }); toast({ title: "Product deleted", description: "Product has been deleted successfully.", }); }, onError: () => { toast({ variant: "destructive", title: "Error", description: "Failed to delete product.", }); }, }); const updateOrderMutation = useMutation({ mutationFn: ({ id, data }: { id: string; data: any }) => adminApi.updateOrder(id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/api/admin/orders'] }); toast({ title: "Order updated", description: "Order status has been updated successfully.", }); }, onError: () => { toast({ variant: "destructive", title: "Error", description: "Failed to update order status.", }); }, }); const handleUpdateOrderStatus = (id: string, data: any) => { updateOrderMutation.mutate({ id, data }); }; const onCreateSeller = (data: SellerFormData) => { createSellerMutation.mutate(data); }; const onCreateCategory = (data: CategoryFormData) => { createCategoryMutation.mutate(data); }; const onEditCategory = (data: CategoryFormData) => { if (editingCategory) { updateCategoryMutation.mutate({ id: editingCategory.id, data }); } }; const onEditProduct = (data: ProductFormData) => { if (editingProduct) { updateProductMutation.mutate({ id: editingProduct.id, data }); } }; const handleEditCategory = (category: any) => { setEditingCategory(category); categoryForm.reset({ name: category.name, icon: category.icon || "", imageUrl: category.imageUrl || "", }); setIsCategoryDialogOpen(true); }; const handleEditProduct = (product: any) => { setEditingProduct(product); productForm.reset({ title: product.title, description: product.description, price: product.price.toString(), originalPrice: product.originalPrice ? product.originalPrice.toString() : "", stock: product.stock.toString(), categoryId: product.categoryId, isActive: product.isActive, }); setIsProductDialogOpen(true); }; const handleCancelEdit = () => { setEditingCategory(null); setEditingProduct(null); setIsCategoryDialogOpen(false); setIsProductDialogOpen(false); categoryForm.reset(); productForm.reset(); }; return (

Shoposphere Admin

Developer Administration Panel

Sellers Users Categories Products Orders Settings Seller Management Create New Seller
( Username )} /> ( Password )} />
{sellersLoading ? (
{[...Array(3)].map((_, i) => (
))}
) : sellers.length > 0 ? (
{sellers.map((seller: any) => (

{seller.username}

Created: {new Date(seller.createdAt).toLocaleDateString()}

Login Credentials:

Username: {seller.username}
Password: {seller.plainTextPassword || 'Not available'}

))}
) : (

No sellers created yet.

)}
User Locations & Information {usersLoading ? (
{[...Array(5)].map((_, i) => (
))}
) : users.length > 0 ? (
{users.map((user: any) => (

{user.firstName} {user.lastName}

@{user.username}

📧 {user.email} • 📞 {user.phone}

Joined: {new Date(user.createdAt).toLocaleDateString()}

{/* Location Information */}
{user.locationDetectedAutomatically && user.googleMapsUrl ? (
Auto-detected location
📍 {Number(user.latitude).toFixed(4)}, {Number(user.longitude).toFixed(4)}
) : user.street && user.city ? (
Manual address

{user.street}, {user.city}, {user.state} {user.pinCode}, {user.country}

) : (
No location provided
)}

User ID: {user.id.slice(-8)}

))}
) : (

No users registered yet.

)}
Category Management { setIsCategoryDialogOpen(open); if (!open) handleCancelEdit(); }}> {editingCategory ? 'Edit Category' : 'Create New Category'}
( Category Name )} /> ( Icon (optional) )} /> ( Image URL (optional) )} />
{editingCategory && ( )}
{categoriesLoading ? (
{[...Array(3)].map((_, i) => (
))}
) : categories.length > 0 ? (
{categories.map((category: any) => (
{category.imageUrl && (
{category.name}
)}

{category.name}

{category.icon && (

Icon: {category.icon}

)} {category.imageUrl && (

Image: {category.imageUrl}

)}
))}
) : (

No categories created yet.

)}
Product Management { setIsProductDialogOpen(open); if (!open) handleCancelEdit(); }}> Edit Product {editingProduct && (
( Product Title )} /> ( Description )} /> ( Price )} /> ( Original Price (optional) )} /> ( Stock )} /> ( Category )} />
)}
{productsLoading ? (
{[...Array(5)].map((_, i) => (
))}
) : products.length > 0 ? (
{products.map((product: any) => (
{product.images && product.images.length > 0 ? ( {product.title} ) : (
No Image
)}

{product.title}

By: {product.seller?.username || 'Unknown Seller'}

₹{parseFloat(product.price).toFixed(2)} {product.isActive ? 'Active' : 'Inactive'}
))}
) : (

No products available.

)}
System Settings

Platform Statistics

{sellers.length}
Total Sellers
{products.length}
Total Products
{categories.length}
Total Categories

Quick Actions

Order Management {ordersLoading ? (
{[...Array(5)].map((_, i) => ( ))}
) : orders.length === 0 ? (

No orders found.

) : (
{orders.map((order: any) => (

Order #{order.id.slice(-8)}

Placed on {new Date(order.createdAt).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}

{order.status} {order.paymentStatus === 'paid' ? 'Paid' : 'Unpaid'}

₹{parseFloat(order.total).toFixed(2)}

{/* Customer Info */}

Customer Information

{order.user && (

Name: {order.user.firstName} {order.user.lastName}

Email: {order.user.email}

Phone: {order.user.phone}

Payment: {order.paymentMethod === 'cod' ? 'Cash on Delivery' : 'UPI'}

)}

Address: {order.shippingAddress}

{/* Admin Order Management Actions */}
{/* Order Items */}

Items Ordered

{order.items?.map((item: any, index: number) => (
{item.product?.images?.[0] ? ( {item.product.title} ) : (
)}

{item.product?.title}

Qty: {item.quantity}

₹{parseFloat(item.price).toFixed(2)}

₹{(parseFloat(item.price) * item.quantity).toFixed(2)} total

))}

Subtotal: ₹{parseFloat(order.subtotal).toFixed(2)}

Tax: ₹{parseFloat(order.tax).toFixed(2)}

Shipping: ₹{parseFloat(order.shipping || '0').toFixed(2)}

Total: ₹{parseFloat(order.total).toFixed(2)}

))}
)}
); }