frontend-hamroun 1.2.16 → 1.2.17

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.
Files changed (158) hide show
  1. package/README.md +4 -0
  2. package/bin/cli.js +673 -0
  3. package/dist/component.d.ts +1 -1
  4. package/dist/context.d.ts +4 -3
  5. package/dist/index.client.d.ts +11 -0
  6. package/dist/index.d.ts +9 -89
  7. package/dist/index.js +396 -67
  8. package/dist/index.js.map +1 -0
  9. package/dist/index.mjs +392 -0
  10. package/dist/index.mjs.map +1 -0
  11. package/dist/jsx-runtime/jsx-runtime.d.ts +0 -1
  12. package/dist/jsx-runtime.d.ts +1 -1
  13. package/dist/renderer.d.ts +0 -10
  14. package/dist/server-renderer.d.ts +0 -3
  15. package/dist/server-types.d.ts +42 -0
  16. package/package.json +69 -41
  17. package/templates/basic-app/index.html +6 -6
  18. package/templates/basic-app/package.json +18 -7
  19. package/templates/basic-app/postcss.config.js +0 -1
  20. package/templates/basic-app/src/main.tsx +1 -10
  21. package/templates/basic-app/tailwind.config.js +2 -23
  22. package/templates/basic-app/tsconfig.json +4 -17
  23. package/templates/basic-app/vite.config.ts +3 -54
  24. package/templates/fullstack-app/api/hello.ts +18 -0
  25. package/templates/fullstack-app/api/users/[id].ts +73 -0
  26. package/templates/fullstack-app/api/users/index.ts +32 -0
  27. package/templates/fullstack-app/package.json +31 -0
  28. package/templates/fullstack-app/server.ts +46 -0
  29. package/templates/fullstack-app/src/pages/index.tsx +59 -0
  30. package/templates/ssr-template/vite.config.ts +1 -11
  31. package/bin/cli.cjs +0 -16
  32. package/bin/cli.mjs +0 -237
  33. package/dist/backend/api-utils.d.ts +0 -38
  34. package/dist/backend/api-utils.js +0 -135
  35. package/dist/backend/auth.d.ts +0 -134
  36. package/dist/backend/auth.js +0 -387
  37. package/dist/backend/database.d.ts +0 -27
  38. package/dist/backend/database.js +0 -91
  39. package/dist/backend/model.d.ts +0 -43
  40. package/dist/backend/model.js +0 -178
  41. package/dist/backend/router.d.ts +0 -27
  42. package/dist/backend/router.js +0 -137
  43. package/dist/backend/server.d.ts +0 -19
  44. package/dist/backend/server.js +0 -268
  45. package/dist/backend/types.d.ts +0 -217
  46. package/dist/backend/types.js +0 -1
  47. package/dist/batch.js +0 -22
  48. package/dist/cli/index.d.ts +0 -2
  49. package/dist/cli/index.js +0 -215
  50. package/dist/component.js +0 -84
  51. package/dist/components/Counter.js +0 -2
  52. package/dist/context.js +0 -18
  53. package/dist/frontend-hamroun.es.js +0 -1378
  54. package/dist/frontend-hamroun.umd.js +0 -66
  55. package/dist/hooks.js +0 -164
  56. package/dist/jsx-runtime/index.d.ts +0 -11
  57. package/dist/jsx-runtime/index.js +0 -19
  58. package/dist/jsx-runtime/jsx-dev-runtime.js +0 -1
  59. package/dist/jsx-runtime/jsx-runtime.js +0 -95
  60. package/dist/jsx-runtime.js +0 -192
  61. package/dist/renderer.js +0 -51
  62. package/dist/server-renderer.js +0 -102
  63. package/dist/types.js +0 -1
  64. package/dist/vdom.js +0 -27
  65. package/scripts/build-cli.js +0 -1199
  66. package/scripts/generate.js +0 -134
  67. package/src/backend/api-utils.ts +0 -178
  68. package/src/backend/auth.ts +0 -544
  69. package/src/backend/database.ts +0 -104
  70. package/src/backend/model.ts +0 -198
  71. package/src/backend/router.ts +0 -176
  72. package/src/backend/server.ts +0 -330
  73. package/src/backend/types.ts +0 -257
  74. package/src/batch.ts +0 -24
  75. package/src/cli/index.js +0 -554
  76. package/src/cli/index.ts +0 -257
  77. package/src/component.ts +0 -98
  78. package/src/components/Counter.tsx +0 -4
  79. package/src/context.ts +0 -29
  80. package/src/hooks.ts +0 -211
  81. package/src/index.ts +0 -144
  82. package/src/jsx-runtime/index.ts +0 -27
  83. package/src/jsx-runtime/jsx-dev-runtime.ts +0 -0
  84. package/src/jsx-runtime/jsx-runtime.ts +0 -104
  85. package/src/jsx-runtime.ts +0 -226
  86. package/src/renderer.ts +0 -55
  87. package/src/server-renderer.ts +0 -114
  88. package/src/shims.d.ts +0 -20
  89. package/src/types/bcrypt.d.ts +0 -30
  90. package/src/types/jsonwebtoken.d.ts +0 -55
  91. package/src/types.d.ts +0 -26
  92. package/src/types.ts +0 -21
  93. package/src/vdom.ts +0 -34
  94. package/templates/basic/.eslintignore +0 -5
  95. package/templates/basic/.eslintrc.json +0 -25
  96. package/templates/basic/docs/rapport_pfe.aux +0 -27
  97. package/templates/basic/docs/rapport_pfe.log +0 -399
  98. package/templates/basic/docs/rapport_pfe.out +0 -10
  99. package/templates/basic/docs/rapport_pfe.pdf +0 -0
  100. package/templates/basic/docs/rapport_pfe.tex +0 -68
  101. package/templates/basic/docs/rapport_pfe.toc +0 -14
  102. package/templates/basic/index.html +0 -12
  103. package/templates/basic/jsconfig.json +0 -14
  104. package/templates/basic/package.json +0 -18
  105. package/templates/basic/postcss.config.js +0 -7
  106. package/templates/basic/src/App.js +0 -105
  107. package/templates/basic/src/App.tsx +0 -65
  108. package/templates/basic/src/api.ts +0 -58
  109. package/templates/basic/src/components/Counter.tsx +0 -26
  110. package/templates/basic/src/components/Header.tsx +0 -9
  111. package/templates/basic/src/components/TodoList.tsx +0 -90
  112. package/templates/basic/src/main.css +0 -3
  113. package/templates/basic/src/main.js +0 -11
  114. package/templates/basic/src/main.ts +0 -20
  115. package/templates/basic/src/main.tsx +0 -144
  116. package/templates/basic/src/server.ts +0 -99
  117. package/templates/basic/tailwind.config.js +0 -32
  118. package/templates/basic/tsconfig.json +0 -20
  119. package/templates/basic/tsconfig.node.json +0 -10
  120. package/templates/basic/vite.config.js +0 -18
  121. package/templates/basic/vite.config.ts +0 -86
  122. package/templates/basic-app/src/App.js +0 -105
  123. package/templates/basic-app/src/App.tsx +0 -143
  124. package/templates/basic-app/src/api.ts +0 -58
  125. package/templates/basic-app/src/components/Counter.tsx +0 -26
  126. package/templates/basic-app/src/components/Header.tsx +0 -9
  127. package/templates/basic-app/src/components/TodoList.tsx +0 -90
  128. package/templates/basic-app/src/main.js +0 -10
  129. package/templates/basic-app/src/main.ts +0 -21
  130. package/templates/basic-app/src/react/index.ts +0 -35
  131. package/templates/basic-app/src/react/jsx-dev-runtime.ts +0 -13
  132. package/templates/basic-app/src/react/jsx-runtime.ts +0 -12
  133. package/templates/basic-app/src/server.ts +0 -99
  134. package/templates/basic-app/src/shims.ts +0 -9
  135. package/templates/basic-app/tsconfig.node.json +0 -10
  136. package/templates/basic-app/vite.config.js +0 -22
  137. package/templates/full-stack/.env.example +0 -11
  138. package/templates/full-stack/README.md +0 -51
  139. package/templates/full-stack/index.html +0 -12
  140. package/templates/full-stack/jsconfig.json +0 -14
  141. package/templates/full-stack/package.json +0 -21
  142. package/templates/full-stack/src/App.js +0 -105
  143. package/templates/full-stack/src/client/App.tsx +0 -50
  144. package/templates/full-stack/src/client/components/Header.tsx +0 -42
  145. package/templates/full-stack/src/client/components/UserList.tsx +0 -29
  146. package/templates/full-stack/src/client/main.tsx +0 -5
  147. package/templates/full-stack/src/main.css +0 -3
  148. package/templates/full-stack/src/main.js +0 -11
  149. package/templates/full-stack/src/main.ts +0 -20
  150. package/templates/full-stack/src/server/index.ts +0 -99
  151. package/templates/full-stack/src/server/routes/auth.ts +0 -39
  152. package/templates/full-stack/src/server/routes/users.ts +0 -48
  153. package/templates/full-stack/src/shims.ts +0 -9
  154. package/templates/full-stack/tsconfig.json +0 -20
  155. package/templates/full-stack/tsconfig.node.json +0 -10
  156. package/templates/full-stack/tsconfig.server.json +0 -15
  157. package/templates/full-stack/vite.config.js +0 -18
  158. package/templates/full-stack/vite.config.ts +0 -85
@@ -1,68 +0,0 @@
1
- \documentclass[12pt,a4paper]{report}
2
- \usepackage[utf8]{inputenc}
3
- \usepackage[french]{babel}
4
- \usepackage{graphicx}
5
- \usepackage{fancyhdr}
6
- \usepackage{hyperref}
7
-
8
- \hypersetup{
9
- colorlinks=true,
10
- linkcolor=blue,
11
- filecolor=magenta,
12
- urlcolor=cyan,
13
- }
14
-
15
- \pagestyle{fancy}
16
- \fancyhf{}
17
- \rhead{Projet de Fin d'Études}
18
- \lhead{Rapport de Stage}
19
- \rfoot{Page \thepage}
20
-
21
- \title{Rapport de Projet de Fin d'Études}
22
- \author{Votre Nom}
23
- \date{\today}
24
-
25
- \begin{document}
26
-
27
- \maketitle
28
- \tableofcontents
29
- \newpage
30
-
31
- \chapter{ÉTUDE PREALABLE}
32
-
33
- \section{Introduction}
34
- Cette section présente une introduction générale au projet, incluant le contexte, les objectifs et la problématique abordée dans ce projet de fin d'études.
35
-
36
- \section{Organisme d'accueil}
37
- Cette section décrit l'organisme d'accueil où s'est déroulé le stage, incluant sa présentation, ses activités principales et sa structure organisationnelle.
38
-
39
- \section{Étude et critique de l'existant}
40
- Cette section analyse la situation actuelle avant l'implémentation du projet.
41
-
42
- \subsection{Critique de l'existant}
43
- Cette partie détaille les limitations, problèmes et défis identifiés dans le système existant qui ont motivé le développement d'une nouvelle solution.
44
-
45
- \subsection{Solution proposée}
46
- Cette partie présente la solution proposée pour résoudre les problèmes identifiés, en décrivant ses principales caractéristiques et avantages.
47
-
48
- \section{Choix méthodologique}
49
-
50
- \subsection{Formalisme de modélisation}
51
- Cette section détaille les formalismes de modélisation utilisés pour concevoir et représenter la solution.
52
-
53
- \subsection{Méthodologie}
54
- Cette partie décrit l'approche méthodologique adoptée pour la réalisation du projet.
55
-
56
- \subsubsection{Présentation de la méthode SCRUM}
57
- Cette partie introduit la méthode SCRUM, ses principes fondamentaux et ses avantages dans le contexte du développement logiciel.
58
-
59
- \subsubsection{La répartition des rôles dans la méthode SCRUM}
60
- Cette section explique les différents rôles dans la méthode SCRUM (Product Owner, Scrum Master, équipe de développement) et leurs responsabilités.
61
-
62
- \subsubsection{Le processus de SCRUM}
63
- Cette partie détaille le processus SCRUM avec ses différentes cérémonies (Sprint Planning, Daily Scrum, Sprint Review, Sprint Retrospective) et artefacts (Product Backlog, Sprint Backlog, Increment).
64
-
65
- \section{Conclusion}
66
- Cette section résume les points clés abordés dans ce chapitre et fait la transition vers le chapitre suivant.
67
-
68
- \end{document}
@@ -1,14 +0,0 @@
1
- \babel@toc {french}{}\relax
2
- \contentsline {chapter}{\numberline {1}ÉTUDE PREALABLE}{2}{chapter.1}%
3
- \contentsline {section}{\numberline {1.1}Introduction}{2}{section.1.1}%
4
- \contentsline {section}{\numberline {1.2}Organisme d'accueil}{2}{section.1.2}%
5
- \contentsline {section}{\numberline {1.3}Étude et critique de l'existant}{2}{section.1.3}%
6
- \contentsline {subsection}{\numberline {1.3.1}Critique de l'existant}{2}{subsection.1.3.1}%
7
- \contentsline {subsection}{\numberline {1.3.2}Solution proposée}{2}{subsection.1.3.2}%
8
- \contentsline {section}{\numberline {1.4}Choix méthodologique}{3}{section.1.4}%
9
- \contentsline {subsection}{\numberline {1.4.1}Formalisme de modélisation}{3}{subsection.1.4.1}%
10
- \contentsline {subsection}{\numberline {1.4.2}Méthodologie}{3}{subsection.1.4.2}%
11
- \contentsline {subsubsection}{Présentation de la méthode SCRUM}{3}{section*.2}%
12
- \contentsline {subsubsection}{La répartition des rôles dans la méthode SCRUM}{3}{section*.3}%
13
- \contentsline {subsubsection}{Le processus de SCRUM}{3}{section*.4}%
14
- \contentsline {section}{\numberline {1.5}Conclusion}{3}{section.1.5}%
@@ -1,12 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Frontend Hamroun App</title>
7
- </head>
8
- <body>
9
- <div id="app"></div>
10
- <script type="module" src="/src/main.js"></script>
11
- </body>
12
- </html>
@@ -1,14 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "useDefineForClassFields": true,
5
- "module": "ESNext",
6
- "moduleResolution": "node",
7
- "allowSyntheticDefaultImports": true,
8
- "resolveJsonModule": true,
9
- "checkJs": false,
10
- "strict": false
11
- },
12
- "include": ["src/**/*.js"],
13
- "exclude": ["node_modules"]
14
- }
@@ -1,18 +0,0 @@
1
- {
2
- "name": "frontend-hamroun-app",
3
- "private": true,
4
- "version": "0.1.0",
5
- "type": "module",
6
- "scripts": {
7
- "dev": "vite",
8
- "build": "vite build",
9
- "preview": "vite preview"
10
- },
11
- "dependencies": {
12
- "frontend-hamroun": "latest"
13
- },
14
- "devDependencies": {
15
- "vite": "^5.0.10",
16
- "vite-plugin-node-polyfills": "^0.23.0"
17
- }
18
- }
@@ -1,7 +0,0 @@
1
- export default {
2
- plugins: {
3
- tailwindcss: {},
4
- autoprefixer: {},
5
- cssnano: process.env.NODE_ENV === 'production' ? { preset: 'default' } : false
6
- },
7
- }
@@ -1,105 +0,0 @@
1
- import { useState, useRef } from 'frontend-hamroun';
2
-
3
- export function App() {
4
- const [count, setCount] = useState(0);
5
- const renderCount = useRef(0);
6
-
7
- renderCount.current++;
8
-
9
- // Return a plain JavaScript object representation of the UI
10
- return {
11
- type: 'div',
12
- props: {
13
- style: {
14
- fontFamily: 'Arial, sans-serif',
15
- maxWidth: '600px',
16
- margin: '0 auto',
17
- padding: '2rem'
18
- },
19
- children: [
20
- {
21
- type: 'h1',
22
- props: {
23
- style: { textAlign: 'center' },
24
- children: 'Frontend Hamroun App'
25
- }
26
- },
27
- {
28
- type: 'p',
29
- props: {
30
- style: { textAlign: 'center' },
31
- children: `Render count: ${renderCount.current}`
32
- }
33
- },
34
- {
35
- type: 'div',
36
- props: {
37
- style: {
38
- display: 'flex',
39
- flexDirection: 'column',
40
- alignItems: 'center',
41
- padding: '1rem',
42
- border: '1px solid #ccc',
43
- borderRadius: '8px'
44
- },
45
- children: [
46
- {
47
- type: 'h2',
48
- props: {
49
- children: 'Counter Example'
50
- }
51
- },
52
- {
53
- type: 'p',
54
- props: {
55
- children: `Count: ${count}`
56
- }
57
- },
58
- {
59
- type: 'div',
60
- props: {
61
- style: {
62
- display: 'flex',
63
- gap: '8px'
64
- },
65
- children: [
66
- {
67
- type: 'button',
68
- props: {
69
- onClick: () => setCount(count - 1),
70
- style: {
71
- padding: '8px 16px',
72
- backgroundColor: '#ff4d4d',
73
- color: 'white',
74
- border: 'none',
75
- borderRadius: '4px',
76
- cursor: 'pointer'
77
- },
78
- children: 'Decrement'
79
- }
80
- },
81
- {
82
- type: 'button',
83
- props: {
84
- onClick: () => setCount(count + 1),
85
- style: {
86
- padding: '8px 16px',
87
- backgroundColor: '#4d79ff',
88
- color: 'white',
89
- border: 'none',
90
- borderRadius: '4px',
91
- cursor: 'pointer'
92
- },
93
- children: 'Increment'
94
- }
95
- }
96
- ]
97
- }
98
- }
99
- ]
100
- }
101
- }
102
- ]
103
- }
104
- };
105
- }
@@ -1,65 +0,0 @@
1
- import { useState, useEffect } from 'frontend-hamroun';
2
- import { Header } from './components/Header';
3
- import { Counter } from './components/Counter';
4
- import { ApiClient } from './api.js';
5
- import { TodoList } from './components/TodoList.js';
6
-
7
- interface AppProps {
8
- api: ApiClient;
9
- }
10
-
11
- export function App({ api }: AppProps) {
12
- const [todos, setTodos] = useState([]);
13
- const [isLoading, setIsLoading] = useState(true);
14
- const [error, setError] = useState<string | null>(null);
15
-
16
- useEffect(() => {
17
- // Fetch data when component mounts
18
- async function fetchData() {
19
- try {
20
- setIsLoading(true);
21
- const data = await api.getTodos();
22
- setTodos(data);
23
- setError(null);
24
- } catch (err) {
25
- setError('Failed to fetch todos');
26
- console.error(err);
27
- } finally {
28
- setIsLoading(false);
29
- }
30
- }
31
-
32
- fetchData();
33
- }, [api]);
34
-
35
- return (
36
- <div className="min-h-screen bg-gray-50">
37
- <Header title="My Front Package App" />
38
-
39
- <main className="container mx-auto px-4 py-8">
40
- <h1 className="text-3xl font-bold text-center mb-8">
41
- Welcome to your Front Package app!
42
- </h1>
43
-
44
- <div className="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl mb-8">
45
- <div className="p-8">
46
- <Counter />
47
- </div>
48
- </div>
49
-
50
- <div className="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl">
51
- <div className="p-8">
52
- <h2 className="text-xl font-bold mb-4">Todo List</h2>
53
- {isLoading ? (
54
- <div className="text-center py-4">Loading...</div>
55
- ) : error ? (
56
- <div className="text-red-500 py-4">{error}</div>
57
- ) : (
58
- <TodoList todos={todos} api={api} setTodos={setTodos} />
59
- )}
60
- </div>
61
- </div>
62
- </main>
63
- </div>
64
- );
65
- }
@@ -1,58 +0,0 @@
1
- export interface Todo {
2
- id: string;
3
- title: string;
4
- completed: boolean;
5
- }
6
-
7
- export interface ApiClientOptions {
8
- baseUrl: string;
9
- }
10
-
11
- export interface ApiClient {
12
- getTodos: () => Promise<Todo[]>;
13
- getTodo: (id: string) => Promise<Todo>;
14
- addTodo: (todo: Omit<Todo, 'id'>) => Promise<Todo>;
15
- updateTodo: (id: string, updates: Partial<Omit<Todo, 'id'>>) => Promise<Todo>;
16
- deleteTodo: (id: string) => Promise<void>;
17
- }
18
-
19
- export function createApiClient(options: ApiClientOptions): ApiClient {
20
- const { baseUrl } = options;
21
-
22
- async function fetchJson<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
23
- const response = await fetch(`${baseUrl}${endpoint}`, {
24
- ...options,
25
- headers: {
26
- 'Content-Type': 'application/json',
27
- ...options.headers,
28
- },
29
- });
30
-
31
- if (!response.ok) {
32
- const error = await response.text();
33
- throw new Error(error || `API request failed with status ${response.status}`);
34
- }
35
-
36
- return response.json();
37
- }
38
-
39
- return {
40
- getTodos: () => fetchJson<Todo[]>('/todos'),
41
-
42
- getTodo: (id: string) => fetchJson<Todo>(`/todos/${id}`),
43
-
44
- addTodo: (todo) => fetchJson<Todo>('/todos', {
45
- method: 'POST',
46
- body: JSON.stringify(todo),
47
- }),
48
-
49
- updateTodo: (id: string, updates) => fetchJson<Todo>(`/todos/${id}`, {
50
- method: 'PATCH',
51
- body: JSON.stringify(updates),
52
- }),
53
-
54
- deleteTodo: (id: string) => fetchJson<void>(`/todos/${id}`, {
55
- method: 'DELETE',
56
- }),
57
- };
58
- }
@@ -1,26 +0,0 @@
1
- import { useState } from 'front-package';
2
-
3
- export function Counter() {
4
- const [count, setCount] = useState(0);
5
-
6
- return (
7
- <div className="text-center">
8
- <h2 className="text-xl font-bold mb-4">Counter Example</h2>
9
- <p className="mb-4">Count: <span className="font-bold">{count}</span></p>
10
- <div className="flex justify-center gap-2">
11
- <button
12
- onClick={() => setCount(count - 1)}
13
- className="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600 transition"
14
- >
15
- Decrement
16
- </button>
17
- <button
18
- onClick={() => setCount(count + 1)}
19
- className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition"
20
- >
21
- Increment
22
- </button>
23
- </div>
24
- </div>
25
- );
26
- }
@@ -1,9 +0,0 @@
1
- export function Header({ title }: { title: string }) {
2
- return (
3
- <header className="bg-primary-600 text-white shadow-lg">
4
- <div className="container mx-auto px-4 py-6">
5
- <h1 className="text-2xl font-bold">{title}</h1>
6
- </div>
7
- </header>
8
- );
9
- }
@@ -1,90 +0,0 @@
1
- import { useState } from 'front-package';
2
- import { ApiClient, Todo } from '../api';
3
-
4
- interface TodoListProps {
5
- todos: Todo[];
6
- api: ApiClient;
7
- setTodos: (todos: Todo[]) => void;
8
- }
9
-
10
- export function TodoList({ todos, api, setTodos }: TodoListProps) {
11
- const [newTodoText, setNewTodoText] = useState('');
12
- const [isSubmitting, setIsSubmitting] = useState(false);
13
-
14
- async function handleAddTodo(e: Event) {
15
- e.preventDefault();
16
- if (!newTodoText.trim()) return;
17
-
18
- try {
19
- setIsSubmitting(true);
20
- const newTodo = await api.addTodo({
21
- title: newTodoText,
22
- completed: false
23
- });
24
-
25
- setTodos([...todos, newTodo]);
26
- setNewTodoText('');
27
- } catch (err) {
28
- console.error('Failed to add todo:', err);
29
- } finally {
30
- setIsSubmitting(false);
31
- }
32
- }
33
-
34
- async function handleToggleTodo(id: string, completed: boolean) {
35
- try {
36
- await api.updateTodo(id, { completed });
37
- setTodos(
38
- todos.map(todo =>
39
- todo.id === id ? { ...todo, completed } : todo
40
- )
41
- );
42
- } catch (err) {
43
- console.error('Failed to update todo:', err);
44
- }
45
- }
46
-
47
- return (
48
- <div>
49
- <form onSubmit={handleAddTodo} className="mb-4">
50
- <div className="flex gap-2">
51
- <input
52
- type="text"
53
- value={newTodoText}
54
- onChange={(e) => setNewTodoText(e.target.value)}
55
- placeholder="Add a new todo..."
56
- className="flex-1 border rounded px-3 py-2"
57
- disabled={isSubmitting}
58
- />
59
- <button
60
- type="submit"
61
- className="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600 transition"
62
- disabled={isSubmitting || !newTodoText.trim()}
63
- >
64
- {isSubmitting ? 'Adding...' : 'Add'}
65
- </button>
66
- </div>
67
- </form>
68
-
69
- <ul className="space-y-2">
70
- {todos.length === 0 ? (
71
- <li className="text-center py-2 text-gray-500">No todos yet</li>
72
- ) : (
73
- todos.map(todo => (
74
- <li key={todo.id} className="flex items-center gap-2 p-2 border-b">
75
- <input
76
- type="checkbox"
77
- checked={todo.completed}
78
- onChange={(e) => handleToggleTodo(todo.id, e.target.checked)}
79
- className="h-5 w-5 text-blue-600"
80
- />
81
- <span className={todo.completed ? 'line-through text-gray-500' : ''}>
82
- {todo.title}
83
- </span>
84
- </li>
85
- ))
86
- )}
87
- </ul>
88
- </div>
89
- );
90
- }
@@ -1,3 +0,0 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
@@ -1,11 +0,0 @@
1
- import { render } from 'frontend-hamroun';
2
- import { App } from './App.js';
3
-
4
- document.addEventListener('DOMContentLoaded', () => {
5
- const rootElement = document.getElementById('app');
6
- if (rootElement) {
7
- // Call App as a function to create the VDOM structure
8
- render(App(), rootElement);
9
- console.log('App rendered successfully');
10
- }
11
- });
@@ -1,20 +0,0 @@
1
- import './main.css';
2
- import { render } from 'frontend-hamroun';
3
- import { App } from './App';
4
- import { createApiClient } from './api';
5
-
6
- // Initialize API client
7
- const api = createApiClient({
8
- baseUrl: import.meta.env.VITE_API_URL || '/api'
9
- });
10
-
11
- // Render the app into the DOM
12
- document.addEventListener('DOMContentLoaded', () => {
13
- const rootElement = document.getElementById('app');
14
- if (rootElement) {
15
- render(<App api={api} />, rootElement);
16
- console.log('App rendered successfully');
17
- } else {
18
- console.error('Root element #app not found');
19
- }
20
- });
@@ -1,144 +0,0 @@
1
- import { render, useState, useEffect, useMemo, useRef, useErrorBoundary, createContext, useContext } from 'frontend-hamroun';
2
- import './main.css';
3
-
4
- // Create a theme context
5
- const ThemeContext = createContext<'light' | 'dark'>('light');
6
-
7
- // Create a component that will throw an error when clicked
8
- function BuggyComponent() {
9
- const [shouldError, setShouldError] = useState(false);
10
-
11
- if (shouldError) {
12
- throw new Error("Test error from BuggyComponent");
13
- }
14
-
15
- return (
16
- <button
17
- onClick={() => setShouldError(true)}
18
- className="bg-red-600 text-white px-4 py-2 rounded mt-4 hover:bg-red-700"
19
- >
20
- Trigger Error
21
- </button>
22
- );
23
- }
24
-
25
- function App() {
26
- const [count, setCount] = useState(0);
27
- const [theme, setTheme] = useState<'light' | 'dark'>('light');
28
- const renderCount = useRef(0);
29
- const [error, resetError] = useErrorBoundary();
30
-
31
- // Demonstrate useEffect
32
- useEffect(() => {
33
- document.title = `Count: ${count}`;
34
- renderCount.current += 1;
35
-
36
- return () => {
37
- console.log('Cleanup effect');
38
- };
39
- }, [count]);
40
-
41
- // Demonstrate useMemo
42
- const doubled = useMemo(() => count * 2, [count]);
43
-
44
- if (error) {
45
- return (
46
- <div className="p-8 max-w-md mx-auto bg-red-50 rounded-lg shadow-lg">
47
- <h1 className="text-2xl font-bold text-red-600 mb-4">Something went wrong!</h1>
48
- <button
49
- onClick={resetError}
50
- className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded"
51
- >
52
- Try again
53
- </button>
54
- </div>
55
- );
56
- }
57
-
58
- return (
59
- <ThemeContext.Provider value={theme}>
60
- <div className={`p-8 max-w-4xl mx-auto rounded-lg shadow-lg transition-colors ${
61
- theme === 'dark'
62
- ? 'bg-gray-800 text-white'
63
- : 'bg-white text-gray-900'
64
- }`}>
65
- <h1 className="text-3xl font-bold mb-6">Welcome to Frontend Hamroun</h1>
66
-
67
- <div className="mb-6">
68
- <button
69
- onClick={() => setCount(count - 1)}
70
- className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded"
71
- >-</button>
72
- <span className="mx-4 text-xl">{count}</span>
73
- <button
74
- onClick={() => setCount(count + 1)}
75
- className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded"
76
- >+</button>
77
- </div>
78
-
79
- <p className="mb-2 text-lg">Doubled value: <span className="font-semibold">{doubled}</span></p>
80
- <p className="mb-4 text-lg">Render count: <span className="font-semibold">{renderCount.current}</span></p>
81
-
82
- <button
83
- onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
84
- className={`px-4 py-2 rounded mb-8 ${
85
- theme === 'dark'
86
- ? 'bg-yellow-400 text-gray-900 hover:bg-yellow-300'
87
- : 'bg-gray-800 text-white hover:bg-gray-700'
88
- }`}
89
- >
90
- Toggle Theme ({theme})
91
- </button>
92
-
93
- <div className="mt-8 border-t pt-6">
94
- <h2 className="text-2xl font-bold mb-4">Test Error Boundary</h2>
95
- <BuggyComponent />
96
- </div>
97
-
98
- <div className="mt-8 border-t pt-6">
99
- <h2 className="text-2xl font-bold mb-4">Test Context</h2>
100
- <ContextConsumer />
101
- </div>
102
- </div>
103
- </ThemeContext.Provider>
104
- );
105
- }
106
-
107
- // Component to test context
108
- function ContextConsumer() {
109
- // Get the full context object for debugging
110
- const themeContext = useContext(ThemeContext);
111
- console.log('Theme context object:', themeContext);
112
-
113
- // Access the current theme from the parent component instead
114
- // This is a workaround until context is properly implemented
115
- return (
116
- <div className={`mt-4 p-4 rounded-md border ${
117
- themeContext === 'dark' ? 'border-gray-600' : 'border-gray-300'
118
- }`}>
119
- <p className="mb-2"><strong>Note:</strong> Context API needs a fix in the framework.</p>
120
- <p className="mb-1">Context object type: {typeof themeContext}</p>
121
- <p className="mb-4">Context object keys: {Object.keys(themeContext as object).join(', ') || 'none'}</p>
122
-
123
- <button
124
- onClick={() => {
125
- // Since we can't get the value directly from context,
126
- // Let's add a button to demonstrate we can still use the Provider
127
- const newTheme = document.body.style.backgroundColor === 'rgb(51, 51, 51)'
128
- ? 'light' : 'dark';
129
-
130
- console.log('Manually changing theme to:', newTheme);
131
- // This won't work yet, but demonstrates the intent
132
- if (ThemeContext) {
133
- console.log('Provider exists, would set value to:', newTheme);
134
- }
135
- }}
136
- className="bg-purple-500 hover:bg-purple-600 text-white px-4 py-2 rounded"
137
- >
138
- Check Context Implementation
139
- </button>
140
- </div>
141
- );
142
- }
143
-
144
- render(<App />, document.getElementById('root')!);