jac-client 0.2.3__py3-none-any.whl → 0.2.4__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 (176) hide show
  1. jac_client/examples/all-in-one/assets/workers/worker.py +5 -0
  2. jac_client/tests/conftest.py +281 -0
  3. jac_client/tests/test_cli.py +755 -0
  4. jac_client/tests/test_it.py +347 -67
  5. {jac_client-0.2.3.dist-info → jac_client-0.2.4.dist-info}/METADATA +28 -30
  6. jac_client-0.2.4.dist-info/RECORD +10 -0
  7. {jac_client-0.2.3.dist-info → jac_client-0.2.4.dist-info}/WHEEL +2 -1
  8. jac_client-0.2.4.dist-info/entry_points.txt +4 -0
  9. jac_client-0.2.4.dist-info/top_level.txt +1 -0
  10. jac_client/docs/README.md +0 -689
  11. jac_client/docs/advanced-state.md +0 -1265
  12. jac_client/docs/asset-serving/intro.md +0 -209
  13. jac_client/docs/assets/pipe_line-v2.svg +0 -32
  14. jac_client/docs/assets/pipe_line.png +0 -0
  15. jac_client/docs/file-system/app.jac.md +0 -121
  16. jac_client/docs/file-system/backend-frontend.md +0 -217
  17. jac_client/docs/file-system/intro.md +0 -72
  18. jac_client/docs/file-system/nested-imports.md +0 -348
  19. jac_client/docs/guide-example/intro.md +0 -115
  20. jac_client/docs/guide-example/step-01-setup.md +0 -270
  21. jac_client/docs/guide-example/step-02-components.md +0 -416
  22. jac_client/docs/guide-example/step-03-styling.md +0 -478
  23. jac_client/docs/guide-example/step-04-todo-ui.md +0 -477
  24. jac_client/docs/guide-example/step-05-local-state.md +0 -530
  25. jac_client/docs/guide-example/step-06-events.md +0 -749
  26. jac_client/docs/guide-example/step-07-effects.md +0 -468
  27. jac_client/docs/guide-example/step-08-walkers.md +0 -534
  28. jac_client/docs/guide-example/step-09-authentication.md +0 -586
  29. jac_client/docs/guide-example/step-10-routing.md +0 -539
  30. jac_client/docs/guide-example/step-11-final.md +0 -963
  31. jac_client/docs/imports.md +0 -1141
  32. jac_client/docs/lifecycle-hooks.md +0 -773
  33. jac_client/docs/routing.md +0 -659
  34. jac_client/docs/styling/intro.md +0 -249
  35. jac_client/docs/styling/js-styling.md +0 -367
  36. jac_client/docs/styling/material-ui.md +0 -341
  37. jac_client/docs/styling/pure-css.md +0 -299
  38. jac_client/docs/styling/sass.md +0 -403
  39. jac_client/docs/styling/styled-components.md +0 -395
  40. jac_client/docs/styling/tailwind.md +0 -298
  41. jac_client/examples/all-in-one/.babelrc +0 -9
  42. jac_client/examples/all-in-one/README.md +0 -16
  43. jac_client/examples/all-in-one/app.jac +0 -426
  44. jac_client/examples/all-in-one/assets/burger.png +0 -0
  45. jac_client/examples/all-in-one/button.jac +0 -7
  46. jac_client/examples/all-in-one/components/button.jac +0 -7
  47. jac_client/examples/all-in-one/package.json +0 -29
  48. jac_client/examples/all-in-one/styles.css +0 -26
  49. jac_client/examples/all-in-one/vite.config.js +0 -28
  50. jac_client/examples/asset-serving/css-with-image/.babelrc +0 -9
  51. jac_client/examples/asset-serving/css-with-image/README.md +0 -91
  52. jac_client/examples/asset-serving/css-with-image/app.jac +0 -88
  53. jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
  54. jac_client/examples/asset-serving/css-with-image/package.json +0 -28
  55. jac_client/examples/asset-serving/css-with-image/styles.css +0 -26
  56. jac_client/examples/asset-serving/css-with-image/vite.config.js +0 -28
  57. jac_client/examples/asset-serving/image-asset/.babelrc +0 -9
  58. jac_client/examples/asset-serving/image-asset/README.md +0 -119
  59. jac_client/examples/asset-serving/image-asset/app.jac +0 -55
  60. jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
  61. jac_client/examples/asset-serving/image-asset/package.json +0 -28
  62. jac_client/examples/asset-serving/image-asset/styles.css +0 -26
  63. jac_client/examples/asset-serving/image-asset/vite.config.js +0 -28
  64. jac_client/examples/asset-serving/import-alias/.babelrc +0 -9
  65. jac_client/examples/asset-serving/import-alias/README.md +0 -83
  66. jac_client/examples/asset-serving/import-alias/app.jac +0 -111
  67. jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
  68. jac_client/examples/asset-serving/import-alias/package.json +0 -28
  69. jac_client/examples/asset-serving/import-alias/vite.config.js +0 -28
  70. jac_client/examples/basic/.babelrc +0 -9
  71. jac_client/examples/basic/README.md +0 -16
  72. jac_client/examples/basic/app.jac +0 -21
  73. jac_client/examples/basic/package.json +0 -27
  74. jac_client/examples/basic/vite.config.js +0 -27
  75. jac_client/examples/basic-auth/.babelrc +0 -9
  76. jac_client/examples/basic-auth/README.md +0 -16
  77. jac_client/examples/basic-auth/app.jac +0 -308
  78. jac_client/examples/basic-auth/package.json +0 -27
  79. jac_client/examples/basic-auth/vite.config.js +0 -27
  80. jac_client/examples/basic-auth-with-router/.babelrc +0 -9
  81. jac_client/examples/basic-auth-with-router/README.md +0 -60
  82. jac_client/examples/basic-auth-with-router/app.jac +0 -464
  83. jac_client/examples/basic-auth-with-router/package.json +0 -28
  84. jac_client/examples/basic-auth-with-router/vite.config.js +0 -27
  85. jac_client/examples/basic-full-stack/.babelrc +0 -9
  86. jac_client/examples/basic-full-stack/README.md +0 -18
  87. jac_client/examples/basic-full-stack/app.jac +0 -320
  88. jac_client/examples/basic-full-stack/package.json +0 -28
  89. jac_client/examples/basic-full-stack/vite.config.js +0 -27
  90. jac_client/examples/css-styling/js-styling/.babelrc +0 -9
  91. jac_client/examples/css-styling/js-styling/README.md +0 -183
  92. jac_client/examples/css-styling/js-styling/app.jac +0 -84
  93. jac_client/examples/css-styling/js-styling/package.json +0 -28
  94. jac_client/examples/css-styling/js-styling/styles.js +0 -100
  95. jac_client/examples/css-styling/js-styling/vite.config.js +0 -27
  96. jac_client/examples/css-styling/material-ui/.babelrc +0 -9
  97. jac_client/examples/css-styling/material-ui/README.md +0 -16
  98. jac_client/examples/css-styling/material-ui/app.jac +0 -122
  99. jac_client/examples/css-styling/material-ui/package.json +0 -32
  100. jac_client/examples/css-styling/material-ui/vite.config.js +0 -27
  101. jac_client/examples/css-styling/pure-css/.babelrc +0 -9
  102. jac_client/examples/css-styling/pure-css/README.md +0 -16
  103. jac_client/examples/css-styling/pure-css/app.jac +0 -64
  104. jac_client/examples/css-styling/pure-css/package.json +0 -28
  105. jac_client/examples/css-styling/pure-css/styles.css +0 -111
  106. jac_client/examples/css-styling/pure-css/vite.config.js +0 -27
  107. jac_client/examples/css-styling/sass-example/.babelrc +0 -9
  108. jac_client/examples/css-styling/sass-example/README.md +0 -16
  109. jac_client/examples/css-styling/sass-example/app.jac +0 -64
  110. jac_client/examples/css-styling/sass-example/package.json +0 -29
  111. jac_client/examples/css-styling/sass-example/styles.scss +0 -153
  112. jac_client/examples/css-styling/sass-example/vite.config.js +0 -27
  113. jac_client/examples/css-styling/styled-components/.babelrc +0 -9
  114. jac_client/examples/css-styling/styled-components/README.md +0 -16
  115. jac_client/examples/css-styling/styled-components/app.jac +0 -71
  116. jac_client/examples/css-styling/styled-components/package.json +0 -29
  117. jac_client/examples/css-styling/styled-components/styled.js +0 -90
  118. jac_client/examples/css-styling/styled-components/vite.config.js +0 -27
  119. jac_client/examples/css-styling/tailwind-example/.babelrc +0 -9
  120. jac_client/examples/css-styling/tailwind-example/README.md +0 -16
  121. jac_client/examples/css-styling/tailwind-example/app.jac +0 -63
  122. jac_client/examples/css-styling/tailwind-example/global.css +0 -1
  123. jac_client/examples/css-styling/tailwind-example/package.json +0 -30
  124. jac_client/examples/css-styling/tailwind-example/vite.config.js +0 -29
  125. jac_client/examples/full-stack-with-auth/.babelrc +0 -9
  126. jac_client/examples/full-stack-with-auth/README.md +0 -16
  127. jac_client/examples/full-stack-with-auth/app.jac +0 -722
  128. jac_client/examples/full-stack-with-auth/package.json +0 -28
  129. jac_client/examples/full-stack-with-auth/vite.config.js +0 -29
  130. jac_client/examples/little-x/app.jac +0 -724
  131. jac_client/examples/little-x/package.json +0 -23
  132. jac_client/examples/little-x/submit-button.jac +0 -8
  133. jac_client/examples/nested-folders/nested-advance/.babelrc +0 -9
  134. jac_client/examples/nested-folders/nested-advance/ButtonRoot.jac +0 -11
  135. jac_client/examples/nested-folders/nested-advance/README.md +0 -77
  136. jac_client/examples/nested-folders/nested-advance/app.jac +0 -35
  137. jac_client/examples/nested-folders/nested-advance/level1/ButtonSecondL.jac +0 -19
  138. jac_client/examples/nested-folders/nested-advance/level1/Card.jac +0 -43
  139. jac_client/examples/nested-folders/nested-advance/level1/level2/ButtonThirdL.jac +0 -25
  140. jac_client/examples/nested-folders/nested-advance/package.json +0 -29
  141. jac_client/examples/nested-folders/nested-advance/vite.config.js +0 -28
  142. jac_client/examples/nested-folders/nested-basic/.babelrc +0 -9
  143. jac_client/examples/nested-folders/nested-basic/README.md +0 -183
  144. jac_client/examples/nested-folders/nested-basic/app.jac +0 -13
  145. jac_client/examples/nested-folders/nested-basic/app.js +0 -7
  146. jac_client/examples/nested-folders/nested-basic/button.jac +0 -7
  147. jac_client/examples/nested-folders/nested-basic/components/button.jac +0 -7
  148. jac_client/examples/nested-folders/nested-basic/package.json +0 -28
  149. jac_client/examples/nested-folders/nested-basic/vite.config.js +0 -27
  150. jac_client/examples/with-router/.babelrc +0 -9
  151. jac_client/examples/with-router/README.md +0 -17
  152. jac_client/examples/with-router/app.jac +0 -323
  153. jac_client/examples/with-router/package.json +0 -28
  154. jac_client/examples/with-router/vite.config.js +0 -27
  155. jac_client/plugin/cli.py +0 -244
  156. jac_client/plugin/client.py +0 -152
  157. jac_client/plugin/client_runtime.jac +0 -234
  158. jac_client/plugin/vite_client_bundle.py +0 -503
  159. jac_client/tests/fixtures/basic-app/app.jac +0 -23
  160. jac_client/tests/fixtures/cl_file/app.cl.jac +0 -48
  161. jac_client/tests/fixtures/cl_file/app.jac +0 -15
  162. jac_client/tests/fixtures/client_app_with_antd/app.jac +0 -34
  163. jac_client/tests/fixtures/js_import/app.jac +0 -34
  164. jac_client/tests/fixtures/js_import/utils.js +0 -21
  165. jac_client/tests/fixtures/package-lock.json +0 -329
  166. jac_client/tests/fixtures/package.json +0 -11
  167. jac_client/tests/fixtures/relative_import/app.jac +0 -11
  168. jac_client/tests/fixtures/relative_import/button.jac +0 -7
  169. jac_client/tests/fixtures/spawn_test/app.jac +0 -129
  170. jac_client/tests/fixtures/test_fragments_spread/app.jac +0 -67
  171. jac_client/tests/test_asset_examples.py +0 -322
  172. jac_client/tests/test_cl.py +0 -530
  173. jac_client/tests/test_create_jac_app.py +0 -131
  174. jac_client/tests/test_nested_file.py +0 -374
  175. jac_client-0.2.3.dist-info/RECORD +0 -171
  176. jac_client-0.2.3.dist-info/entry_points.txt +0 -4
@@ -1,724 +0,0 @@
1
- import datetime;
2
- cl import from lodash { * as _ }
3
- cl import from antd { Button, Input, Card, Typography, Space }
4
- cl import from pluralize { default as pluralize }
5
- cl import from 'react-animated-components' { Rotate }
6
-
7
- node Profile {
8
- has username: str = "";
9
-
10
- can update with update_profile entry {
11
- self.username = visitor.new_username;
12
- report self ;
13
- }
14
-
15
- can get with get_profile entry {
16
- follwers = [
17
- {"id": jid(i), "username": i.username} for i in [self-->(`?Profile)]
18
- ];
19
- report {"user": self, "followers": follwers} ;
20
- }
21
-
22
- can follow with follow_request entry {
23
- current_profile = [root-->(`?Profile)];
24
- current_profile[0] +>: Follow() :+> self;
25
- report self ;
26
- }
27
-
28
- can un_follow with un_follow_request entry {
29
- current_profile = [root-->(`?Profile)];
30
- follow_edge = [edge current_profile[0]->:Follow:->self];
31
- del follow_edge[0] ;
32
- report self ;
33
- }
34
- }
35
-
36
- obj TweetInfo {
37
- has username: str;
38
- has id: str;
39
- has content: str;
40
- has embedding: list;
41
- has likes: list;
42
- has comments: list;
43
- }
44
-
45
- node Tweet {
46
- has content: str;
47
- has embedding: list;
48
- has created_at: str = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S");
49
-
50
- can update with update_tweet exit {
51
- self.content = visitor.updated_content;
52
- report self ;
53
- }
54
-
55
- can delete with remove_tweet exit {
56
- del self ;
57
- disengage;
58
- }
59
-
60
- can like_tweet with like_tweet entry {
61
- current_profile = [root-->(`?Profile)];
62
- self +>: Like() :+> current_profile[0];
63
- report self ;
64
- }
65
-
66
- can remove_like with remove_like entry {
67
- current_profile = [root-->(`?Profile)];
68
- like_edge = [edge self->:Like:->current_profile[0]];
69
- del like_edge[0] ;
70
- report self ;
71
- }
72
-
73
- can comment with comment_tweet entry {
74
- current_profile = [root-->(`?Profile)];
75
- comment_node = current_profile[0] +>: Post() :+> Comment(
76
- content=visitor.content
77
- );
78
- grant(comment_node[0], level=ConnectPerm);
79
- self ++> comment_node[0];
80
- report comment_node[0] ;
81
- }
82
-
83
- def get_info() -> TweetInfo {
84
- return TweetInfo(
85
- username=[self<-:Post:<-][0].username,
86
- id=jid(self),
87
- content=self.content,
88
- embedding=self.embedding,
89
- likes=[i.username for i in [self->:Like:->]],
90
- comments=[
91
- {
92
- "username": [i<--(`?Profile)][0].username,
93
- "id": jid(i),
94
- "content": i.content
95
- } for i in [self-->(`?Comment)]
96
- ]
97
- );
98
- }
99
-
100
- can get with load_feed entry {
101
- tweet_info = self.get_info();
102
- visitor.results.append({"Tweet_Info": tweet_info});
103
- }
104
- }
105
-
106
- node Comment {
107
- has content: str;
108
-
109
- can update with update_comment entry {
110
- self.content = visitor.updated_content;
111
- report self ;
112
- }
113
-
114
- can delete with remove_comment entry {
115
- del self ;
116
- disengage;
117
- }
118
- }
119
-
120
- edge Follow {}
121
-
122
- edge Like {}
123
-
124
- edge Post {}
125
-
126
- walker visit_profile {
127
- can visit_profile with `root entry {
128
- visit [-->(`?Profile)] else {
129
- new_profile = here ++> Profile();
130
- grant(new_profile[0], level=ConnectPerm);
131
- visit new_profile;
132
- }
133
- }
134
- }
135
-
136
- walker update_profile(visit_profile) {
137
- has new_username: str;
138
- }
139
-
140
- walker get_profile(visit_profile) {}
141
-
142
- walker load_user_profiles {
143
- can load_profiles with `root entry {
144
- self.profiles: list = [];
145
- for each_root in allroots() {
146
- profile = [each_root-->(`?Profile)][0];
147
- self.profiles.append({"name": profile.username, "id": jid(profile)});
148
- }
149
- }
150
-
151
- can report_profiles with exit {
152
- report self.profiles ;
153
- }
154
- }
155
-
156
- walker follow_request {}
157
-
158
- walker un_follow_request {}
159
-
160
- walker create_tweet(visit_profile) {
161
- has content: str;
162
-
163
- can tweet with Profile entry {
164
- tweet_node = here +>: Post() :+> Tweet(content=self.content, embedding=[]);
165
- grant(tweet_node[0], level=ConnectPerm);
166
- report tweet_node ;
167
- }
168
- }
169
-
170
- walker update_tweet {
171
- has updated_content: str;
172
- }
173
-
174
- walker remove_tweet {}
175
-
176
- walker like_tweet {}
177
-
178
- walker remove_like {}
179
-
180
- walker comment_tweet {
181
- has content: str;
182
- }
183
-
184
- walker update_comment {
185
- has updated_content: str;
186
- }
187
-
188
- walker remove_comment {}
189
-
190
- walker load_feed(visit_profile) {
191
- has search_query: str = "";
192
- has results: list = [];
193
-
194
- can load with Profile entry {
195
- visit [-->(`?Tweet)];
196
- for user_node in [->:Follow:->(`?Profile)] {
197
- visit [user_node-->(`?Tweet)];
198
- }
199
- }
200
-
201
- can report_feed with exit {
202
- report self.results ;
203
- }
204
- }
205
-
206
- # Client-side UI Components (marked with 'cl' for browser execution)
207
- # ===================================================================
208
-
209
- # Reactive state management
210
- cl let [appState, setAppState] = createState(
211
- {"tweets": [], "loading": False}
212
- );
213
-
214
- # Manual routing functions removed - now using reactive createRouter
215
-
216
- # Shared data model for client/server
217
- cl obj ClientTweet {
218
- has username: str = "";
219
- has id: str = "";
220
- has content: str = "";
221
- has likes: list = [];
222
- has comments: list = [];
223
- }
224
-
225
- cl obj ClientProfile {
226
- has username: str = "";
227
- has id: str = "";
228
- }
229
-
230
- # UI Components - Render a single tweet card
231
- cl def TweetCard(tweet: ClientTweet) -> any {
232
- return <div
233
- class="tweet-card"
234
- style={{
235
- "border": "1px solid #e1e8ed",
236
- "padding": "15px",
237
- "margin": "10px 0",
238
- "borderRadius": "8px"
239
- }}
240
- >
241
- <div
242
- class="tweet-header"
243
- style={{"fontWeight": "bold", "marginBottom": "80px"}}
244
- >
245
- @{tweet.username}
246
- </div>
247
- <div
248
- class="tweet-content"
249
- style={{"marginBottom": "12px"}}
250
- >
251
- {tweet.content}
252
- </div>
253
- <div
254
- class="tweet-actions"
255
- style={{"display": "flex", "gap": "15px"}}
256
- >
257
- <button
258
- onclick={like_tweet_action(tweet.id)}
259
- style={{"padding": "5px 10px", "cursor": "pointer"}}
260
- >
261
- Like ({tweet.likes.length})
262
- </button>
263
- <button
264
- style={{"padding": "5px 10px"}}
265
- >
266
- Comment ({tweet.comments.length})
267
- </button>
268
- </div>
269
- </div>;
270
- }
271
-
272
- # Handle liking a tweet - calls server walker directly
273
- # The compiler automatically transforms this to __jacCallFunction at compile time!
274
- cl async def like_tweet_action(
275
- tweet_id: str
276
- ) -> any {
277
- try {
278
- result = await like_tweet(tweet_id);
279
- print("Tweet liked:", result);
280
- # Re-render feed after like
281
- window.location.reload();
282
- } except Exception as e {
283
- print("Error liking tweet:", e);
284
- }
285
- }
286
-
287
- # Render the main feed view
288
- cl def FeedView(tweets: list) -> any {
289
- return <div
290
- class="feed-container"
291
- style={{"maxWidth": "600px", "margin": "0 auto", "fontFamily": "sans-serif"}}
292
- >
293
- <div
294
- class="feed-header"
295
- style={{"padding": "20px", "borderBottom": "1px solid #e1e8ed"}}
296
- >
297
- <h1
298
- style={{"margin": "0"}}
299
- >
300
- LittleX Feed
301
- </h1>
302
- </div>
303
- <div class="feed-content">
304
- {[TweetCard(tweet) for tweet in tweets]}
305
- </div>
306
- </div>;
307
- }
308
-
309
- # Render login form
310
- cl def LoginForm() -> any {
311
- suggestions = ['good luck', 'have fun', 'enjoy the ride'];
312
- randomSuggestion = _.sample(suggestions);
313
- result = "Good luck with your journey!";
314
- return <Card
315
- title="Login to LittleX"
316
- style={{"maxWidth": "400px", "margin": "50px auto"}}
317
- >
318
- <Card.Meta
319
- title={randomSuggestion}
320
- description={result}
321
- />
322
- <form
323
- onSubmit={handle_login}
324
- >
325
- <div
326
- style={{"marginBottom": "15px"}}
327
- >
328
- <label
329
- style={{"display": "block", "marginBottom": "5px"}}
330
- >
331
- Username:
332
- </label>
333
- <input
334
- type="text"
335
- id="username"
336
- style={{
337
- "width": "100%",
338
- "padding": "8px",
339
- "boxSizing": "border-box"
340
- }}
341
- />
342
- </div>
343
- <div
344
- style={{"marginBottom": "15px"}}
345
- >
346
- <label
347
- style={{"display": "block", "marginBottom": "5px"}}
348
- >
349
- Password:
350
- </label>
351
- <input
352
- type="password"
353
- id="password"
354
- style={{
355
- "width": "100%",
356
- "padding": "8px",
357
- "boxSizing": "border-box"
358
- }}
359
- />
360
- </div>
361
- <Button
362
- htmlType="submit"
363
- style={{
364
- "width": "100%",
365
- "padding": "10px",
366
- "backgroundColor": "#1da1f2",
367
- "color": "white",
368
- "border": "none",
369
- "borderRadius": "4px",
370
- "cursor": "pointer"
371
- }}
372
- >
373
- Login
374
- </Button>
375
- <Button
376
- color="default"
377
- variant="dashed"
378
- >
379
- Dashed
380
- </Button>
381
- <Button
382
- color="default"
383
- variant="filled"
384
- >
385
- Filled
386
- </Button>
387
- <Button
388
- color="default"
389
- variant="text"
390
- >
391
- Text
392
- </Button>
393
- <Button
394
- color="default"
395
- variant="link"
396
- >
397
- Link
398
- </Button>
399
- </form>
400
- <div
401
- style={{"marginTop": "15px", "textAlign": "center"}}
402
- >
403
- <Link href="/signup">
404
- Don't have an account? Sign up
405
- </Link>
406
- </div>
407
- </Card>;
408
- }
409
-
410
- # Handle login form submission
411
- cl async def handle_login(event: any) -> None {
412
- event.preventDefault();
413
- username = document.getElementById("username").value;
414
- password = document.getElementById("password").value;
415
- success = await jacLogin(username, password);
416
- if success {
417
- navigate("/home");
418
- } else {
419
- alert("Login failed. Please try again.");
420
- }
421
- }
422
-
423
- # Render signup form
424
- cl def SignupForm() -> any {
425
- return <div
426
- class="signup-container"
427
- style={{
428
- "maxWidth": "400px",
429
- "margin": "50px auto",
430
- "padding": "20px",
431
- "border": "1px solid #e1e8ed",
432
- "borderRadius": "8px",
433
- "fontFamily": "sans-serif"
434
- }}
435
- >
436
- <Typography.Title
437
- level={2}
438
- style={{"marginTop": "0"}}
439
- >
440
- Sign Up for LittleX
441
- </Typography.Title>
442
- <form
443
- onSubmit={handle_signup}
444
- >
445
- <div
446
- style={{"marginBottom": "15px"}}
447
- >
448
- <label
449
- style={{"display": "block", "marginBottom": "5px"}}
450
- >
451
- Username:
452
- </label>
453
- <input
454
- type="text"
455
- id="signup-username"
456
- required
457
- style={{
458
- "width": "100%",
459
- "padding": "8px",
460
- "boxSizing": "border-box"
461
- }}
462
- />
463
- </div>
464
- <div
465
- style={{"marginBottom": "15px"}}
466
- >
467
- <label
468
- style={{"display": "block", "marginBottom": "5px"}}
469
- >
470
- Password:
471
- </label>
472
- <input
473
- type="password"
474
- id="signup-password"
475
- required
476
- style={{
477
- "width": "100%",
478
- "padding": "8px",
479
- "boxSizing": "border-box"
480
- }}
481
- />
482
- </div>
483
- <div
484
- style={{"marginBottom": "15px"}}
485
- >
486
- <label
487
- style={{"display": "block", "marginBottom": "5px"}}
488
- >
489
- Confirm Password:
490
- </label>
491
- <input
492
- type="password"
493
- id="signup-password-confirm"
494
- required
495
- style={{
496
- "width": "100%",
497
- "padding": "8px",
498
- "boxSizing": "border-box"
499
- }}
500
- />
501
- </div>
502
- <button
503
- type="submit"
504
- style={{
505
- "width": "100%",
506
- "padding": "10px",
507
- "backgroundColor": "#1da1f2",
508
- "color": "white",
509
- "border": "none",
510
- "borderRadius": "4px",
511
- "cursor": "pointer"
512
- }}
513
- >
514
- Sign Up
515
- </button>
516
- </form>
517
- <div
518
- style={{"marginTop": "15px", "textAlign": "center"}}
519
- >
520
- <Link href="/login">
521
- Already have an account? Login
522
- </Link>
523
- </div>
524
- </div>;
525
- }
526
-
527
- # Navigation helper functions removed - using Link component and navigate() directly
528
-
529
- # Handle signup form submission
530
- cl async def handle_signup(event: any) -> None {
531
- event.preventDefault();
532
- username = document.getElementById("signup-username").value;
533
- password = document.getElementById("signup-password").value;
534
- password_confirm = document.getElementById("signup-password-confirm").value;
535
- # Client-side validation
536
- if password != password_confirm {
537
- alert("Passwords do not match!");
538
- return;
539
- }
540
- if username.length < 3 {
541
- alert("Username must be at least 3 characters long.");
542
- return;
543
- }
544
- if password.length < 6 {
545
- alert("Password must be at least 6 characters long.");
546
- return;
547
- }
548
- # Use runtime auth function - no need to know about /user/create endpoint!
549
- result = await jacSignup(username, password);
550
- if result["success"] if "success" in result else False {
551
- alert("Account created successfully! Welcome to LittleX!");
552
- navigate("/home");
553
- } else {
554
- alert(result["error"] if "error" in result else "Signup failed");
555
- }
556
- }
557
-
558
- # Handle logout
559
- cl def logout_action() -> None {
560
- jacLogout();
561
- navigate("/login");
562
- }
563
-
564
- # Main App component with declarative router
565
- cl def App() -> any {
566
- # Create routes array manually (workaround for JS compiler bug with named args)
567
- login_route = {
568
- "path": "/login",
569
- "component": lambda -> any{ return LoginForm(); } ,
570
- "guard": None
571
- };
572
- signup_route = {
573
- "path": "/signup",
574
- "component": lambda -> any{ return SignupForm(); } ,
575
- "guard": None
576
- };
577
- home_route = {
578
- "path": "/home",
579
- "component": lambda -> any{ return HomeView(); } ,
580
- "guard": jacIsLoggedIn
581
- };
582
- profile_route = {
583
- "path": "/profile",
584
- "component": lambda -> any{ return ProfileView(); } ,
585
- "guard": jacIsLoggedIn
586
- };
587
-
588
- routes = [login_route, signup_route, home_route, profile_route];
589
- router = initRouter(routes, "/login");
590
-
591
- # Get current path for navbar
592
- currentPath = router.path();
593
-
594
- return <div class="app-container">
595
- {build_nav_bar(currentPath)}
596
- <Rotate>
597
- <span>
598
- 😂
599
- </span>
600
- </Rotate>
601
- {router.render()}
602
- </div>;
603
- }
604
-
605
- # Helper to build navigation bar
606
- cl def build_nav_bar(route: str) -> any {
607
- if not jacIsLoggedIn() or route == "/login" or route == "/signup" {
608
- return None;
609
- }
610
- return <nav
611
- style={{
612
- "backgroundColor": "#1da1f2",
613
- "padding": "15px",
614
- "marginBottom": "20px"
615
- }}
616
- >
617
- <div
618
- style={{
619
- "maxWidth": "600px",
620
- "margin": "0 auto",
621
- "display": "flex",
622
- "gap": "20px",
623
- "alignItems": "center"
624
- }}
625
- >
626
- <Link href="/home">
627
- <span
628
- style={{
629
- "color": "white",
630
- "textDecoration": "none",
631
- "fontWeight": "bold"
632
- }}
633
- >
634
- Home
635
- </span>
636
- </Link>
637
- <Link href="/profile">
638
- <span
639
- style={{
640
- "color": "white",
641
- "textDecoration": "none",
642
- "fontWeight": "bold"
643
- }}
644
- >
645
- Profile
646
- </span>
647
- </Link>
648
- <button
649
- onClick={logout_action}
650
- style={{
651
- "marginLeft": "auto",
652
- "padding": "5px 15px",
653
- "backgroundColor": "white",
654
- "color": "#1da1f2",
655
- "border": "none",
656
- "borderRadius": "4px",
657
- "cursor": "pointer",
658
- "fontWeight": "bold"
659
- }}
660
- >
661
- Logout
662
- </button>
663
- </div>
664
- </nav>;
665
- }
666
-
667
- # Home view - simplified for testing reactive routing
668
- cl def HomeView() -> any {
669
- if not jacIsLoggedIn() {
670
- navigate("/login");
671
- return <div></div>;
672
- }
673
-
674
- return <div
675
- style={{"textAlign": "center", "padding": "50px", "fontFamily": "sans-serif"}}
676
- >
677
- <h1>
678
- Home Feed
679
- </h1>
680
- <p>
681
- Welcome to LittleX! This is the home page.
682
- </p>
683
- <p>
684
- The reactive router is working!
685
- </p>
686
- </div>;
687
- }
688
-
689
- # Profile view
690
- cl def ProfileView() -> any {
691
- if not jacIsLoggedIn() {
692
- navigate("/login");
693
- return <div></div>;
694
- }
695
- return <div
696
- class="profile-container"
697
- style={{
698
- "maxWidth": "600px",
699
- "margin": "20px auto",
700
- "padding": "20px",
701
- "fontFamily": "sans-serif"
702
- }}
703
- >
704
- <h1>
705
- Profile
706
- </h1>
707
- <div
708
- style={{
709
- "padding": "15px",
710
- "border": "1px solid #e1e8ed",
711
- "borderRadius": "8px"
712
- }}
713
- >
714
- <p>
715
- Profile information will be displayed here.
716
- </p>
717
- </div>
718
- </div>;
719
- }
720
-
721
- # Main SPA entry point - simplified with reactive routing
722
- cl def jac_app() -> any {
723
- return App();
724
- }