jac-client 0.2.3__py3-none-any.whl → 0.2.8__py3-none-any.whl

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 (224) hide show
  1. jac_client/examples/all-in-one/app.jac +494 -347
  2. jac_client/examples/all-in-one/assets/workers/worker.py +5 -0
  3. jac_client/examples/all-in-one/button.jac +1 -1
  4. jac_client/examples/all-in-one/components/CategoryFilter.jac +35 -0
  5. jac_client/examples/all-in-one/components/Header.jac +13 -0
  6. jac_client/examples/all-in-one/components/ProfitOverview.jac +50 -0
  7. jac_client/examples/all-in-one/components/Summary.jac +53 -0
  8. jac_client/examples/all-in-one/components/TransactionForm.jac +158 -0
  9. jac_client/examples/all-in-one/components/TransactionItem.jac +55 -0
  10. jac_client/examples/all-in-one/components/TransactionList.jac +37 -0
  11. jac_client/examples/all-in-one/components/button.jac +1 -1
  12. jac_client/examples/all-in-one/components/navigation.jac +132 -0
  13. jac_client/examples/all-in-one/constants/categories.jac +37 -0
  14. jac_client/examples/all-in-one/constants/clients.jac +13 -0
  15. jac_client/examples/all-in-one/context/BudgetContext.jac +28 -0
  16. jac_client/examples/all-in-one/hooks/useBudget.jac +116 -0
  17. jac_client/examples/all-in-one/hooks/useLocalStorage.jac +36 -0
  18. jac_client/examples/all-in-one/pages/BudgetPlanner.cl.jac +70 -0
  19. jac_client/examples/all-in-one/pages/BudgetPlanner.jac +126 -0
  20. jac_client/examples/all-in-one/pages/FeaturesTest.cl.jac +552 -0
  21. jac_client/examples/all-in-one/pages/FeaturesTest.jac +126 -0
  22. jac_client/examples/all-in-one/pages/LandingPage.jac +101 -0
  23. jac_client/examples/all-in-one/pages/loginPage.jac +132 -0
  24. jac_client/examples/all-in-one/pages/nestedDemo.jac +61 -0
  25. jac_client/examples/all-in-one/pages/notFound.jac +24 -0
  26. jac_client/examples/all-in-one/pages/signupPage.jac +133 -0
  27. jac_client/examples/all-in-one/utils/formatters.jac +52 -0
  28. jac_client/examples/asset-serving/css-with-image/{app.jac → src/app.jac} +4 -4
  29. jac_client/examples/asset-serving/image-asset/{app.jac → src/app.jac} +4 -4
  30. jac_client/examples/asset-serving/import-alias/{app.jac → src/app.jac} +5 -5
  31. jac_client/examples/basic/{app.jac → src/app.jac} +4 -4
  32. jac_client/examples/basic-auth/src/app.jac +371 -0
  33. jac_client/examples/basic-auth-with-router/{app.jac → src/app.jac} +28 -28
  34. jac_client/examples/basic-full-stack/{app.jac → src/app.jac} +166 -127
  35. jac_client/examples/css-styling/js-styling/{app.jac → src/app.jac} +7 -7
  36. jac_client/examples/css-styling/material-ui/{app.jac → src/app.jac} +6 -6
  37. jac_client/examples/css-styling/pure-css/{app.jac → src/app.jac} +7 -7
  38. jac_client/examples/css-styling/sass-example/{app.jac → src/app.jac} +7 -7
  39. jac_client/examples/css-styling/styled-components/{app.jac → src/app.jac} +6 -6
  40. jac_client/examples/css-styling/tailwind-example/{app.jac → src/app.jac} +7 -7
  41. jac_client/examples/full-stack-with-auth/{app.jac → src/app.jac} +47 -47
  42. jac_client/examples/little-x/{app.jac → src/app.jac} +27 -32
  43. jac_client/examples/little-x/src/submit-button.jac +16 -0
  44. jac_client/examples/nested-folders/nested-advance/{ButtonRoot.jac → src/ButtonRoot.jac} +1 -1
  45. jac_client/examples/nested-folders/nested-advance/{app.jac → src/app.jac} +1 -1
  46. jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/ButtonSecondL.jac +1 -1
  47. jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/Card.jac +1 -1
  48. jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/level2/ButtonThirdL.jac +1 -1
  49. jac_client/examples/nested-folders/nested-basic/{app.jac → src/app.jac} +2 -2
  50. jac_client/examples/nested-folders/nested-basic/{button.jac → src/button.jac} +1 -1
  51. jac_client/examples/nested-folders/nested-basic/{components → src/components}/button.jac +1 -1
  52. jac_client/examples/ts-support/src/app.jac +35 -0
  53. jac_client/examples/with-router/{app.jac → src/app.jac} +15 -15
  54. jac_client/plugin/cli.jac +504 -0
  55. jac_client/plugin/client.jac +45 -0
  56. jac_client/plugin/client_runtime.cl.jac +42 -0
  57. jac_client/plugin/impl/client.impl.jac +193 -0
  58. jac_client/plugin/impl/client_runtime.impl.jac +195 -0
  59. jac_client/plugin/impl/vite_client_bundle.impl.jac +72 -0
  60. jac_client/plugin/plugin_config.jac +195 -0
  61. jac_client/plugin/src/__init__.jac +20 -0
  62. jac_client/plugin/src/asset_processor.jac +33 -0
  63. jac_client/plugin/src/babel_processor.jac +18 -0
  64. jac_client/plugin/src/compiler.jac +67 -0
  65. jac_client/plugin/src/config_loader.jac +32 -0
  66. jac_client/plugin/src/impl/asset_processor.impl.jac +127 -0
  67. jac_client/plugin/src/impl/babel_processor.impl.jac +89 -0
  68. jac_client/plugin/src/impl/compiler.impl.jac +288 -0
  69. jac_client/plugin/src/impl/config_loader.impl.jac +119 -0
  70. jac_client/plugin/src/impl/import_processor.impl.jac +33 -0
  71. jac_client/plugin/src/impl/jac_to_js.impl.jac +41 -0
  72. jac_client/plugin/src/impl/package_installer.impl.jac +105 -0
  73. jac_client/plugin/src/impl/vite_bundler.impl.jac +626 -0
  74. jac_client/plugin/src/import_processor.jac +19 -0
  75. jac_client/plugin/src/jac_to_js.jac +35 -0
  76. jac_client/plugin/src/package_installer.jac +26 -0
  77. jac_client/plugin/src/vite_bundler.jac +44 -0
  78. jac_client/plugin/vite_client_bundle.jac +31 -0
  79. jac_client/tests/conftest.py +283 -0
  80. jac_client/tests/fixtures/basic-app/app.jac +2 -2
  81. jac_client/tests/fixtures/cl_file/app.cl.jac +2 -2
  82. jac_client/tests/fixtures/client_app_with_antd/app.jac +1 -1
  83. jac_client/tests/fixtures/js_import/app.jac +5 -5
  84. jac_client/tests/fixtures/spawn_test/app.jac +15 -18
  85. jac_client/tests/fixtures/with-ts/app.jac +35 -0
  86. jac_client/tests/test_cli.py +811 -0
  87. jac_client/tests/test_it.py +592 -97
  88. {jac_client-0.2.3.dist-info → jac_client-0.2.8.dist-info}/METADATA +41 -34
  89. jac_client-0.2.8.dist-info/RECORD +97 -0
  90. {jac_client-0.2.3.dist-info → jac_client-0.2.8.dist-info}/WHEEL +2 -1
  91. jac_client-0.2.8.dist-info/entry_points.txt +4 -0
  92. jac_client-0.2.8.dist-info/top_level.txt +1 -0
  93. jac_client/docs/README.md +0 -689
  94. jac_client/docs/advanced-state.md +0 -1265
  95. jac_client/docs/asset-serving/intro.md +0 -209
  96. jac_client/docs/assets/pipe_line-v2.svg +0 -32
  97. jac_client/docs/assets/pipe_line.png +0 -0
  98. jac_client/docs/file-system/app.jac.md +0 -121
  99. jac_client/docs/file-system/backend-frontend.md +0 -217
  100. jac_client/docs/file-system/intro.md +0 -72
  101. jac_client/docs/file-system/nested-imports.md +0 -348
  102. jac_client/docs/guide-example/intro.md +0 -115
  103. jac_client/docs/guide-example/step-01-setup.md +0 -270
  104. jac_client/docs/guide-example/step-02-components.md +0 -416
  105. jac_client/docs/guide-example/step-03-styling.md +0 -478
  106. jac_client/docs/guide-example/step-04-todo-ui.md +0 -477
  107. jac_client/docs/guide-example/step-05-local-state.md +0 -530
  108. jac_client/docs/guide-example/step-06-events.md +0 -749
  109. jac_client/docs/guide-example/step-07-effects.md +0 -468
  110. jac_client/docs/guide-example/step-08-walkers.md +0 -534
  111. jac_client/docs/guide-example/step-09-authentication.md +0 -586
  112. jac_client/docs/guide-example/step-10-routing.md +0 -539
  113. jac_client/docs/guide-example/step-11-final.md +0 -963
  114. jac_client/docs/imports.md +0 -1141
  115. jac_client/docs/lifecycle-hooks.md +0 -773
  116. jac_client/docs/routing.md +0 -659
  117. jac_client/docs/styling/intro.md +0 -249
  118. jac_client/docs/styling/js-styling.md +0 -367
  119. jac_client/docs/styling/material-ui.md +0 -341
  120. jac_client/docs/styling/pure-css.md +0 -299
  121. jac_client/docs/styling/sass.md +0 -403
  122. jac_client/docs/styling/styled-components.md +0 -395
  123. jac_client/docs/styling/tailwind.md +0 -298
  124. jac_client/examples/all-in-one/.babelrc +0 -9
  125. jac_client/examples/all-in-one/README.md +0 -16
  126. jac_client/examples/all-in-one/assets/burger.png +0 -0
  127. jac_client/examples/all-in-one/package.json +0 -29
  128. jac_client/examples/all-in-one/styles.css +0 -26
  129. jac_client/examples/all-in-one/vite.config.js +0 -28
  130. jac_client/examples/asset-serving/css-with-image/.babelrc +0 -9
  131. jac_client/examples/asset-serving/css-with-image/README.md +0 -91
  132. jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
  133. jac_client/examples/asset-serving/css-with-image/package.json +0 -28
  134. jac_client/examples/asset-serving/css-with-image/styles.css +0 -26
  135. jac_client/examples/asset-serving/css-with-image/vite.config.js +0 -28
  136. jac_client/examples/asset-serving/image-asset/.babelrc +0 -9
  137. jac_client/examples/asset-serving/image-asset/README.md +0 -119
  138. jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
  139. jac_client/examples/asset-serving/image-asset/package.json +0 -28
  140. jac_client/examples/asset-serving/image-asset/styles.css +0 -26
  141. jac_client/examples/asset-serving/image-asset/vite.config.js +0 -28
  142. jac_client/examples/asset-serving/import-alias/.babelrc +0 -9
  143. jac_client/examples/asset-serving/import-alias/README.md +0 -83
  144. jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
  145. jac_client/examples/asset-serving/import-alias/package.json +0 -28
  146. jac_client/examples/asset-serving/import-alias/vite.config.js +0 -28
  147. jac_client/examples/basic/.babelrc +0 -9
  148. jac_client/examples/basic/README.md +0 -16
  149. jac_client/examples/basic/package.json +0 -27
  150. jac_client/examples/basic/vite.config.js +0 -27
  151. jac_client/examples/basic-auth/.babelrc +0 -9
  152. jac_client/examples/basic-auth/README.md +0 -16
  153. jac_client/examples/basic-auth/app.jac +0 -308
  154. jac_client/examples/basic-auth/package.json +0 -27
  155. jac_client/examples/basic-auth/vite.config.js +0 -27
  156. jac_client/examples/basic-auth-with-router/.babelrc +0 -9
  157. jac_client/examples/basic-auth-with-router/README.md +0 -60
  158. jac_client/examples/basic-auth-with-router/package.json +0 -28
  159. jac_client/examples/basic-auth-with-router/vite.config.js +0 -27
  160. jac_client/examples/basic-full-stack/.babelrc +0 -9
  161. jac_client/examples/basic-full-stack/README.md +0 -18
  162. jac_client/examples/basic-full-stack/package.json +0 -28
  163. jac_client/examples/basic-full-stack/vite.config.js +0 -27
  164. jac_client/examples/css-styling/js-styling/.babelrc +0 -9
  165. jac_client/examples/css-styling/js-styling/README.md +0 -183
  166. jac_client/examples/css-styling/js-styling/package.json +0 -28
  167. jac_client/examples/css-styling/js-styling/styles.js +0 -100
  168. jac_client/examples/css-styling/js-styling/vite.config.js +0 -27
  169. jac_client/examples/css-styling/material-ui/.babelrc +0 -9
  170. jac_client/examples/css-styling/material-ui/README.md +0 -16
  171. jac_client/examples/css-styling/material-ui/package.json +0 -32
  172. jac_client/examples/css-styling/material-ui/vite.config.js +0 -27
  173. jac_client/examples/css-styling/pure-css/.babelrc +0 -9
  174. jac_client/examples/css-styling/pure-css/README.md +0 -16
  175. jac_client/examples/css-styling/pure-css/package.json +0 -28
  176. jac_client/examples/css-styling/pure-css/styles.css +0 -111
  177. jac_client/examples/css-styling/pure-css/vite.config.js +0 -27
  178. jac_client/examples/css-styling/sass-example/.babelrc +0 -9
  179. jac_client/examples/css-styling/sass-example/README.md +0 -16
  180. jac_client/examples/css-styling/sass-example/package.json +0 -29
  181. jac_client/examples/css-styling/sass-example/styles.scss +0 -153
  182. jac_client/examples/css-styling/sass-example/vite.config.js +0 -27
  183. jac_client/examples/css-styling/styled-components/.babelrc +0 -9
  184. jac_client/examples/css-styling/styled-components/README.md +0 -16
  185. jac_client/examples/css-styling/styled-components/package.json +0 -29
  186. jac_client/examples/css-styling/styled-components/styled.js +0 -90
  187. jac_client/examples/css-styling/styled-components/vite.config.js +0 -27
  188. jac_client/examples/css-styling/tailwind-example/.babelrc +0 -9
  189. jac_client/examples/css-styling/tailwind-example/README.md +0 -16
  190. jac_client/examples/css-styling/tailwind-example/global.css +0 -1
  191. jac_client/examples/css-styling/tailwind-example/package.json +0 -30
  192. jac_client/examples/css-styling/tailwind-example/vite.config.js +0 -29
  193. jac_client/examples/full-stack-with-auth/.babelrc +0 -9
  194. jac_client/examples/full-stack-with-auth/README.md +0 -16
  195. jac_client/examples/full-stack-with-auth/package.json +0 -28
  196. jac_client/examples/full-stack-with-auth/vite.config.js +0 -29
  197. jac_client/examples/little-x/package.json +0 -23
  198. jac_client/examples/little-x/submit-button.jac +0 -8
  199. jac_client/examples/nested-folders/nested-advance/.babelrc +0 -9
  200. jac_client/examples/nested-folders/nested-advance/README.md +0 -77
  201. jac_client/examples/nested-folders/nested-advance/package.json +0 -29
  202. jac_client/examples/nested-folders/nested-advance/vite.config.js +0 -28
  203. jac_client/examples/nested-folders/nested-basic/.babelrc +0 -9
  204. jac_client/examples/nested-folders/nested-basic/README.md +0 -183
  205. jac_client/examples/nested-folders/nested-basic/app.js +0 -7
  206. jac_client/examples/nested-folders/nested-basic/package.json +0 -28
  207. jac_client/examples/nested-folders/nested-basic/vite.config.js +0 -27
  208. jac_client/examples/with-router/.babelrc +0 -9
  209. jac_client/examples/with-router/README.md +0 -17
  210. jac_client/examples/with-router/package.json +0 -28
  211. jac_client/examples/with-router/vite.config.js +0 -27
  212. jac_client/plugin/cli.py +0 -244
  213. jac_client/plugin/client.py +0 -152
  214. jac_client/plugin/client_runtime.jac +0 -234
  215. jac_client/plugin/vite_client_bundle.py +0 -503
  216. jac_client/tests/fixtures/js_import/utils.js +0 -21
  217. jac_client/tests/fixtures/package-lock.json +0 -329
  218. jac_client/tests/fixtures/package.json +0 -11
  219. jac_client/tests/test_asset_examples.py +0 -322
  220. jac_client/tests/test_cl.py +0 -530
  221. jac_client/tests/test_create_jac_app.py +0 -131
  222. jac_client/tests/test_nested_file.py +0 -374
  223. jac_client-0.2.3.dist-info/RECORD +0 -171
  224. jac_client-0.2.3.dist-info/entry_points.txt +0 -4
@@ -0,0 +1,371 @@
1
+ # Simple Authentication App with Jac Client Utils
2
+ cl import from react {
3
+ useState,
4
+ useEffect
5
+ }
6
+ cl import from '@jac-client/utils' { jacSignup, jacLogin, jacLogout, jacIsLoggedIn }
7
+
8
+ cl {
9
+ def:pub app -> any {
10
+ has isLoggedIn: bool = False;
11
+ has isSignup: bool = False;
12
+ has username: str = "";
13
+ has password: str = "";
14
+ has error: str = "";
15
+ has loading: bool = False;
16
+
17
+ # Check login status on mount
18
+ useEffect(lambda -> None{ isLoggedIn = jacIsLoggedIn();} , []);
19
+
20
+ # Handle login
21
+ async def handleLogin -> None {
22
+ error = "";
23
+ if not username.trim() or not password {
24
+ error = "Please fill in all fields";
25
+ return;
26
+ }
27
+ loading = True;
28
+ success = await jacLogin(username, password);
29
+ loading = False;
30
+ if success {
31
+ isLoggedIn = True;
32
+ username = "";
33
+ password = "";
34
+ } else {
35
+ error = "Invalid username or password";
36
+ }
37
+ }
38
+
39
+ # Handle signup
40
+ async def handleSignup -> None {
41
+ error = "";
42
+ if not username.trim() or not password {
43
+ error = "Please fill in all fields";
44
+ return;
45
+ }
46
+ if password.length < 6 {
47
+ error = "Password must be at least 6 characters";
48
+ return;
49
+ }
50
+ loading = True;
51
+ result = await jacSignup(username, password);
52
+ loading = False;
53
+ if result["success"] {
54
+ isLoggedIn = True;
55
+ username = "";
56
+ password = "";
57
+ } else {
58
+ error = result["error"] if result["error"] else "Signup failed";
59
+ }
60
+ }
61
+
62
+ # Handle logout
63
+ def handleLogout -> None {
64
+ jacLogout();
65
+ isLoggedIn = False;
66
+ username = "";
67
+ password = "";
68
+ error = "";
69
+ }
70
+
71
+ # Handle form submit
72
+ async def handleSubmit(e: any) -> None {
73
+ e.preventDefault();
74
+ if isSignup {
75
+ await handleSignup();
76
+ } else {
77
+ await handleLogin();
78
+ }
79
+ }
80
+
81
+ # Logged in view - Dashboard
82
+ if isLoggedIn {
83
+ return <div
84
+ style={{
85
+ "minHeight": "100vh",
86
+ "background": "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
87
+ "display": "flex",
88
+ "alignItems": "center",
89
+ "justifyContent": "center",
90
+ "fontFamily": "system-ui, -apple-system, sans-serif"
91
+ }}
92
+ >
93
+ <div
94
+ style={{
95
+ "background": "#ffffff",
96
+ "borderRadius": "16px",
97
+ "padding": "48px",
98
+ "boxShadow": "0 20px 60px rgba(0,0,0,0.3)",
99
+ "maxWidth": "500px",
100
+ "width": "90%",
101
+ "textAlign": "center"
102
+ }}
103
+ >
104
+ <h1
105
+ style={{
106
+ "fontSize": "2.5rem",
107
+ "marginBottom": "16px",
108
+ "color": "#1f2937",
109
+ "fontWeight": "700"
110
+ }}
111
+ >
112
+ ✅ Welcome!
113
+ </h1>
114
+ <p
115
+ style={{
116
+ "fontSize": "1.1rem",
117
+ "color": "#6b7280",
118
+ "marginBottom": "32px"
119
+ }}
120
+ >
121
+ You are successfully logged in
122
+ </p>
123
+ <div
124
+ style={{
125
+ "background": "#f3f4f6",
126
+ "padding": "24px",
127
+ "borderRadius": "12px",
128
+ "marginBottom": "32px"
129
+ }}
130
+ >
131
+ <p
132
+ style={{
133
+ "fontSize": "0.9rem",
134
+ "color": "#6b7280",
135
+ "marginBottom": "8px"
136
+ }}
137
+ >
138
+ Logged in as:
139
+ </p>
140
+ <p
141
+ style={{
142
+ "fontSize": "1.2rem",
143
+ "fontWeight": "600",
144
+ "color": "#667eea"
145
+ }}
146
+ >
147
+ User
148
+ </p>
149
+ </div>
150
+ <button
151
+ onClick={handleLogout}
152
+ style={{
153
+ "width": "100%",
154
+ "padding": "14px 24px",
155
+ "background": "#ef4444",
156
+ "color": "#ffffff",
157
+ "border": "none",
158
+ "borderRadius": "10px",
159
+ "fontSize": "16px",
160
+ "fontWeight": "600",
161
+ "cursor": "pointer",
162
+ "transition": "all 0.3s",
163
+ "boxShadow": "0 4px 12px rgba(239,68,68,0.3)"
164
+ }}
165
+ >
166
+ Logout
167
+ </button>
168
+ </div>
169
+ </div>;
170
+ }
171
+
172
+ # Login/Signup view
173
+ return <div
174
+ style={{
175
+ "minHeight": "100vh",
176
+ "background": "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
177
+ "display": "flex",
178
+ "alignItems": "center",
179
+ "justifyContent": "center",
180
+ "fontFamily": "system-ui, -apple-system, sans-serif",
181
+ "padding": "20px"
182
+ }}
183
+ >
184
+ <div
185
+ style={{
186
+ "background": "#ffffff",
187
+ "borderRadius": "16px",
188
+ "padding": "48px",
189
+ "boxShadow": "0 20px 60px rgba(0,0,0,0.3)",
190
+ "maxWidth": "400px",
191
+ "width": "100%"
192
+ }}
193
+ >
194
+ # Header
195
+ <div
196
+ style={{"textAlign": "center", "marginBottom": "32px"}}
197
+ >
198
+ <h1
199
+ style={{
200
+ "fontSize": "2rem",
201
+ "fontWeight": "700",
202
+ "color": "#1f2937",
203
+ "marginBottom": "8px"
204
+ }}
205
+ >
206
+ {("Create Account" if isSignup else "Welcome Back")}
207
+ </h1>
208
+ <p
209
+ style={{"color": "#6b7280", "fontSize": "0.95rem"}}
210
+ >
211
+ {(
212
+ "Sign up to get started"
213
+ if isSignup
214
+ else "Sign in to continue"
215
+ )}
216
+ </p>
217
+ </div>
218
+ # Form
219
+ <form
220
+ onSubmit={handleSubmit}
221
+ style={{"marginBottom": "24px"}}
222
+ >
223
+ <div
224
+ style={{"marginBottom": "20px"}}
225
+ >
226
+ <label
227
+ style={{
228
+ "display": "block",
229
+ "marginBottom": "8px",
230
+ "color": "#374151",
231
+ "fontSize": "14px",
232
+ "fontWeight": "600"
233
+ }}
234
+ >
235
+ Username
236
+ </label>
237
+ <input
238
+ type="text"
239
+ value={username}
240
+ onChange={lambda e: any -> None{ username = e.target.value;} }
241
+ placeholder="Enter your username"
242
+ style={{
243
+ "width": "100%",
244
+ "padding": "12px 16px",
245
+ "border": "2px solid #e5e7eb",
246
+ "borderRadius": "10px",
247
+ "fontSize": "16px",
248
+ "outline": "none",
249
+ "transition": "border 0.2s",
250
+ "boxSizing": "border-box"
251
+ }}
252
+ />
253
+ </div>
254
+ <div
255
+ style={{"marginBottom": "24px"}}
256
+ >
257
+ <label
258
+ style={{
259
+ "display": "block",
260
+ "marginBottom": "8px",
261
+ "color": "#374151",
262
+ "fontSize": "14px",
263
+ "fontWeight": "600"
264
+ }}
265
+ >
266
+ Password
267
+ </label>
268
+ <input
269
+ type="password"
270
+ value={password}
271
+ onChange={lambda e: any -> None{ password = e.target.value;} }
272
+ placeholder="Enter your password"
273
+ style={{
274
+ "width": "100%",
275
+ "padding": "12px 16px",
276
+ "border": "2px solid #e5e7eb",
277
+ "borderRadius": "10px",
278
+ "fontSize": "16px",
279
+ "outline": "none",
280
+ "transition": "border 0.2s",
281
+ "boxSizing": "border-box"
282
+ }}
283
+ />
284
+ </div>
285
+ {(
286
+ <div
287
+ style={{
288
+ "padding": "12px",
289
+ "background": "#fee2e2",
290
+ "border": "1px solid #fecaca",
291
+ "borderRadius": "8px",
292
+ "marginBottom": "20px"
293
+ }}
294
+ >
295
+ <p
296
+ style={{
297
+ "color": "#dc2626",
298
+ "fontSize": "14px",
299
+ "margin": "0"
300
+ }}
301
+ >
302
+ {error}
303
+ </p>
304
+ </div>
305
+ )
306
+ if error
307
+ else None}
308
+ <button
309
+ type="submit"
310
+ disabled={loading}
311
+ style={{
312
+ "width": "100%",
313
+ "padding": "14px 24px",
314
+ "background": (("#9ca3af" if loading else "#667eea")),
315
+ "color": "#ffffff",
316
+ "border": "none",
317
+ "borderRadius": "10px",
318
+ "fontSize": "16px",
319
+ "fontWeight": "600",
320
+ "cursor": (("not-allowed" if loading else "pointer")),
321
+ "transition": "all 0.3s",
322
+ "boxShadow": "0 4px 12px rgba(102,126,234,0.4)"
323
+ }}
324
+ >
325
+ {(
326
+ (
327
+ "Processing..."
328
+ if loading
329
+ else ("Sign Up" if isSignup else "Sign In")
330
+ )
331
+ )}
332
+ </button>
333
+ </form>
334
+ # Toggle between login/signup
335
+ <div
336
+ style={{"textAlign": "center"}}
337
+ >
338
+ <p
339
+ style={{
340
+ "color": "#6b7280",
341
+ "fontSize": "14px",
342
+ "marginBottom": "8px"
343
+ }}
344
+ >
345
+ {(
346
+ (
347
+ "Already have an account?"
348
+ if isSignup
349
+ else "Don't have an account?"
350
+ )
351
+ )}
352
+ </p>
353
+ <button
354
+ onClick={lambda -> None{ isSignup = not isSignup; error = ""; username = ""; password = "";} }
355
+ style={{
356
+ "background": "none",
357
+ "border": "none",
358
+ "color": "#667eea",
359
+ "fontSize": "14px",
360
+ "fontWeight": "600",
361
+ "cursor": "pointer",
362
+ "textDecoration": "underline"
363
+ }}
364
+ >
365
+ {(("Sign In" if isSignup else "Create Account"))}
366
+ </button>
367
+ </div>
368
+ </div>
369
+ </div>;
370
+ }
371
+ }
@@ -19,9 +19,9 @@ cl import from "@jac-client/utils" {
19
19
 
20
20
  cl {
21
21
  # Navigation Component
22
- def Navigation() -> any {
23
- let isLoggedIn = jacIsLoggedIn();
24
- let navigate = useNavigate();
22
+ def Navigation -> any {
23
+ isLoggedIn = jacIsLoggedIn();
24
+ navigate = useNavigate();
25
25
 
26
26
  def handleLogout(e: any) -> None {
27
27
  e.preventDefault();
@@ -108,36 +108,36 @@ cl {
108
108
  }
109
109
 
110
110
  # Login Page
111
- def LoginPage() -> any {
112
- let [username, setUsername] = useState("");
113
- let [password, setPassword] = useState("");
114
- let [error, setError] = useState("");
115
- let navigate = useNavigate();
111
+ def LoginPage -> any {
112
+ has username: str = "";
113
+ has password: str = "";
114
+ has error: str = "";
115
+ navigate = useNavigate();
116
116
 
117
117
  async def handleLogin(e: any) -> None {
118
118
  e.preventDefault();
119
- setError("");
119
+ error = "";
120
120
  if not username or not password {
121
- setError("Please fill in all fields");
121
+ error = "Please fill in all fields";
122
122
  return;
123
123
  }
124
124
  success = await jacLogin(username, password);
125
125
  if success {
126
126
  navigate("/dashboard");
127
127
  } else {
128
- setError("Invalid credentials");
128
+ error = "Invalid credentials";
129
129
  }
130
130
  }
131
131
 
132
132
  def handleUsernameChange(e: any) -> None {
133
- setUsername(e.target.value);
133
+ username = e.target.value;
134
134
  }
135
135
 
136
136
  def handlePasswordChange(e: any) -> None {
137
- setPassword(e.target.value);
137
+ password = e.target.value;
138
138
  }
139
139
 
140
- let errorDisplay = None;
140
+ errorDisplay = None;
141
141
  if error {
142
142
  errorDisplay = <div
143
143
  style={{"color": "#dc2626", "fontSize": "14px", "marginBottom": "12px"}}
@@ -234,36 +234,36 @@ cl {
234
234
  }
235
235
 
236
236
  # Signup Page
237
- def SignupPage() -> any {
238
- let [username, setUsername] = useState("");
239
- let [password, setPassword] = useState("");
240
- let [error, setError] = useState("");
241
- let navigate = useNavigate();
237
+ def SignupPage -> any {
238
+ has username: str = "";
239
+ has password: str = "";
240
+ has error: str = "";
241
+ navigate = useNavigate();
242
242
 
243
243
  async def handleSignup(e: any) -> None {
244
244
  e.preventDefault();
245
- setError("");
245
+ error = "";
246
246
  if not username or not password {
247
- setError("Please fill in all fields");
247
+ error = "Please fill in all fields";
248
248
  return;
249
249
  }
250
250
  result = await jacSignup(username, password);
251
251
  if result["success"] {
252
252
  navigate("/dashboard");
253
253
  } else {
254
- setError(result["error"] if result["error"] else "Signup failed");
254
+ error = result["error"] if result["error"] else "Signup failed";
255
255
  }
256
256
  }
257
257
 
258
258
  def handleUsernameChange(e: any) -> None {
259
- setUsername(e.target.value);
259
+ username = e.target.value;
260
260
  }
261
261
 
262
262
  def handlePasswordChange(e: any) -> None {
263
- setPassword(e.target.value);
263
+ password = e.target.value;
264
264
  }
265
265
 
266
- let errorDisplay = None;
266
+ errorDisplay = None;
267
267
  if error {
268
268
  errorDisplay = <div
269
269
  style={{"color": "#dc2626", "fontSize": "14px", "marginBottom": "12px"}}
@@ -360,7 +360,7 @@ cl {
360
360
  }
361
361
 
362
362
  # Dashboard Page (Protected Route)
363
- def DashboardPage() -> any {
363
+ def DashboardPage -> any {
364
364
  # Check if user is logged in, redirect if not
365
365
  if not jacIsLoggedIn() {
366
366
  return <Navigate to="/login" />;
@@ -423,7 +423,7 @@ cl {
423
423
  }
424
424
 
425
425
  # Home/Landing Page - auto-redirect based on auth status
426
- def HomePage() -> any {
426
+ def HomePage -> any {
427
427
  if jacIsLoggedIn() {
428
428
  return <Navigate to="/dashboard" />;
429
429
  }
@@ -431,7 +431,7 @@ cl {
431
431
  }
432
432
 
433
433
  # Main App with React Router
434
- def app() -> any {
434
+ def:pub app -> any {
435
435
  return <Router>
436
436
  <div
437
437
  style={{