1/**
2 * Main Application Logic
3 *
4 * Initializes router, defines page components, and manages state
5 */
6
7import router from './router.js';
8
9// Simple State Management
10const state = {
11 user: null,
12 visitCount: 0,
13
14 setUser(user) {
15 this.user = user;
16 },
17
18 incrementVisit() {
19 this.visitCount++;
20 }
21};
22
23// Page Components
24
25/**
26 * Home Page Component
27 */
28function HomePage() {
29 return `
30 <div class="page-enter">
31 <h1>Welcome to SPA Router Demo</h1>
32 <p>This is a demonstration of a simple single-page application using hash-based routing.</p>
33
34 <div class="card">
35 <h2>Features</h2>
36 <ul>
37 <li>Hash-based routing (#/path)</li>
38 <li>Dynamic route parameters</li>
39 <li>Page transition animations</li>
40 <li>Mobile responsive design</li>
41 <li>Navigation guards</li>
42 <li>404 error handling</li>
43 </ul>
44 </div>
45
46 <div class="card">
47 <h2>Getting Started</h2>
48 <p>Use the navigation bar above to explore different pages:</p>
49 <ul>
50 <li><strong>Home:</strong> You are here!</li>
51 <li><strong>About:</strong> Learn more about this project</li>
52 <li><strong>Contact:</strong> Fill out a contact form</li>
53 <li><strong>User Profile:</strong> View dynamic route parameters</li>
54 </ul>
55 </div>
56
57 <div class="card">
58 <h3>Visit Counter</h3>
59 <p>This page has been loaded <strong>${state.visitCount}</strong> time(s).</p>
60 </div>
61
62 <a href="#/about" class="btn">Learn More</a>
63 </div>
64 `;
65}
66
67/**
68 * About Page Component
69 */
70function AboutPage() {
71 return `
72 <div class="page-enter">
73 <h1>About This Project</h1>
74
75 <div class="card">
76 <h2>What is a Single Page Application?</h2>
77 <p>
78 A Single Page Application (SPA) is a web application that loads a single HTML page
79 and dynamically updates content as the user interacts with the app. This provides
80 a more fluid user experience similar to desktop applications.
81 </p>
82 </div>
83
84 <div class="card">
85 <h2>Hash-Based Routing</h2>
86 <p>
87 This implementation uses hash-based routing (<code>#/path</code>), which:
88 </p>
89 <ul>
90 <li>Works without server configuration</li>
91 <li>Doesn't trigger page reloads</li>
92 <li>Maintains browser history</li>
93 <li>Enables back/forward navigation</li>
94 </ul>
95 </div>
96
97 <div class="card">
98 <h2>Technology Stack</h2>
99 <ul>
100 <li><strong>HTML5:</strong> Semantic markup</li>
101 <li><strong>CSS3:</strong> Custom properties, animations, flexbox</li>
102 <li><strong>JavaScript ES6+:</strong> Modules, classes, async/await</li>
103 <li><strong>No Framework:</strong> Pure vanilla JavaScript</li>
104 </ul>
105 </div>
106
107 <a href="#/contact" class="btn btn-secondary">Get in Touch</a>
108 </div>
109 `;
110}
111
112/**
113 * Contact Page Component
114 */
115function ContactPage() {
116 // Add form submission handler after render
117 setTimeout(() => {
118 const form = document.getElementById('contact-form');
119 if (form) {
120 form.addEventListener('submit', handleContactSubmit);
121 }
122 }, 0);
123
124 return `
125 <div class="page-enter">
126 <h1>Contact Us</h1>
127 <p>Have questions? Fill out the form below and we'll get back to you.</p>
128
129 <form id="contact-form" class="card">
130 <div class="form-group">
131 <label class="form-label" for="name">Name:</label>
132 <input type="text" id="name" name="name" class="form-control" required>
133 </div>
134
135 <div class="form-group">
136 <label class="form-label" for="email">Email:</label>
137 <input type="email" id="email" name="email" class="form-control" required>
138 </div>
139
140 <div class="form-group">
141 <label class="form-label" for="message">Message:</label>
142 <textarea id="message" name="message" rows="5" class="form-control" required></textarea>
143 </div>
144
145 <button type="submit" class="btn">Send Message</button>
146 </form>
147
148 <div id="form-result" style="margin-top: 1rem;"></div>
149 </div>
150 `;
151}
152
153/**
154 * User Profile Page Component (Dynamic Route)
155 */
156function UserProfilePage(params) {
157 const userId = params.id || 'unknown';
158
159 // Simulate user data
160 const userData = {
161 '123': { name: 'John Doe', email: 'john@example.com', role: 'Developer' },
162 '456': { name: 'Jane Smith', email: 'jane@example.com', role: 'Designer' },
163 'unknown': { name: 'Guest User', email: 'N/A', role: 'Visitor' }
164 };
165
166 const user = userData[userId] || userData['unknown'];
167
168 return `
169 <div class="page-enter">
170 <h1>User Profile</h1>
171
172 <div class="card">
173 <h2>${user.name}</h2>
174 <p><strong>User ID:</strong> ${userId}</p>
175 <p><strong>Email:</strong> ${user.email}</p>
176 <p><strong>Role:</strong> ${user.role}</p>
177 </div>
178
179 <div class="card">
180 <h3>Dynamic Route Parameters</h3>
181 <p>This page demonstrates dynamic routing. The URL pattern is <code>/user/:id</code></p>
182 <p>Current route: <code>/user/${userId}</code></p>
183 <p>Try different user IDs:</p>
184 <ul>
185 <li><a href="#/user/123">/user/123</a> - John Doe</li>
186 <li><a href="#/user/456">/user/456</a> - Jane Smith</li>
187 <li><a href="#/user/789">/user/789</a> - Unknown user</li>
188 </ul>
189 </div>
190
191 <a href="#/" class="btn">Back to Home</a>
192 </div>
193 `;
194}
195
196/**
197 * 404 Not Found Page
198 */
199function NotFoundPage() {
200 return `
201 <div class="page-enter">
202 <h1>404 - Page Not Found</h1>
203 <p>The page you're looking for doesn't exist.</p>
204 <a href="#/" class="btn">Go Home</a>
205 </div>
206 `;
207}
208
209// Event Handlers
210
211function handleContactSubmit(e) {
212 e.preventDefault();
213
214 const formData = {
215 name: document.getElementById('name').value,
216 email: document.getElementById('email').value,
217 message: document.getElementById('message').value
218 };
219
220 // Simulate form submission
221 const resultDiv = document.getElementById('form-result');
222 resultDiv.innerHTML = `
223 <div class="card" style="border-left-color: #2ecc71;">
224 <h3>Thank you, ${formData.name}!</h3>
225 <p>Your message has been received. We'll respond to ${formData.email} soon.</p>
226 </div>
227 `;
228
229 // Reset form
230 document.getElementById('contact-form').reset();
231}
232
233// Router Configuration
234
235// Register routes
236router.addRoute('/', HomePage);
237router.addRoute('/about', AboutPage);
238router.addRoute('/contact', ContactPage);
239router.addRoute('/user/:id', UserProfilePage);
240
241// Set 404 handler
242router.setNotFound(NotFoundPage);
243
244// Navigation guards
245router.beforeEach((path) => {
246 console.log('Navigating to:', path);
247 state.incrementVisit();
248 return true; // Continue navigation
249});
250
251router.afterEach((path, params) => {
252 console.log('Navigation complete:', path, params);
253 // Update page title
254 const titles = {
255 '/': 'Home',
256 '/about': 'About',
257 '/contact': 'Contact',
258 };
259 document.title = `SPA Example - ${titles[path] || 'Page'}`;
260});
261
262console.log('App initialized successfully');