jac-client 0.2.3__tar.gz → 0.2.9__tar.gz
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.
- {jac_client-0.2.3 → jac_client-0.2.9}/PKG-INFO +41 -34
- {jac_client-0.2.3 → jac_client-0.2.9}/README.md +29 -17
- jac_client-0.2.9/jac_client/examples/all-in-one/assets/workers/worker.py +5 -0
- {jac_client-0.2.3 → jac_client-0.2.9}/jac_client/examples/all-in-one/button.jac +1 -1
- jac_client-0.2.9/jac_client/examples/all-in-one/components/CategoryFilter.jac +35 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/components/Header.jac +13 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/components/ProfitOverview.jac +50 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/components/Summary.jac +53 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/components/TransactionForm.jac +158 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/components/TransactionItem.jac +55 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/components/TransactionList.jac +37 -0
- {jac_client-0.2.3 → jac_client-0.2.9}/jac_client/examples/all-in-one/components/button.jac +1 -1
- jac_client-0.2.9/jac_client/examples/all-in-one/components/navigation.jac +132 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/constants/categories.jac +37 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/constants/clients.jac +13 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/context/BudgetContext.jac +28 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/hooks/useBudget.jac +116 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/hooks/useLocalStorage.jac +36 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/main.jac +573 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/pages/BudgetPlanner.jac +133 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/pages/FeaturesTest.jac +141 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/pages/LandingPage.jac +101 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/pages/budget_planner_ui.cl.jac +70 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/pages/features_test_ui.cl.jac +563 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/pages/loginPage.jac +132 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/pages/nestedDemo.jac +61 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/pages/notFound.jac +19 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/pages/signupPage.jac +133 -0
- jac_client-0.2.9/jac_client/examples/all-in-one/utils/formatters.jac +52 -0
- jac_client-0.2.3/jac_client/examples/asset-serving/css-with-image/app.jac → jac_client-0.2.9/jac_client/examples/asset-serving/css-with-image/main.jac +4 -4
- jac_client-0.2.3/jac_client/examples/asset-serving/image-asset/app.jac → jac_client-0.2.9/jac_client/examples/asset-serving/image-asset/main.jac +4 -4
- jac_client-0.2.3/jac_client/examples/asset-serving/import-alias/app.jac → jac_client-0.2.9/jac_client/examples/asset-serving/import-alias/main.jac +5 -5
- jac_client-0.2.3/jac_client/examples/basic/app.jac → jac_client-0.2.9/jac_client/examples/basic/main.jac +4 -4
- jac_client-0.2.9/jac_client/examples/basic-auth/main.jac +371 -0
- jac_client-0.2.3/jac_client/examples/basic-auth-with-router/app.jac → jac_client-0.2.9/jac_client/examples/basic-auth-with-router/main.jac +28 -28
- jac_client-0.2.3/jac_client/examples/basic-full-stack/app.jac → jac_client-0.2.9/jac_client/examples/basic-full-stack/main.jac +166 -127
- jac_client-0.2.3/jac_client/examples/css-styling/js-styling/app.jac → jac_client-0.2.9/jac_client/examples/css-styling/js-styling/main.jac +7 -7
- jac_client-0.2.3/jac_client/examples/css-styling/material-ui/app.jac → jac_client-0.2.9/jac_client/examples/css-styling/material-ui/main.jac +6 -6
- jac_client-0.2.3/jac_client/examples/css-styling/pure-css/app.jac → jac_client-0.2.9/jac_client/examples/css-styling/pure-css/main.jac +7 -7
- jac_client-0.2.3/jac_client/examples/css-styling/sass-example/app.jac → jac_client-0.2.9/jac_client/examples/css-styling/sass-example/main.jac +7 -7
- jac_client-0.2.3/jac_client/examples/css-styling/styled-components/app.jac → jac_client-0.2.9/jac_client/examples/css-styling/styled-components/main.jac +6 -6
- jac_client-0.2.3/jac_client/examples/css-styling/tailwind-example/app.jac → jac_client-0.2.9/jac_client/examples/css-styling/tailwind-example/main.jac +7 -7
- jac_client-0.2.3/jac_client/examples/full-stack-with-auth/app.jac → jac_client-0.2.9/jac_client/examples/full-stack-with-auth/main.jac +47 -47
- jac_client-0.2.3/jac_client/examples/little-x/app.jac → jac_client-0.2.9/jac_client/examples/little-x/main.jac +27 -32
- jac_client-0.2.9/jac_client/examples/little-x/src/submit-button.jac +16 -0
- jac_client-0.2.3/jac_client/examples/nested-folders/nested-advance/app.jac → jac_client-0.2.9/jac_client/examples/nested-folders/nested-advance/main.jac +1 -1
- {jac_client-0.2.3/jac_client/examples/nested-folders/nested-advance → jac_client-0.2.9/jac_client/examples/nested-folders/nested-advance/src}/ButtonRoot.jac +1 -1
- {jac_client-0.2.3/jac_client/examples/nested-folders/nested-advance → jac_client-0.2.9/jac_client/examples/nested-folders/nested-advance/src}/level1/ButtonSecondL.jac +1 -1
- {jac_client-0.2.3/jac_client/examples/nested-folders/nested-advance → jac_client-0.2.9/jac_client/examples/nested-folders/nested-advance/src}/level1/Card.jac +1 -1
- {jac_client-0.2.3/jac_client/examples/nested-folders/nested-advance → jac_client-0.2.9/jac_client/examples/nested-folders/nested-advance/src}/level1/level2/ButtonThirdL.jac +1 -1
- jac_client-0.2.3/jac_client/examples/nested-folders/nested-basic/app.jac → jac_client-0.2.9/jac_client/examples/nested-folders/nested-basic/main.jac +2 -2
- {jac_client-0.2.3/jac_client/examples/nested-folders/nested-basic → jac_client-0.2.9/jac_client/examples/nested-folders/nested-basic/src}/button.jac +1 -1
- {jac_client-0.2.3/jac_client/tests/fixtures/relative_import → jac_client-0.2.9/jac_client/examples/nested-folders/nested-basic/src/components}/button.jac +1 -1
- jac_client-0.2.9/jac_client/examples/ts-support/main.jac +35 -0
- jac_client-0.2.3/jac_client/examples/with-router/app.jac → jac_client-0.2.9/jac_client/examples/with-router/main.jac +15 -15
- jac_client-0.2.9/jac_client/plugin/cli.jac +231 -0
- jac_client-0.2.9/jac_client/plugin/client.jac +70 -0
- jac_client-0.2.9/jac_client/plugin/client_runtime.cl.jac +46 -0
- jac_client-0.2.9/jac_client/plugin/impl/client.impl.jac +234 -0
- jac_client-0.2.9/jac_client/plugin/impl/client_runtime.impl.jac +349 -0
- jac_client-0.2.9/jac_client/plugin/impl/vite_client_bundle.impl.jac +72 -0
- jac_client-0.2.9/jac_client/plugin/plugin_config.jac +423 -0
- jac_client-0.2.9/jac_client/plugin/src/__init__.jac +20 -0
- jac_client-0.2.9/jac_client/plugin/src/asset_processor.jac +33 -0
- jac_client-0.2.9/jac_client/plugin/src/babel_processor.jac +18 -0
- jac_client-0.2.9/jac_client/plugin/src/compiler.jac +67 -0
- jac_client-0.2.9/jac_client/plugin/src/config_loader.jac +33 -0
- jac_client-0.2.9/jac_client/plugin/src/impl/asset_processor.impl.jac +127 -0
- jac_client-0.2.9/jac_client/plugin/src/impl/babel_processor.impl.jac +89 -0
- jac_client-0.2.9/jac_client/plugin/src/impl/compiler.impl.jac +288 -0
- jac_client-0.2.9/jac_client/plugin/src/impl/config_loader.impl.jac +127 -0
- jac_client-0.2.9/jac_client/plugin/src/impl/import_processor.impl.jac +33 -0
- jac_client-0.2.9/jac_client/plugin/src/impl/jac_to_js.impl.jac +41 -0
- jac_client-0.2.9/jac_client/plugin/src/impl/package_installer.impl.jac +105 -0
- jac_client-0.2.9/jac_client/plugin/src/impl/vite_bundler.impl.jac +707 -0
- jac_client-0.2.9/jac_client/plugin/src/import_processor.jac +19 -0
- jac_client-0.2.9/jac_client/plugin/src/jac_to_js.jac +35 -0
- jac_client-0.2.9/jac_client/plugin/src/package_installer.jac +26 -0
- jac_client-0.2.9/jac_client/plugin/src/vite_bundler.jac +50 -0
- jac_client-0.2.9/jac_client/plugin/utils/__init__.jac +1 -0
- jac_client-0.2.9/jac_client/plugin/utils/impl/node_installer.impl.jac +249 -0
- jac_client-0.2.9/jac_client/plugin/utils/node_installer.jac +41 -0
- jac_client-0.2.9/jac_client/plugin/vite_client_bundle.jac +31 -0
- jac_client-0.2.9/jac_client/templates/client.jacpack +72 -0
- jac_client-0.2.9/jac_client/templates/fullstack.jacpack +61 -0
- jac_client-0.2.9/jac_client/tests/conftest.py +324 -0
- {jac_client-0.2.3 → jac_client-0.2.9}/jac_client/tests/fixtures/basic-app/app.jac +2 -2
- {jac_client-0.2.3 → jac_client-0.2.9}/jac_client/tests/fixtures/cl_file/app.cl.jac +2 -2
- {jac_client-0.2.3 → jac_client-0.2.9}/jac_client/tests/fixtures/client_app_with_antd/app.jac +1 -1
- {jac_client-0.2.3 → jac_client-0.2.9}/jac_client/tests/fixtures/js_import/app.jac +5 -5
- {jac_client-0.2.3 → jac_client-0.2.9}/jac_client/tests/fixtures/spawn_test/app.jac +15 -18
- jac_client-0.2.9/jac_client/tests/fixtures/with-ts/app.jac +35 -0
- jac_client-0.2.9/jac_client/tests/test_cli.py +925 -0
- jac_client-0.2.9/jac_client/tests/test_e2e.py +232 -0
- jac_client-0.2.9/jac_client/tests/test_helpers.py +65 -0
- jac_client-0.2.9/jac_client/tests/test_it.py +780 -0
- jac_client-0.2.9/jac_client.egg-info/PKG-INFO +197 -0
- jac_client-0.2.9/jac_client.egg-info/SOURCES.txt +107 -0
- jac_client-0.2.9/jac_client.egg-info/dependency_links.txt +1 -0
- jac_client-0.2.9/jac_client.egg-info/entry_points.txt +4 -0
- jac_client-0.2.9/jac_client.egg-info/requires.txt +5 -0
- jac_client-0.2.9/jac_client.egg-info/top_level.txt +1 -0
- jac_client-0.2.9/pyproject.toml +48 -0
- jac_client-0.2.9/setup.cfg +4 -0
- jac_client-0.2.3/jac_client/docs/README.md +0 -689
- jac_client-0.2.3/jac_client/docs/advanced-state.md +0 -1265
- jac_client-0.2.3/jac_client/docs/asset-serving/intro.md +0 -209
- jac_client-0.2.3/jac_client/docs/assets/pipe_line-v2.svg +0 -32
- jac_client-0.2.3/jac_client/docs/assets/pipe_line.png +0 -0
- jac_client-0.2.3/jac_client/docs/file-system/app.jac.md +0 -121
- jac_client-0.2.3/jac_client/docs/file-system/backend-frontend.md +0 -217
- jac_client-0.2.3/jac_client/docs/file-system/intro.md +0 -72
- jac_client-0.2.3/jac_client/docs/file-system/nested-imports.md +0 -348
- jac_client-0.2.3/jac_client/docs/guide-example/intro.md +0 -115
- jac_client-0.2.3/jac_client/docs/guide-example/step-01-setup.md +0 -270
- jac_client-0.2.3/jac_client/docs/guide-example/step-02-components.md +0 -416
- jac_client-0.2.3/jac_client/docs/guide-example/step-03-styling.md +0 -478
- jac_client-0.2.3/jac_client/docs/guide-example/step-04-todo-ui.md +0 -477
- jac_client-0.2.3/jac_client/docs/guide-example/step-05-local-state.md +0 -530
- jac_client-0.2.3/jac_client/docs/guide-example/step-06-events.md +0 -749
- jac_client-0.2.3/jac_client/docs/guide-example/step-07-effects.md +0 -468
- jac_client-0.2.3/jac_client/docs/guide-example/step-08-walkers.md +0 -534
- jac_client-0.2.3/jac_client/docs/guide-example/step-09-authentication.md +0 -586
- jac_client-0.2.3/jac_client/docs/guide-example/step-10-routing.md +0 -539
- jac_client-0.2.3/jac_client/docs/guide-example/step-11-final.md +0 -963
- jac_client-0.2.3/jac_client/docs/imports.md +0 -1141
- jac_client-0.2.3/jac_client/docs/lifecycle-hooks.md +0 -773
- jac_client-0.2.3/jac_client/docs/routing.md +0 -659
- jac_client-0.2.3/jac_client/docs/styling/intro.md +0 -249
- jac_client-0.2.3/jac_client/docs/styling/js-styling.md +0 -367
- jac_client-0.2.3/jac_client/docs/styling/material-ui.md +0 -341
- jac_client-0.2.3/jac_client/docs/styling/pure-css.md +0 -299
- jac_client-0.2.3/jac_client/docs/styling/sass.md +0 -403
- jac_client-0.2.3/jac_client/docs/styling/styled-components.md +0 -395
- jac_client-0.2.3/jac_client/docs/styling/tailwind.md +0 -298
- jac_client-0.2.3/jac_client/examples/all-in-one/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/all-in-one/README.md +0 -16
- jac_client-0.2.3/jac_client/examples/all-in-one/app.jac +0 -426
- jac_client-0.2.3/jac_client/examples/all-in-one/assets/burger.png +0 -0
- jac_client-0.2.3/jac_client/examples/all-in-one/package.json +0 -29
- jac_client-0.2.3/jac_client/examples/all-in-one/styles.css +0 -26
- jac_client-0.2.3/jac_client/examples/all-in-one/vite.config.js +0 -28
- jac_client-0.2.3/jac_client/examples/asset-serving/css-with-image/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/asset-serving/css-with-image/README.md +0 -91
- jac_client-0.2.3/jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
- jac_client-0.2.3/jac_client/examples/asset-serving/css-with-image/package.json +0 -28
- jac_client-0.2.3/jac_client/examples/asset-serving/css-with-image/styles.css +0 -26
- jac_client-0.2.3/jac_client/examples/asset-serving/css-with-image/vite.config.js +0 -28
- jac_client-0.2.3/jac_client/examples/asset-serving/image-asset/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/asset-serving/image-asset/README.md +0 -119
- jac_client-0.2.3/jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
- jac_client-0.2.3/jac_client/examples/asset-serving/image-asset/package.json +0 -28
- jac_client-0.2.3/jac_client/examples/asset-serving/image-asset/styles.css +0 -26
- jac_client-0.2.3/jac_client/examples/asset-serving/image-asset/vite.config.js +0 -28
- jac_client-0.2.3/jac_client/examples/asset-serving/import-alias/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/asset-serving/import-alias/README.md +0 -83
- jac_client-0.2.3/jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
- jac_client-0.2.3/jac_client/examples/asset-serving/import-alias/package.json +0 -28
- jac_client-0.2.3/jac_client/examples/asset-serving/import-alias/vite.config.js +0 -28
- jac_client-0.2.3/jac_client/examples/basic/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/basic/README.md +0 -16
- jac_client-0.2.3/jac_client/examples/basic/package.json +0 -27
- jac_client-0.2.3/jac_client/examples/basic/vite.config.js +0 -27
- jac_client-0.2.3/jac_client/examples/basic-auth/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/basic-auth/README.md +0 -16
- jac_client-0.2.3/jac_client/examples/basic-auth/app.jac +0 -308
- jac_client-0.2.3/jac_client/examples/basic-auth/package.json +0 -27
- jac_client-0.2.3/jac_client/examples/basic-auth/vite.config.js +0 -27
- jac_client-0.2.3/jac_client/examples/basic-auth-with-router/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/basic-auth-with-router/README.md +0 -60
- jac_client-0.2.3/jac_client/examples/basic-auth-with-router/package.json +0 -28
- jac_client-0.2.3/jac_client/examples/basic-auth-with-router/vite.config.js +0 -27
- jac_client-0.2.3/jac_client/examples/basic-full-stack/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/basic-full-stack/README.md +0 -18
- jac_client-0.2.3/jac_client/examples/basic-full-stack/package.json +0 -28
- jac_client-0.2.3/jac_client/examples/basic-full-stack/vite.config.js +0 -27
- jac_client-0.2.3/jac_client/examples/css-styling/js-styling/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/css-styling/js-styling/README.md +0 -183
- jac_client-0.2.3/jac_client/examples/css-styling/js-styling/package.json +0 -28
- jac_client-0.2.3/jac_client/examples/css-styling/js-styling/styles.js +0 -100
- jac_client-0.2.3/jac_client/examples/css-styling/js-styling/vite.config.js +0 -27
- jac_client-0.2.3/jac_client/examples/css-styling/material-ui/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/css-styling/material-ui/README.md +0 -16
- jac_client-0.2.3/jac_client/examples/css-styling/material-ui/package.json +0 -32
- jac_client-0.2.3/jac_client/examples/css-styling/material-ui/vite.config.js +0 -27
- jac_client-0.2.3/jac_client/examples/css-styling/pure-css/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/css-styling/pure-css/README.md +0 -16
- jac_client-0.2.3/jac_client/examples/css-styling/pure-css/package.json +0 -28
- jac_client-0.2.3/jac_client/examples/css-styling/pure-css/styles.css +0 -111
- jac_client-0.2.3/jac_client/examples/css-styling/pure-css/vite.config.js +0 -27
- jac_client-0.2.3/jac_client/examples/css-styling/sass-example/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/css-styling/sass-example/README.md +0 -16
- jac_client-0.2.3/jac_client/examples/css-styling/sass-example/package.json +0 -29
- jac_client-0.2.3/jac_client/examples/css-styling/sass-example/styles.scss +0 -153
- jac_client-0.2.3/jac_client/examples/css-styling/sass-example/vite.config.js +0 -27
- jac_client-0.2.3/jac_client/examples/css-styling/styled-components/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/css-styling/styled-components/README.md +0 -16
- jac_client-0.2.3/jac_client/examples/css-styling/styled-components/package.json +0 -29
- jac_client-0.2.3/jac_client/examples/css-styling/styled-components/styled.js +0 -90
- jac_client-0.2.3/jac_client/examples/css-styling/styled-components/vite.config.js +0 -27
- jac_client-0.2.3/jac_client/examples/css-styling/tailwind-example/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/css-styling/tailwind-example/README.md +0 -16
- jac_client-0.2.3/jac_client/examples/css-styling/tailwind-example/global.css +0 -1
- jac_client-0.2.3/jac_client/examples/css-styling/tailwind-example/package.json +0 -30
- jac_client-0.2.3/jac_client/examples/css-styling/tailwind-example/vite.config.js +0 -29
- jac_client-0.2.3/jac_client/examples/full-stack-with-auth/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/full-stack-with-auth/README.md +0 -16
- jac_client-0.2.3/jac_client/examples/full-stack-with-auth/package.json +0 -28
- jac_client-0.2.3/jac_client/examples/full-stack-with-auth/vite.config.js +0 -29
- jac_client-0.2.3/jac_client/examples/little-x/package.json +0 -23
- jac_client-0.2.3/jac_client/examples/little-x/submit-button.jac +0 -8
- jac_client-0.2.3/jac_client/examples/nested-folders/nested-advance/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/nested-folders/nested-advance/README.md +0 -77
- jac_client-0.2.3/jac_client/examples/nested-folders/nested-advance/package.json +0 -29
- jac_client-0.2.3/jac_client/examples/nested-folders/nested-advance/vite.config.js +0 -28
- jac_client-0.2.3/jac_client/examples/nested-folders/nested-basic/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/nested-folders/nested-basic/README.md +0 -183
- jac_client-0.2.3/jac_client/examples/nested-folders/nested-basic/app.js +0 -7
- jac_client-0.2.3/jac_client/examples/nested-folders/nested-basic/package.json +0 -28
- jac_client-0.2.3/jac_client/examples/nested-folders/nested-basic/vite.config.js +0 -27
- jac_client-0.2.3/jac_client/examples/with-router/.babelrc +0 -9
- jac_client-0.2.3/jac_client/examples/with-router/README.md +0 -17
- jac_client-0.2.3/jac_client/examples/with-router/package.json +0 -28
- jac_client-0.2.3/jac_client/examples/with-router/vite.config.js +0 -27
- jac_client-0.2.3/jac_client/plugin/cli.py +0 -244
- jac_client-0.2.3/jac_client/plugin/client.py +0 -152
- jac_client-0.2.3/jac_client/plugin/client_runtime.jac +0 -234
- jac_client-0.2.3/jac_client/plugin/vite_client_bundle.py +0 -503
- jac_client-0.2.3/jac_client/tests/fixtures/js_import/utils.js +0 -21
- jac_client-0.2.3/jac_client/tests/fixtures/package-lock.json +0 -329
- jac_client-0.2.3/jac_client/tests/fixtures/package.json +0 -11
- jac_client-0.2.3/jac_client/tests/test_asset_examples.py +0 -322
- jac_client-0.2.3/jac_client/tests/test_cl.py +0 -530
- jac_client-0.2.3/jac_client/tests/test_create_jac_app.py +0 -131
- jac_client-0.2.3/jac_client/tests/test_it.py +0 -329
- jac_client-0.2.3/jac_client/tests/test_nested_file.py +0 -374
- jac_client-0.2.3/pyproject.toml +0 -36
- {jac_client-0.2.3 → jac_client-0.2.9}/jac_client/tests/__init__.py +0 -0
- {jac_client-0.2.3 → jac_client-0.2.9}/jac_client/tests/fixtures/cl_file/app.jac +0 -0
- {jac_client-0.2.3 → jac_client-0.2.9}/jac_client/tests/fixtures/relative_import/app.jac +0 -0
- {jac_client-0.2.3/jac_client/examples/nested-folders/nested-basic/components → jac_client-0.2.9/jac_client/tests/fixtures/relative_import}/button.jac +0 -0
- {jac_client-0.2.3 → jac_client-0.2.9}/jac_client/tests/fixtures/test_fragments_spread/app.jac +0 -0
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jac-client
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: Build full-stack web applications with Jac - one language for frontend and backend.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Author-email: jason@mars.ninja
|
|
9
|
-
Maintainer: Jason Mars
|
|
10
|
-
Maintainer-email: jason@mars.ninja
|
|
11
|
-
Requires-Python: >=3.12.0,<4.0.0
|
|
12
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
-
Requires-Dist: jaclang (==0.9.3)
|
|
18
|
-
Project-URL: Documentation, https://jac-lang.org
|
|
19
|
-
Project-URL: Homepage, https://jaseci.org
|
|
5
|
+
Author-email: Jason Mars <jason@mars.ninja>
|
|
6
|
+
Maintainer-email: Jason Mars <jason@mars.ninja>
|
|
7
|
+
License-Expression: MIT
|
|
20
8
|
Project-URL: Repository, https://github.com/Jaseci-Labs/jaseci
|
|
9
|
+
Project-URL: Homepage, https://jaseci.org
|
|
10
|
+
Project-URL: Documentation, https://jac-lang.org
|
|
11
|
+
Keywords: jac,jaclang,jaseci,frontend,full-stack,web-development
|
|
12
|
+
Requires-Python: >=3.12
|
|
21
13
|
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: jaclang>=0.9.9
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: python-dotenv==1.0.1; extra == "dev"
|
|
17
|
+
Requires-Dist: pytest==8.3.5; extra == "dev"
|
|
22
18
|
|
|
23
19
|
# Jac Client
|
|
24
20
|
|
|
@@ -28,11 +24,11 @@ Jac Client enables you to write React-like components, manage state, and build i
|
|
|
28
24
|
|
|
29
25
|
---
|
|
30
26
|
|
|
31
|
-
##
|
|
27
|
+
## Features
|
|
32
28
|
|
|
33
29
|
- **Single Language**: Write frontend and backend in Jac
|
|
34
30
|
- **No HTTP Client**: Use `jacSpawn()` instead of fetch/axios
|
|
35
|
-
- **React Hooks**: Use standard React `useState` and `useEffect` hooks
|
|
31
|
+
- **React Hooks**: Use standard React `useState` and `useEffect` hooks (useState is auto-injected when using `has` variables)
|
|
36
32
|
- **Component-Based**: Build reusable UI components with JSX
|
|
37
33
|
- **Graph Database**: Built-in graph data model eliminates need for SQL/NoSQL
|
|
38
34
|
- **Type Safety**: Type checking across frontend and backend
|
|
@@ -40,7 +36,7 @@ Jac Client enables you to write React-like components, manage state, and build i
|
|
|
40
36
|
|
|
41
37
|
---
|
|
42
38
|
|
|
43
|
-
##
|
|
39
|
+
## Quick Start
|
|
44
40
|
|
|
45
41
|
### Installation
|
|
46
42
|
|
|
@@ -51,16 +47,20 @@ pip install jac-client
|
|
|
51
47
|
### Create a New App
|
|
52
48
|
|
|
53
49
|
```bash
|
|
54
|
-
jac
|
|
50
|
+
jac create --use client my-app
|
|
55
51
|
cd my-app
|
|
56
|
-
jac
|
|
52
|
+
jac start src/app.jac
|
|
57
53
|
```
|
|
58
54
|
|
|
59
|
-
Visit `http://localhost:8000
|
|
55
|
+
Visit `http://localhost:8000` to see your app! (The `app` component is served at the root by default.)
|
|
56
|
+
|
|
57
|
+
You can also access the app at `http://localhost:8000/cl/app`.
|
|
58
|
+
|
|
59
|
+
> **Note**: The `--npm` flag creates a client-side project with an organized folder structure. Without `--npm`, `jac create` creates a standard Jac project.
|
|
60
60
|
|
|
61
61
|
---
|
|
62
62
|
|
|
63
|
-
##
|
|
63
|
+
## Documentation
|
|
64
64
|
|
|
65
65
|
For detailed guides and tutorials, see the **[docs folder](jac_client/docs/)**:
|
|
66
66
|
|
|
@@ -72,16 +72,19 @@ For detailed guides and tutorials, see the **[docs folder](jac_client/docs/)**:
|
|
|
72
72
|
|
|
73
73
|
---
|
|
74
74
|
|
|
75
|
-
##
|
|
75
|
+
## Example
|
|
76
76
|
|
|
77
77
|
### Simple Counter with React Hooks
|
|
78
78
|
|
|
79
79
|
```jac
|
|
80
|
-
|
|
80
|
+
# Note: useState is auto-injected when using has variables in cl blocks
|
|
81
|
+
# Only useEffect needs explicit import
|
|
82
|
+
cl import from react { useEffect }
|
|
81
83
|
|
|
82
84
|
cl {
|
|
83
85
|
def Counter() -> any {
|
|
84
|
-
|
|
86
|
+
# useState is automatically available - no import needed!
|
|
87
|
+
[count, setCount] = useState(0);
|
|
85
88
|
|
|
86
89
|
useEffect(lambda -> None {
|
|
87
90
|
console.log("Count changed:", count);
|
|
@@ -103,10 +106,13 @@ cl {
|
|
|
103
106
|
}
|
|
104
107
|
```
|
|
105
108
|
|
|
109
|
+
> **Note:** When using `has` variables in `cl {}` blocks or `.cl.jac` files, the `useState` import is automatically injected. You only need to explicitly import other hooks like `useEffect`.
|
|
110
|
+
|
|
106
111
|
### Full-Stack Todo App
|
|
107
112
|
|
|
108
113
|
```jac
|
|
109
|
-
|
|
114
|
+
# useState is auto-injected, only import useEffect
|
|
115
|
+
cl import from react { useEffect }
|
|
110
116
|
cl import from '@jac-client/utils' { jacSpawn }
|
|
111
117
|
|
|
112
118
|
# Backend: Jac nodes and walkers
|
|
@@ -132,7 +138,8 @@ walker read_todos {
|
|
|
132
138
|
# Frontend: React component
|
|
133
139
|
cl {
|
|
134
140
|
def app() -> any {
|
|
135
|
-
|
|
141
|
+
# useState is automatically available - no import needed!
|
|
142
|
+
[todos, setTodos] = useState([]);
|
|
136
143
|
|
|
137
144
|
useEffect(lambda -> None {
|
|
138
145
|
async def loadTodos() -> None {
|
|
@@ -154,7 +161,7 @@ cl {
|
|
|
154
161
|
|
|
155
162
|
---
|
|
156
163
|
|
|
157
|
-
##
|
|
164
|
+
## Requirements
|
|
158
165
|
|
|
159
166
|
- Python: 3.12+
|
|
160
167
|
- Node.js: For npm and Vite
|
|
@@ -162,9 +169,10 @@ cl {
|
|
|
162
169
|
|
|
163
170
|
---
|
|
164
171
|
|
|
165
|
-
##
|
|
172
|
+
## ️ How It Works
|
|
166
173
|
|
|
167
174
|
Jac Client is a plugin that:
|
|
175
|
+
|
|
168
176
|
1. Compiles your `.jac` client code to JavaScript
|
|
169
177
|
2. Bundles dependencies with Vite for optimal performance
|
|
170
178
|
3. Provides a runtime for reactive state and components
|
|
@@ -172,7 +180,7 @@ Jac Client is a plugin that:
|
|
|
172
180
|
|
|
173
181
|
---
|
|
174
182
|
|
|
175
|
-
##
|
|
183
|
+
## Learn More
|
|
176
184
|
|
|
177
185
|
- **Full Documentation**: See [docs/](jac_client/docs/) for comprehensive guides
|
|
178
186
|
- **Examples**: Check `jac_client/examples/` for working examples
|
|
@@ -180,11 +188,10 @@ Jac Client is a plugin that:
|
|
|
180
188
|
|
|
181
189
|
---
|
|
182
190
|
|
|
183
|
-
##
|
|
191
|
+
## License
|
|
184
192
|
|
|
185
193
|
MIT License - see [LICENSE](../LICENSE) file.
|
|
186
194
|
|
|
187
195
|
---
|
|
188
196
|
|
|
189
|
-
**Happy coding with Jac!**
|
|
190
|
-
|
|
197
|
+
**Happy coding with Jac!**
|
|
@@ -6,11 +6,11 @@ Jac Client enables you to write React-like components, manage state, and build i
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Features
|
|
10
10
|
|
|
11
11
|
- **Single Language**: Write frontend and backend in Jac
|
|
12
12
|
- **No HTTP Client**: Use `jacSpawn()` instead of fetch/axios
|
|
13
|
-
- **React Hooks**: Use standard React `useState` and `useEffect` hooks
|
|
13
|
+
- **React Hooks**: Use standard React `useState` and `useEffect` hooks (useState is auto-injected when using `has` variables)
|
|
14
14
|
- **Component-Based**: Build reusable UI components with JSX
|
|
15
15
|
- **Graph Database**: Built-in graph data model eliminates need for SQL/NoSQL
|
|
16
16
|
- **Type Safety**: Type checking across frontend and backend
|
|
@@ -18,7 +18,7 @@ Jac Client enables you to write React-like components, manage state, and build i
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## Quick Start
|
|
22
22
|
|
|
23
23
|
### Installation
|
|
24
24
|
|
|
@@ -29,16 +29,20 @@ pip install jac-client
|
|
|
29
29
|
### Create a New App
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
jac
|
|
32
|
+
jac create --use client my-app
|
|
33
33
|
cd my-app
|
|
34
|
-
jac
|
|
34
|
+
jac start src/app.jac
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
Visit `http://localhost:8000
|
|
37
|
+
Visit `http://localhost:8000` to see your app! (The `app` component is served at the root by default.)
|
|
38
|
+
|
|
39
|
+
You can also access the app at `http://localhost:8000/cl/app`.
|
|
40
|
+
|
|
41
|
+
> **Note**: The `--npm` flag creates a client-side project with an organized folder structure. Without `--npm`, `jac create` creates a standard Jac project.
|
|
38
42
|
|
|
39
43
|
---
|
|
40
44
|
|
|
41
|
-
##
|
|
45
|
+
## Documentation
|
|
42
46
|
|
|
43
47
|
For detailed guides and tutorials, see the **[docs folder](jac_client/docs/)**:
|
|
44
48
|
|
|
@@ -50,16 +54,19 @@ For detailed guides and tutorials, see the **[docs folder](jac_client/docs/)**:
|
|
|
50
54
|
|
|
51
55
|
---
|
|
52
56
|
|
|
53
|
-
##
|
|
57
|
+
## Example
|
|
54
58
|
|
|
55
59
|
### Simple Counter with React Hooks
|
|
56
60
|
|
|
57
61
|
```jac
|
|
58
|
-
|
|
62
|
+
# Note: useState is auto-injected when using has variables in cl blocks
|
|
63
|
+
# Only useEffect needs explicit import
|
|
64
|
+
cl import from react { useEffect }
|
|
59
65
|
|
|
60
66
|
cl {
|
|
61
67
|
def Counter() -> any {
|
|
62
|
-
|
|
68
|
+
# useState is automatically available - no import needed!
|
|
69
|
+
[count, setCount] = useState(0);
|
|
63
70
|
|
|
64
71
|
useEffect(lambda -> None {
|
|
65
72
|
console.log("Count changed:", count);
|
|
@@ -81,10 +88,13 @@ cl {
|
|
|
81
88
|
}
|
|
82
89
|
```
|
|
83
90
|
|
|
91
|
+
> **Note:** When using `has` variables in `cl {}` blocks or `.cl.jac` files, the `useState` import is automatically injected. You only need to explicitly import other hooks like `useEffect`.
|
|
92
|
+
|
|
84
93
|
### Full-Stack Todo App
|
|
85
94
|
|
|
86
95
|
```jac
|
|
87
|
-
|
|
96
|
+
# useState is auto-injected, only import useEffect
|
|
97
|
+
cl import from react { useEffect }
|
|
88
98
|
cl import from '@jac-client/utils' { jacSpawn }
|
|
89
99
|
|
|
90
100
|
# Backend: Jac nodes and walkers
|
|
@@ -110,7 +120,8 @@ walker read_todos {
|
|
|
110
120
|
# Frontend: React component
|
|
111
121
|
cl {
|
|
112
122
|
def app() -> any {
|
|
113
|
-
|
|
123
|
+
# useState is automatically available - no import needed!
|
|
124
|
+
[todos, setTodos] = useState([]);
|
|
114
125
|
|
|
115
126
|
useEffect(lambda -> None {
|
|
116
127
|
async def loadTodos() -> None {
|
|
@@ -132,7 +143,7 @@ cl {
|
|
|
132
143
|
|
|
133
144
|
---
|
|
134
145
|
|
|
135
|
-
##
|
|
146
|
+
## Requirements
|
|
136
147
|
|
|
137
148
|
- Python: 3.12+
|
|
138
149
|
- Node.js: For npm and Vite
|
|
@@ -140,9 +151,10 @@ cl {
|
|
|
140
151
|
|
|
141
152
|
---
|
|
142
153
|
|
|
143
|
-
##
|
|
154
|
+
## ️ How It Works
|
|
144
155
|
|
|
145
156
|
Jac Client is a plugin that:
|
|
157
|
+
|
|
146
158
|
1. Compiles your `.jac` client code to JavaScript
|
|
147
159
|
2. Bundles dependencies with Vite for optimal performance
|
|
148
160
|
3. Provides a runtime for reactive state and components
|
|
@@ -150,7 +162,7 @@ Jac Client is a plugin that:
|
|
|
150
162
|
|
|
151
163
|
---
|
|
152
164
|
|
|
153
|
-
##
|
|
165
|
+
## Learn More
|
|
154
166
|
|
|
155
167
|
- **Full Documentation**: See [docs/](jac_client/docs/) for comprehensive guides
|
|
156
168
|
- **Examples**: Check `jac_client/examples/` for working examples
|
|
@@ -158,10 +170,10 @@ Jac Client is a plugin that:
|
|
|
158
170
|
|
|
159
171
|
---
|
|
160
172
|
|
|
161
|
-
##
|
|
173
|
+
## License
|
|
162
174
|
|
|
163
175
|
MIT License - see [LICENSE](../LICENSE) file.
|
|
164
176
|
|
|
165
177
|
---
|
|
166
178
|
|
|
167
|
-
**Happy coding with Jac!**
|
|
179
|
+
**Happy coding with Jac!**
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Category filter component
|
|
2
|
+
# Demonstrates: iteration with map, conditional classes, events
|
|
3
|
+
|
|
4
|
+
cl import from ..constants.categories { CATEGORIES, CATEGORY_LABELS, CATEGORY_COLORS }
|
|
5
|
+
|
|
6
|
+
cl {
|
|
7
|
+
# Filter buttons for categories
|
|
8
|
+
def:pub CategoryFilter(selectedCategory: str, onSelect: any) -> any {
|
|
9
|
+
# Add "ALL" to the beginning of categories
|
|
10
|
+
allCategories = ["ALL"].concat(CATEGORIES);
|
|
11
|
+
|
|
12
|
+
return <div className="category-filter">
|
|
13
|
+
<h3 className="filter-title">Filter by Category</h3>
|
|
14
|
+
<div className="filter-buttons">
|
|
15
|
+
{allCategories.map(lambda cat: str -> any {
|
|
16
|
+
isActive = selectedCategory == cat;
|
|
17
|
+
color = CATEGORY_COLORS[cat] if cat != "ALL" else "#374151";
|
|
18
|
+
|
|
19
|
+
return <button
|
|
20
|
+
key={cat}
|
|
21
|
+
className={("filter-btn active") if isActive else ("filter-btn")}
|
|
22
|
+
style={{
|
|
23
|
+
"borderColor": color,
|
|
24
|
+
"backgroundColor": (color) if isActive else ("transparent"),
|
|
25
|
+
"color": ("#fff") if isActive else (color)
|
|
26
|
+
}}
|
|
27
|
+
onClick={lambda: onSelect(cat)}
|
|
28
|
+
>
|
|
29
|
+
{(cat) if cat == "ALL" else (CATEGORY_LABELS[cat])}
|
|
30
|
+
</button>;
|
|
31
|
+
})}
|
|
32
|
+
</div>
|
|
33
|
+
</div>;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Header component
|
|
2
|
+
# Demonstrates: simple component, CSS classes
|
|
3
|
+
|
|
4
|
+
cl {
|
|
5
|
+
def:pub Header() -> any {
|
|
6
|
+
return <header className="header">
|
|
7
|
+
<div className="header-content">
|
|
8
|
+
<h1 className="header-title">Budget Planner</h1>
|
|
9
|
+
<p className="header-subtitle">Track your income and expenses</p>
|
|
10
|
+
</div>
|
|
11
|
+
</header>;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Profit Overview component - monthly profit snapshot
|
|
2
|
+
# Demonstrates: context usage, calculated displays, formatting
|
|
3
|
+
|
|
4
|
+
cl import from ..context.BudgetContext { useBudgetContext }
|
|
5
|
+
cl import from ..utils.formatters { formatCurrency }
|
|
6
|
+
|
|
7
|
+
cl {
|
|
8
|
+
def:pub ProfitOverview() -> any {
|
|
9
|
+
budget = useBudgetContext();
|
|
10
|
+
|
|
11
|
+
businessIncome = budget["businessIncome"];
|
|
12
|
+
businessExpenses = budget["businessExpenses"];
|
|
13
|
+
taxReserve = budget["taxReserve"];
|
|
14
|
+
netProfit = budget["netProfit"];
|
|
15
|
+
|
|
16
|
+
return <div className="profit-overview">
|
|
17
|
+
<h3 className="profit-title">Monthly Profit Snapshot</h3>
|
|
18
|
+
|
|
19
|
+
<div className="profit-breakdown">
|
|
20
|
+
<div className="profit-row income">
|
|
21
|
+
<span className="profit-label">Business Income</span>
|
|
22
|
+
<span className="profit-value positive">
|
|
23
|
+
+{formatCurrency(businessIncome)}
|
|
24
|
+
</span>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div className="profit-row expense">
|
|
28
|
+
<span className="profit-label">Business Expenses</span>
|
|
29
|
+
<span className="profit-value negative">
|
|
30
|
+
-{formatCurrency(businessExpenses)}
|
|
31
|
+
</span>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div className="profit-row tax">
|
|
35
|
+
<span className="profit-label">Tax Reserve (20%)</span>
|
|
36
|
+
<span className="profit-value negative">
|
|
37
|
+
-{formatCurrency(taxReserve)}
|
|
38
|
+
</span>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div className="profit-row total">
|
|
42
|
+
<span className="profit-label">Net Profit</span>
|
|
43
|
+
<span className={("profit-value bold positive") if netProfit >= 0 else ("profit-value bold negative")}>
|
|
44
|
+
{("+") if netProfit > 0 else ("")}{formatCurrency(netProfit)}
|
|
45
|
+
</span>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Summary component - displays budget totals with business/personal breakdown
|
|
2
|
+
# Demonstrates: context usage, conditional rendering, ternary operator, 6-card layout
|
|
3
|
+
|
|
4
|
+
cl import from ..context.BudgetContext { useBudgetContext }
|
|
5
|
+
cl import from ..utils.formatters { formatCurrency }
|
|
6
|
+
|
|
7
|
+
cl {
|
|
8
|
+
def:pub Summary() -> any {
|
|
9
|
+
budget = useBudgetContext();
|
|
10
|
+
|
|
11
|
+
# Business/Personal breakdown
|
|
12
|
+
businessIncome = budget["businessIncome"];
|
|
13
|
+
businessExpenses = budget["businessExpenses"];
|
|
14
|
+
personalIncome = budget["personalIncome"];
|
|
15
|
+
personalExpenses = budget["personalExpenses"];
|
|
16
|
+
taxReserve = budget["taxReserve"];
|
|
17
|
+
netProfit = budget["netProfit"];
|
|
18
|
+
|
|
19
|
+
return <div className="summary">
|
|
20
|
+
<div className="summary-card business-income">
|
|
21
|
+
<span className="summary-label">Business Income</span>
|
|
22
|
+
<span className="summary-value">{formatCurrency(businessIncome)}</span>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div className="summary-card business-expenses">
|
|
26
|
+
<span className="summary-label">Business Expenses</span>
|
|
27
|
+
<span className="summary-value">{formatCurrency(businessExpenses)}</span>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div className="summary-card personal-income">
|
|
31
|
+
<span className="summary-label">Personal Income</span>
|
|
32
|
+
<span className="summary-value">{formatCurrency(personalIncome)}</span>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div className="summary-card personal-expenses">
|
|
36
|
+
<span className="summary-label">Personal Expenses</span>
|
|
37
|
+
<span className="summary-value">{formatCurrency(personalExpenses)}</span>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<div className="summary-card tax-reserve">
|
|
41
|
+
<span className="summary-label">Tax Reserve (20%)</span>
|
|
42
|
+
<span className="summary-value">{formatCurrency(taxReserve)}</span>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<div className={("summary-card net-profit positive") if netProfit >= 0 else ("summary-card net-profit negative")}>
|
|
46
|
+
<span className="summary-label">Net Profit</span>
|
|
47
|
+
<span className="summary-value">
|
|
48
|
+
{("+") if netProfit > 0 else ("")}{formatCurrency(netProfit)}
|
|
49
|
+
</span>
|
|
50
|
+
</div>
|
|
51
|
+
</div>;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Transaction form component
|
|
2
|
+
# Demonstrates: form handling, useState, events, select options
|
|
3
|
+
|
|
4
|
+
cl import from ..context.BudgetContext { useBudgetContext }
|
|
5
|
+
cl import from ..constants.categories { CATEGORIES, CATEGORY_LABELS }
|
|
6
|
+
cl import from ..constants.clients { CLIENTS }
|
|
7
|
+
|
|
8
|
+
cl {
|
|
9
|
+
def:pub TransactionForm() -> any {
|
|
10
|
+
[description, setDescription] = useState("");
|
|
11
|
+
[amount, setAmount] = useState("");
|
|
12
|
+
[category, setCategory] = useState("OTHER");
|
|
13
|
+
[txType, setTxType] = useState("expense");
|
|
14
|
+
[isBusiness, setIsBusiness] = useState(false);
|
|
15
|
+
[clientName, setClientName] = useState("");
|
|
16
|
+
budget = useBudgetContext();
|
|
17
|
+
|
|
18
|
+
def handleSubmit(e: any) -> None {
|
|
19
|
+
e.preventDefault();
|
|
20
|
+
|
|
21
|
+
# Validate inputs
|
|
22
|
+
trimmedDesc = description.trim();
|
|
23
|
+
if trimmedDesc == "" or amount == "" {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
parsedAmount = parseFloat(amount);
|
|
28
|
+
if isNaN(parsedAmount) or parsedAmount <= 0 {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# Add the transaction
|
|
33
|
+
budget["addTransaction"](trimmedDesc, parsedAmount, category, txType, isBusiness, clientName);
|
|
34
|
+
|
|
35
|
+
# Reset form
|
|
36
|
+
setDescription("");
|
|
37
|
+
setAmount("");
|
|
38
|
+
setCategory("OTHER");
|
|
39
|
+
setIsBusiness(false);
|
|
40
|
+
setClientName("");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
# Filter categories based on type (income only has INCOME category)
|
|
44
|
+
availableCategories = CATEGORIES.filter(lambda cat: str -> bool {
|
|
45
|
+
if txType == "income" {
|
|
46
|
+
return cat == "INCOME";
|
|
47
|
+
}
|
|
48
|
+
return cat != "INCOME";
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
# Show client dropdown only for business income
|
|
52
|
+
showClientDropdown = (txType == "income" and isBusiness);
|
|
53
|
+
|
|
54
|
+
return <form className="transaction-form" onSubmit={handleSubmit}>
|
|
55
|
+
<div className="form-row">
|
|
56
|
+
<div className="form-group type-toggle">
|
|
57
|
+
<button
|
|
58
|
+
type="button"
|
|
59
|
+
className={("toggle-btn active") if txType == "expense" else ("toggle-btn")}
|
|
60
|
+
onClick={lambda: setTxType("expense")}
|
|
61
|
+
>
|
|
62
|
+
Expense
|
|
63
|
+
</button>
|
|
64
|
+
<button
|
|
65
|
+
type="button"
|
|
66
|
+
className={("toggle-btn active income") if txType == "income" else ("toggle-btn")}
|
|
67
|
+
onClick={lambda: setTxType("income")}
|
|
68
|
+
>
|
|
69
|
+
Income
|
|
70
|
+
</button>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<div className="form-group business-toggle">
|
|
74
|
+
<button
|
|
75
|
+
type="button"
|
|
76
|
+
className={("toggle-btn active") if isBusiness else ("toggle-btn")}
|
|
77
|
+
onClick={lambda: setIsBusiness(true)}
|
|
78
|
+
>
|
|
79
|
+
Business
|
|
80
|
+
</button>
|
|
81
|
+
<button
|
|
82
|
+
type="button"
|
|
83
|
+
className={("toggle-btn active") if not isBusiness else ("toggle-btn")}
|
|
84
|
+
onClick={lambda: setIsBusiness(false)}
|
|
85
|
+
>
|
|
86
|
+
Personal
|
|
87
|
+
</button>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<div className="form-row">
|
|
92
|
+
<div className="form-group">
|
|
93
|
+
<label htmlFor="description">Description</label>
|
|
94
|
+
<input
|
|
95
|
+
id="description"
|
|
96
|
+
type="text"
|
|
97
|
+
value={description}
|
|
98
|
+
onChange={lambda e: any -> None { setDescription(e.target.value); }}
|
|
99
|
+
placeholder="Enter description..."
|
|
100
|
+
className="form-input"
|
|
101
|
+
/>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<div className="form-group">
|
|
105
|
+
<label htmlFor="amount">Amount</label>
|
|
106
|
+
<input
|
|
107
|
+
id="amount"
|
|
108
|
+
type="number"
|
|
109
|
+
value={amount}
|
|
110
|
+
onChange={lambda e: any -> None { setAmount(e.target.value); }}
|
|
111
|
+
placeholder="0.00"
|
|
112
|
+
min="0"
|
|
113
|
+
step="0.01"
|
|
114
|
+
className="form-input"
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div className="form-group">
|
|
119
|
+
<label htmlFor="category">Category</label>
|
|
120
|
+
<select
|
|
121
|
+
id="category"
|
|
122
|
+
value={category}
|
|
123
|
+
onChange={lambda e: any -> None { setCategory(e.target.value); }}
|
|
124
|
+
className="form-select"
|
|
125
|
+
>
|
|
126
|
+
{availableCategories.map(lambda cat: str -> any {
|
|
127
|
+
return <option key={cat} value={cat}>
|
|
128
|
+
{CATEGORY_LABELS[cat]}
|
|
129
|
+
</option>;
|
|
130
|
+
})}
|
|
131
|
+
</select>
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
{showClientDropdown and <div className="form-group">
|
|
135
|
+
<label htmlFor="client">Client</label>
|
|
136
|
+
<select
|
|
137
|
+
id="client"
|
|
138
|
+
value={clientName}
|
|
139
|
+
onChange={lambda e: any -> None { setClientName(e.target.value); }}
|
|
140
|
+
className="form-select"
|
|
141
|
+
>
|
|
142
|
+
<option value="">Select Client (Optional)</option>
|
|
143
|
+
{CLIENTS.map(lambda client: str -> any {
|
|
144
|
+
return <option key={client} value={client}>{client}</option>;
|
|
145
|
+
})}
|
|
146
|
+
</select>
|
|
147
|
+
</div>}
|
|
148
|
+
|
|
149
|
+
<div className="form-group">
|
|
150
|
+
<label>Action</label>
|
|
151
|
+
<button type="submit" className="submit-btn">
|
|
152
|
+
Add {(txType[0].toUpperCase() + txType.slice(1))}
|
|
153
|
+
</button>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</form>;
|
|
157
|
+
}
|
|
158
|
+
}
|