From 3f04e8c7d71ca736f359d069d27d524ac141f18f Mon Sep 17 00:00:00 2001 From: Neeldhara Misra Date: Sun, 20 Jul 2025 10:07:04 +0530 Subject: [PATCH] Refactor site structure and add comprehensive interactive index - Move Puzzles and Miscellany under Themes - Add Contest Problems as new theme - Create About page with comprehensive site information - Create InteractiveIndex component with advanced filtering and sorting - Update navigation to include Index, Themes, and About - Add pagination (10 items per page) with search and tag filtering - Update routing structure for new theme organization - Remove standalone Puzzles and Miscellany pages - Add new theme pages: /themes/puzzles, /themes/miscellany, /themes/contest-problems - Update homepage to point to new interactive index - Maintain consistent layout and styling across all new pages --- src/App.tsx | 14 +- src/components/InteractiveIndex.tsx | 292 ++++++++++++++++++++++ src/components/Navigation.tsx | 4 +- src/pages/About.tsx | 56 +++++ src/pages/Index.tsx | 8 +- src/pages/Themes.tsx | 23 +- src/pages/theme-pages/ContestProblems.tsx | 19 ++ src/pages/theme-pages/Miscellany.tsx | 19 ++ src/pages/theme-pages/Puzzles.tsx | 19 ++ 9 files changed, 443 insertions(+), 11 deletions(-) create mode 100644 src/components/InteractiveIndex.tsx create mode 100644 src/pages/About.tsx create mode 100644 src/pages/theme-pages/ContestProblems.tsx create mode 100644 src/pages/theme-pages/Miscellany.tsx create mode 100644 src/pages/theme-pages/Puzzles.tsx diff --git a/src/App.tsx b/src/App.tsx index 8ae9b8d..236755a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,15 +4,18 @@ import { TooltipProvider } from "@/components/ui/tooltip"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { BrowserRouter, Routes, Route } from "react-router-dom"; import Index from "./pages/Index"; +import InteractiveIndex from "./components/InteractiveIndex"; import Themes from "./pages/Themes"; -import Puzzles from "./pages/Puzzles"; -import Miscellany from "./pages/Miscellany"; +import About from "./pages/About"; import DiscreteMath from "./pages/theme-pages/DiscreteMath"; import SocialChoice from "./pages/theme-pages/SocialChoice"; import AdvancedAlgorithms from "./pages/theme-pages/AdvancedAlgorithms"; import DataStructures from "./pages/theme-pages/DataStructures"; import Games from "./pages/theme-pages/Games"; import CardsMath from "./pages/theme-pages/CardsMath"; +import Puzzles from "./pages/theme-pages/Puzzles"; +import Miscellany from "./pages/theme-pages/Miscellany"; +import ContestProblems from "./pages/theme-pages/ContestProblems"; import BinaryNumberGamePage from "./pages/BinaryNumberGamePage"; import BinaryNumberGameGreenScreen from "./pages/BinaryNumberGameGreenScreen"; import BinarySearchTrickPage from "./pages/BinarySearchTrickPage"; @@ -38,9 +41,9 @@ const App = () => ( } /> + } /> } /> - } /> - } /> + } /> {/* Theme-specific routes */} } /> @@ -56,6 +59,9 @@ const App = () => ( } /> } /> } /> + } /> + } /> + } /> {/* Direct interactive routes */} } /> diff --git a/src/components/InteractiveIndex.tsx b/src/components/InteractiveIndex.tsx new file mode 100644 index 0000000..adb4608 --- /dev/null +++ b/src/components/InteractiveIndex.tsx @@ -0,0 +1,292 @@ +import React, { useState, useMemo } from 'react'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Input } from '@/components/ui/input'; +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +import { Search, SortAsc, SortDesc } from 'lucide-react'; +import Layout from '@/components/Layout'; + +interface Interactive { + id: string; + title: string; + description: string; + tags: string[]; + path: string; + theme: string; + dateAdded?: string; // For recency sorting +} + +// This would ideally be generated from the actual components, but for now we'll hardcode +const allInteractives: Interactive[] = [ + { + id: 'binary-number-game', + title: 'Binary Number Representation', + description: 'Learn how numbers are represented in binary (base-2) format through an interactive guessing game.', + tags: ['binary', 'numbers', 'conversion', 'representation'], + path: '/binary-number-game', + theme: 'Discrete Math', + dateAdded: '2024-01-15' + }, + { + id: 'binary-search-trick', + title: 'Binary Search Magic Trick', + description: 'Perform an amazing magic trick that reveals how binary numbers work. Think of a number and watch the magic happen!', + tags: ['binary', 'magic', 'numbers', 'trick', 'data-structures'], + path: '/binary-search-trick', + theme: 'Data Structures', + dateAdded: '2024-02-20' + }, + { + id: 'game-of-sim', + title: 'Game of Sim', + description: 'A strategic two-player game where you take turns coloring edges between vertices, trying to avoid creating a triangle of your own color.', + tags: ['strategy', 'graph-theory', 'two-player', 'logic', 'game-theory'], + path: '/game-of-sim', + theme: 'Games', + dateAdded: '2024-03-10' + } +]; + +type SortField = 'title' | 'dateAdded'; +type SortDirection = 'asc' | 'desc'; + +const InteractiveIndex = () => { + const [searchTerm, setSearchTerm] = useState(''); + const [selectedTag, setSelectedTag] = useState(''); + const [sortField, setSortField] = useState('title'); + const [sortDirection, setSortDirection] = useState('asc'); + const [currentPage, setCurrentPage] = useState(1); + const itemsPerPage = 10; + + // Get all unique tags + const allTags = useMemo(() => { + const tags = new Set(); + allInteractives.forEach(interactive => { + interactive.tags.forEach(tag => tags.add(tag)); + }); + return Array.from(tags).sort(); + }, []); + + // Filter and sort interactives + const filteredAndSortedInteractives = useMemo(() => { + let filtered = allInteractives.filter(interactive => { + const matchesSearch = interactive.title.toLowerCase().includes(searchTerm.toLowerCase()) || + interactive.description.toLowerCase().includes(searchTerm.toLowerCase()) || + interactive.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase())); + + const matchesTag = !selectedTag || interactive.tags.includes(selectedTag); + + return matchesSearch && matchesTag; + }); + + // Sort + filtered.sort((a, b) => { + let aValue = a[sortField]; + let bValue = b[sortField]; + + if (sortField === 'title') { + aValue = aValue.toLowerCase(); + bValue = bValue.toLowerCase(); + } + + if (aValue < bValue) return sortDirection === 'asc' ? -1 : 1; + if (aValue > bValue) return sortDirection === 'asc' ? 1 : -1; + return 0; + }); + + return filtered; + }, [searchTerm, selectedTag, sortField, sortDirection]); + + // Pagination + const totalPages = Math.ceil(filteredAndSortedInteractives.length / itemsPerPage); + const startIndex = (currentPage - 1) * itemsPerPage; + const paginatedInteractives = filteredAndSortedInteractives.slice(startIndex, startIndex + itemsPerPage); + + const handleTagClick = (tag: string) => { + setSelectedTag(selectedTag === tag ? '' : tag); + setCurrentPage(1); + }; + + const handleSortChange = (field: SortField) => { + if (sortField === field) { + setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc'); + } else { + setSortField(field); + setSortDirection('asc'); + } + setCurrentPage(1); + }; + + return ( + +
+
+

All Interactives

+ + {/* Search and Sort Controls */} +
+
+ + { + setSearchTerm(e.target.value); + setCurrentPage(1); + }} + className="pl-10" + /> +
+ +
+ + + +
+
+ + {/* Tag Filter */} + {selectedTag && ( +
+ Filtered by: + setSelectedTag('')} + > + {selectedTag} × + +
+ )} + + {/* Tags */} +
+

Filter by Tags

+
+ {allTags.map(tag => ( + handleTagClick(tag)} + > + {tag} + + ))} +
+
+ + {/* Results Count */} +
+

+ Showing {filteredAndSortedInteractives.length} of {allInteractives.length} interactives +

+
+ + {/* Interactive List */} +
+ {paginatedInteractives.map(interactive => ( + + + + + {interactive.title} + + +
+ {interactive.tags.map(tag => ( + handleTagClick(tag)} + > + {tag} + + ))} +
+
+ +

{interactive.description}

+
+ + {interactive.theme} + +
+
+
+ ))} +
+ + {/* Pagination */} + {totalPages > 1 && ( +
+ + +
+ {Array.from({ length: totalPages }, (_, i) => i + 1).map(page => ( + + ))} +
+ + +
+ )} + + {paginatedInteractives.length === 0 && ( +
+

No interactives found matching your criteria.

+
+ )} +
+
+
+ ); +}; + +export default InteractiveIndex; \ No newline at end of file diff --git a/src/components/Navigation.tsx b/src/components/Navigation.tsx index 1becbb6..444e1d6 100644 --- a/src/components/Navigation.tsx +++ b/src/components/Navigation.tsx @@ -5,9 +5,9 @@ const Navigation = () => { const location = useLocation(); const navItems = [ + { name: "Index", path: "/index" }, { name: "Themes", path: "/themes" }, - { name: "Puzzles", path: "/puzzles" }, - { name: "Miscellany", path: "/miscellany" } + { name: "About", path: "/about" } ]; return ( diff --git a/src/pages/About.tsx b/src/pages/About.tsx new file mode 100644 index 0000000..ab404f1 --- /dev/null +++ b/src/pages/About.tsx @@ -0,0 +1,56 @@ +import Layout from "@/components/Layout"; + +const About = () => { + return ( + +
+
+

About Interactives

+ +
+

+ Welcome to Interactives, a comprehensive educational platform designed to enhance learning through interactive experiences. Our mission is to make complex concepts accessible and engaging through hands-on exploration. +

+ +

Our Mission

+

+ We believe that learning is most effective when it's interactive, visual, and engaging. Our platform provides a collection of carefully crafted interactive tools that supplement traditional educational methods, helping students and educators alike to better understand and explore complex topics. +

+ +

What We Offer

+
    +
  • Interactive Demonstrations: Visual representations of complex concepts
  • +
  • Educational Games: Learning through play and problem-solving
  • +
  • Algorithm Visualizations: Step-by-step breakdowns of computational processes
  • +
  • Mathematical Explorations: Hands-on discovery of mathematical principles
  • +
  • Social Choice Simulations: Understanding collective decision-making
  • +
+ +

Our Approach

+

+ Each interactive is designed with careful attention to pedagogy, ensuring that users not only learn the concepts but also develop intuition and deeper understanding. We focus on creating experiences that are both educational and enjoyable, making learning a rewarding journey rather than a chore. +

+ +

For Educators

+

+ Our platform serves as a valuable supplement to classroom instruction, providing tools that can be used to illustrate concepts, engage students, and provide hands-on practice. Many of our interactives are designed to work well in both individual and group learning environments. +

+ +

For Students

+

+ Whether you're studying computer science, mathematics, or related fields, our interactives provide a unique way to explore and understand complex topics. Use them to supplement your coursework, prepare for exams, or simply satisfy your curiosity about how things work. +

+ +
+

+ Interactives is an ongoing project, with new content and features being added regularly. We welcome feedback and suggestions for new topics or improvements to existing interactives. +

+
+
+
+
+
+ ); +}; + +export default About; \ No newline at end of file diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx index 274bb01..fd9683e 100644 --- a/src/pages/Index.tsx +++ b/src/pages/Index.tsx @@ -23,14 +23,14 @@ const Index = () => {
diff --git a/src/pages/Themes.tsx b/src/pages/Themes.tsx index 96e416e..96fd329 100644 --- a/src/pages/Themes.tsx +++ b/src/pages/Themes.tsx @@ -6,7 +6,10 @@ import { Database, Gamepad2, CreditCard, - Calculator + Calculator, + Puzzle, + Sparkles, + Trophy } from "lucide-react"; import Layout from "@/components/Layout"; import ThemeCard from "@/components/ThemeCard"; @@ -48,6 +51,24 @@ const Themes = () => { description: "Discover mathematical principles and probability theory through card games and interactive demonstrations.", path: "/themes/cards-math", icon: + }, + { + title: "Puzzles", + description: "Get ready for an engaging collection of educational puzzles designed to challenge your problem-solving skills and reinforce key concepts across multiple disciplines.", + path: "/themes/puzzles", + icon: + }, + { + title: "Miscellany", + description: "Discover unique educational experiments, creative tools, and innovative interactive content that doesn't fit into traditional categories but sparks curiosity and enhances learning.", + path: "/themes/miscellany", + icon: + }, + { + title: "Contest Problems", + description: "Practice with problems from programming competitions, mathematical olympiads, and algorithmic challenges with interactive solutions and explanations.", + path: "/themes/contest-problems", + icon: } ]; diff --git a/src/pages/theme-pages/ContestProblems.tsx b/src/pages/theme-pages/ContestProblems.tsx new file mode 100644 index 0000000..d3b9d7f --- /dev/null +++ b/src/pages/theme-pages/ContestProblems.tsx @@ -0,0 +1,19 @@ +import ComingSoon from "@/components/ComingSoon"; +import Layout from "@/components/Layout"; + +const ContestProblems = () => { + return ( + +
+
+ +
+
+
+ ); +}; + +export default ContestProblems; \ No newline at end of file diff --git a/src/pages/theme-pages/Miscellany.tsx b/src/pages/theme-pages/Miscellany.tsx new file mode 100644 index 0000000..8962c5e --- /dev/null +++ b/src/pages/theme-pages/Miscellany.tsx @@ -0,0 +1,19 @@ +import ComingSoon from "@/components/ComingSoon"; +import Layout from "@/components/Layout"; + +const Miscellany = () => { + return ( + +
+
+ +
+
+
+ ); +}; + +export default Miscellany; \ No newline at end of file diff --git a/src/pages/theme-pages/Puzzles.tsx b/src/pages/theme-pages/Puzzles.tsx new file mode 100644 index 0000000..21acd4c --- /dev/null +++ b/src/pages/theme-pages/Puzzles.tsx @@ -0,0 +1,19 @@ +import ComingSoon from "@/components/ComingSoon"; +import Layout from "@/components/Layout"; + +const Puzzles = () => { + return ( + +
+
+ +
+
+
+ ); +}; + +export default Puzzles; \ No newline at end of file