-
-
📊
-
Track Progress
-
- Per-framework progress tracking with completion stats and bookmarks
-
+ {/* Hover Effect Overlay */}
+
+
+ ))}
-
-
🎯
-
Practice Modes
-
- Sequential, random, and bookmarked modes to suit your study style
-
-
+ {/* Enhanced Features Section */}
+
+
+
+ 📊
+
+
+ Track Progress
+
+
+ Per-framework progress tracking with completion stats and bookmarks
+
+
-
-
💡
-
Expert Answers
-
- Comprehensive senior-level answers to ace your technical interviews
-
-
-
+
+
+ 🎯
+
+
+ Practice Modes
+
+
+ Sequential, random, and bookmarked modes to suit your study style
+
+
- {/* Footer */}
-
-
-
-
-
-
+
+
+ 💡
+
+
+ Expert Answers
+
+
+ Comprehensive senior-level answers to ace your technical interviews
+
-
- Built with React 19, TypeScript, and Tailwind CSS
-
-
- Crafted with ❤️ by{" "}
- Hussein Tirawi
-
-
- © 2024 All rights reserved
-
-
+
+ {/* Enhanced Footer */}
+
+
+
+
+ Built with React 19, TypeScript, and Tailwind CSS
+
+
+ Crafted with ❤️ by{" "}
+
+ Hussein Tirawi
+
+
+
+ © 2024 All rights reserved
+
+
diff --git a/src/pages/QuizPage.tsx b/src/pages/QuizPage.tsx
index ad9835b..f4b0d49 100644
--- a/src/pages/QuizPage.tsx
+++ b/src/pages/QuizPage.tsx
@@ -246,6 +246,44 @@ export default function QuizPage() {
onComplete={handleCompleteQuiz}
/>
+
+ {/* Enhanced Footer */}
+
+
+
+
+
+ Built with React 19, TypeScript, and Tailwind CSS
+
+
+ Crafted with ❤️ by{" "}
+
+ Hussein Tirawi
+
+
+
+ © 2024 All rights reserved
+
+
+
+
+
);
}
diff --git a/src/pages/QuizSelectionPage.tsx b/src/pages/QuizSelectionPage.tsx
new file mode 100644
index 0000000..4322c55
--- /dev/null
+++ b/src/pages/QuizSelectionPage.tsx
@@ -0,0 +1,1061 @@
+/**
+ * Quiz Selection Page - Modern card-based quiz selection with hover details
+ */
+
+import React, { useState, useRef, useEffect } from "react";
+import { useNavigate } from "react-router-dom";
+import { FrameworkIcon } from "../components/common/icons/FrameworkIcon";
+
+interface QuizCard {
+ id: string;
+ framework: string;
+ level: "junior" | "intermediate" | "senior";
+ title: string;
+ subtitle: string;
+ skills: string[];
+ duration: string;
+ evaluation: string;
+ description: string;
+ icon: string;
+}
+
+const QUIZ_CARDS: QuizCard[] = [
+ // Angular Cards
+ {
+ id: "angular-junior",
+ framework: "angular",
+ level: "junior",
+ title: "Junior Angular Developer | TypeScript",
+ subtitle: "Component Architecture & Services",
+ skills: [
+ "Angular Components",
+ "TypeScript",
+ "Services",
+ "Dependency Injection",
+ "RxJS",
+ "Angular CLI",
+ "Modules",
+ "Directives",
+ ],
+ duration: "45 minutes",
+ evaluation: "Automatic",
+ description:
+ "This quiz evaluates fundamental Angular concepts including components, services, and basic TypeScript knowledge.",
+ icon: "angular",
+ },
+ {
+ id: "angular-intermediate",
+ framework: "angular",
+ level: "intermediate",
+ title: "Intermediate Angular Developer | Advanced Features",
+ subtitle: "Advanced Patterns & State Management",
+ skills: [
+ "Angular Forms",
+ "Routing",
+ "Guards",
+ "Interceptors",
+ "State Management",
+ "Testing",
+ "Performance",
+ "Angular Material",
+ ],
+ duration: "60 minutes",
+ evaluation: "Automatic",
+ description:
+ "This quiz covers intermediate Angular concepts including advanced routing, forms, and state management patterns.",
+ icon: "angular",
+ },
+ {
+ id: "angular-senior",
+ framework: "angular",
+ level: "senior",
+ title: "Senior Angular Developer | Enterprise Architecture",
+ subtitle: "Enterprise Solutions & Performance",
+ skills: [
+ "Architecture Patterns",
+ "Microservices",
+ "Performance Optimization",
+ "Security",
+ "Testing Strategies",
+ "CI/CD",
+ "Advanced RxJS",
+ "Angular Universal",
+ ],
+ duration: "75 minutes",
+ evaluation: "Automatic",
+ description:
+ "This quiz evaluates senior-level Angular expertise including enterprise architecture and performance optimization.",
+ icon: "angular",
+ },
+
+ // React Cards
+ {
+ id: "react-junior",
+ framework: "react",
+ level: "junior",
+ title: "Junior React Developer | JavaScript",
+ subtitle: "Component Basics & Hooks",
+ skills: [
+ "React Components",
+ "JSX",
+ "Props",
+ "State",
+ "Hooks",
+ "Event Handling",
+ "Conditional Rendering",
+ "Lists",
+ ],
+ duration: "45 minutes",
+ evaluation: "Automatic",
+ description:
+ "This quiz covers fundamental React concepts including components, hooks, and basic JavaScript patterns.",
+ icon: "react",
+ },
+ {
+ id: "react-intermediate",
+ framework: "react",
+ level: "intermediate",
+ title: "Intermediate React Developer | Advanced Patterns",
+ subtitle: "State Management & Performance",
+ skills: [
+ "Context API",
+ "Custom Hooks",
+ "Performance",
+ "Testing",
+ "Routing",
+ "Forms",
+ "Error Boundaries",
+ "Code Splitting",
+ ],
+ duration: "60 minutes",
+ evaluation: "Automatic",
+ description:
+ "This quiz evaluates intermediate React skills including state management and performance optimization.",
+ icon: "react",
+ },
+ {
+ id: "react-senior",
+ framework: "react",
+ level: "senior",
+ title: "Senior React Developer | Enterprise Solutions",
+ subtitle: "Architecture & Advanced Patterns",
+ skills: [
+ "React Architecture",
+ "Design Patterns",
+ "Performance",
+ "Testing Strategies",
+ "SSR/SSG",
+ "Micro Frontends",
+ "Advanced Hooks",
+ "Concurrent Features",
+ ],
+ duration: "75 minutes",
+ evaluation: "Automatic",
+ description:
+ "This quiz covers senior-level React expertise including enterprise architecture and advanced patterns.",
+ icon: "react",
+ },
+
+ // Next.js Cards
+ {
+ id: "nextjs-junior",
+ framework: "nextjs",
+ level: "junior",
+ title: "Junior Next.js Developer | Full-Stack Basics",
+ subtitle: "Pages & API Routes",
+ skills: [
+ "Next.js Pages",
+ "API Routes",
+ "File-based Routing",
+ "Static Generation",
+ "Image Optimization",
+ "CSS Modules",
+ "Environment Variables",
+ "Deployment",
+ ],
+ duration: "45 minutes",
+ evaluation: "Automatic",
+ description:
+ "This quiz covers fundamental Next.js concepts including pages, API routes, and basic full-stack development.",
+ icon: "nextjs",
+ },
+ {
+ id: "nextjs-intermediate",
+ framework: "nextjs",
+ level: "intermediate",
+ title: "Intermediate Next.js Developer | App Router",
+ subtitle: "Modern Architecture & Performance",
+ skills: [
+ "App Router",
+ "Server Components",
+ "Client Components",
+ "Streaming",
+ "Middleware",
+ "Caching",
+ "Performance",
+ "SEO",
+ ],
+ duration: "60 minutes",
+ evaluation: "Automatic",
+ description:
+ "This quiz evaluates intermediate Next.js skills including App Router and modern architecture patterns.",
+ icon: "nextjs",
+ },
+ {
+ id: "nextjs-senior",
+ framework: "nextjs",
+ level: "senior",
+ title: "Senior Next.js Developer | Enterprise Architecture",
+ subtitle: "Advanced Patterns & Optimization",
+ skills: [
+ "Enterprise Architecture",
+ "Microservices",
+ "Performance",
+ "Security",
+ "Advanced Caching",
+ "Edge Functions",
+ "Monitoring",
+ "Scalability",
+ ],
+ duration: "75 minutes",
+ evaluation: "Automatic",
+ description:
+ "This quiz covers senior-level Next.js expertise including enterprise architecture and advanced optimization.",
+ icon: "nextjs",
+ },
+
+ // Redux Cards
+ {
+ id: "redux-junior",
+ framework: "redux",
+ level: "junior",
+ title: "Junior Redux Developer | State Management",
+ subtitle: "Basic State Management",
+ skills: [
+ "Redux Basics",
+ "Actions",
+ "Reducers",
+ "Store",
+ "React-Redux",
+ "useSelector",
+ "useDispatch",
+ "Provider",
+ ],
+ duration: "45 minutes",
+ evaluation: "Automatic",
+ description:
+ "This quiz covers fundamental Redux concepts including basic state management and React integration.",
+ icon: "redux",
+ },
+ {
+ id: "redux-intermediate",
+ framework: "redux",
+ level: "intermediate",
+ title: "Intermediate Redux Developer | Advanced Patterns",
+ subtitle: "Middleware & Redux Toolkit",
+ skills: [
+ "Redux Toolkit",
+ "Middleware",
+ "Async Actions",
+ "Selectors",
+ "DevTools",
+ "Performance",
+ "Testing",
+ "Best Practices",
+ ],
+ duration: "60 minutes",
+ evaluation: "Automatic",
+ description:
+ "This quiz evaluates intermediate Redux skills including middleware and Redux Toolkit patterns.",
+ icon: "redux",
+ },
+ {
+ id: "redux-senior",
+ framework: "redux",
+ level: "senior",
+ title: "Senior Redux Developer | Enterprise Architecture",
+ subtitle: "Advanced State Management",
+ skills: [
+ "Enterprise Patterns",
+ "Microservices",
+ "Performance",
+ "Security",
+ "Advanced Middleware",
+ "State Persistence",
+ "Monitoring",
+ "Scalability",
+ ],
+ duration: "75 minutes",
+ evaluation: "Automatic",
+ description:
+ "This quiz covers senior-level Redux expertise including enterprise architecture and advanced state management.",
+ icon: "redux",
+ },
+];
+
+const DifficultyIndicator = ({ level }: { level: "junior" | "intermediate" | "senior" }) => {
+ const bars = level === "junior" ? 1 : level === "intermediate" ? 2 : 3;
+ const label = level.charAt(0).toUpperCase() + level.slice(1);
+
+ return (
+
+
+ {[1, 2, 3].map((bar) => (
+
+ ))}
+
+
{label}
+
+ );
+};
+
+const QuizCardComponent = ({
+ card,
+ isHovered,
+ onMouseEnter,
+ onMouseLeave,
+ onClick,
+}: {
+ card: QuizCard;
+ isHovered: boolean;
+ onMouseEnter: () => void;
+ onMouseLeave: () => void;
+ onClick: () => void;
+}) => {
+ const handleKeyDown = (e: React.KeyboardEvent) => {
+ if (e.key === "Enter" || e.key === " ") {
+ e.preventDefault();
+ onClick();
+ }
+ };
+
+ return (
+
+
+ {/* Header with Icons */}
+
+
+
+
+
+
+ {card.framework.toUpperCase()}
+
+
+
+
+
+ {/* Title and Subtitle */}
+
+
+ {card.title}
+
+
+ {card.subtitle}
+
+
+
+ {/* Skills */}
+
+
+ Tested Skills
+
+
+ {card.skills.slice(0, 3).map((skill, index) => (
+
+ {skill}
+
+ ))}
+ {card.skills.length > 3 && (
+
+ +{card.skills.length - 3}
+
+ )}
+
+
+
+ {/* Duration and Evaluation */}
+
+
+
+
{card.duration}
+
+
+
+
{card.evaluation}
+
+
+
+ {/* Start Quiz Button - Always Visible */}
+
+
+
+ Start Quiz
+
+
+
+
+ {/* Hover Gradient Overlay - Behind content */}
+
+
+
+ );
+};
+
+const QuizDetailsPopup = ({
+ card,
+ isVisible,
+ position,
+ onClose,
+ onStartQuiz,
+}: {
+ card: QuizCard | null;
+ isVisible: boolean;
+ position: { x: number; y: number };
+ onClose: () => void;
+ onStartQuiz?: (card: QuizCard) => void;
+}) => {
+ if (!card || !isVisible) return null;
+
+ // Determine arrow direction based on popup position
+ const isLeftPosition = position.x < window.innerWidth / 2;
+ const arrowClass = isLeftPosition
+ ? "absolute -left-2 top-1/2 h-4 w-4 -translate-y-1/2 rotate-45 border-b border-l border-gray-200 bg-white"
+ : "absolute -right-2 top-1/2 h-4 w-4 -translate-y-1/2 rotate-45 border-t border-r border-gray-200 bg-white";
+
+ return (
+ <>
+ {/* Mobile Overlay */}
+
+
+ {/* Desktop Popup */}
+
+ {/* Arrow pointing to card */}
+
+
+ {/* Header */}
+
+
{card.title}
+
{card.subtitle}
+
+
+ {/* Tested Skills */}
+
+
+ Tested Skills
+
+
+ {card.skills.map((skill, index) => (
+
+ {skill}
+
+ ))}
+
+
+
+ {/* Duration */}
+
+
+ Duration
+
+
+ {card.duration}
+
+
+
+ {/* Evaluation */}
+
+
+ Evaluation
+
+
+ {card.evaluation}
+
+
+
+ {/* Test Overview */}
+
+
+ Test Overview
+
+
+
+
Choice Questions
+
+ Assessing knowledge of {card.framework}, JavaScript, and related technologies
+
+
+
+
+ Interactive Quiz - Level: {card.level.charAt(0).toUpperCase() + card.level.slice(1)}
+
+
{card.description}
+
+
+
+
+
+ {/* Mobile Modal */}
+
+ {/* Close Button */}
+
+
+ {/* Header */}
+
+
{card.title}
+
{card.subtitle}
+
+
+ {/* Tested Skills */}
+
+
+ Tested Skills
+
+
+ {card.skills.map((skill, index) => (
+
+ {skill}
+
+ ))}
+
+
+
+ {/* Duration */}
+
+
+ Duration
+
+
+ {card.duration}
+
+
+
+ {/* Evaluation */}
+
+
+ Evaluation
+
+
+ {card.evaluation}
+
+
+
+ {/* Test Overview */}
+
+
+ Test Overview
+
+
+
+
Choice Questions
+
+ Assessing knowledge of {card.framework}, JavaScript, and related technologies
+
+
+
+
+ Interactive Quiz - Level: {card.level.charAt(0).toUpperCase() + card.level.slice(1)}
+
+
{card.description}
+
+
+
+
+ {/* Start Quiz Button */}
+
+
+ >
+ );
+};
+
+export default function QuizSelectionPage() {
+ const navigate = useNavigate();
+ const [hoveredCard, setHoveredCard] = useState
(null);
+ const [popupPosition, setPopupPosition] = useState({ x: 0, y: 0 });
+ const [isMobile, setIsMobile] = useState(false);
+ const [searchTerm, setSearchTerm] = useState("");
+ const [selectedFramework, setSelectedFramework] = useState("all");
+ const [selectedLevel, setSelectedLevel] = useState("all");
+ const cardRefs = useRef<{ [key: string]: HTMLDivElement | null }>({});
+
+ // Check if mobile on mount and resize
+ useEffect(() => {
+ const checkMobile = () => {
+ setIsMobile(window.innerWidth < 1024);
+ };
+
+ checkMobile();
+ window.addEventListener("resize", checkMobile);
+ return () => window.removeEventListener("resize", checkMobile);
+ }, []);
+
+ // Handle escape key to close popup
+ useEffect(() => {
+ const handleEscape = (e: KeyboardEvent) => {
+ if (e.key === "Escape" && hoveredCard) {
+ closePopup();
+ }
+ };
+
+ document.addEventListener("keydown", handleEscape);
+ return () => document.removeEventListener("keydown", handleEscape);
+ }, [hoveredCard]);
+
+ const handleCardHover = (cardId: string) => {
+ if (isMobile) return; // Don't show hover on mobile
+ setHoveredCard(cardId);
+
+ // Calculate popup position
+ const cardElement = cardRefs.current[cardId];
+ if (cardElement) {
+ const rect = cardElement.getBoundingClientRect();
+ const popupWidth = 448; // 28rem = 448px
+ const popupHeight = 400; // Estimated popup height
+
+ // Calculate position with screen boundary checks
+ let x = rect.right + 20;
+ let y = rect.top + rect.height / 2;
+
+ // Check if popup would go off right edge
+ if (x + popupWidth > window.innerWidth) {
+ x = rect.left - popupWidth - 20; // Position to the left instead
+ }
+
+ // Check if popup would go off bottom edge
+ if (y + popupHeight / 2 > window.innerHeight) {
+ y = window.innerHeight - popupHeight / 2 - 20;
+ }
+
+ // Check if popup would go off top edge
+ if (y - popupHeight / 2 < 20) {
+ y = popupHeight / 2 + 20;
+ }
+
+ setPopupPosition({ x, y });
+ }
+ };
+
+ const handleCardClick = (card: QuizCard) => {
+ if (isMobile) {
+ // On mobile, show details modal instead of navigating directly
+ setHoveredCard(card.id);
+ } else {
+ navigate(`/quiz/${card.framework}/${card.level}`);
+ }
+ };
+
+ const handleStartQuiz = (card: QuizCard) => {
+ navigate(`/quiz/${card.framework}/${card.level}`);
+ };
+
+ const closePopup = () => {
+ setHoveredCard(null);
+ };
+
+ // Filter cards based on search and filters
+ const filteredCards = QUIZ_CARDS.filter((card) => {
+ const matchesSearch =
+ card.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
+ card.subtitle.toLowerCase().includes(searchTerm.toLowerCase()) ||
+ card.skills.some((skill) => skill.toLowerCase().includes(searchTerm.toLowerCase()));
+
+ const matchesFramework = selectedFramework === "all" || card.framework === selectedFramework;
+ const matchesLevel = selectedLevel === "all" || card.level === selectedLevel;
+
+ return matchesSearch && matchesFramework && matchesLevel;
+ });
+
+ // Get unique frameworks and levels for filter options
+ const frameworks = Array.from(new Set(QUIZ_CARDS.map((card) => card.framework)));
+ const levels = Array.from(new Set(QUIZ_CARDS.map((card) => card.level)));
+
+ return (
+
+
+
+ {/* Enhanced Header */}
+
+ {/* Main Title Section */}
+
+
+
+
+ Developer Quiz Selection
+
+
+
+ Choose your quiz level and framework to test your skills
+
+
+
+
+
12 Quizzes Available
+
+
+
+
+
3 Difficulty Levels
+
+
+
+
+ {/* Search and Filter Section */}
+
+
+ {/* Search Bar */}
+
+
+
setSearchTerm(e.target.value)}
+ className="w-full rounded-lg border border-gray-300 bg-gray-50 py-3 pl-10 pr-4 text-gray-900 placeholder-gray-500 transition-all duration-200 focus:border-blue-500 focus:bg-white focus:outline-none focus:ring-2 focus:ring-blue-500/20"
+ />
+
+
+ {/* Filters */}
+
+ {/* Framework Filter */}
+
+
+ {/* Level Filter */}
+
+
+
+
+ {/* Results Summary */}
+
+
+ Showing {filteredCards.length} of {QUIZ_CARDS.length} quizzes
+
+ {(searchTerm || selectedFramework !== "all" || selectedLevel !== "all") && (
+
+ )}
+
+
+
+
+ {/* Quiz Cards Grid */}
+
+ {filteredCards.length > 0 ? (
+ filteredCards.map((card, index) => (
+
{
+ cardRefs.current[card.id] = el;
+ }}
+ className="transform transition-all duration-300 hover:scale-105"
+ style={{
+ animationDelay: `${index * 100}ms`,
+ animation: "fadeInUp 0.6s ease-out forwards",
+ opacity: 0,
+ }}
+ >
+ handleCardHover(card.id)}
+ onMouseLeave={() => setHoveredCard(null)}
+ onClick={() => handleCardClick(card)}
+ />
+
+ ))
+ ) : (
+
+
+
No quizzes found
+
Try adjusting your search terms or filters
+
+
+ )}
+
+
+ {/* Details Popup */}
+
c.id === hoveredCard) || null : null}
+ isVisible={!!hoveredCard}
+ position={popupPosition}
+ onClose={closePopup}
+ onStartQuiz={handleStartQuiz}
+ />
+
+
+ {/* Enhanced Footer */}
+
+
+
+
+
+ Built with React 19, TypeScript, and Tailwind CSS
+
+
+ Crafted with ❤️ by{" "}
+
+ Hussein Tirawi
+
+
+
+ © 2024 All rights reserved
+
+
+
+
+
+
+ );
+}
diff --git a/src/types/quiz-results.ts b/src/types/quiz-results.ts
index 0484ad6..e6997f0 100644
--- a/src/types/quiz-results.ts
+++ b/src/types/quiz-results.ts
@@ -80,8 +80,8 @@ export interface RecommendationsProps {
}
export interface TabNavigationProps {
- selectedTab: "overview" | "analysis";
- onTabChange: (tab: "overview" | "analysis") => void;
+ selectedTab: "overview" | "analysis" | "dashboard";
+ onTabChange: (tab: "overview" | "analysis" | "dashboard") => void;
}
export interface ActionButtonsProps {
diff --git a/tailwind.config.js b/tailwind.config.js
index 088cc2d..1e98245 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -9,6 +9,11 @@ export default {
sans: ["ui-sans-serif", "system-ui", "sans-serif"],
mono: ["ui-monospace", "SFMono-Regular", "monospace"],
},
+ scale: {
+ 102: "1.02",
+ 105: "1.05",
+ 110: "1.10",
+ },
},
},
plugins: [],