frontend-hamroun 1.2.75 → 1.2.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/batch/package.json +16 -0
- package/dist/client-router/package.json +16 -0
- package/dist/component/package.json +16 -0
- package/dist/context/package.json +16 -0
- package/dist/event-bus/package.json +16 -0
- package/dist/forms/package.json +16 -0
- package/dist/hooks/package.json +16 -0
- package/dist/jsx-runtime/package.json +16 -0
- package/dist/lifecycle-events/package.json +16 -0
- package/dist/package.json +71 -0
- package/dist/render-component/package.json +16 -0
- package/dist/renderer/package.json +16 -0
- package/dist/router/package.json +16 -0
- package/dist/server/package.json +17 -0
- package/dist/server/src/client-router.d.ts +60 -0
- package/dist/server/src/client-router.js +210 -0
- package/dist/server/src/client-router.js.map +1 -0
- package/dist/server/src/component.js +1 -1
- package/dist/server/src/event-bus.d.ts +23 -0
- package/dist/server/src/event-bus.js +75 -0
- package/dist/server/src/event-bus.js.map +1 -0
- package/dist/server/src/forms.d.ts +40 -0
- package/dist/server/src/forms.js +148 -0
- package/dist/server/src/forms.js.map +1 -0
- package/dist/server/src/hooks.js +2 -2
- package/dist/server/src/index.js +19 -11
- package/dist/server/src/lifecycle-events.d.ts +108 -0
- package/dist/server/src/lifecycle-events.js +177 -0
- package/dist/server/src/lifecycle-events.js.map +1 -0
- package/dist/server/src/renderComponent.js +1 -1
- package/dist/server/src/renderer.js +3 -3
- package/dist/server/src/router.d.ts +55 -0
- package/dist/server/src/router.js +166 -0
- package/dist/server/src/router.js.map +1 -0
- package/dist/server/src/server/index.d.ts +75 -2
- package/dist/server/src/server/index.js +224 -8
- package/dist/server/src/server/index.js.map +1 -1
- package/dist/server/src/server/server.js +1 -1
- package/dist/server/src/server/templates.d.ts +28 -0
- package/dist/server/src/server/templates.js +204 -0
- package/dist/server/src/server/templates.js.map +1 -0
- package/dist/server/src/server/utils.d.ts +70 -0
- package/dist/server/src/server/utils.js +156 -0
- package/dist/server/src/server/utils.js.map +1 -0
- package/dist/server/src/server-renderer.js +1 -1
- package/dist/server/src/store.d.ts +41 -0
- package/dist/server/src/store.js +99 -0
- package/dist/server/src/store.js.map +1 -0
- package/dist/server/src/utils.d.ts +46 -0
- package/dist/server/src/utils.js +144 -0
- package/dist/server/src/utils.js.map +1 -0
- package/dist/server/tsconfig.server.tsbuildinfo +1 -1
- package/dist/server-renderer/package.json +16 -0
- package/dist/store/package.json +16 -0
- package/dist/types/package.json +16 -0
- package/dist/utils/package.json +16 -0
- package/dist/vdom/package.json +16 -0
- package/dist/wasm/package.json +16 -0
- package/package.json +14 -13
- package/templates/complete-app/build.js +284 -0
- package/templates/complete-app/package.json +40 -0
- package/templates/complete-app/public/styles.css +345 -0
- package/templates/complete-app/src/api/index.js +31 -0
- package/templates/complete-app/src/client.js +93 -0
- package/templates/complete-app/src/components/App.js +66 -0
- package/templates/complete-app/src/components/Footer.js +19 -0
- package/templates/complete-app/src/components/Header.js +38 -0
- package/templates/complete-app/src/pages/About.js +59 -0
- package/templates/complete-app/src/pages/Home.js +54 -0
- package/templates/complete-app/src/pages/WasmDemo.js +136 -0
- package/templates/complete-app/src/server.js +186 -0
- package/templates/complete-app/src/wasm/build.bat +16 -0
- package/templates/complete-app/src/wasm/build.sh +16 -0
- package/templates/complete-app/src/wasm/example.go +101 -0
- package/templates/fullstack-app/build/main.css +225 -15
- package/templates/fullstack-app/build/main.css.map +2 -2
- package/templates/fullstack-app/build/main.js +657 -372
- package/templates/fullstack-app/build/main.js.map +4 -4
- package/templates/fullstack-app/build.ts +3 -4
- package/templates/fullstack-app/public/styles.css +222 -15
- package/templates/fullstack-app/server.ts +46 -12
- package/templates/fullstack-app/src/components/ClientHome.tsx +0 -0
- package/templates/fullstack-app/src/components/ErrorBoundary.tsx +36 -0
- package/templates/fullstack-app/src/components/Layout.tsx +23 -26
- package/templates/fullstack-app/src/components/StateDemo.tsx +207 -0
- package/templates/fullstack-app/src/components/UserList.tsx +30 -13
- package/templates/fullstack-app/src/data/api.ts +173 -38
- package/templates/fullstack-app/src/main.tsx +88 -154
- package/templates/fullstack-app/src/middleware.ts +28 -0
- package/templates/fullstack-app/src/pages/404.tsx +28 -0
- package/templates/fullstack-app/src/pages/[id].tsx +0 -0
- package/templates/fullstack-app/src/pages/_app.tsx +11 -0
- package/templates/fullstack-app/src/pages/_document.tsx +25 -0
- package/templates/fullstack-app/src/pages/_error.tsx +45 -0
- package/templates/fullstack-app/src/pages/about.tsx +71 -0
- package/templates/fullstack-app/src/pages/api/users/[id].ts +73 -0
- package/templates/fullstack-app/src/pages/api/users/index.ts +43 -0
- package/templates/fullstack-app/src/pages/index.tsx +97 -20
- package/templates/fullstack-app/src/pages/users/[id].tsx +153 -0
- package/templates/fullstack-app/src/pages/wasm-demo.tsx +1 -0
- package/templates/go/example.go +99 -86
- package/templates/go-wasm-app/babel.config.js +8 -2
- package/templates/go-wasm-app/build.config.js +62 -0
- package/templates/go-wasm-app/build.js +218 -0
- package/templates/go-wasm-app/package.json +21 -12
- package/templates/go-wasm-app/server.js +59 -510
- package/templates/go-wasm-app/src/app.js +173 -0
- package/templates/go-wasm-app/vite.config.js +16 -5
- package/templates/ssr-template/client.js +54 -26
- package/templates/ssr-template/server.js +5 -28
- package/templates/ssr-template/vite.config.js +21 -5
- package/dist/server/wasm.d.ts +0 -7
- package/dist/wasm.d.ts +0 -37
@@ -47,6 +47,107 @@ function finishRender() {
|
|
47
47
|
}
|
48
48
|
currentRender = 0;
|
49
49
|
}
|
50
|
+
function useState(initial) {
|
51
|
+
if (!currentRender) {
|
52
|
+
throw new Error("useState must be called within a render");
|
53
|
+
}
|
54
|
+
if (isServer) {
|
55
|
+
if (!serverStates.has(currentRender)) {
|
56
|
+
serverStates.set(currentRender, /* @__PURE__ */ new Map());
|
57
|
+
}
|
58
|
+
const componentState = serverStates.get(currentRender);
|
59
|
+
const index2 = stateIndices.get(currentRender) || 0;
|
60
|
+
if (!componentState.has(index2)) {
|
61
|
+
componentState.set(index2, initial);
|
62
|
+
}
|
63
|
+
const state2 = componentState.get(index2);
|
64
|
+
const setState2 = (newValue) => {
|
65
|
+
};
|
66
|
+
stateIndices.set(currentRender, index2 + 1);
|
67
|
+
return [state2, setState2];
|
68
|
+
}
|
69
|
+
if (!states.has(currentRender)) {
|
70
|
+
states.set(currentRender, []);
|
71
|
+
}
|
72
|
+
const componentStates = states.get(currentRender);
|
73
|
+
const index = stateIndices.get(currentRender);
|
74
|
+
if (index >= componentStates.length) {
|
75
|
+
componentStates.push(initial);
|
76
|
+
}
|
77
|
+
const state = componentStates[index];
|
78
|
+
const setState = (newValue) => {
|
79
|
+
const nextValue = typeof newValue === "function" ? newValue(componentStates[index]) : newValue;
|
80
|
+
if (componentStates[index] === nextValue)
|
81
|
+
return;
|
82
|
+
componentStates[index] = nextValue;
|
83
|
+
if (isBatching) {
|
84
|
+
batchUpdates(() => rerender(currentRender));
|
85
|
+
} else {
|
86
|
+
rerender(currentRender);
|
87
|
+
}
|
88
|
+
};
|
89
|
+
stateIndices.set(currentRender, index + 1);
|
90
|
+
return [state, setState];
|
91
|
+
}
|
92
|
+
function useEffect(callback, deps) {
|
93
|
+
if (!currentRender)
|
94
|
+
throw new Error("useEffect must be called within a render");
|
95
|
+
const effectIndex = stateIndices.get(currentRender);
|
96
|
+
if (!effects.has(currentRender)) {
|
97
|
+
effects.set(currentRender, []);
|
98
|
+
}
|
99
|
+
const componentEffects = effects.get(currentRender);
|
100
|
+
const prevEffect = componentEffects[effectIndex];
|
101
|
+
if (!prevEffect || !deps || !prevEffect.deps || deps.some((dep, i) => dep !== prevEffect.deps[i])) {
|
102
|
+
if (prevEffect == null ? void 0 : prevEffect.cleanup) {
|
103
|
+
prevEffect.cleanup();
|
104
|
+
}
|
105
|
+
queueMicrotask(() => {
|
106
|
+
const cleanup = callback() || void 0;
|
107
|
+
componentEffects[effectIndex] = { cleanup, deps };
|
108
|
+
});
|
109
|
+
}
|
110
|
+
stateIndices.set(currentRender, effectIndex + 1);
|
111
|
+
}
|
112
|
+
function useMemo(factory, deps) {
|
113
|
+
if (!currentRender)
|
114
|
+
throw new Error("useMemo must be called within a render");
|
115
|
+
const memoIndex = stateIndices.get(currentRender);
|
116
|
+
if (!memos.has(currentRender)) {
|
117
|
+
memos.set(currentRender, []);
|
118
|
+
}
|
119
|
+
const componentMemos = memos.get(currentRender);
|
120
|
+
const prevMemo = componentMemos[memoIndex];
|
121
|
+
if (!prevMemo || deps && deps.some((dep, i) => !Object.is(dep, prevMemo.deps[i]))) {
|
122
|
+
const value = factory();
|
123
|
+
componentMemos[memoIndex] = { value, deps };
|
124
|
+
stateIndices.set(currentRender, memoIndex + 1);
|
125
|
+
return value;
|
126
|
+
}
|
127
|
+
stateIndices.set(currentRender, memoIndex + 1);
|
128
|
+
return prevMemo.value;
|
129
|
+
}
|
130
|
+
async function rerender(rendererId) {
|
131
|
+
try {
|
132
|
+
const componentEffects = effects.get(rendererId);
|
133
|
+
if (componentEffects) {
|
134
|
+
componentEffects.forEach((effect) => {
|
135
|
+
if (effect.cleanup)
|
136
|
+
effect.cleanup();
|
137
|
+
});
|
138
|
+
effects.set(rendererId, []);
|
139
|
+
}
|
140
|
+
if (globalRenderCallback && globalContainer && currentElement) {
|
141
|
+
await globalRenderCallback(currentElement, globalContainer);
|
142
|
+
}
|
143
|
+
} catch (error) {
|
144
|
+
console.error("Error during rerender:", error);
|
145
|
+
}
|
146
|
+
}
|
147
|
+
function useErrorBoundary() {
|
148
|
+
const [error, setError] = useState(null);
|
149
|
+
return [error, () => setError(null)];
|
150
|
+
}
|
50
151
|
function jsx(type, props) {
|
51
152
|
console.log("JSX Transform:", { type, props });
|
52
153
|
const processedProps = { ...props };
|
@@ -149,13 +250,16 @@ async function render(element, container) {
|
|
149
250
|
}
|
150
251
|
});
|
151
252
|
}
|
152
|
-
var isBatching, queue, currentRender, stateIndices, globalRenderCallback, globalContainer, currentElement, isServer, serverStates, isHydrating;
|
253
|
+
var isBatching, queue, currentRender, states, stateIndices, effects, memos, globalRenderCallback, globalContainer, currentElement, isServer, serverStates, isHydrating;
|
153
254
|
var init_dist = __esm({
|
154
255
|
"node_modules/frontend-hamroun/dist/index.mjs"() {
|
155
256
|
isBatching = false;
|
156
257
|
queue = [];
|
157
258
|
currentRender = 0;
|
259
|
+
states = /* @__PURE__ */ new Map();
|
158
260
|
stateIndices = /* @__PURE__ */ new Map();
|
261
|
+
effects = /* @__PURE__ */ new Map();
|
262
|
+
memos = /* @__PURE__ */ new Map();
|
159
263
|
globalRenderCallback = null;
|
160
264
|
globalContainer = null;
|
161
265
|
currentElement = null;
|
@@ -165,143 +269,382 @@ var init_dist = __esm({
|
|
165
269
|
}
|
166
270
|
});
|
167
271
|
|
168
|
-
// src/
|
169
|
-
var
|
170
|
-
|
171
|
-
|
272
|
+
// src/pages/404.tsx
|
273
|
+
var __exports = {};
|
274
|
+
__export(__exports, {
|
275
|
+
default: () => NotFound
|
276
|
+
});
|
277
|
+
function NotFound({ initialState: initialState2 }) {
|
278
|
+
return /* @__PURE__ */ jsx("div", { className: "not-found-container max-w-4xl mx-auto p-6" }, /* @__PURE__ */ jsx("div", { className: "bg-gray-50 border border-gray-200 rounded-lg p-8 shadow-sm" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-gray-700 mb-4" }, "Page Not Found"), /* @__PURE__ */ jsx("p", { className: "text-lg text-gray-600 mb-4" }, "The page you are looking for does not exist or has been moved."), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-6" }, "Path: ", /* @__PURE__ */ jsx("code", { className: "bg-gray-100 px-2 py-1 rounded" }, initialState2?.route || "unknown")), /* @__PURE__ */ jsx("div", { className: "mt-6" }, /* @__PURE__ */ jsx(
|
279
|
+
"a",
|
280
|
+
{
|
281
|
+
href: "/",
|
282
|
+
className: "inline-block px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
|
283
|
+
},
|
284
|
+
"Back to Home"
|
285
|
+
))));
|
286
|
+
}
|
287
|
+
var init__ = __esm({
|
288
|
+
"src/pages/404.tsx"() {
|
289
|
+
"use strict";
|
290
|
+
init_dist();
|
291
|
+
}
|
292
|
+
});
|
293
|
+
|
294
|
+
// src/pages/[id].tsx
|
295
|
+
var id_exports = {};
|
296
|
+
var init_id = __esm({
|
297
|
+
"src/pages/[id].tsx"() {
|
172
298
|
"use strict";
|
173
|
-
AppConfig = {
|
174
|
-
// App information
|
175
|
-
title: "Frontend Hamroun App",
|
176
|
-
description: "A full-stack application built with Frontend Hamroun",
|
177
|
-
// Navigation
|
178
|
-
navigation: [
|
179
|
-
{ path: "/", label: "Home" },
|
180
|
-
{ path: "/about", label: "About" },
|
181
|
-
{ path: "/users", label: "Users" }
|
182
|
-
],
|
183
|
-
// API endpoints
|
184
|
-
api: {
|
185
|
-
baseUrl: "/api",
|
186
|
-
endpoints: {
|
187
|
-
users: "/users",
|
188
|
-
posts: "/posts"
|
189
|
-
}
|
190
|
-
},
|
191
|
-
// Default meta tags
|
192
|
-
meta: {
|
193
|
-
viewport: "width=device-width, initial-scale=1.0",
|
194
|
-
charset: "UTF-8",
|
195
|
-
author: "Your Name",
|
196
|
-
keywords: "frontend-hamroun, fullstack, template"
|
197
|
-
},
|
198
|
-
// Style customization
|
199
|
-
theme: {
|
200
|
-
primaryColor: "#0066cc",
|
201
|
-
backgroundColor: "#ffffff",
|
202
|
-
textColor: "#333333",
|
203
|
-
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif'
|
204
|
-
}
|
205
|
-
};
|
206
|
-
config_default = AppConfig;
|
207
299
|
}
|
208
300
|
});
|
209
301
|
|
210
302
|
// src/components/Layout.tsx
|
211
|
-
function Layout({ children, title =
|
212
|
-
|
213
|
-
|
303
|
+
function Layout({ children, title = "Frontend Hamroun App" }) {
|
304
|
+
return /* @__PURE__ */ jsx("div", { className: "min-h-screen flex flex-col bg-gray-50" }, /* @__PURE__ */ jsx("header", { className: "bg-blue-600 text-white" }, /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-4 flex justify-between items-center" }, /* @__PURE__ */ jsx("h1", { className: "text-xl font-bold" }, /* @__PURE__ */ jsx("a", { href: "/", className: "hover:text-blue-100" }, title)), /* @__PURE__ */ jsx("nav", null, /* @__PURE__ */ jsx("ul", { className: "flex space-x-6" }, /* @__PURE__ */ jsx("li", null, /* @__PURE__ */ jsx("a", { href: "/", className: "hover:text-blue-100" }, "Home")), /* @__PURE__ */ jsx("li", null, /* @__PURE__ */ jsx("a", { href: "/about", className: "hover:text-blue-100" }, "About")))))), /* @__PURE__ */ jsx("main", { className: "flex-grow container mx-auto px-4 py-8" }, children), /* @__PURE__ */ jsx("footer", { className: "bg-gray-800 text-white" }, /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-6" }, /* @__PURE__ */ jsx("p", { className: "text-center text-gray-400" }, "\xA9 ", (/* @__PURE__ */ new Date()).getFullYear(), " Frontend Hamroun App. All rights reserved."))));
|
305
|
+
}
|
306
|
+
var init_Layout = __esm({
|
307
|
+
"src/components/Layout.tsx"() {
|
308
|
+
"use strict";
|
309
|
+
init_dist();
|
310
|
+
}
|
311
|
+
});
|
312
|
+
|
313
|
+
// src/pages/_app.tsx
|
314
|
+
var app_exports = {};
|
315
|
+
__export(app_exports, {
|
316
|
+
default: () => App
|
317
|
+
});
|
318
|
+
function App({ Component, pageProps, initialState: initialState2 }) {
|
319
|
+
return /* @__PURE__ */ jsx(Layout, null, /* @__PURE__ */ jsx(Component, { ...pageProps, initialState: initialState2 }));
|
320
|
+
}
|
321
|
+
var init_app = __esm({
|
322
|
+
"src/pages/_app.tsx"() {
|
323
|
+
"use strict";
|
324
|
+
init_dist();
|
325
|
+
init_Layout();
|
326
|
+
}
|
327
|
+
});
|
328
|
+
|
329
|
+
// src/pages/_document.tsx
|
330
|
+
var document_exports = {};
|
331
|
+
__export(document_exports, {
|
332
|
+
default: () => Document
|
333
|
+
});
|
334
|
+
function Document({
|
335
|
+
title = "Frontend Hamroun App",
|
336
|
+
headContent,
|
337
|
+
bodyContent,
|
338
|
+
scripts
|
339
|
+
}) {
|
340
|
+
return /* @__PURE__ */ jsx("html", { lang: "en" }, /* @__PURE__ */ jsx("head", null, /* @__PURE__ */ jsx("meta", { charSet: "UTF-8" }), /* @__PURE__ */ jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }), /* @__PURE__ */ jsx("title", null, title), /* @__PURE__ */ jsx("link", { rel: "stylesheet", href: "/styles.css" }), headContent), /* @__PURE__ */ jsx("body", null, /* @__PURE__ */ jsx("div", { id: "root" }, bodyContent), /* @__PURE__ */ jsx("script", { src: "/build/main.js", type: "module" }), scripts));
|
341
|
+
}
|
342
|
+
var init_document = __esm({
|
343
|
+
"src/pages/_document.tsx"() {
|
344
|
+
"use strict";
|
345
|
+
init_dist();
|
346
|
+
}
|
347
|
+
});
|
348
|
+
|
349
|
+
// src/pages/_error.tsx
|
350
|
+
var error_exports = {};
|
351
|
+
__export(error_exports, {
|
352
|
+
default: () => ErrorPage
|
353
|
+
});
|
354
|
+
function ErrorPage({ initialState: initialState2 }) {
|
355
|
+
const { error } = initialState2 || {};
|
356
|
+
const [showDetails, setShowDetails] = useState(false);
|
357
|
+
const isDev = true;
|
358
|
+
return /* @__PURE__ */ jsx("div", { className: "error-page-container max-w-4xl mx-auto p-6" }, /* @__PURE__ */ jsx("div", { className: "bg-red-50 border border-red-200 rounded-lg p-8 shadow-sm" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-red-700 mb-4" }, "Something went wrong"), /* @__PURE__ */ jsx("p", { className: "text-lg text-red-600 mb-4" }, error?.message || "An unexpected error occurred"), isDev && error?.stack && /* @__PURE__ */ jsx("div", { className: "mt-6" }, /* @__PURE__ */ jsx(
|
359
|
+
"button",
|
360
|
+
{
|
361
|
+
className: "text-blue-600 underline mb-2",
|
362
|
+
onClick: () => setShowDetails(!showDetails)
|
363
|
+
},
|
364
|
+
showDetails ? "Hide" : "Show",
|
365
|
+
" technical details"
|
366
|
+
), showDetails && /* @__PURE__ */ jsx("pre", { className: "bg-gray-100 p-4 rounded-md text-sm overflow-auto max-h-96 text-gray-800" }, error.stack)), /* @__PURE__ */ jsx("div", { className: "mt-6" }, /* @__PURE__ */ jsx(
|
214
367
|
"a",
|
215
368
|
{
|
216
|
-
href:
|
217
|
-
className: "
|
369
|
+
href: "/",
|
370
|
+
className: "inline-block px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
|
218
371
|
},
|
219
|
-
|
220
|
-
))))
|
372
|
+
"Back to Home"
|
373
|
+
))));
|
221
374
|
}
|
222
|
-
var
|
223
|
-
"src/
|
375
|
+
var init_error = __esm({
|
376
|
+
"src/pages/_error.tsx"() {
|
224
377
|
"use strict";
|
225
378
|
init_dist();
|
226
|
-
init_config();
|
227
379
|
}
|
228
380
|
});
|
229
381
|
|
230
|
-
// src/pages/about
|
382
|
+
// src/pages/about.tsx
|
231
383
|
var about_exports = {};
|
232
384
|
__export(about_exports, {
|
233
|
-
default: () =>
|
385
|
+
default: () => AboutPage,
|
386
|
+
getServerSideProps: () => getServerSideProps
|
234
387
|
});
|
235
|
-
|
388
|
+
function AboutPage({ initialState: initialState2 }) {
|
389
|
+
return /* @__PURE__ */ jsx(Layout, { title: "About - Frontend Hamroun" }, /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-blue-600 mb-6" }, "About Frontend Hamroun"), /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-8 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "What is Frontend Hamroun?"), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-4" }, "Frontend Hamroun is a lightweight JavaScript framework for building modern web applications. It provides a familiar component-based architecture with hooks, JSX support, and server-side rendering capabilities."), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-4" }, "This framework is designed to be simple yet powerful, offering the essential features needed for web application development without the complexity of larger frameworks."), /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-gray-700 mt-6 mb-2" }, "Key Features:"), /* @__PURE__ */ jsx("ul", { className: "list-disc pl-6 text-gray-600 space-y-2" }, /* @__PURE__ */ jsx("li", null, "Component-based architecture"), /* @__PURE__ */ jsx("li", null, "JSX support"), /* @__PURE__ */ jsx("li", null, "Hooks for state and effects"), /* @__PURE__ */ jsx("li", null, "Server-side rendering"), /* @__PURE__ */ jsx("li", null, "Minimal API surface"), /* @__PURE__ */ jsx("li", null, "File-based routing"), /* @__PURE__ */ jsx("li", null, "Built-in API routes"))), /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "Getting Started"), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-4" }, "This application was created using the Frontend Hamroun fullstack template, which provides a complete setup for building applications with server-side rendering, API routes, and client-side navigation."), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 p-4 rounded-md mt-4" }, /* @__PURE__ */ jsx("h3", { className: "text-md font-medium text-gray-700 mb-2" }, "Quick Start:"), /* @__PURE__ */ jsx("pre", { className: "bg-gray-800 text-gray-100 p-4 rounded overflow-x-auto" }, /* @__PURE__ */ jsx("code", null, `# Create a new application
|
390
|
+
npx frontend-hamroun create my-app
|
391
|
+
|
392
|
+
# Change directory
|
393
|
+
cd my-app
|
394
|
+
|
395
|
+
# Start the development server
|
396
|
+
npm run dev`))))));
|
397
|
+
}
|
398
|
+
async function getServerSideProps() {
|
399
|
+
return {
|
400
|
+
props: {
|
401
|
+
pageTitle: "About Frontend Hamroun",
|
402
|
+
description: "Learn more about the Frontend Hamroun framework"
|
403
|
+
}
|
404
|
+
};
|
405
|
+
}
|
236
406
|
var init_about = __esm({
|
407
|
+
"src/pages/about.tsx"() {
|
408
|
+
"use strict";
|
409
|
+
init_dist();
|
410
|
+
init_Layout();
|
411
|
+
}
|
412
|
+
});
|
413
|
+
|
414
|
+
// src/pages/about/index.tsx
|
415
|
+
var about_exports2 = {};
|
416
|
+
__export(about_exports2, {
|
417
|
+
default: () => about_default
|
418
|
+
});
|
419
|
+
var AboutPage2, about_default;
|
420
|
+
var init_about2 = __esm({
|
237
421
|
"src/pages/about/index.tsx"() {
|
238
422
|
"use strict";
|
239
423
|
init_dist();
|
240
424
|
init_Layout();
|
241
|
-
|
425
|
+
AboutPage2 = ({ initialState: initialState2 }) => {
|
242
426
|
return /* @__PURE__ */ jsx(Layout, { title: "About This App" }, /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto bg-white shadow-lg rounded-lg overflow-hidden" }, /* @__PURE__ */ jsx("div", { className: "p-8" }, /* @__PURE__ */ jsx("p", { className: "text-lg text-gray-700 mb-6" }, "This is a frontend application built with Frontend Hamroun framework and styled with Tailwind CSS."), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-8" }, "It features server-side rendering, client-side navigation, and websocket-based live reloading during development."), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 p-6 rounded-lg border border-gray-200 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "Key Features"), /* @__PURE__ */ jsx("ul", { className: "space-y-2 text-gray-700" }, /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Server-side rendering"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Client-side navigation"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Component-based architecture"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Integrated API backend"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Live reload during development"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Tailwind CSS for styling"))), /* @__PURE__ */ jsx("a", { href: "/", className: "inline-block px-6 py-3 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 transition-colors" }, "Back to Home"))));
|
243
427
|
};
|
244
|
-
about_default =
|
428
|
+
about_default = AboutPage2;
|
245
429
|
}
|
246
430
|
});
|
247
431
|
|
248
432
|
// src/components/UserList.tsx
|
249
|
-
|
433
|
+
function UserList({ users }) {
|
434
|
+
if (!users || users.length === 0) {
|
435
|
+
return /* @__PURE__ */ jsx("div", { className: "empty-state p-4 text-center bg-gray-50 rounded" }, /* @__PURE__ */ jsx("p", { className: "text-gray-500" }, "No users available"));
|
436
|
+
}
|
437
|
+
return /* @__PURE__ */ jsx("div", { className: "user-list" }, /* @__PURE__ */ jsx("ul", { className: "divide-y divide-gray-100" }, users.map((user) => /* @__PURE__ */ jsx("li", { key: user.id, className: "py-3" }, /* @__PURE__ */ jsx("div", { className: "flex justify-between" }, /* @__PURE__ */ jsx("div", null, /* @__PURE__ */ jsx("p", { className: "font-medium text-gray-900" }, user.name), /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500" }, user.email)), /* @__PURE__ */ jsx(
|
438
|
+
"a",
|
439
|
+
{
|
440
|
+
href: `/users/${user.id}`,
|
441
|
+
className: "text-blue-600 hover:underline text-sm self-center"
|
442
|
+
},
|
443
|
+
"View Profile"
|
444
|
+
))))));
|
445
|
+
}
|
250
446
|
var init_UserList = __esm({
|
251
447
|
"src/components/UserList.tsx"() {
|
252
448
|
"use strict";
|
253
449
|
init_dist();
|
254
|
-
UserList = ({ users }) => {
|
255
|
-
if (!users || users.length === 0) {
|
256
|
-
return /* @__PURE__ */ jsx("div", { className: "p-4 bg-gray-50 rounded-lg border border-gray-200 my-4" }, /* @__PURE__ */ jsx("p", { className: "text-gray-500 italic" }, "No users found or still loading..."));
|
257
|
-
}
|
258
|
-
return /* @__PURE__ */ jsx("div", { className: "rounded-lg overflow-hidden my-4" }, /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium mb-3" }, "Users (", users.length, ")"), /* @__PURE__ */ jsx("ul", { className: "divide-y divide-gray-200 border border-gray-200 rounded-lg overflow-hidden" }, users.map((user) => /* @__PURE__ */ jsx("li", { key: user.id, className: "flex justify-between items-center p-4 hover:bg-gray-50" }, /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-800" }, user.name), /* @__PURE__ */ jsx("span", { className: "text-gray-500 text-sm" }, user.email)))));
|
259
|
-
};
|
260
|
-
UserList_default = UserList;
|
261
450
|
}
|
262
451
|
});
|
263
452
|
|
264
|
-
// src/
|
265
|
-
|
266
|
-
const
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
453
|
+
// src/components/StateDemo.tsx
|
454
|
+
function StateDemo() {
|
455
|
+
const [state, setState] = useState({
|
456
|
+
count: 0,
|
457
|
+
lastUpdated: null,
|
458
|
+
history: []
|
459
|
+
});
|
460
|
+
const [isLoading, setIsLoading] = useState(false);
|
461
|
+
const [showHistory, setShowHistory] = useState(false);
|
462
|
+
const isSSR = typeof window === "undefined";
|
463
|
+
const stats = useMemo(() => {
|
464
|
+
if (isSSR || !state || !state.history || state.history.length === 0) {
|
465
|
+
return { avg: 0, max: 0, min: 0 };
|
466
|
+
}
|
467
|
+
try {
|
468
|
+
const sum = state.history.reduce((a, b) => a + b, 0);
|
469
|
+
return {
|
470
|
+
avg: parseFloat((sum / state.history.length).toFixed(1)),
|
471
|
+
max: Math.max(...state.history),
|
472
|
+
min: Math.min(...state.history)
|
473
|
+
};
|
474
|
+
} catch (error) {
|
475
|
+
console.error("Error calculating stats:", error);
|
476
|
+
return { avg: 0, max: 0, min: 0 };
|
477
|
+
}
|
478
|
+
}, [state?.history]);
|
479
|
+
const increment = () => {
|
480
|
+
if (isSSR)
|
481
|
+
return;
|
482
|
+
setIsLoading(true);
|
483
|
+
setTimeout(() => {
|
484
|
+
setState((prevState) => ({
|
485
|
+
count: prevState.count + 1,
|
486
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
|
487
|
+
history: [...prevState.history || [], prevState.count + 1]
|
488
|
+
}));
|
489
|
+
setIsLoading(false);
|
490
|
+
}, 300);
|
491
|
+
};
|
492
|
+
const decrement = () => {
|
493
|
+
if (isSSR)
|
494
|
+
return;
|
495
|
+
setIsLoading(true);
|
496
|
+
setTimeout(() => {
|
497
|
+
setState((prevState) => ({
|
498
|
+
count: Math.max(0, prevState.count - 1),
|
499
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
|
500
|
+
history: prevState.count > 0 ? [...prevState.history || [], prevState.count - 1] : prevState.history || []
|
501
|
+
}));
|
502
|
+
setIsLoading(false);
|
503
|
+
}, 300);
|
504
|
+
};
|
505
|
+
const reset = () => {
|
506
|
+
if (isSSR)
|
507
|
+
return;
|
508
|
+
setState({
|
509
|
+
count: 0,
|
510
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
|
511
|
+
history: []
|
275
512
|
});
|
276
|
-
|
277
|
-
|
513
|
+
};
|
514
|
+
const toggleHistory = () => {
|
515
|
+
if (isSSR)
|
516
|
+
return;
|
517
|
+
setShowHistory((prev) => !prev);
|
518
|
+
};
|
519
|
+
if (isSSR) {
|
520
|
+
return /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "State Management Demo"), /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ jsx("button", { className: "px-4 py-2 bg-gray-200 text-gray-800 rounded-lg" }, "-"), /* @__PURE__ */ jsx("span", { className: "text-2xl font-bold mx-4" }, "0"), /* @__PURE__ */ jsx("button", { className: "px-4 py-2 bg-blue-600 text-white rounded-lg" }, "+")), /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500" }, "Interactive counter (client-side only)"));
|
521
|
+
}
|
522
|
+
return /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "State Management Demo"), /* @__PURE__ */ jsx("div", { className: "mb-6" }, /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ jsx(
|
523
|
+
"button",
|
524
|
+
{
|
525
|
+
onClick: decrement,
|
526
|
+
className: "px-4 py-2 bg-gray-200 text-gray-800 rounded-lg hover:bg-gray-300 disabled:opacity-50",
|
527
|
+
disabled: state.count === 0 || isLoading
|
528
|
+
},
|
529
|
+
isLoading ? "..." : "-"
|
530
|
+
), /* @__PURE__ */ jsx("span", { className: "text-2xl font-bold mx-4" }, state.count), /* @__PURE__ */ jsx(
|
531
|
+
"button",
|
532
|
+
{
|
533
|
+
onClick: increment,
|
534
|
+
className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50",
|
535
|
+
disabled: isLoading
|
536
|
+
},
|
537
|
+
isLoading ? "..." : "+"
|
538
|
+
)), /* @__PURE__ */ jsx(
|
539
|
+
"button",
|
540
|
+
{
|
541
|
+
onClick: reset,
|
542
|
+
className: "text-sm text-gray-600 hover:text-red-600",
|
543
|
+
disabled: state.count === 0 && (!state.history || state.history.length === 0)
|
544
|
+
},
|
545
|
+
"Reset Counter"
|
546
|
+
)), state.lastUpdated && /* @__PURE__ */ jsx("div", { className: "mb-4" }, /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500" }, "Last updated: ", state.lastUpdated)), state.history && state.history.length > 0 && /* @__PURE__ */ jsx("div", { className: "border-t pt-4 mt-4" }, /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ jsx("h3", { className: "text-md font-medium text-gray-700" }, "Statistics"), /* @__PURE__ */ jsx(
|
547
|
+
"button",
|
548
|
+
{
|
549
|
+
onClick: toggleHistory,
|
550
|
+
className: "text-sm text-blue-600 hover:underline"
|
551
|
+
},
|
552
|
+
showHistory ? "Hide History" : "Show History"
|
553
|
+
)), /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-2 mb-3" }, /* @__PURE__ */ jsx("div", { className: "bg-blue-50 p-2 rounded text-center" }, /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500" }, "Average"), /* @__PURE__ */ jsx("div", { className: "font-bold" }, stats.avg)), /* @__PURE__ */ jsx("div", { className: "bg-green-50 p-2 rounded text-center" }, /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500" }, "Maximum"), /* @__PURE__ */ jsx("div", { className: "font-bold" }, stats.max)), /* @__PURE__ */ jsx("div", { className: "bg-red-50 p-2 rounded text-center" }, /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500" }, "Minimum"), /* @__PURE__ */ jsx("div", { className: "font-bold" }, stats.min))), showHistory && /* @__PURE__ */ jsx("div", { className: "mt-3" }, /* @__PURE__ */ jsx("h4", { className: "text-sm font-medium text-gray-600 mb-1" }, "History (", state.history.length, " events)"), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 p-2 rounded max-h-24 overflow-y-auto text-xs" }, state.history.map((value, index) => /* @__PURE__ */ jsx(
|
554
|
+
"span",
|
555
|
+
{
|
556
|
+
key: index,
|
557
|
+
className: "inline-block bg-gray-200 rounded px-2 py-1 m-1"
|
558
|
+
},
|
559
|
+
value
|
560
|
+
))))));
|
561
|
+
}
|
562
|
+
var init_StateDemo = __esm({
|
563
|
+
"src/components/StateDemo.tsx"() {
|
564
|
+
"use strict";
|
565
|
+
init_dist();
|
566
|
+
}
|
567
|
+
});
|
568
|
+
|
569
|
+
// src/components/ErrorBoundary.tsx
|
570
|
+
function ErrorBoundary({ children, fallback }) {
|
571
|
+
const [error, resetError] = useErrorBoundary();
|
572
|
+
if (error) {
|
573
|
+
if (fallback) {
|
574
|
+
return fallback(error, resetError);
|
278
575
|
}
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
576
|
+
return /* @__PURE__ */ jsx("div", { className: "error-boundary p-4 border border-red-500 rounded bg-red-50" }, /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-red-800 mb-2" }, "Something went wrong"), /* @__PURE__ */ jsx("p", { className: "text-red-600 mb-2" }, error.message), /* @__PURE__ */ jsx(
|
577
|
+
"button",
|
578
|
+
{
|
579
|
+
onClick: resetError,
|
580
|
+
className: "px-3 py-1 bg-red-600 text-white rounded hover:bg-red-700"
|
581
|
+
},
|
582
|
+
"Try again"
|
583
|
+
), /* @__PURE__ */ jsx("pre", { className: "mt-3 text-xs overflow-auto p-2 bg-gray-100" }, error.stack));
|
285
584
|
}
|
585
|
+
return children;
|
286
586
|
}
|
287
|
-
var
|
587
|
+
var init_ErrorBoundary = __esm({
|
588
|
+
"src/components/ErrorBoundary.tsx"() {
|
589
|
+
"use strict";
|
590
|
+
init_dist();
|
591
|
+
}
|
592
|
+
});
|
593
|
+
|
594
|
+
// src/data/api.ts
|
595
|
+
var sampleUsers, samplePosts, delay, UserApi;
|
288
596
|
var init_api = __esm({
|
289
597
|
"src/data/api.ts"() {
|
290
598
|
"use strict";
|
599
|
+
init_dist();
|
600
|
+
sampleUsers = [
|
601
|
+
{ id: 1, name: "User 1", email: "user1@example.com" },
|
602
|
+
{ id: 2, name: "User 2", email: "user2@example.com" },
|
603
|
+
{ id: 3, name: "User 3", email: "user3@example.com" }
|
604
|
+
];
|
605
|
+
samplePosts = [
|
606
|
+
{ id: 1, title: "Post 1", content: "Content for post 1", authorId: 1 },
|
607
|
+
{ id: 2, title: "Post 2", content: "Content for post 2", authorId: 2 },
|
608
|
+
{ id: 3, title: "Post 3", content: "Content for post 3", authorId: 1 }
|
609
|
+
];
|
610
|
+
delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
291
611
|
UserApi = {
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
}
|
302
|
-
|
303
|
-
|
304
|
-
|
612
|
+
// Get all users
|
613
|
+
async getAll() {
|
614
|
+
try {
|
615
|
+
await delay(300);
|
616
|
+
return [...sampleUsers];
|
617
|
+
} catch (error) {
|
618
|
+
console.error("Error fetching users:", error);
|
619
|
+
return [];
|
620
|
+
}
|
621
|
+
},
|
622
|
+
// Get user by ID
|
623
|
+
async getById(id) {
|
624
|
+
try {
|
625
|
+
const userId = typeof id === "string" ? parseInt(id, 10) : id;
|
626
|
+
await delay(200);
|
627
|
+
const user = sampleUsers.find((u) => u.id === userId);
|
628
|
+
if (!user)
|
629
|
+
throw new Error("User not found");
|
630
|
+
return { ...user };
|
631
|
+
} catch (error) {
|
632
|
+
console.error(`Error fetching user ${id}:`, error);
|
633
|
+
return null;
|
634
|
+
}
|
635
|
+
},
|
636
|
+
// Get posts (all or by author)
|
637
|
+
async getPosts(authorId) {
|
638
|
+
try {
|
639
|
+
const userId = authorId ? typeof authorId === "string" ? parseInt(authorId, 10) : authorId : void 0;
|
640
|
+
await delay(400);
|
641
|
+
const posts = userId ? samplePosts.filter((p) => p.authorId === userId) : samplePosts;
|
642
|
+
return [...posts];
|
643
|
+
} catch (error) {
|
644
|
+
console.error("Error fetching posts:", error);
|
645
|
+
return [];
|
646
|
+
}
|
647
|
+
}
|
305
648
|
};
|
306
649
|
}
|
307
650
|
});
|
@@ -309,23 +652,78 @@ var init_api = __esm({
|
|
309
652
|
// src/pages/index.tsx
|
310
653
|
var pages_exports = {};
|
311
654
|
__export(pages_exports, {
|
312
|
-
default: () =>
|
655
|
+
default: () => HomePage,
|
656
|
+
getServerSideProps: () => getServerSideProps2
|
313
657
|
});
|
314
|
-
|
658
|
+
function HomePage({ users, posts, initialState: initialState2 }) {
|
659
|
+
const [state, setState] = useState(initialState2 || {});
|
660
|
+
const [refreshTrigger, setRefreshTrigger] = useState(0);
|
661
|
+
useEffect(() => {
|
662
|
+
if (refreshTrigger === 0)
|
663
|
+
return;
|
664
|
+
async function fetchData() {
|
665
|
+
try {
|
666
|
+
const [users2, posts2] = await Promise.all([
|
667
|
+
UserApi.getAll(),
|
668
|
+
UserApi.getPosts()
|
669
|
+
]);
|
670
|
+
batchUpdates(() => {
|
671
|
+
setState((prev) => ({
|
672
|
+
...prev,
|
673
|
+
data: {
|
674
|
+
...prev.data,
|
675
|
+
users: users2,
|
676
|
+
posts: posts2
|
677
|
+
},
|
678
|
+
lastUpdate: (/* @__PURE__ */ new Date()).toISOString()
|
679
|
+
}));
|
680
|
+
});
|
681
|
+
} catch (error) {
|
682
|
+
console.error("Error fetching data:", error);
|
683
|
+
}
|
684
|
+
}
|
685
|
+
fetchData();
|
686
|
+
}, [refreshTrigger]);
|
687
|
+
const handleRefresh = () => {
|
688
|
+
setRefreshTrigger((t) => t + 1);
|
689
|
+
};
|
690
|
+
return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto py-8" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-blue-600 mb-6" }, "Welcome to your Next-style Frontend Hamroun application!"), /* @__PURE__ */ jsx("div", { className: "mb-8" }, /* @__PURE__ */ jsx(
|
691
|
+
"button",
|
692
|
+
{
|
693
|
+
className: "mb-4 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700",
|
694
|
+
onClick: handleRefresh
|
695
|
+
},
|
696
|
+
"Refresh Data"
|
697
|
+
), /* @__PURE__ */ jsx("div", { className: "bg-blue-50 p-4 rounded-lg border border-blue-100 mb-6" }, /* @__PURE__ */ jsx("p", { className: "text-blue-700" }, "Last updated: ", state.lastUpdate || "Never"))), /* @__PURE__ */ jsx(ErrorBoundary, null, /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "User List"), /* @__PURE__ */ jsx(UserList, { users: users || state.data?.users || [] }))), /* @__PURE__ */ jsx(ErrorBoundary, null, /* @__PURE__ */ jsx(StateDemo, null)), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 rounded-lg p-6 border border-gray-200 mt-8" }, /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-gray-700 mb-3" }, "Application State"), /* @__PURE__ */ jsx("pre", { className: "overflow-auto p-4 bg-gray-100 rounded-md text-sm text-gray-800" }, JSON.stringify({ users, posts, ...state }, null, 2))));
|
698
|
+
}
|
699
|
+
async function getServerSideProps2() {
|
700
|
+
try {
|
701
|
+
const users = await UserApi.getAll();
|
702
|
+
const posts = await UserApi.getPosts();
|
703
|
+
return {
|
704
|
+
props: {
|
705
|
+
users,
|
706
|
+
posts
|
707
|
+
}
|
708
|
+
};
|
709
|
+
} catch (error) {
|
710
|
+
console.error("Error fetching initial data:", error);
|
711
|
+
return {
|
712
|
+
props: {
|
713
|
+
users: [],
|
714
|
+
posts: []
|
715
|
+
}
|
716
|
+
};
|
717
|
+
}
|
718
|
+
}
|
315
719
|
var init_pages = __esm({
|
316
720
|
"src/pages/index.tsx"() {
|
317
721
|
"use strict";
|
318
722
|
init_dist();
|
319
|
-
init_Layout();
|
320
723
|
init_UserList();
|
724
|
+
init_StateDemo();
|
725
|
+
init_ErrorBoundary();
|
321
726
|
init_api();
|
322
|
-
HomePage = ({ initialState: initialState2 }) => /* @__PURE__ */ jsx(Layout, { title: "Home" }, /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto py-8" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-blue-600 mb-6" }, "Welcome to your Frontend Hamroun application!"), /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "User List"), /* @__PURE__ */ jsx(UserList_default, { users: initialState2.data?.users || [] })), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 rounded-lg p-6 border border-gray-200" }, /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-gray-700 mb-3" }, "Application State"), /* @__PURE__ */ jsx("pre", { className: "overflow-auto p-4 bg-gray-100 rounded-md text-sm text-gray-800" }, JSON.stringify(initialState2, null, 2)))));
|
323
|
-
HomePage.getInitialData = async () => {
|
324
|
-
return {
|
325
|
-
users: await UserApi.getAll()
|
326
|
-
};
|
327
|
-
};
|
328
|
-
pages_default = HomePage;
|
329
727
|
}
|
330
728
|
});
|
331
729
|
|
@@ -354,185 +752,118 @@ var init_users = __esm({
|
|
354
752
|
}
|
355
753
|
});
|
356
754
|
|
357
|
-
// src/
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
// import("./pages/**/*.tsx") in src/router.ts
|
364
|
-
var globImport_pages_tsx = __glob({
|
365
|
-
"./pages/about/index.tsx": () => Promise.resolve().then(() => (init_about(), about_exports)),
|
366
|
-
"./pages/index.tsx": () => Promise.resolve().then(() => (init_pages(), pages_exports)),
|
367
|
-
"./pages/users.tsx": () => Promise.resolve().then(() => (init_users(), users_exports))
|
368
|
-
});
|
369
|
-
|
370
|
-
// import("./pages/**/*/index.tsx") in src/router.ts
|
371
|
-
var globImport_pages_index_tsx = __glob({
|
372
|
-
"./pages/about/index.tsx": () => Promise.resolve().then(() => (init_about(), about_exports))
|
755
|
+
// src/pages/users/[id].tsx
|
756
|
+
var id_exports2 = {};
|
757
|
+
__export(id_exports2, {
|
758
|
+
default: () => UserDetail,
|
759
|
+
getServerSideProps: () => getServerSideProps3
|
373
760
|
});
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
761
|
+
function UserDetail({ user, posts, initialState: initialState2 }) {
|
762
|
+
const [userData, setUserData] = useState(user);
|
763
|
+
const [userPosts, setUserPosts] = useState(posts || []);
|
764
|
+
const [loading, setLoading] = useState(false);
|
765
|
+
const [error, setError] = useState(null);
|
766
|
+
const { id } = initialState2?.params || {};
|
767
|
+
useEffect(() => {
|
768
|
+
if (!userData && id) {
|
769
|
+
setLoading(true);
|
770
|
+
Promise.all([
|
771
|
+
UserApi.getById(id),
|
772
|
+
UserApi.getPosts(id)
|
773
|
+
]).then(([userData2, postsData]) => {
|
774
|
+
setUserData(userData2);
|
775
|
+
setUserPosts(postsData);
|
776
|
+
setLoading(false);
|
777
|
+
}).catch((err) => {
|
778
|
+
console.error("Error fetching user data:", err);
|
779
|
+
setError(err.message || "Failed to load user data");
|
780
|
+
setLoading(false);
|
781
|
+
});
|
782
|
+
}
|
783
|
+
}, [userData, id]);
|
784
|
+
if (loading) {
|
785
|
+
return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-4" }, /* @__PURE__ */ jsx("div", { className: "animate-pulse rounded-md bg-gray-100 p-8" }, /* @__PURE__ */ jsx("div", { className: "h-8 bg-gray-200 rounded w-1/4 mb-4" }), /* @__PURE__ */ jsx("div", { className: "h-4 bg-gray-200 rounded w-1/2 mb-2" }), /* @__PURE__ */ jsx("div", { className: "h-4 bg-gray-200 rounded w-3/4 mb-4" }), /* @__PURE__ */ jsx("div", { className: "h-40 bg-gray-200 rounded mb-4" })));
|
392
786
|
}
|
393
|
-
|
394
|
-
|
395
|
-
return this.notFoundComponent;
|
787
|
+
if (error) {
|
788
|
+
return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-4" }, /* @__PURE__ */ jsx("div", { className: "rounded-md bg-red-50 p-4 border border-red-200" }, /* @__PURE__ */ jsx("h2", { className: "text-lg font-bold text-red-700" }, "Error Loading User"), /* @__PURE__ */ jsx("p", { className: "text-red-600" }, error)));
|
396
789
|
}
|
397
|
-
|
398
|
-
|
399
|
-
return this.routes;
|
790
|
+
if (!userData) {
|
791
|
+
return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-4" }, /* @__PURE__ */ jsx("div", { className: "rounded-md bg-yellow-50 p-4 border border-yellow-200" }, /* @__PURE__ */ jsx("h2", { className: "text-lg font-bold text-yellow-700" }, "User Not Found"), /* @__PURE__ */ jsx("p", { className: "text-yellow-600" }, "Could not find user with ID: ", id), /* @__PURE__ */ jsx("a", { href: "/users", className: "text-blue-600 hover:underline mt-2 block" }, "Back to Users List")));
|
400
792
|
}
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
let isMatch = true;
|
415
|
-
const params = {};
|
416
|
-
for (let i = 0; i < routeSegments.length; i++) {
|
417
|
-
const routeSegment = routeSegments[i];
|
418
|
-
const pathSegment = pathSegments[i];
|
419
|
-
if (routeSegment.startsWith("[") && routeSegment.endsWith("]")) {
|
420
|
-
const paramName = routeSegment.slice(1, -1);
|
421
|
-
params[paramName] = pathSegment;
|
422
|
-
} else if (routeSegment !== pathSegment) {
|
423
|
-
isMatch = false;
|
424
|
-
break;
|
425
|
-
}
|
426
|
-
}
|
427
|
-
if (isMatch) {
|
428
|
-
console.log(`[Router] Found dynamic route match: ${route}`);
|
429
|
-
return this.routes[route];
|
430
|
-
}
|
793
|
+
return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-4" }, /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-6" }, /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-gray-800 mb-4" }, userData.name), /* @__PURE__ */ jsx("div", { className: "user-info mb-6" }, /* @__PURE__ */ jsx("p", { className: "text-gray-600" }, /* @__PURE__ */ jsx("span", { className: "font-bold" }, "ID:"), " ", userData.id), /* @__PURE__ */ jsx("p", { className: "text-gray-600" }, /* @__PURE__ */ jsx("span", { className: "font-bold" }, "Email:"), " ", userData.email)), /* @__PURE__ */ jsx("a", { href: "/users", className: "text-blue-600 hover:underline" }, "Back to Users List")), userPosts && userPosts.length > 0 ? /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-gray-800 mb-4" }, "Posts by ", userData.name), /* @__PURE__ */ jsx("div", { className: "space-y-4" }, userPosts.map((post) => /* @__PURE__ */ jsx("div", { key: post.id, className: "border-b pb-4" }, /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold" }, post.title), /* @__PURE__ */ jsx("p", { className: "text-gray-600" }, post.content))))) : /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-gray-800 mb-4" }, "Posts by ", userData.name), /* @__PURE__ */ jsx("p", { className: "text-gray-500 italic" }, "No posts found for this user.")));
|
794
|
+
}
|
795
|
+
async function getServerSideProps3({ params }) {
|
796
|
+
try {
|
797
|
+
const userId = params.id;
|
798
|
+
const [user, posts] = await Promise.all([
|
799
|
+
UserApi.getById(parseInt(userId)),
|
800
|
+
UserApi.getPosts(parseInt(userId))
|
801
|
+
]);
|
802
|
+
if (!user) {
|
803
|
+
return {
|
804
|
+
notFound: true
|
805
|
+
};
|
431
806
|
}
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
try {
|
437
|
-
console.log(`[Router] Trying direct import: ./pages/${resolvedPath}.tsx`);
|
438
|
-
const directModule = await /* @vite-ignore */
|
439
|
-
globImport_pages_tsx(`./pages/${resolvedPath}.tsx`).catch(() => null);
|
440
|
-
if (directModule) {
|
441
|
-
component = directModule.default || directModule;
|
442
|
-
}
|
443
|
-
} catch (e) {
|
444
|
-
console.warn(`[Router] Error importing ./pages/${resolvedPath}.tsx:`, e);
|
445
|
-
}
|
446
|
-
if (!component && !resolvedPath.endsWith("index")) {
|
447
|
-
try {
|
448
|
-
console.log(`[Router] Trying index file: ./pages/${resolvedPath}/index.tsx`);
|
449
|
-
const indexModule = await /* @vite-ignore */
|
450
|
-
globImport_pages_index_tsx(`./pages/${resolvedPath}/index.tsx`).catch(() => null);
|
451
|
-
if (indexModule) {
|
452
|
-
component = indexModule.default || indexModule;
|
453
|
-
}
|
454
|
-
} catch (e) {
|
455
|
-
console.warn(`[Router] Error importing ./pages/${resolvedPath}/index.tsx:`, e);
|
456
|
-
}
|
457
|
-
}
|
458
|
-
} catch (routeError) {
|
459
|
-
console.warn(`[Router] Error resolving Next.js style route:`, routeError);
|
807
|
+
return {
|
808
|
+
props: {
|
809
|
+
user,
|
810
|
+
posts
|
460
811
|
}
|
461
|
-
|
462
|
-
|
463
|
-
|
812
|
+
};
|
813
|
+
} catch (error) {
|
814
|
+
console.error(`Error fetching user ${params.id}:`, error);
|
815
|
+
return {
|
816
|
+
props: {
|
817
|
+
error: {
|
818
|
+
message: error.message,
|
819
|
+
status: error.status || 500
|
820
|
+
},
|
821
|
+
user: null,
|
822
|
+
posts: []
|
464
823
|
}
|
465
|
-
}
|
466
|
-
console.warn(`[Router] Error importing component for ${normalizedPath}:`, error);
|
467
|
-
}
|
468
|
-
console.warn(`[Router] No component found for path: ${normalizedPath}`);
|
469
|
-
return this.notFoundComponent;
|
824
|
+
};
|
470
825
|
}
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
return this.routes;
|
478
|
-
} catch (error) {
|
479
|
-
console.error("[Router] Error discovering routes:", error);
|
480
|
-
await this.tryLoadCoreRoutes();
|
481
|
-
return this.routes;
|
482
|
-
}
|
826
|
+
}
|
827
|
+
var init_id2 = __esm({
|
828
|
+
"src/pages/users/[id].tsx"() {
|
829
|
+
"use strict";
|
830
|
+
init_dist();
|
831
|
+
init_api();
|
483
832
|
}
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
for (const { path, route } of pageModules) {
|
492
|
-
if (!this.routes[route]) {
|
493
|
-
try {
|
494
|
-
console.log(`[Router] Attempting to load route: ${route}`);
|
495
|
-
const module = await import(
|
496
|
-
/* @vite-ignore */
|
497
|
-
`${path}.tsx`
|
498
|
-
).catch(() => null);
|
499
|
-
if (module && module.default) {
|
500
|
-
this.routes[route] = module.default;
|
501
|
-
console.log(`[Router] Registered route: ${route}`);
|
502
|
-
}
|
503
|
-
} catch (error) {
|
504
|
-
console.warn(`[Router] Could not load route: ${route}`, error);
|
505
|
-
}
|
506
|
-
}
|
507
|
-
}
|
833
|
+
});
|
834
|
+
|
835
|
+
// src/pages/wasm-demo.tsx
|
836
|
+
var wasm_demo_exports = {};
|
837
|
+
var init_wasm_demo = __esm({
|
838
|
+
"src/pages/wasm-demo.tsx"() {
|
839
|
+
"use strict";
|
508
840
|
}
|
509
|
-
};
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
};
|
528
|
-
|
841
|
+
});
|
842
|
+
|
843
|
+
// src/main.tsx
|
844
|
+
init_dist();
|
845
|
+
|
846
|
+
// import("./pages/**/*.tsx") in src/main.tsx
|
847
|
+
var globImport_pages_tsx = __glob({
|
848
|
+
"./pages/404.tsx": () => Promise.resolve().then(() => (init__(), __exports)),
|
849
|
+
"./pages/[id].tsx": () => Promise.resolve().then(() => (init_id(), id_exports)),
|
850
|
+
"./pages/_app.tsx": () => Promise.resolve().then(() => (init_app(), app_exports)),
|
851
|
+
"./pages/_document.tsx": () => Promise.resolve().then(() => (init_document(), document_exports)),
|
852
|
+
"./pages/_error.tsx": () => Promise.resolve().then(() => (init_error(), error_exports)),
|
853
|
+
"./pages/about.tsx": () => Promise.resolve().then(() => (init_about(), about_exports)),
|
854
|
+
"./pages/about/index.tsx": () => Promise.resolve().then(() => (init_about2(), about_exports2)),
|
855
|
+
"./pages/index.tsx": () => Promise.resolve().then(() => (init_pages(), pages_exports)),
|
856
|
+
"./pages/users.tsx": () => Promise.resolve().then(() => (init_users(), users_exports)),
|
857
|
+
"./pages/users/[id].tsx": () => Promise.resolve().then(() => (init_id2(), id_exports2)),
|
858
|
+
"./pages/wasm-demo.tsx": () => Promise.resolve().then(() => (init_wasm_demo(), wasm_demo_exports))
|
859
|
+
});
|
860
|
+
|
861
|
+
// import("./pages/**/*/index.tsx") in src/main.tsx
|
862
|
+
var globImport_pages_index_tsx = __glob({
|
863
|
+
"./pages/about/index.tsx": () => Promise.resolve().then(() => (init_about2(), about_exports2))
|
864
|
+
});
|
529
865
|
|
530
866
|
// src/main.tsx
|
531
|
-
init_pages();
|
532
|
-
init_about();
|
533
|
-
init_users();
|
534
|
-
var isHydrating2 = document.getElementById("root")?.innerHTML.trim() !== "";
|
535
|
-
console.log("[Client] Running client-side code. Hydration state:", isHydrating2);
|
536
867
|
var initialState = window.__INITIAL_STATE__ || {
|
537
868
|
route: window.location.pathname,
|
538
869
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
@@ -543,113 +874,73 @@ var initialState = window.__INITIAL_STATE__ || {
|
|
543
874
|
}
|
544
875
|
};
|
545
876
|
console.log("[Client] Initial state:", initialState);
|
546
|
-
|
547
|
-
|
548
|
-
console.log(`[Client] Fetching data from API: ${path}`);
|
549
|
-
const response = await fetch(`/api${path}`);
|
550
|
-
if (!response.ok) {
|
551
|
-
throw new Error(`API request failed: ${response.status}`);
|
552
|
-
}
|
553
|
-
const data = await response.json();
|
554
|
-
console.log(`[Client] Received data:`, data);
|
555
|
-
return data;
|
556
|
-
} catch (error) {
|
557
|
-
console.error(`[Client] Error fetching data from ${path}:`, error);
|
558
|
-
return null;
|
559
|
-
}
|
560
|
-
}
|
561
|
-
function initializeRouter() {
|
562
|
-
console.log("[Client] Initializing router with known pages");
|
563
|
-
router.register("index", pages_default);
|
564
|
-
router.register("about", about_default);
|
565
|
-
router.register("users", users_default);
|
566
|
-
}
|
567
|
-
initializeRouter();
|
568
|
-
async function renderApp() {
|
877
|
+
var isHydrating2 = document.getElementById("root")?.innerHTML.trim() !== "";
|
878
|
+
async function handleRouteChange(path, isPushState = true) {
|
569
879
|
try {
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
if (!rootElement) {
|
574
|
-
console.error("[Client] Root element not found");
|
575
|
-
return;
|
880
|
+
console.log(`[Router] Navigating to: ${path}`);
|
881
|
+
if (isPushState) {
|
882
|
+
window.history.pushState(null, "", path);
|
576
883
|
}
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
};
|
584
|
-
console.log(`[Client] Updated state with ${users.length} users`);
|
585
|
-
}
|
586
|
-
let PageComponent = null;
|
587
|
-
if (currentPath === "/about") {
|
588
|
-
try {
|
589
|
-
const AboutPage2 = await Promise.resolve().then(() => (init_about(), about_exports));
|
590
|
-
PageComponent = AboutPage2.default;
|
591
|
-
} catch (err) {
|
592
|
-
console.error("[Client] Failed to load about page:", err);
|
593
|
-
}
|
594
|
-
} else if (currentPath === "/users") {
|
884
|
+
const normalizedPath = path === "/" ? "index" : path.replace(/^\//, "");
|
885
|
+
let Page;
|
886
|
+
try {
|
887
|
+
const module = await globImport_pages_tsx(`./pages/${normalizedPath}.tsx`);
|
888
|
+
Page = module.default;
|
889
|
+
} catch (error) {
|
890
|
+
console.warn(`[Router] Could not load page for ${path}, trying index file`);
|
595
891
|
try {
|
596
|
-
const
|
597
|
-
|
598
|
-
} catch (
|
599
|
-
console.error(
|
600
|
-
}
|
601
|
-
} else {
|
602
|
-
PageComponent = await router.resolve(currentPath);
|
603
|
-
}
|
604
|
-
if (!PageComponent) {
|
605
|
-
console.warn(`[Client] Page component not found for ${currentPath}, checking special cases`);
|
606
|
-
if (currentPath === "/users") {
|
892
|
+
const module = await globImport_pages_index_tsx(`./pages/${normalizedPath}/index.tsx`);
|
893
|
+
Page = module.default;
|
894
|
+
} catch (innerError) {
|
895
|
+
console.error(`[Router] Failed to load page component for ${path}`);
|
607
896
|
try {
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
897
|
+
const notFoundModule = await Promise.resolve().then(() => (init__(), __exports));
|
898
|
+
Page = notFoundModule.default;
|
899
|
+
} catch (notFoundError) {
|
900
|
+
const rootElement2 = document.getElementById("root");
|
901
|
+
if (rootElement2) {
|
902
|
+
render(
|
903
|
+
/* @__PURE__ */ jsx("div", { style: { padding: "20px", maxWidth: "800px", margin: "0 auto" } }, /* @__PURE__ */ jsx("h1", null, "Page Not Found"), /* @__PURE__ */ jsx("p", null, "The page you requested could not be found."), /* @__PURE__ */ jsx("a", { href: "/", style: { color: "#0066cc" } }, "Go to Home")),
|
904
|
+
rootElement2
|
905
|
+
);
|
612
906
|
}
|
613
|
-
|
614
|
-
console.error("[Client] Failed to import Users page:", err);
|
907
|
+
return;
|
615
908
|
}
|
616
909
|
}
|
617
910
|
}
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
911
|
+
let pageProps = initialState.pageProps || {};
|
912
|
+
if (Page.getServerSideProps) {
|
913
|
+
try {
|
914
|
+
const response = await fetch(`/api/__props${path}`);
|
915
|
+
if (response.ok) {
|
916
|
+
const data = await response.json();
|
917
|
+
pageProps = data.props || {};
|
918
|
+
}
|
919
|
+
} catch (error) {
|
920
|
+
console.error("[Router] Error fetching page props:", error);
|
921
|
+
}
|
626
922
|
}
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
923
|
+
const updatedState = {
|
924
|
+
...initialState,
|
925
|
+
route: path,
|
926
|
+
pageProps
|
927
|
+
};
|
928
|
+
const rootElement = document.getElementById("root");
|
929
|
+
if (!rootElement)
|
930
|
+
return;
|
931
|
+
if (isHydrating2 && path === initialState.route) {
|
631
932
|
console.log("[Client] Hydrating server-rendered content");
|
632
|
-
hydrate(/* @__PURE__ */ jsx(
|
933
|
+
hydrate(/* @__PURE__ */ jsx(Page, { ...pageProps, initialState: updatedState }), rootElement);
|
633
934
|
isHydrating2 = false;
|
634
935
|
} else {
|
635
936
|
console.log("[Client] Rendering client-side");
|
636
|
-
render(/* @__PURE__ */ jsx(
|
937
|
+
render(/* @__PURE__ */ jsx(Page, { ...pageProps, initialState: updatedState }), rootElement);
|
637
938
|
}
|
638
939
|
} catch (error) {
|
639
|
-
console.error("[
|
640
|
-
const rootElement = document.getElementById("root");
|
641
|
-
if (rootElement) {
|
642
|
-
rootElement.innerHTML = `
|
643
|
-
<div style="padding: 20px; color: red;">
|
644
|
-
<h1>Error</h1>
|
645
|
-
<p>${error.message}</p>
|
646
|
-
<pre>${error.stack}</pre>
|
647
|
-
</div>
|
648
|
-
`;
|
649
|
-
}
|
940
|
+
console.error("[Router] Navigation error:", error);
|
650
941
|
}
|
651
942
|
}
|
652
|
-
|
943
|
+
handleRouteChange(window.location.pathname, false);
|
653
944
|
document.addEventListener("click", (e) => {
|
654
945
|
let target = e.target;
|
655
946
|
while (target && target.tagName !== "A") {
|
@@ -657,17 +948,14 @@ document.addEventListener("click", (e) => {
|
|
657
948
|
if (!target)
|
658
949
|
break;
|
659
950
|
}
|
660
|
-
if (target && target.tagName === "A" && target.getAttribute("href") && target.getAttribute("href")
|
951
|
+
if (target && target.tagName === "A" && target.getAttribute("href") && target.getAttribute("href")?.startsWith("/") && !target.getAttribute("href")?.startsWith("//") && !target.getAttribute("target")) {
|
661
952
|
e.preventDefault();
|
662
|
-
const href = target.getAttribute("href");
|
663
|
-
|
664
|
-
isHydrating2 = false;
|
665
|
-
renderApp();
|
953
|
+
const href = target.getAttribute("href") || "/";
|
954
|
+
handleRouteChange(href);
|
666
955
|
}
|
667
956
|
});
|
668
957
|
window.addEventListener("popstate", () => {
|
669
|
-
|
670
|
-
renderApp();
|
958
|
+
handleRouteChange(window.location.pathname, false);
|
671
959
|
});
|
672
960
|
if (typeof io !== "undefined") {
|
673
961
|
const socket = io();
|
@@ -675,8 +963,5 @@ if (typeof io !== "undefined") {
|
|
675
963
|
console.log("[Dev] Reloading page due to file changes");
|
676
964
|
window.location.reload();
|
677
965
|
});
|
678
|
-
socket.on("welcome", (data) => {
|
679
|
-
console.log("[Dev] Connected to development server:", data);
|
680
|
-
});
|
681
966
|
}
|
682
967
|
//# sourceMappingURL=main.js.map
|