interactives/src/pages/theme-pages/discrete-math/Foundations.tsx
gpt-engineer-app[bot] 13062b5fa3 Fix link generation for interactive
Correctly generate the URL for the Rules of Inference interactive to ensure it points to the correct path.
2025-08-11 11:34:10 +00:00

120 lines
No EOL
6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useState } from "react";
import { Link } from "react-router-dom";
import { Search } from "lucide-react";
import Layout from "@/components/Layout";
import InteractiveCard from "@/components/InteractiveCard";
import SocialShare from "@/components/SocialShare";
import BinaryNumberGame from "@/components/BinaryNumberGame";
import TernaryNumberGame from "@/components/TernaryNumberGame";
import BalancedTernaryGame from "@/components/BalancedTernaryGame";
import ZeckendorfGame from "@/components/ZeckendorfGame";
import ZeckendorfSearchTrick from "@/components/ZeckendorfSearchTrick";
import KnightsAndKnavesI from "@/components/KnightsAndKnavesI";
import RulesOfInferencePlayground from "@/components/RulesOfInferencePlayground";
interface Interactive {
id: string;
title: string;
description: string;
tags: string[];
component: React.ComponentType;
greenScreenPath: string;
}
const interactives: 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"],
component: BinaryNumberGame,
greenScreenPath: "/binary-number-game"
}, {
id: "ternary-number-game",
title: "Ternary Number Representation",
description: "Learn how numbers are represented in ternary (base-3) format by toggling between 0, 1, or 2 copies of powers of three.",
tags: ["ternary", "numbers", "conversion", "representation", "base-3"],
component: TernaryNumberGame,
greenScreenPath: "/ternary-number-game"
}, {
id: "balanced-ternary-game",
title: "Balanced Ternary Representation",
description: "Explore balanced ternary using digits T (-1), 0, and 1. Add or subtract powers of three to match the target number.",
tags: ["balanced-ternary", "numbers", "conversion", "representation", "base-3", "signed-digits"],
component: BalancedTernaryGame,
greenScreenPath: "/balanced-ternary-game"
}, {
id: "zeckendorf-game",
title: "Zeckendorf Representation",
description: "Learn how numbers are represented using Fibonacci numbers with the unique Zeckendorf representation (no consecutive Fibonacci numbers).",
tags: ["fibonacci", "numbers", "representation", "zeckendorf", "combinatorics"],
component: ZeckendorfGame,
greenScreenPath: "/discrete-math/foundations/zeckendorf"
}, {
id: "knights-and-knaves-i",
title: "Knights and Knaves - I",
description: "Drag statements into the arena to test consistency of As claim and roles in a classic Knights & Knaves puzzle.",
tags: ["logic", "puzzle", "knights", "knaves", "truth-tellers"],
component: KnightsAndKnavesI,
greenScreenPath: "/themes/discrete-math/foundations"
}, {
id: "rules-of-inference",
title: "Rules of Inference Playground",
description: "Practice applying resolution and equivalence rules to derive conclusions step by step.",
tags: ["logic", "proofs", "inference", "resolution", "deduction"],
component: RulesOfInferencePlayground,
greenScreenPath: "/discrete-math/foundations/rules-of-inference"
}];
const Foundations = () => {
const [searchTerm, setSearchTerm] = useState("");
const [selectedInteractive, setSelectedInteractive] = useState<Interactive | null>(null);
const filteredInteractives = interactives.filter(interactive => interactive.title.toLowerCase().includes(searchTerm.toLowerCase()) || interactive.description.toLowerCase().includes(searchTerm.toLowerCase()) || interactive.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase())));
if (selectedInteractive) {
const InteractiveComponent = selectedInteractive.component;
return <div className="min-h-screen bg-background p-6">
<div className="max-w-4xl mx-auto space-y-6">
<div className="flex items-center justify-between">
<button onClick={() => setSelectedInteractive(null)} className="text-primary hover:text-primary/80 font-medium">
Back to Foundations
</button>
<Link to="/themes/discrete-math" className="text-primary hover:text-primary/80 font-medium">
Back to Discrete Math
</Link>
</div>
<InteractiveComponent />
<SocialShare
title={`${selectedInteractive.title} - Interactive Learning`}
description={selectedInteractive.description}
url={`${window.location.origin}${selectedInteractive.greenScreenPath}`}
/>
</div>
</div>;
}
return <Layout>
<div className="container mx-auto px-4 py-8">
<div className="space-y-8">
<div className="flex items-center gap-4">
<Link to="/themes/discrete-math" className="text-primary hover:text-primary/80 font-medium">
Back to Discrete Math
</Link>
<h1 className="text-3xl font-bold text-foreground">Foundations</h1>
</div>
<div className="relative max-w-md">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground w-4 h-4" />
<input type="text" placeholder="Search interactives..." value={searchTerm} onChange={e => setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-outline rounded-md bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" />
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{filteredInteractives.map(interactive => <InteractiveCard key={interactive.id} title={interactive.title} description={interactive.description} tags={interactive.tags} onClick={() => setSelectedInteractive(interactive)} />)}
</div>
{filteredInteractives.length === 0 && <div className="text-center py-12">
<p className="text-muted-foreground">
No interactives found matching "{searchTerm}"
</p>
</div>}
</div>
</div>
</Layout>;
};
export default Foundations;