diff --git a/src/src/components/presentation/FadeIn.tsx b/src/src/components/presentation/FadeIn.tsx deleted file mode 100644 index 2f01c0f..0000000 --- a/src/src/components/presentation/FadeIn.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// src/components/presentation/FadeIn.tsx -import React from 'react'; - -interface FadeInProps { - delay?: number; - children: React.ReactNode; - className?: string; -} - -export const FadeIn: React.FC = ({ - delay = 0, - children, - className = "" -}) => { - return ( -
- {children} -
- ); -}; diff --git a/src/src/components/presentation/Highlight.tsx b/src/src/components/presentation/Highlight.tsx deleted file mode 100644 index 2fe2e19..0000000 --- a/src/src/components/presentation/Highlight.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// src/components/presentation/Highlight.tsx -interface HighlightProps { - color?: 'yellow' | 'blue' | 'green' | 'red' | 'purple'; - delay?: number; - children: React.ReactNode; -} - -export const Highlight: React.FC = ({ - color = 'yellow', - delay = 0, - children -}) => { - const colorClasses = { - yellow: 'bg-yellow-bright/20 text-yellow-bright', - blue: 'bg-blue-bright/20 text-blue-bright', - green: 'bg-green-bright/20 text-green-bright', - red: 'bg-red-bright/20 text-red-bright', - purple: 'bg-purple-bright/20 text-purple-bright', - }; - - return ( - - {children} - - ); -}; diff --git a/src/src/components/presentation/ImageWithCaption.tsx b/src/src/components/presentation/ImageWithCaption.tsx deleted file mode 100644 index e193cb1..0000000 --- a/src/src/components/presentation/ImageWithCaption.tsx +++ /dev/null @@ -1,36 +0,0 @@ -// src/components/presentation/ImageWithCaption.tsx -interface ImageWithCaptionProps { - src: string; - alt: string; - caption?: string; - width?: string; - delay?: number; -} - -export const ImageWithCaption: React.FC = ({ - src, - alt, - caption, - width = "100%", - delay = 0 -}) => { - return ( -
- {alt} - {caption && ( -
- {caption} -
- )} -
- ); -}; diff --git a/src/src/components/presentation/Presentation.astro b/src/src/components/presentation/Presentation.astro new file mode 100644 index 0000000..62bc0c5 --- /dev/null +++ b/src/src/components/presentation/Presentation.astro @@ -0,0 +1,373 @@ +--- +// src/components/presentation/Presentation.astro +export interface Props { + autoStart?: boolean; + title?: string; +} + +const { autoStart = false, title = "Start Presentation" } = Astro.props; +--- + + + +
+ + + + diff --git a/src/src/components/presentation/Presentation.tsx b/src/src/components/presentation/Presentation.tsx deleted file mode 100644 index 926ffb7..0000000 --- a/src/src/components/presentation/Presentation.tsx +++ /dev/null @@ -1,386 +0,0 @@ -// src/components/presentation/Presentation.tsx -import React, { useEffect, useState, useRef } from 'react'; - -interface PresentationProps { - title?: string; -} - -export const Presentation: React.FC = ({ - title = "Start Presentation" -}) => { - const [slides, setSlides] = useState([]); - const [currentSlide, setCurrentSlide] = useState(0); - const [isPresenting, setIsPresenting] = useState(false); - const [isBlackedOut, setIsBlackedOut] = useState(false); - const [showHelp, setShowHelp] = useState(false); - const [animationIndex, setAnimationIndex] = useState(0); - const [currentAnimations, setCurrentAnimations] = useState([]); - - const containerRef = useRef(null); - const contentRef = useRef(null); - - // Initialize slides when component mounts - useEffect(() => { - const initializeSlides = () => { - const slideElements = Array.from(document.querySelectorAll('.presentation-slide')); - console.log('Found slides:', slideElements.length); - - const slideHTML = slideElements.map(el => el.outerHTML); - setSlides(slideHTML); - }; - - // Run after a short delay to ensure all components are rendered - const timer = setTimeout(initializeSlides, 100); - return () => clearTimeout(timer); - }, []); - - // Setup slide animations - const setupSlideAnimations = () => { - if (!contentRef.current) return; - - const animations = Array.from(contentRef.current.querySelectorAll('[data-animate]')); - setCurrentAnimations(animations); - setAnimationIndex(0); - - // Hide all animated elements initially - animations.forEach(el => { - const element = el as HTMLElement; - element.style.opacity = '0'; - element.style.transform = 'translateY(20px)'; - }); - }; - - // Show next animation - const showNextAnimation = (): boolean => { - if (animationIndex < currentAnimations.length) { - const element = currentAnimations[animationIndex] as HTMLElement; - element.style.transition = 'opacity 0.5s ease, transform 0.5s ease'; - element.style.opacity = '1'; - element.style.transform = 'translateY(0)'; - setAnimationIndex(prev => prev + 1); - return true; - } - return false; - }; - - // Show previous animation - const showPrevAnimation = (): boolean => { - if (animationIndex > 0) { - const newIndex = animationIndex - 1; - const element = currentAnimations[newIndex] as HTMLElement; - element.style.opacity = '0'; - element.style.transform = 'translateY(20px)'; - setAnimationIndex(newIndex); - return true; - } - return false; - }; - - // Display slide - const displaySlide = (index: number) => { - if (index >= 0 && index < slides.length && contentRef.current) { - contentRef.current.innerHTML = slides[index]; - setCurrentSlide(index); - setupSlideAnimations(); - } - }; - - // Navigation functions - const nextSlide = () => { - if (showNextAnimation()) return; - - if (currentSlide < slides.length - 1) { - displaySlide(currentSlide + 1); - } - }; - - const prevSlide = () => { - if (showPrevAnimation()) return; - - if (currentSlide > 0) { - displaySlide(currentSlide - 1); - // Show all animations on previous slide - setTimeout(() => { - currentAnimations.forEach(el => { - const element = el as HTMLElement; - element.style.opacity = '1'; - element.style.transform = 'translateY(0)'; - }); - setAnimationIndex(currentAnimations.length); - }, 50); - } - }; - - // Start presentation - const startPresentation = () => { - setIsPresenting(true); - displaySlide(0); - document.body.classList.add('presentation-active'); - }; - - // End presentation - const endPresentation = () => { - setIsPresenting(false); - setIsBlackedOut(false); - setShowHelp(false); - document.body.classList.remove('presentation-active'); - }; - - // Keyboard controls - useEffect(() => { - const handleKeyPress = (event: KeyboardEvent) => { - if (!isPresenting) return; - - switch (event.key) { - case 'Escape': - endPresentation(); - break; - case 'ArrowRight': - case ' ': - event.preventDefault(); - nextSlide(); - break; - case 'ArrowLeft': - event.preventDefault(); - prevSlide(); - break; - case 'b': - case 'B': - event.preventDefault(); - setIsBlackedOut(prev => !prev); - break; - case '?': - event.preventDefault(); - setShowHelp(prev => !prev); - break; - case 'Home': - event.preventDefault(); - displaySlide(0); - break; - case 'End': - event.preventDefault(); - displaySlide(slides.length - 1); - break; - } - }; - - document.addEventListener('keydown', handleKeyPress); - return () => document.removeEventListener('keydown', handleKeyPress); - }, [isPresenting, currentSlide, animationIndex, currentAnimations, slides.length]); - - const progress = slides.length > 0 ? ((currentSlide + 1) / slides.length) * 100 : 0; - - if (slides.length === 0) { - return null; // Don't show button if no slides - } - - return ( - <> - {/* Start Presentation Button */} - - - {/* Presentation Container */} - {isPresenting && ( -
- {/* Main Content */} -
-
- Loading slide... -
-
- - {/* Slide Counter */} -
- {currentSlide + 1} / {slides.length} -
- - {/* Help Toggle */} - - - {/* Progress Bar */} -
- - {/* Blackout Overlay */} - {isBlackedOut && ( -
- )} - - {/* Help Overlay */} - {showHelp && ( -
-
-

- 🎮 Presentation Controls -

-
-
- - Space - Next slide/animation -
-
- - Previous slide/animation -
-
- B - Toggle blackout -
-
- Home - First slide -
-
- End - Last slide -
-
- Esc - Exit presentation -
-
- ? - Toggle this help -
-
-
-
- )} -
- )} - - {/* Global styles for presentation mode */} - {isPresenting && ( - - )} - - ); -}; diff --git a/src/src/components/presentation/Slide.astro b/src/src/components/presentation/Slide.astro new file mode 100644 index 0000000..5e3a1c6 --- /dev/null +++ b/src/src/components/presentation/Slide.astro @@ -0,0 +1,13 @@ +--- +export interface Props { + centered?: boolean + highlight?: boolean + large?: boolean +} + +const { centered, highlight, large} = Astro.props +--- + +
+ +
diff --git a/src/src/components/presentation/Slide.tsx b/src/src/components/presentation/Slide.tsx deleted file mode 100644 index 612c106..0000000 --- a/src/src/components/presentation/Slide.tsx +++ /dev/null @@ -1,34 +0,0 @@ -// src/components/presentation/Slide.tsx -import React from 'react'; - -interface SlideProps { - title?: string; - centered?: boolean; - children: React.ReactNode; - className?: string; -} - -export const Slide: React.FC = ({ - title, - centered = false, - children, - className = "" -}) => { - return ( -
- {title && ( -
-

- {title} -

-
- )} -
- {children} -
-
- ); -}; diff --git a/src/src/components/presentation/SlideIn.tsx b/src/src/components/presentation/SlideIn.tsx deleted file mode 100644 index c18c8f4..0000000 --- a/src/src/components/presentation/SlideIn.tsx +++ /dev/null @@ -1,25 +0,0 @@ -// src/components/presentation/SlideIn.tsx -interface SlideInProps { - direction?: 'left' | 'right' | 'up' | 'down'; - delay?: number; - children: React.ReactNode; - className?: string; -} - -export const SlideIn: React.FC = ({ - direction = 'up', - delay = 0, - children, - className = "" -}) => { - return ( -
- {children} -
- ); -}; diff --git a/src/src/components/presentation/TwoColumn.tsx b/src/src/components/presentation/TwoColumn.tsx deleted file mode 100644 index 730ac9d..0000000 --- a/src/src/components/presentation/TwoColumn.tsx +++ /dev/null @@ -1,33 +0,0 @@ -// src/components/presentation/TwoColumn.tsx -interface TwoColumnProps { - leftWidth?: string; - rightWidth?: string; - gap?: string; - left: React.ReactNode; - right: React.ReactNode; -} - -export const TwoColumn: React.FC = ({ - leftWidth = "1fr", - rightWidth = "1fr", - gap = "2rem", - left, - right -}) => { - return ( -
-
- {left} -
-
- {right} -
-
- ); -}; diff --git a/src/src/content/resources/curriculum/python/intro-to-python.mdx b/src/src/content/resources/curriculum/python/intro-to-python.mdx index bb745f4..73a35c7 100644 --- a/src/src/content/resources/curriculum/python/intro-to-python.mdx +++ b/src/src/content/resources/curriculum/python/intro-to-python.mdx @@ -6,111 +6,68 @@ duration: "2 hours" tags: ["python", "programming", "beginner", "fundamentals"] --- -import { Slide } from "@/components/presentation/Slide"; -import { FadeIn } from "@/components/presentation/FadeIn"; -import { Highlight } from "@/components/presentation/Highlight"; -import { TwoColumn } from "@/components/presentation/TwoColumn"; - - +import Slide from "@/components/presentation/Slide.astro"; + # Welcome to Python! 🐍 **A beginner-friendly programming language** - - - Easy to learn and read - Powerful and versatile - Great for beginners - Used by major companies - - - - - + ## What is Python? - - -Python is a high-level programming language that emphasizes: +Python is a **high-level programming language** that emphasizes: - **Readability** - Code that looks like English - **Simplicity** - Easy to learn and use - **Versatility** - Can be used for many things - - - - ### Created by Guido van Rossum in 1991 Named after "Monty Python's Flying Circus" 🎭 - - - - - + ## Why Learn Python? - -

🌐 Web Development

-

Build websites and web applications

- -

🤖 Data Science & AI

-

Analyze data and build machine learning models

- - } - right={ - -

🎮 Game Development

-

Create games and interactive applications

- -

🔧 Automation

-

Automate repetitive tasks

-
- } -/> +### 🌐 Web Development +Build websites and web applications +### 🤖 Data Science & AI +Analyze data and build machine learning models + +### 🎮 Game Development +Create games and interactive applications + +### 🔧 Automation +Automate repetitive tasks
- - + ## Your First Python Program - - Let's write the classic "Hello, World!" program: ```python print("Hello, World!") ``` - - - - ### How to run it: 1. Open a text editor 2. Type the code above 3. Save as `hello.py` 4. Run with: `python hello.py` - - - - - + ## Variables and Data Types - - ### Creating Variables ```python name = "Alice" # String @@ -119,48 +76,192 @@ height = 5.6 # Float is_student = True # Boolean ``` - - - - -### Python is dynamically typed +### Python is **dynamically typed** You don't need to declare the type! ```python x = 42 # x is an integer x = "Hello" # Now x is a string ``` - - - - + +## Working with Strings +### String Operations +```python +# Creating strings +greeting = "Hello" +name = "World" + +# Concatenation +message = greeting + ", " + name + "!" +print(message) # Output: Hello, World! + +# String methods +text = "python programming" +print(text.upper()) # PYTHON PROGRAMMING +print(text.capitalize()) # Python programming +print(text.replace("python", "Python")) # Python programming +``` + + + +## Numbers and Math + +### Basic Math Operations +```python +# Arithmetic operators +a = 10 +b = 3 + +print(a + b) # Addition: 13 +print(a - b) # Subtraction: 7 +print(a * b) # Multiplication: 30 +print(a / b) # Division: 3.333... +print(a // b) # Floor division: 3 +print(a % b) # Modulo (remainder): 1 +print(a ** b) # Exponentiation: 1000 +``` + + + +## Lists - Storing Multiple Values + +### Creating and Using Lists +```python +# Creating a list +fruits = ["apple", "banana", "orange"] +numbers = [1, 2, 3, 4, 5] + +# Accessing items (indexing starts at 0) +print(fruits[0]) # apple +print(fruits[-1]) # orange (last item) + +# Adding items +fruits.append("grape") +fruits.insert(1, "strawberry") + +# List methods +print(len(fruits)) # Length of list +print("apple" in fruits) # Check if item exists +``` + + + +## Control Flow - Making Decisions + +### If Statements +```python +age = 18 + +if age >= 18: + print("You can vote!") +elif age >= 16: + print("You can drive!") +else: + print("You're still young!") + +# Comparison operators +# == (equal), != (not equal) +# > (greater), < (less) +# >= (greater or equal), <= (less or equal) +``` + + + +## Loops - Repeating Actions + +### For Loops +```python +# Loop through a list +fruits = ["apple", "banana", "orange"] +for fruit in fruits: + print(f"I like {fruit}") + +# Loop through numbers +for i in range(5): + print(f"Count: {i}") # 0, 1, 2, 3, 4 +``` + +### While Loops +```python +count = 0 +while count < 3: + print(f"Count is {count}") + count += 1 # Same as count = count + 1 +``` + + + +## Functions - Organizing Your Code + +### Creating Functions +```python +def greet(name): + """This function greets someone""" + return f"Hello, {name}!" + +def add_numbers(a, b): + """Add two numbers and return the result""" + result = a + b + return result + +# Using functions +message = greet("Alice") +print(message) # Hello, Alice! + +sum_result = add_numbers(5, 3) +print(sum_result) # 8 +``` + + + +## Practice Exercise + +### Build a Simple Calculator +```python +def calculator(): + print("Simple Calculator") + print("Operations: +, -, *, /") + + num1 = float(input("Enter first number: ")) + operation = input("Enter operation (+, -, *, /): ") + num2 = float(input("Enter second number: ")) + + if operation == "+": + result = num1 + num2 + elif operation == "-": + result = num1 - num2 + elif operation == "*": + result = num1 * num2 + elif operation == "/": + if num2 != 0: + result = num1 / num2 + else: + return "Error: Division by zero!" + else: + return "Error: Invalid operation!" + + return f"Result: {result}" + +# Run the calculator +print(calculator()) +``` + + + ## 🎉 Congratulations! - - You've learned the basics of Python programming! - - - - ### What's Next? - Practice with small projects - Learn about modules and packages - Explore Python libraries - Build something cool! - - - - **Ready to code? Let's build something amazing! 🚀** - - - ## Course Materials @@ -169,7 +270,7 @@ This curriculum covers the fundamentals of Python programming in an interactive, ### Getting Started -Before we dive into the presentation slides above, let's set up our development environment and understand what we'll be covering in this course. +The presentation above covers all the core concepts you need to start programming in Python. Each slide builds upon the previous one, taking you from basic concepts to writing your first functional program. #### What You'll Need @@ -178,4 +279,13 @@ Before we dive into the presentation slides above, let's set up our development - Terminal/command prompt access - About 2 hours of focused time -Ready to start? Click the "Start Presentation" button above to begin with the interactive slides! +#### Course Objectives + +By the end of this presentation, you'll be able to: +- Understand Python syntax and basic programming concepts +- Work with variables, strings, numbers, and lists +- Use conditional statements and loops +- Create and use functions +- Build a simple calculator program + +The presentation automatically starts when you visit this page. Use arrow keys to navigate between slides, or escape to exit presentati diff --git a/src/src/layouts/presentation.astro b/src/src/layouts/presentation.astro new file mode 100644 index 0000000..dceccfe --- /dev/null +++ b/src/src/layouts/presentation.astro @@ -0,0 +1,43 @@ +--- +// src/layouts/presentation.astro +import "@/style/globals.css"; +import { ClientRouter } from "astro:transitions"; + +export interface Props { + title: string; + description: string; +} + +const { title, description } = Astro.props; +const ogImage = "https://timmypidashev.dev/og-image.jpg"; +--- + + + + {title} + + + + + + + + + + + + + + + + + + +
+ +
+ + diff --git a/src/src/pages/resources/[...slug].astro b/src/src/pages/resources/[...slug].astro index da075ca..d04b40b 100644 --- a/src/src/pages/resources/[...slug].astro +++ b/src/src/pages/resources/[...slug].astro @@ -1,11 +1,11 @@ --- import { getCollection } from "astro:content"; import ContentLayout from "@/layouts/content.astro"; -import { Presentation } from "@/components/presentation/Presentation"; +import PresentationLayout from "@/layouts/presentation.astro"; +import Presentation from "@/components/presentation/Presentation.astro"; const { slug } = Astro.params; -// Same pattern as your blog const resources = await getCollection("resources"); const resource = resources.find(item => item.slug === slug); @@ -23,51 +23,19 @@ const formattedDate = new Date(resource.data.date).toLocaleDateString("en-US", { month: "long", day: "numeric" }); + +// Check if this is a curriculum resource to auto-start presentation +const isCurriculum = resource.slug.includes('curriculum'); +const LayoutComponent = isCurriculum ? PresentationLayout : ContentLayout; --- - - +
-
- - {resource.data.image && ( -
- {resource.data.title} -
- )} - -

{resource.data.title}

-

{resource.data.description}

- -
-
- {resource.data.duration} - - -
-
- -
- {resource.data.tags.map((tag) => ( - - #{tag} - - ))} -
- -
- -
-
+
-
+