/** * Browse API — fetches plants with disease counts from the Turso DB * for the browse page. Runs server-side only. */ import { sql, eq } from "drizzle-orm"; import { getDb } from "@/lib/db/index"; import { plants, diseases, plantViews } from "@/lib/db/schema"; import type { PlantCardData } from "@/components/PlantCard"; export type { PlantCardData }; /** * Get all plants with their disease counts for the browse page. */ export async function getBrowsePlants(): Promise { const db = getDb(); // LEFT JOIN to include plants with zero diseases const rows = await db .select({ id: plants.id, commonName: plants.commonName, scientificName: plants.scientificName, family: plants.family, category: plants.category, imageUrl: plants.imageUrl, updatedAt: plants.updatedAt, viewCount: sql`COALESCE(${plantViews.viewCount}, 0)`, diseaseCount: sql`COUNT(${diseases.id})`, }) .from(plants) .leftJoin(diseases, eq(diseases.plantId, plants.id)) .leftJoin(plantViews, eq(plantViews.plantId, plants.id)) .groupBy(plants.id) .orderBy(plants.commonName); return rows.map((r) => ({ id: r.id, commonName: r.commonName, scientificName: r.scientificName, family: r.family, category: r.category, imageUrl: r.imageUrl, updatedAt: r.updatedAt, viewCount: r.viewCount, diseaseCount: r.diseaseCount, })); } /** * Get a single plant with disease count (for detail page lookups). */ export async function getBrowsePlant(id: string): Promise { const db = getDb(); const rows = await db .select({ id: plants.id, commonName: plants.commonName, scientificName: plants.scientificName, family: plants.family, category: plants.category, imageUrl: plants.imageUrl, diseaseCount: sql`COUNT(${diseases.id})`, }) .from(plants) .leftJoin(diseases, eq(diseases.plantId, plants.id)) .where(eq(plants.id, id)) .groupBy(plants.id) .limit(1); return rows[0] ?? null; } /** * Get featured plants for the homepage (subset). */ const FEATURED_IDS = [ "tomato", "basil", "rose", "monstera", "snake-plant", "pepper", "apple", "corn", "wheat", "strawberry", "blueberry", "lettuce", ]; export async function getFeaturedPlants(): Promise { const all = await getBrowsePlants(); const featured = all.filter((p) => FEATURED_IDS.includes(p.id)); // If fewer than expected are found, pad with first available plants if (featured.length < 6) { const rest = all.filter((p) => !FEATURED_IDS.includes(p.id)); return [...featured, ...rest].slice(0, 12); } return featured.slice(0, 12); }