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,116 @@
1
+ # Custom hook for budget operations
2
+ # Demonstrates: custom hooks, useState, array methods
3
+
4
+ cl import from react { useCallback, useMemo }
5
+
6
+ cl {
7
+ # Main budget management hook
8
+ def:pub useBudget() -> dict {
9
+ # Simple useState - no complex localStorage hook
10
+ [transactions, setTransactions] = useState([]);
11
+
12
+ # Add a new transaction
13
+ def addTransaction(description: str, amount: float, category: str, txType: str, isBusiness: bool, clientName: str) -> None {
14
+ newTx = {
15
+ "id": Date.now().toString(),
16
+ "description": description,
17
+ "amount": amount,
18
+ "category": category,
19
+ "type": txType,
20
+ "date": Reflect.construct(Date, []).toISOString(),
21
+ "isBusinessTransaction": isBusiness,
22
+ "clientName": clientName if clientName != "" else None
23
+ };
24
+ setTransactions(transactions.concat([newTx]));
25
+ }
26
+
27
+ # Delete a transaction by ID
28
+ def deleteTransaction(id: str) -> None {
29
+ filtered = transactions.filter(lambda tx: dict -> bool {
30
+ return tx["id"] != id;
31
+ });
32
+ setTransactions(filtered);
33
+ }
34
+
35
+ # Calculate totals
36
+ totalIncome = 0.0;
37
+ totalExpenses = 0.0;
38
+ for tx in transactions {
39
+ if tx["type"] == "income" {
40
+ totalIncome = totalIncome + tx["amount"];
41
+ } else {
42
+ totalExpenses = totalExpenses + tx["amount"];
43
+ }
44
+ }
45
+ balance = totalIncome - totalExpenses;
46
+
47
+ # Calculate business/personal breakdown
48
+ businessIncome = 0.0;
49
+ businessExpenses = 0.0;
50
+ personalIncome = 0.0;
51
+ personalExpenses = 0.0;
52
+
53
+ for tx in transactions {
54
+ isBusiness = tx["isBusinessTransaction"] || false;
55
+ amount = tx["amount"];
56
+
57
+ if tx["type"] == "income" {
58
+ if isBusiness {
59
+ businessIncome = businessIncome + amount;
60
+ } else {
61
+ personalIncome = personalIncome + amount;
62
+ }
63
+ } else {
64
+ if isBusiness {
65
+ businessExpenses = businessExpenses + amount;
66
+ } else {
67
+ personalExpenses = personalExpenses + amount;
68
+ }
69
+ }
70
+ }
71
+
72
+ # Tax calculations
73
+ TAX_RATE = 0.20;
74
+ taxReserve = businessIncome * TAX_RATE;
75
+ netProfit = businessIncome - businessExpenses - taxReserve;
76
+
77
+ # Get expense breakdown by category (for chart)
78
+ def getExpensesByCategory() -> list {
79
+ categoryTotals = {};
80
+ for tx in transactions {
81
+ if tx["type"] == "expense" {
82
+ cat = tx["category"];
83
+ if categoryTotals[cat] {
84
+ categoryTotals[cat] = categoryTotals[cat] + tx["amount"];
85
+ } else {
86
+ categoryTotals[cat] = tx["amount"];
87
+ }
88
+ }
89
+ }
90
+ result = [];
91
+ for key in Object.keys(categoryTotals) {
92
+ result = result.concat([{
93
+ "name": key,
94
+ "value": categoryTotals[key]
95
+ }]);
96
+ }
97
+ return result;
98
+ }
99
+
100
+ return {
101
+ "transactions": transactions,
102
+ "addTransaction": addTransaction,
103
+ "deleteTransaction": deleteTransaction,
104
+ "totalIncome": totalIncome,
105
+ "totalExpenses": totalExpenses,
106
+ "balance": balance,
107
+ "expensesByCategory": getExpensesByCategory(),
108
+ "businessIncome": businessIncome,
109
+ "businessExpenses": businessExpenses,
110
+ "personalIncome": personalIncome,
111
+ "personalExpenses": personalExpenses,
112
+ "taxReserve": taxReserve,
113
+ "netProfit": netProfit
114
+ };
115
+ }
116
+ }
@@ -0,0 +1,36 @@
1
+ # Custom hook for localStorage persistence
2
+ # Demonstrates: custom hooks, try/except error handling, useEffect
3
+
4
+ cl import from react { useEffect }
5
+
6
+ cl {
7
+ # Custom hook for syncing state with localStorage
8
+ def useLocalStorage(key: str, initialValue: list) -> list {
9
+ # Initialize state with value from localStorage or default
10
+ [storedValue, setStoredValue] = useState(lambda -> any {
11
+ try {
12
+ item = window.localStorage.getItem(key);
13
+ if item {
14
+ return JSON.parse(item);
15
+ }else{
16
+ return initialValue;
17
+ }
18
+
19
+ } except Exception as e {
20
+ console.log("Error reading from localStorage");
21
+ return initialValue;
22
+ }
23
+ });
24
+
25
+ # Update localStorage when state changes
26
+ useEffect(lambda -> None {
27
+ try {
28
+ window.localStorage.setItem(key, JSON.stringify(storedValue));
29
+ } except Exception as e {
30
+ console.log("Error saving to localStorage");
31
+ }
32
+ }, [key, storedValue]);
33
+
34
+ return [storedValue, setStoredValue];
35
+ }
36
+ }
@@ -0,0 +1,70 @@
1
+ # Budget Planner Page
2
+ # Main application page with budget tracking features
3
+
4
+ # Local JAC file imports
5
+ cl import from ..context.BudgetContext { useBudgetContext }
6
+ cl import from ..components.Header { Header }
7
+ cl import from ..components.Summary { Summary }
8
+ cl import from ..components.ProfitOverview { ProfitOverview }
9
+ cl import from ..components.TransactionForm { TransactionForm }
10
+ cl import from ..components.TransactionList { TransactionList }
11
+ cl import from ..components.CategoryFilter { CategoryFilter }
12
+ cl import from ..constants.categories { CATEGORY_COLORS }
13
+
14
+ # cl import from "..components.PieChart.tsx" { PieChart }
15
+
16
+
17
+ cl def:pub BudgetPlanner() -> any {
18
+ [filter, setFilter] = useState("ALL");
19
+ budget = useBudgetContext();
20
+
21
+ # Filter transactions based on selected category
22
+ filtered = budget["transactions"];
23
+ if filter != "ALL" {
24
+ filtered = filtered.filter(lambda tx: dict -> bool {
25
+ return tx["category"] == filter;
26
+ });
27
+ }
28
+
29
+ # Sort by date (newest first)
30
+ sorted = filtered.slice().sort(lambda a: dict, b: dict -> int {
31
+ return Reflect.construct(Date, [b["date"]]).getTime() - Reflect.construct(Date, [a["date"]]).getTime();
32
+ });
33
+
34
+ # Prepare chart data with colors
35
+ chartData = budget["expensesByCategory"].map(lambda item: dict -> dict {
36
+ return {
37
+ "name": item["name"],
38
+ "value": item["value"],
39
+ "color": CATEGORY_COLORS[item["name"]]
40
+ };
41
+ });
42
+
43
+ return <div className="app-container">
44
+ <Header />
45
+
46
+ <main className="main-content">
47
+ <div className="left-panel">
48
+ <Summary />
49
+ <ProfitOverview />
50
+ <TransactionForm />
51
+ <CategoryFilter
52
+ selectedCategory={filter}
53
+ onSelect={setFilter}
54
+ />
55
+ <TransactionList
56
+ transactions={sorted}
57
+ onDelete={budget["deleteTransaction"]}
58
+ />
59
+ </div>
60
+
61
+ <div className="right-panel">
62
+ # <PieChart
63
+ # data={chartData}
64
+ # title="Expense Breakdown"
65
+ # colors={CATEGORY_COLORS}
66
+ # />
67
+ </div>
68
+ </main>
69
+ </div>;
70
+ }
@@ -0,0 +1,126 @@
1
+ # Features Test Page - Backend Logic
2
+ # This file is intentionally kept empty to demonstrate the separation of concerns
3
+ # where UI logic resides in .cl.jac files and backend walker logic in app.jac
4
+
5
+ # All walker implementations for this feature are in src/app.jac
6
+ # This demonstrates that you can have separate .jac files for different purposes
7
+ # Features Test - Backend Walkers
8
+ # This file demonstrates walker functionality for testing various JAC features
9
+
10
+ import from datetime { datetime, timedelta }
11
+
12
+ # Node definition for storing test data
13
+ node TestData {
14
+ has message: str;
15
+ has count: int = 0;
16
+ has created_at: str = "";
17
+ }
18
+
19
+ # Walker: Create test data
20
+ walker create_test_data {
21
+ has message: str;
22
+
23
+ can create with `root entry {
24
+ new_data = here ++> TestData(
25
+ message=self.message,
26
+ count=1,
27
+ created_at=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
28
+ );
29
+ report new_data;
30
+ }
31
+ }
32
+
33
+ # Walker: Read all test data
34
+ walker read_test_data {
35
+ can read with `root entry {
36
+ visit [-->(`?TestData)];
37
+ }
38
+
39
+ can report_data with exit {
40
+ report here;
41
+ }
42
+ }
43
+
44
+ # Walker: Update test data
45
+ walker update_test_data {
46
+ has new_message: str;
47
+
48
+ can update with TestData entry {
49
+ here.message = self.new_message;
50
+ here.count = here.count + 1;
51
+ report here;
52
+ }
53
+ }
54
+
55
+ # Walker: Delete test data
56
+ walker delete_test_data {
57
+ can delete with TestData entry {
58
+ del here;
59
+ report {"status": "deleted"};
60
+ }
61
+ }
62
+
63
+ # Walker: String manipulation test
64
+ walker test_string_methods {
65
+ has input_text: str;
66
+
67
+ can process with `root entry {
68
+ result = {
69
+ "original": self.input_text,
70
+ "uppercase": self.input_text.upper(),
71
+ "lowercase": self.input_text.lower(),
72
+ "capitalized": self.input_text.capitalize(),
73
+ "reversed": self.input_text[::-1],
74
+ "length": len(self.input_text),
75
+ "words": self.input_text.split(),
76
+ "trimmed": self.input_text.strip(),
77
+ "replaced": self.input_text.replace("test", "demo")
78
+ };
79
+ report result;
80
+ }
81
+ }
82
+
83
+ # Walker: Array/List operations test
84
+ walker test_list_operations {
85
+ has numbers: list;
86
+
87
+ can process with `root entry {
88
+ result = {
89
+ "original": self.numbers,
90
+ "sorted": sorted(self.numbers),
91
+ "reversed": list(reversed(self.numbers)),
92
+ "sum": sum(self.numbers),
93
+ "max": max(self.numbers) if len(self.numbers) > 0 else 0,
94
+ "min": min(self.numbers) if len(self.numbers) > 0 else 0,
95
+ "length": len(self.numbers),
96
+ "doubled": [x * 2 for x in self.numbers]
97
+ };
98
+ report result;
99
+ }
100
+ }
101
+
102
+ # Walker: Complex data processing
103
+ walker process_complex_data {
104
+ has items: list;
105
+
106
+ can process with `root entry {
107
+ processed = [];
108
+ for item in self.items {
109
+ processed.append({
110
+ "id": item.get("id", 0),
111
+ "name": item.get("name", "").upper(),
112
+ "value": item.get("value", 0) * 2,
113
+ "processed_at": datetime.now().strftime("%H:%M:%S")
114
+ });
115
+ }
116
+
117
+ result = {
118
+ "original_count": len(self.items),
119
+ "processed_count": len(processed),
120
+ "items": processed,
121
+ "total_value": sum([p["value"] for p in processed])
122
+ };
123
+
124
+ report result;
125
+ }
126
+ }