import { fetchQuery } from "convex/nextjs" import { api } from "@/convex/_generated/api" import { hasConvexUrl } from "@/lib/convex-config" import type { Product } from "@/lib/products/types" import type { Manual } from "@/lib/manuals-types" type ConvexProductDoc = { _id: string name: string description?: string price: number currency: string images: string[] metadata?: Record stripeProductId?: string stripePriceId?: string active: boolean } type ConvexManualDoc = { filename: string path: string manufacturer: string category: string size?: number lastModified?: number searchTerms?: string[] commonNames?: string[] thumbnailUrl?: string manualUrl?: string } type ConvexOrderItem = { productId?: string | null productName: string price: number quantity: number priceId: string image?: string } export type ConvexAdminOrder = { id: string customerEmail: string customerName?: string totalAmount: number currency: string status: "pending" | "paid" | "fulfilled" | "cancelled" | "refunded" stripeSessionId: string | null paymentIntentId: string | null createdAt: string updatedAt: string shippingAddress?: { name?: string address?: string city?: string state?: string zipCode?: string country?: string } items: ConvexOrderItem[] } function mapConvexProduct(product: ConvexProductDoc): Product { return { id: product._id, stripeId: product.stripeProductId ?? product._id, name: product.name, description: product.description ?? null, price: product.price, currency: product.currency, images: product.images ?? [], metadata: product.metadata, priceId: product.stripePriceId, } } function mapConvexManual(manual: ConvexManualDoc): Manual { return { filename: manual.filename, path: manual.manualUrl || manual.path, manufacturer: manual.manufacturer, category: manual.category, size: manual.size, lastModified: manual.lastModified ? new Date(manual.lastModified) : undefined, searchTerms: manual.searchTerms, commonNames: manual.commonNames, thumbnailUrl: manual.thumbnailUrl, } } export async function listConvexProducts(): Promise { if (!hasConvexUrl()) { return [] } const products = await fetchQuery(api.products.listActive, {}) return (products as ConvexProductDoc[]).map(mapConvexProduct) } export async function listConvexAdminProducts(search?: string): Promise { if (!hasConvexUrl()) { return [] } const products = await fetchQuery(api.products.listAdmin, { search }) return (products as ConvexProductDoc[]).map(mapConvexProduct) } export async function getConvexProduct(id: string): Promise { if (!hasConvexUrl()) { return null } const products = await fetchQuery(api.products.listAdmin, {}) const match = (products as ConvexProductDoc[]).find((product) => { return product._id === id || product.stripeProductId === id }) return match ? mapConvexProduct(match) : null } export async function listConvexManuals(): Promise { if (!hasConvexUrl()) { return [] } const manuals = await fetchQuery(api.manuals.list, {}) return (manuals as ConvexManualDoc[]).map(mapConvexManual) } export async function getConvexManualDashboard() { if (!hasConvexUrl()) { return null } return await fetchQuery(api.manuals.dashboard, {}) } export async function getConvexOrderMetrics() { if (!hasConvexUrl()) { return null } return await fetchQuery(api.orders.getMetrics, {}) } export async function listConvexOrders(options?: { status?: ConvexAdminOrder["status"] search?: string }): Promise { if (!hasConvexUrl()) { return [] } return await fetchQuery(api.orders.listAdmin, { status: options?.status, search: options?.search, }) }