"use client"; // Core React imports import { useState, useEffect } from "react"; // Local component imports import ChatBotCard from "./chat-bot-card"; // Type definitions and data import { ChatBot } from "@/app/(audiences)/for-students/data/chatbots"; /** * Props interface for the Section component that displays a group of chatbots * in a responsive grid layout with a title and subtitle */ interface SectionProps { title: string; subtitle: string; bots: ChatBot[]; columns?: number; } /** * Renders a section of chatbots with a header and responsive grid layout * Returns null if no bots are provided */ function Section({ title, subtitle, bots, columns = 4 }: SectionProps) { if (bots.length === 0) return null; return (

{title}

{subtitle}

{/* Responsive grid: 1 column on mobile, 2 on sm screens, configurable columns on lg */}
{bots.map((chatbot) => ( ))}
); } /** * Props interface for the main ChatBotGrid component * Includes filter criteria and functions to fetch different bot categories */ interface ChatBotGridProps { selectedCategories: string[]; selectedSubjects: string[]; searchQuery: string; getPopularBots: () => ChatBot[]; getTrendingBots: () => ChatBot[]; getAllBots: () => ChatBot[]; } /** * Main component that displays a filterable grid of chatbots * Supports filtering by category, subject, and search query * Shows different sections based on filter state */ export default function ChatBotGrid({ selectedCategories, selectedSubjects, searchQuery, getPopularBots, getTrendingBots, getAllBots, }: ChatBotGridProps) { // Initialize state with lazy evaluation using callback functions const [filteredPopularBots, setFilteredPopularBots] = useState( () => getPopularBots(), ); const [filteredTrendingBots, setFilteredTrendingBots] = useState( () => getTrendingBots(), ); const [filteredAllBots, setFilteredAllBots] = useState(() => getAllBots(), ); /** * Effect to filter bots whenever filter criteria or bot data changes * Applies search query, category, and subject filters */ useEffect(() => { const filterBots = (bots: ChatBot[]) => { let filtered = bots; // Apply text search filter across multiple fields if (searchQuery) { const query = searchQuery.toLowerCase(); filtered = filtered.filter( (bot) => bot.title.toLowerCase().includes(query) || bot.description.toLowerCase().includes(query) || bot.subject.toLowerCase().includes(query) || bot.category.toLowerCase().includes(query), ); } // Apply category filter if categories are selected if (selectedCategories.length > 0) { filtered = filtered.filter( (bot) => bot.category && selectedCategories.includes(bot.category), ); } // Apply subject filter if subjects are selected if (selectedSubjects.length > 0) { filtered = filtered.filter((bot) => selectedSubjects.includes(bot.subject), ); } return filtered; }; // Update all filtered bot lists setFilteredPopularBots(filterBots(getPopularBots())); setFilteredTrendingBots(filterBots(getTrendingBots())); setFilteredAllBots(filterBots(getAllBots())); }, [ selectedCategories, selectedSubjects, searchQuery, getPopularBots, getTrendingBots, getAllBots, ]); // Check if any filters are active const hasFiltersOrSearch = selectedCategories.length > 0 || selectedSubjects.length > 0 || searchQuery; // When filters are active, show only search results if (hasFiltersOrSearch) { return (
); } // Filter bots by category and subject for different sections const tutorBots = filteredAllBots.filter((bot) => bot.category === "教育"); const teachingBots = filteredAllBots.filter((bot) => bot.subject === "教學"); const assessmentBots = filteredAllBots.filter( (bot) => bot.subject === "評量", ); // Default view showing multiple sections of categorized bots return (
); }