From febc7ae4beb332bf4a2e26ea760055776bb70a7b Mon Sep 17 00:00:00 2001 From: Tushar Verma Date: Tue, 4 Nov 2025 12:40:59 +0530 Subject: [PATCH] feat: Implement search functionality for chapters and lessons --- .../OutlineDrawer/OutlineDrawer.module.css | 21 +++++ .../OutlineDrawer/OutlineDrawer.tsx | 88 ++++++++++++++++--- app/utils/hooks.ts | 47 ++++++++++ 3 files changed, 142 insertions(+), 14 deletions(-) create mode 100644 app/utils/hooks.ts diff --git a/app/components/OutlineDrawer/OutlineDrawer.module.css b/app/components/OutlineDrawer/OutlineDrawer.module.css index 5a06e20..17a8b2b 100644 --- a/app/components/OutlineDrawer/OutlineDrawer.module.css +++ b/app/components/OutlineDrawer/OutlineDrawer.module.css @@ -2,3 +2,24 @@ display: flex; flex-direction: column; } + +/* + No results message styling + Displayed when search query returns no matching chapters or lessons +*/ +.noResults { + text-align: center; + padding: 2rem 1rem; + color: var(--chakra-colors-gray-500); +} + +.noResults p:first-child { + font-weight: 600; + margin-bottom: 0.5rem; + font-size: 1rem; +} + +.noResults p:last-child { + font-size: 0.875rem; + opacity: 0.8; +} diff --git a/app/components/OutlineDrawer/OutlineDrawer.tsx b/app/components/OutlineDrawer/OutlineDrawer.tsx index 1804539..6a4aae1 100644 --- a/app/components/OutlineDrawer/OutlineDrawer.tsx +++ b/app/components/OutlineDrawer/OutlineDrawer.tsx @@ -7,6 +7,9 @@ import { DrawerCloseButton, DrawerBody, Button, + Input, + InputGroup, + InputLeftElement, } from "@chakra-ui/react"; import styles from "./OutlineDrawer.module.css"; import { ContentOutline } from "@/lib/types"; @@ -14,6 +17,8 @@ import ChapterItem from "../ChapterItem"; import { isChapterCompleted } from "@/lib/client-functions"; import Link from "next/link"; import CertificateButton from "../CertificateButton/CertificateButton"; +import { useSearch } from "@/app/utils/hooks"; +import { SearchIcon } from "@chakra-ui/icons"; export default function OutlineDrawer({ isOpen, @@ -30,6 +35,16 @@ export default function OutlineDrawer({ activeChapterIndex: number; activeStepIndex: number; }) { + /** + * Initialize the search hook + * + * This hook provides: + * - searchQuery: Current search string + * - setSearchQuery: Function to update search + * - filteredOutline: Filtered chapters based on search + */ + const { searchQuery, setSearchQuery, filteredOutline } = useSearch(outline); + return ( <> + {/* Search Input Section */} + {/* + Added to allow users to search through chapters and lessons + This helps users quickly find specific topics without scrolling + */} + + + + + setSearchQuery(e.target.value)} + borderRadius="md" + focusBorderColor="blue.400" + _placeholder={{ color: "gray.400" }} + /> + + diff --git a/app/utils/hooks.ts b/app/utils/hooks.ts new file mode 100644 index 0000000..1d9760b --- /dev/null +++ b/app/utils/hooks.ts @@ -0,0 +1,47 @@ +import { useState, useMemo } from "react"; +import { ContentOutline, Chapter } from "@/lib/types"; + +/** + * Hook to search chapters and lessons by title + * Returns filtered outline based on search query + */ +export function useSearch(outline: ContentOutline) { + const [searchQuery, setSearchQuery] = useState(""); + + // Filter outline based on search query (memoized for performance) + const filteredOutline = useMemo(() => { + if (!searchQuery.trim()) { + return outline; + } + + const query = searchQuery.toLowerCase().trim(); + + // Filter chapters and steps by search query + const filtered = outline + .map((chapter) => { + const chapterMatches = chapter.title.toLowerCase().includes(query); + const matchingSteps = chapter.steps.filter((step) => + step.title.toLowerCase().includes(query) + ); + + // Include chapter if title or any step matches + if (chapterMatches || matchingSteps.length > 0) { + return { + ...chapter, + steps: chapterMatches ? chapter.steps : matchingSteps, + }; + } + + return null; + }) + .filter((chapter): chapter is Chapter => chapter !== null); + + return filtered; + }, [searchQuery, outline]); + + return { + searchQuery, + setSearchQuery, + filteredOutline, + }; +}