1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState, useEffect } from "https://esm.sh/react@18.2.0?deps=react@18.2.0";
3import type { Project, Skill, Experience, ContactFormData, SocialLink } from "../../shared/types.ts";
4
168
169// Components
170const DarkModeToggle: React.FC<{ darkMode: boolean; toggleDarkMode: () => void }> = ({ darkMode, toggleDarkMode }) => (
171 <button
172 onClick={toggleDarkMode}
178);
179
180const Navigation: React.FC = () => (
181 <nav className="fixed top-0 left-0 right-0 bg-white/90 dark:bg-gray-900/90 backdrop-blur-sm z-40 border-b border-gray-200 dark:border-gray-700">
182 <div className="max-w-6xl mx-auto px-4 py-4">
201);
202
203const HeroSection: React.FC = () => (
204 <section className="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100 dark:from-gray-900 dark:to-gray-800 pt-20">
205 <div className="max-w-6xl mx-auto px-4 text-center">
233);
234
235const AboutSection: React.FC = () => (
236 <section id="about" className="section-padding bg-white dark:bg-gray-900">
237 <div className="max-w-6xl mx-auto">
287);
288
289const ProjectCard: React.FC<{ project: Project }> = ({ project }) => (
290 <div className="project-card">
291 <div className="p-6">
369);
370
371const ProjectsSection: React.FC = () => (
372 <section id="projects" className="section-padding bg-gray-50 dark:bg-gray-800">
373 <div className="max-w-6xl mx-auto">
384);
385
386const SkillsSection: React.FC = () => (
387 <section id="skills" className="section-padding bg-white dark:bg-gray-900">
388 <div className="max-w-6xl mx-auto">
410);
411
412const ExperienceSection: React.FC = () => (
413 <section id="experience" className="section-padding bg-gray-50 dark:bg-gray-800">
414 <div className="max-w-6xl mx-auto">
451);
452
453const ContactForm: React.FC = () => {
454 const [formData, setFormData] = useState({
455 name: '',
461 const [statusMessage, setStatusMessage] = useState('');
462
463 const handleSubmit = async (e: React.FormEvent) => {
464 e.preventDefault();
465 setIsSubmitting(true);
493 };
494
495 const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
496 setFormData({
497 ...formData,
578};
579
580const ContactSection: React.FC = () => (
581 <section id="contact" className="section-padding bg-white dark:bg-gray-900">
582 <div className="max-w-6xl mx-auto">
657);
658
659const Footer: React.FC = () => (
660 <footer className="bg-gray-900 dark:bg-gray-950 text-white py-12">
661 <div className="max-w-6xl mx-auto px-4">
685 </p>
686 <p className="text-gray-500 text-xs mt-2">
687 Built with React, TypeScript, and Tailwind CSS on Val Town
688 </p>
689 </div>
693);
694
695const App: React.FC = () => {
696 const [darkMode, setDarkMode] = useState(false);
697