Skip to content

Commit c773078

Browse files
committed
Added first exercise
1 parent 8567260 commit c773078

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+15914
-2574
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ workspace/
88
data.db
99
/playground
1010
**/tsconfig.tsbuildinfo
11-
11+
.react-router
1212
# in a real app you'd want to not commit the .env
1313
# file as well, but since this is for a workshop
1414
# we're going to keep them around.

.vscode/settings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,9 @@
77
],
88
"workbench.editorAssociations": {
99
"*.db": "sqlite-viewer.view"
10-
}
10+
},
11+
"cSpell.words": [
12+
"Kakariki",
13+
"Kiira"
14+
]
1115
}

exercises/01.example/01.problem.hello/README.mdx

Lines changed: 0 additions & 1 deletion
This file was deleted.

exercises/01.example/01.problem.hello/index.js

Lines changed: 0 additions & 8 deletions
This file was deleted.

exercises/01.example/01.problem.hello/package.json

Lines changed: 0 additions & 6 deletions
This file was deleted.

exercises/01.example/01.problem.hello/tsconfig.json

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Registering Routes in React Router
2+
3+
Welcome to your first exercise! In this exercise,
4+
you will learn how to register routes in a React Router application.
5+
6+
## Exercise Overview
7+
8+
In this exercise, you will:
9+
1. Explore the `app/routes` directory.
10+
2. Register those routes in the `app/routes.ts` file.
11+
3. (Bonus) Create a utility to easily define landing page routes.
12+
13+
14+
## Getting Started
15+
16+
Due to Kody 🐨 being on vacation our assistant will be Kiira the Kakariki 🐥!
17+
18+
To get started, find our helpful assistants comments in the `app/routes.ts` file. (They include 🐥 emoji)
19+
20+
21+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
@import "tailwindcss";
2+
3+
@theme {
4+
--font-sans: "Inter", ui-sans-serif, system-ui, sans-serif,
5+
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
6+
}
7+
8+
html,
9+
body {
10+
@apply bg-white dark:bg-gray-950;
11+
12+
@media (prefers-color-scheme: dark) {
13+
color-scheme: dark;
14+
}
15+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { ShoppingBag } from "lucide-react"
2+
import { Link } from "react-router";
3+
4+
export const Footer = () => {
5+
return (
6+
<footer className="bg-white dark:bg-gray-900 border-t border-stone-200 dark:border-gray-700">
7+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
8+
<div className="grid grid-cols-1 md:grid-cols-4 gap-12">
9+
<div className="col-span-1 md:col-span-2">
10+
<div className="flex items-center space-x-3 mb-6">
11+
<ShoppingBag className="w-7 h-7 text-amber-600 dark:text-amber-500" />
12+
<span className="text-xl font-light text-gray-900 dark:text-white tracking-wide">
13+
EpicStore
14+
</span>
15+
</div>
16+
<p className="text-gray-600 dark:text-gray-400 font-light leading-relaxed max-w-md">
17+
Your premier destination for premium epic products. Discover the perfect product that combines
18+
style, comfort, and quality craftsmanship.
19+
</p>
20+
</div>
21+
<div>
22+
<h3 className="text-sm font-medium text-gray-900 dark:text-white uppercase tracking-wider mb-6">
23+
Shop
24+
</h3>
25+
<ul className="space-y-4">
26+
<li><Link to="/products" className="text-gray-600 dark:text-gray-400 hover:text-amber-600 dark:hover:text-amber-500 font-light transition-colors duration-300">All Products</Link></li>
27+
<li><Link to="/products?category=Running" className="text-gray-600 dark:text-gray-400 hover:text-amber-600 dark:hover:text-amber-500 font-light transition-colors duration-300">Running</Link></li>
28+
<li><Link to="/products?category=Casual" className="text-gray-600 dark:text-gray-400 hover:text-amber-600 dark:hover:text-amber-500 font-light transition-colors duration-300">Casual</Link></li>
29+
<li><Link to="/products?category=Formal" className="text-gray-600 dark:text-gray-400 hover:text-amber-600 dark:hover:text-amber-500 font-light transition-colors duration-300">Formal</Link></li>
30+
</ul>
31+
</div>
32+
<div>
33+
<h3 className="text-sm font-medium text-gray-900 dark:text-white uppercase tracking-wider mb-6">
34+
Company
35+
</h3>
36+
<ul className="space-y-4">
37+
<li><Link to="/about" className="text-gray-600 dark:text-gray-400 hover:text-amber-600 dark:hover:text-amber-500 font-light transition-colors duration-300">About</Link></li>
38+
<li><Link to="/contact" className="text-gray-600 dark:text-gray-400 hover:text-amber-600 dark:hover:text-amber-500 font-light transition-colors duration-300">Contact</Link></li>
39+
<li><Link to="/terms-of-service" className="text-gray-600 dark:text-gray-400 hover:text-amber-600 dark:hover:text-amber-500 font-light transition-colors duration-300">Terms of Service</Link></li>
40+
<li><Link to="/terms-of-use" className="text-gray-600 dark:text-gray-400 hover:text-amber-600 dark:hover:text-amber-500 font-light transition-colors duration-300">Terms of Use</Link></li>
41+
</ul>
42+
</div>
43+
</div>
44+
<div className="mt-12 pt-8 border-t border-stone-200 dark:border-gray-700">
45+
<p className="text-center text-gray-500 dark:text-gray-400 font-light">
46+
© 2025 EpicStore. All rights reserved.
47+
</p>
48+
</div>
49+
</div>
50+
</footer>
51+
)
52+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { Link, useLocation } from 'react-router';
2+
import { ShoppingBag, Search, Menu, X } from 'lucide-react';
3+
import { useState } from 'react';
4+
5+
export const Header = () => {
6+
const [isMenuOpen, setIsMenuOpen] = useState(false);
7+
const navigation = [
8+
{ name: 'Home', href: '/' },
9+
{ name: 'Products', href: '/products' },
10+
{ name: 'About', href: '/about' },
11+
{ name: 'Contact', href: '/contact' },
12+
];
13+
const location = useLocation()
14+
const isActive = (href: string) => location.pathname === href;
15+
16+
return (
17+
<nav className="bg-white/95 dark:bg-gray-900/95 backdrop-blur-md border-b border-stone-200 dark:border-gray-700 sticky top-0 z-50">
18+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
19+
<div className="flex justify-between items-center h-20">
20+
<div className="flex items-center">
21+
<Link to="/" className="flex items-center space-x-3">
22+
<ShoppingBag className="w-8 h-8 text-amber-600 dark:text-amber-500" />
23+
<span className="text-2xl font-light text-gray-900 dark:text-white tracking-wide">
24+
EpicStore
25+
</span>
26+
</Link>
27+
</div>
28+
29+
<div className="hidden md:block flex-1 max-w-lg mx-8">
30+
<div className="relative">
31+
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5" />
32+
<input
33+
type="text"
34+
placeholder="Search for products..."
35+
className="w-full pl-10 pr-4 py-3 border border-gray-200 dark:border-gray-600 rounded-full bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-amber-500 focus:border-transparent"
36+
/>
37+
</div>
38+
</div>
39+
40+
<div className="hidden md:block">
41+
<div className="flex items-center space-x-8">
42+
{navigation.map((item) => (
43+
<Link
44+
key={item.name}
45+
to={item.href}
46+
className={`text-sm font-medium tracking-wide transition-colors duration-300 ${isActive(item.href)
47+
? 'text-amber-600 dark:text-amber-500'
48+
: 'text-gray-700 dark:text-gray-300 hover:text-amber-600 dark:hover:text-amber-500'
49+
}`}
50+
>
51+
{item.name}
52+
</Link>
53+
))}
54+
<div className="flex items-center space-x-4">
55+
{/* <button className="p-2 text-gray-700 dark:text-gray-300 hover:text-amber-600 dark:hover:text-amber-500 transition-colors duration-300">
56+
<Heart className="w-5 h-5" />
57+
</button>
58+
<button className="p-2 text-gray-700 dark:text-gray-300 hover:text-amber-600 dark:hover:text-amber-500 transition-colors duration-300">
59+
<User className="w-5 h-5" />
60+
</button>
61+
<ShoppingCart /> */}
62+
63+
</div>
64+
</div>
65+
</div>
66+
67+
<div className="md:hidden flex items-center space-x-4">
68+
{/* <ShoppingCart /> */}
69+
<button
70+
onClick={() => setIsMenuOpen(!isMenuOpen)}
71+
className="text-gray-700 dark:text-gray-300 hover:text-amber-600 dark:hover:text-amber-500 p-2"
72+
>
73+
{isMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
74+
</button>
75+
</div>
76+
</div>
77+
</div>
78+
79+
{isMenuOpen && (
80+
<div className="md:hidden">
81+
<div className="px-4 pt-2 pb-6 space-y-4 bg-white dark:bg-gray-900 border-t border-stone-200 dark:border-gray-700">
82+
<div className="relative mb-4">
83+
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5" />
84+
<input
85+
type="text"
86+
placeholder="Search for products..."
87+
className="w-full pl-10 pr-4 py-3 border border-gray-200 dark:border-gray-600 rounded-full bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-amber-500 focus:border-transparent"
88+
/>
89+
</div>
90+
{navigation.map((item) => (
91+
<Link
92+
key={item.name}
93+
to={item.href}
94+
onClick={() => setIsMenuOpen(false)}
95+
className={`block text-base font-medium tracking-wide transition-colors duration-300 ${isActive(item.href)
96+
? 'text-amber-600 dark:text-amber-500'
97+
: 'text-gray-700 dark:text-gray-300 hover:text-amber-600 dark:hover:text-amber-500'
98+
}`}
99+
>
100+
{item.name}
101+
</Link>
102+
))}
103+
</div>
104+
</div>
105+
)}
106+
</nav>
107+
)
108+
}

0 commit comments

Comments
 (0)