fix: add lesson 3

This commit is contained in:
Tim Rijkse
2026-02-27 13:56:19 +01:00
parent 1822546a8e
commit 7d50c78e39
60 changed files with 19865 additions and 1 deletions

View File

@@ -0,0 +1,6 @@
node_modules
.next
out
.DS_Store
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,103 @@
export default function AboutPage() {
return (
<div style={{
maxWidth: '800px',
margin: '0 auto',
padding: '40px 20px'
}}>
<h1 style={{
fontSize: '36px',
fontWeight: 'bold',
marginBottom: '24px',
color: '#1a1a1a'
}}>Over Ons</h1>
<p style={{
fontSize: '18px',
lineHeight: '1.8',
color: '#444',
marginBottom: '20px'
}}>
Wij zijn een team van gepassioneerde developers die geloven in de
kracht van AI-assisted development. Onze missie is om het bouwen
van websites sneller en toegankelijker te maken voor iedereen.
</p>
<div style={{
display: 'flex',
gap: '20px',
marginTop: '40px',
flexWrap: 'wrap'
}}>
<div style={{
flex: '1',
minWidth: '250px',
padding: '24px',
backgroundColor: '#f8f9fa',
borderRadius: '12px',
border: '1px solid #e0e0e0'
}}>
<h3 style={{
fontSize: '20px',
fontWeight: '600',
marginBottom: '12px',
color: '#333'
}}>Onze Visie</h3>
<p style={{
color: '#666',
lineHeight: '1.6'
}}>
AI maakt development niet makkelijker het maakt het SNELLER.
Je moet nog steeds begrijpen wat je bouwt.
</p>
</div>
<div style={{
flex: '1',
minWidth: '250px',
padding: '24px',
backgroundColor: '#f8f9fa',
borderRadius: '12px',
border: '1px solid #e0e0e0'
}}>
<h3 style={{
fontSize: '20px',
fontWeight: '600',
marginBottom: '12px',
color: '#333'
}}>Ons Team</h3>
<p style={{
color: '#666',
lineHeight: '1.6'
}}>
Vier developers, twee designers, en een AI die nooit slaapt.
Samen bouwen we de toekomst.
</p>
</div>
<div style={{
flex: '1',
minWidth: '250px',
padding: '24px',
backgroundColor: '#f8f9fa',
borderRadius: '12px',
border: '1px solid #e0e0e0'
}}>
<h3 style={{
fontSize: '20px',
fontWeight: '600',
marginBottom: '12px',
color: '#333'
}}>Contact</h3>
<p style={{
color: '#666',
lineHeight: '1.6'
}}>
Vragen? Neem contact op via ons contactformulier of stuur
een mail naar info@debugchallenge.nl.
</p>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,124 @@
"use client";
import { useState } from "react";
export default function ContactPage() {
const [naam, setNaam] = useState("");
const [email, setEmail] = useState("");
const [bericht, setBericht] = useState("");
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
alert(`Bedankt ${naam}! Je bericht is verzonden.`);
};
return (
<div style={{
maxWidth: '600px',
margin: '0 auto',
padding: '40px 20px'
}}>
<h1 style={{
fontSize: '36px',
fontWeight: 'bold',
marginBottom: '8px',
color: '#1a1a1a'
}}>Contact</h1>
<p style={{
color: '#666',
marginBottom: '32px',
fontSize: '16px'
}}>Heb je een vraag? Vul het formulier in!</p>
<form onSubmit={handleSubmit} style={{
display: 'flex',
flexDirection: 'column',
gap: '16px'
}}>
<div>
<label style={{
display: 'block',
marginBottom: '6px',
fontWeight: '500',
color: '#333'
}}>Naam</label>
<input
type="text"
value={naam}
onChange={(e) => setNaam(e.target.value)}
required
style={{
width: '100%',
padding: '10px 14px',
border: '1px solid #ccc',
borderRadius: '8px',
fontSize: '16px',
outline: 'none'
}}
/>
</div>
<div>
<label style={{
display: 'block',
marginBottom: '6px',
fontWeight: '500',
color: '#333'
}}>Email</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
style={{
width: '100%',
padding: '10px 14px',
border: '1px solid #ccc',
borderRadius: '8px',
fontSize: '16px',
outline: 'none'
}}
/>
</div>
<div>
<label style={{
display: 'block',
marginBottom: '6px',
fontWeight: '500',
color: '#333'
}}>Bericht</label>
<textarea
value={bericht}
onChange={(e) => setBericht(e.target.value)}
required
rows={5}
style={{
width: '100%',
padding: '10px 14px',
border: '1px solid #ccc',
borderRadius: '8px',
fontSize: '16px',
outline: 'none',
resize: 'vertical'
}}
/>
</div>
<button type="submit" style={{
backgroundColor: '#3b82f6',
color: 'white',
padding: '12px 24px',
border: 'none',
borderRadius: '8px',
fontSize: '16px',
fontWeight: '600',
cursor: 'pointer'
}}>
Verstuur Bericht
</button>
</form>
</div>
);
}

View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -0,0 +1,23 @@
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: "Debug Challenge - Les 3",
description: "Fix alle fouten in dit project!",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="nl">
<body className="min-h-screen bg-white text-gray-900">
<Navbar />
{children}
<Footer />
</body>
</html>
);
}

View File

@@ -0,0 +1,12 @@
import Hero from "@/componenst/Hero";
import FeatureCards from "@/components/FeatureCards";
export default function Home() {
return (
<main>
<Hero />
<FeatureCards />
<TestimonialSection />
</main>
);
}

View File

@@ -0,0 +1,85 @@
import { Zap, Shield, Rocket } from "lucide-react"
interface Feature {
icon: React.ReactNode;
titel: string;
beschrijving: string;
}
const features: Feature[] = [
{
icon: <Zap size={32} />,
titel: "Supersnel",
beschrijving: "Bouw componenten in seconden met AI-powered code generation."
},
{
icon: <Shield size={32} />,
titel: "Betrouwbaar",
beschrijving: "TypeScript en ESLint zorgen voor foutloze, veilige code."
},
{
icon: <Rocket size={32} />,
titel: "Deploy Direct",
beschrijving: "Push naar GitHub en je site is live op Vercel binnen minuten."
}
];
export default function FeatureCards() {
return (
<section style={{
padding: '60px 20px',
backgroundColor: '#f9fafb',
}}>
<div style={{
maxWidth: '1000px',
margin: '0 auto'
}}>
<h2 style={{
fontSize: '32px',
fontWeight: 'bold',
textAlign: 'center',
marginBottom: '40px',
color: '#1a1a1a'
}}>Waarom Dit Project?</h2>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(3, 1fr)',
gap: '24px'
}}>
{features.map((feature, index) => (
<div key={index} style={{
backgroundColor: 'white',
padding: '32px',
borderRadius: '16px',
border: '1px solid #e5e7eb',
textAlign: 'center',
boxShadow: '0 1px 3px rgba(0,0,0,0.1)'
}}>
<div style={{
display: 'inline-flex',
padding: '12px',
backgroundColor: '#ede9fe',
borderRadius: '12px',
marginBottom: '16px',
color: '#7c3aed'
}}>
{feature.icon}
</div>
<h3 style={{
fontSize: '20px',
fontWeight: '600',
marginBottom: '8px',
color: '#1a1a1a'
}}>{feature.titel}</h3>
<p style={{
color: '#6b7280',
lineHeight: '1.6'
}}>{feature.beschrijving}</p>
</div>
))}
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,82 @@
import Link from "next/link"
export default function Footer() {
return (
<footer style={{
backgroundColor: '#1f2937',
color: 'white',
padding: '40px 20px',
marginTop: '60px'
}}>
<div style={{
maxWidth: '1000px',
margin: '0 auto',
display: 'flex',
justifyContent: 'space-between',
flexWrap: 'wrap',
gap: '32px'
}}>
<div>
<h3 style={{
fontSize: '18px',
fontWeight: '600',
marginBottom: '12px'
}}>🚀 Debug Challenge</h3>
<p style={{
color: '#9ca3af',
maxWidth: '300px',
lineHeight: '1.6',
fontSize: '14px'
}}>
Een project van NOVI Hogeschool om te leren
debuggen met Cursor AI.
</p>
</div>
<div>
<h3 style={{
fontSize: '18px',
fontWeight: '600',
marginBottom: '12px'
}}>Links</h3>
<div style={{
display: 'flex',
flexDirection: 'column',
gap: '8px'
}}>
<Link href="/" style={{ color: '#9ca3af', textDecoration: 'none', fontSize: '14px' }}>Home</Link>
<Link href="/about" style={{ color: '#9ca3af', textDecoration: 'none', fontSize: '14px' }}>Over Ons</Link>
<Link href="/contact" style={{ color: '#9ca3af', textDecoration: 'none', fontSize: '14px' }}>Contact</Link>
</div>
</div>
<div>
<h3 style={{
fontSize: '18px',
fontWeight: '600',
marginBottom: '12px'
}}>NOVI Hogeschool</h3>
<p style={{
color: '#9ca3af',
fontSize: '14px',
lineHeight: '1.6'
}}>
AI Development Cursus<br/>
Utrecht, Nederland
</p>
</div>
</div>
<div style={{
borderTop: '1px solid #374151',
marginTop: '32px',
paddingTop: '20px',
textAlign: 'center',
color: '#6b7280',
fontSize: '13px'
}}>
© 2025 Debug Challenge Les 3 Huiswerk
</div>
</footer>
)
}

View File

@@ -0,0 +1,53 @@
import { ArrowRight } from "lucide-react";
import Link from "next/link";
export default function Hero() {
return (
<section style={{
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
padding: '80px 20px',
textAlign: 'center',
color: 'white',
minHeight: '500px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}>
<div style={{
maxWidth: '700px'
}}>
<h1 style={{
fontSize: '48px',
fontWeight: 'bold',
marginBottom: '16px',
lineHeight: '1.2'
}}>
Bouw Sneller met AI
</h1>
<p style={{
fontSize: '20px',
marginBottom: '32px',
opacity: '0.9',
lineHeight: '1.6'
}}>
Ontdek hoe je met Cursor en Next.js in minuten een professionele
website bouwt. Van idee tot deployment in no-time.
</p>
<Link href="/about" style={{
display: 'inline-flex',
alignItems: 'center',
gap: '8px',
backgroundColor: 'white',
color: '#764ba2',
padding: '14px 28px',
borderRadius: '9999px',
fontWeight: '600',
fontSize: '16px',
textDecoration: 'none'
}}>
Meer Weten <ArrowRight size={18} />
</Link>
</div>
</section>
);
}

View File

@@ -0,0 +1,59 @@
"use client";
import Link from "next/link";
import { useState } from "react";
export default function Navbar() {
const [menuOpen, setMenuOpen] = useState(false);
return (
<nav style={{
backgroundColor: 'white',
borderBottom: '1px solid #e5e7eb',
padding: '0 20px',
position: 'sticky',
top: '0',
zIndex: '50'
}}>
<div style={{
maxWidth: '1200px',
margin: '0 auto',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
height: '64px'
}}>
<Link href="/" style={{
fontSize: '20px',
fontWeight: 'bold',
color: '#7c3aed',
textDecoration: 'none'
}}>
🚀 Debug Challenge
</Link>
<div style={{
display: 'flex',
gap: '24px',
alignItems: 'center'
}}>
<Link href="/" style={{
color: '#4b5563',
textDecoration: 'none',
fontWeight: '500'
}}>Home</Link>
<Link href="/about" style={{
color: '#4b5563',
textDecoration: 'none',
fontWeight: '500'
}}>Over Ons</Link>
<Link href="/contact" style={{
color: '#4b5563',
textDecoration: 'none',
fontWeight: '500'
}}>Contact</Link>
</div>
</div>
</nav>
);
}

View File

@@ -0,0 +1,73 @@
const testimonials = [
{
naam: "Lisa de Vries",
rol: "Frontend Developer",
tekst: "Cursor heeft mijn workflow compleet veranderd. Ik bouw nu in uren wat vroeger dagen kostte.",
},
{
naam: "Mark Jansen",
rol: "Student NOVI",
tekst: "Eindelijk een tool die écht begrijpt wat ik wil bouwen. De Composer feature is geweldig!",
},
{
naam: "Sophie Bakker",
rol: "Full-Stack Developer",
tekst: "Van OpenCode naar Cursor was de beste beslissing. Geen token limits meer, gewoon bouwen.",
},
];
export default function TestimonialSection() {
return (
<section style={{
padding: '60px 20px',
backgroundColor: 'white'
}}>
<div style={{
maxWidth: '1000px',
margin: '0 auto'
}}>
<h2 style={{
fontSize: '32px',
fontWeight: 'bold',
textAlign: 'center',
marginBottom: '40px',
color: '#1a1a1a'
}}>Wat Anderen Zeggen</h2>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(3, 1fr)',
gap: '24px'
}}>
{testimonials.map((t, i) => (
<div key={i} style={{
padding: '28px',
backgroundColor: '#faf5ff',
borderRadius: '16px',
border: '1px solid #e9d5ff'
}}>
<p style={{
fontStyle: 'italic',
color: '#4b5563',
marginBottom: '16px',
lineHeight: '1.6',
fontSize: '15px'
}}>"{t.tekst}"</p>
<div>
<p style={{
fontWeight: '600',
color: '#1a1a1a',
fontSize: '15px'
}}>{t.naam}</p>
<p style={{
color: '#7c3aed',
fontSize: '13px'
}}>{t.rol}</p>
</div>
</div>
))}
</div>
</div>
</section>
)
}

View File

@@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default nextConfig;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
{
"name": "les3-debug-challenge",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"next": "14.2.5",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"typescript": "^5",
"postcss": "^8",
"autoprefixer": "^10",
"tailwindcss": "^3.4.1",
"eslint": "^8",
"eslint-config-next": "14.2.5"
}
}

View File

@@ -0,0 +1,9 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
export default config;

View File

@@ -0,0 +1,13 @@
import type { Config } from "tailwindcss";
const config: Config = {
content: [
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {},
},
plugins: [],
};
export default config;

View File

@@ -0,0 +1,20 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [{ "name": "next" }],
"paths": { "@/*": ["./*"] }
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}