Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,21 @@ npm start
npm run build
```

### Testing the Environment with Examples

To quickly test if the environment is set up correctly and see how challenges are loaded, you can use the provided example challenge:

```bash
# Copy the example challenge into the interviews directory
cp -r examples/prop-drilling src/interviews/

# Ensure your development server is running
npm start
```

The **Context API Refactor** challenge should now automatically appear on the main interface at `http://localhost:8080`.


### Creating Interview Patterns

Interview patterns are modular challenges that can be loaded dynamically. See [src/interviews/README.md](./src/interviews/README.md) for detailed pattern creation guidelines.
Expand Down
80 changes: 80 additions & 0 deletions examples/prop-drilling/PropDrillingChallenge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React, { useState } from 'react';

// ==========================================
// Candidate Task: Refactor this using Context
// ==========================================

const UserInfo = ({ user }: { user: { name: string; email: string } }) => (
<div className="flex items-center gap-2">
<div className="w-8 h-8 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold">
{user.name.charAt(0)}
</div>
<span className="font-medium">{user.name}</span>
</div>
);

const Header = ({ user }: { user: { name: string; email: string } }) => (
<header className="p-4 bg-slate-100 dark:bg-slate-800 border-b flex justify-between items-center">
<h1 className="text-xl font-bold">Dashboard</h1>
<UserInfo user={user} />
</header>
);

const ThemeToggle = ({ theme, toggleTheme }: { theme: string; toggleTheme: () => void }) => (
<button
onClick={toggleTheme}
className="px-4 py-2 rounded bg-slate-200 dark:bg-slate-700 hover:bg-slate-300 dark:hover:bg-slate-600 transition-colors"
>
Toggle Theme (Current: {theme})
</button>
);

const Sidebar = ({ theme, toggleTheme }: { theme: string; toggleTheme: () => void }) => (
<aside className="w-64 p-4 border-r bg-slate-50 dark:bg-slate-900 h-full flex flex-col gap-4">
<h2 className="font-semibold text-lg">Settings</h2>
<ThemeToggle theme={theme} toggleTheme={toggleTheme} />
</aside>
);

const Content = ({ user }: { user: { name: string; email: string } }) => (
<div className="p-8 flex-1">
<h2 className="text-2xl font-bold mb-4">Welcome back, {user.name}!</h2>
<p className="text-slate-600 dark:text-slate-400">
This is a deeply nested component structure. Currently, the user object and theme state are being passed down multiple levels via props.
</p>
<p className="text-slate-600 dark:text-slate-400 mt-2">
Your task is to refactor this code to use the React Context API and avoid prop drilling!
</p>
</div>
);

const MainLayout = ({
user,
theme,
toggleTheme
}: {
user: { name: string; email: string };
theme: string;
toggleTheme: () => void
}) => (
<div className="flex flex-1 overflow-hidden">
<Sidebar theme={theme} toggleTheme={toggleTheme} />
<Content user={user} />
</div>
);

export default function PropDrillingChallenge() {
const [user] = useState({ name: 'Alex Developer', email: 'alex@example.com' });
const [theme, setTheme] = useState('light');

const toggleTheme = () => {
setTheme(prev => prev === 'light' ? 'dark' : 'light');
};

return (
<div className={`h-full flex flex-col ${theme === 'dark' ? 'dark bg-slate-950 text-white' : 'bg-white text-slate-900'}`}>
<Header user={user} />
<MainLayout user={user} theme={theme} toggleTheme={toggleTheme} />
</div>
);
}
36 changes: 36 additions & 0 deletions examples/prop-drilling/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { InterviewPattern } from "@/interviews/types";
import PropDrillingChallenge from "./PropDrillingChallenge";

export const pattern: InterviewPattern = {
id: "prop-drilling-refactor",
name: "Context API Refactor",
description: "Refactor a prop-drilling architecture to use React Context.",
version: "1.0.0",
author: "Codeflow",
estimatedTime: "15-20 minutes",
tags: ["react", "context-api", "refactoring"],
type: "react",
component: PropDrillingChallenge,
readmes: [
{
title: "Instructions",
content: `
# Prop Drilling Refactor

## Objective
The provided component structure suffers from "prop drilling". State \`user\` and \`theme\` are passed down through multiple intermediate components that don't need them.

Your task is to refactor this code to use the **React Context API** to manage global state.

## Requirements
1. Create a \`UserContext\` and a \`ThemeContext\` (or a single combined \`AppContext\`).
2. Provide the state at the top level of the challenge component.
3. Consume the context in the components that actually need the data (e.g., \`UserInfo\`, \`ThemeToggle\`, \`Content\`).
4. Remove all unnecessary props from intermediate components like \`Header\`, \`MainLayout\`, and \`Sidebar\`.

## Bonus
* Implement custom hooks for consuming your contexts (e.g., \`useTheme\` or \`useUser\`).
`.trim(),
},
],
};
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
"@/*": ["./src/*"]
}
},
"include": ["src"]
"include": ["src", "examples"]
}