180 Commits

Author SHA1 Message Date
notkshitij e3935c9760 Added confirm password text box and show/hide password toggles in both password fields. 2025-07-18 02:47:16 +05:30
notkshitij 4115193ef7 Added loader while checking whether password was leaked previously. 2025-07-18 02:40:15 +05:30
notkshitij 2afda4873b Added basic password strength indicator 2025-07-18 02:34:05 +05:30
notkshitij bc41904e06 Akcually, axios and sha1 are required in backend 🤓 2025-07-18 02:30:59 +05:30
notkshitij 4fb54705ca Removed axios and sha1 packages from backend. 2025-07-18 02:13:31 +05:30
notkshitij 12ce8b1ec3 Added axios and sha1 packages. 2025-07-18 02:13:12 +05:30
notkshitij 9c3feca6a7 feat(login): improve error handling and show rate limit message
- Display meaningful error messages on login failure, including rate limiting (429)
- Added fallback for unexpected JSON responses from the server
- Integrated `Message` component for error display
- Cleaned up form value clearing and error state management
2025-07-18 02:12:46 +05:30
notkshitij aaf88fda56 feat(signup): add password strength and breach check using HIBP API
- Implemented frontend password validation for minimum strength:
  - Requires 8+ characters with uppercase, lowercase, digit, and special character.
- Integrated haveibeenpwned (HIBP) k-anonymity API to detect breached passwords.
- Display appropriate error messages for weak or pwned passwords.
- Updated Message component to support "error" and "default" types with styling.
- Cleaned up SignupPage form UI and removed unused refs (e.g., roleElement).
- Created passwordUtils.js to isolate SHA-1 hashing and API call logic.
2025-07-18 02:06:43 +05:30
notkshitij 23a271fbce Removed package-lock.json and updated .gitignore. 2025-07-18 01:26:13 +05:30
notkshitij f3e52cda73 Added new packages and updated some existing ones. 2025-07-18 01:25:27 +05:30
notkshitij 04e69202b6 Added password policy and checking if password appeared in a breach w/ haveibeenpwed api. 2025-07-18 01:22:01 +05:30
notkshitij 001727ab85 Added helmet secure headers and HTTPS redirection. 2025-07-18 01:21:07 +05:30
notkshitij 351f57229c Apply rate limiter logic. 2025-07-18 01:18:10 +05:30
notkshitij 25cfa659c7 Added rate limiting logic in middleware. 2025-07-18 01:17:53 +05:30
notkshitij d5d1e16d1f Moved the query parameter into the correct position and added logging for the final URI for database connect. 2025-07-18 01:06:42 +05:30
notkshitij e40eae866a Merged Salvi's commit he made to master branch (0ffcd1274d659b3e5c44a4813c57eb46e6ea4bed) for fixing UI changes. 2025-06-24 13:50:01 +05:30
notkshitij 3458d21567 Added multilingual (English, Hindi, Marathi & French) in features section. 2025-06-23 20:31:13 +05:30
notkshitij 63c73bc6d9 Added guide for translation! 2025-06-23 20:22:06 +05:30
notkshitij 90d09350e2 Perfomed complete Marathi translation. Not exactly complete but up to where mr & fr was done. 2025-06-21 00:53:25 +05:30
notkshitij 06b11cb2eb Perfomed complete Hindi translation. Not exactly complete but up to where fr was done. 2025-06-21 00:51:41 +05:30
notkshitij 14295f1931 Merge branch 'main' into frontend-multilingual up to commit 0aa8a3842c 2025-06-21 00:28:12 +05:30
notkshitij 0aa8a3842c Merged models/ directory from bhakti's branch up to commit 3d79d69640 since that is the branch we used for demo during hackathon. 2025-06-21 00:22:49 +05:30
notkshitij 1395496fce Merged all changes from frontend branch w/ main branch up to commit 0d757995bb 2025-06-21 00:21:57 +05:30
notkshitij 91aaa092f3 Added package-lock.json and node_modules in global .gitignore 2025-06-21 00:20:32 +05:30
notkshitij a7ae00beac Removed package-lock.json, package.json and node_modules from root dir. Not needed. 2025-06-21 00:20:27 +05:30
KaranSalvi 7ad0db73b0 Resolved conflict by deleting multer.js and updated packages 2025-06-21 00:19:50 +05:30
notkshitij 36693ba21b Made ForgetPassword and ResetPassword multilingual. Also added en and fr translations for the same. 2025-06-20 23:28:44 +05:30
notkshitij 9e170a91ef Added translation for SignupPage.jsx along with en and fr translations. 2025-06-20 23:24:53 +05:30
notkshitij 911b08ba71 Removed unused jsx files from Home directory in src/pages. 2025-06-20 23:19:34 +05:30
notkshitij 36781b3af4 Made Testimonial.jsx multilingual. Also updated en and fr translations for the same. 2025-06-20 23:17:54 +05:30
notkshitij a70afd8615 Fixed Cards.jsx, now the homepage is not blank. Also added key:values for text in Cards.jsx 2025-06-20 23:13:22 +05:30
notkshitij 9fe5d04fca Made pages in Home/ directory multilingual:
- Cards.jsx
- Customization.jsx
- Footer.jsx
- Hero.jsx
- Hero2.jsx
- HomePage.jsx

Also added language key:values for en and fr in locales.
2025-06-20 23:12:38 +05:30
notkshitij 23e12d3c7e Support for language context in MainLoginPage.jsx
- Updated MainLoginPage component to accept a `language` prop with a default value of "en".
- Modified Navbar2 to receive the `language` prop for localization.
- Passed the `language` context to the Outlet for nested routes, enabling language-specific rendering in child components.
2025-06-19 16:29:29 +05:30
notkshitij 4b6faef5eb Replaced static text in LoginPage.jsx with translation function t(key, language). 2025-06-19 16:28:26 +05:30
notkshitij cacf3f9c0d Added language switcher function in App.jsx 2025-06-19 16:26:04 +05:30
notkshitij 697a873148 Added English (default) and French locales. This directory will store key-value pairs for translation where key will be the English word/phrase and value will be the translation of that word/phrase. 2025-06-19 16:23:35 +05:30
notkshitij c123c4985c Added service/translation.js -> Implements a translation service that dynamically loads phrases based on user language preference. 2025-06-19 16:23:35 +05:30
notkshitij 64a34fdf0d Added language switching component. This component will render a dropdown or buttons for language selection and update the language globally when changed. 2025-06-19 16:23:22 +05:30
notkshitij 5484b122a1 Added a better description in README. 2025-06-07 15:48:46 +05:30
notkshitij b2fe22195f Merged all the changes from bhakti's branch into main. 2025-04-05 18:24:23 +05:30
KaranSalvi ce864c7c55 feat: Add logs 2025-03-26 22:51:07 +05:30
KaranSalvi 407d6df417 feat:Added monitoring charts 2025-03-26 22:50:05 +05:30
KaranSalvi b961ef8fd3 feat:Fixed all the UI Pages 2025-03-26 21:31:14 +05:30
KaranSalvi aba9651c43 feat:Add individual crop page 2025-03-26 00:25:09 +05:30
KaranSalvi 0dbb68d518 feat:Add env variables file 2025-03-25 21:33:21 +05:30
KaranSalvi 262446fff7 feat: Add some new connection 2025-03-25 19:40:56 +05:30
KaranSalvi 914501036d feat: Set up RTK query for the statemanagement 2025-03-25 17:48:15 +05:30
KaranSalvi 7e204690d3 Fix: FUCK OMBAASE MESSED UP. 2025-02-23 11:38:02 +05:30
KaranSalvi ae1b2566a3 added models. 2025-02-23 11:22:34 +05:30
KaranSalvi dc0afc8d5a Changed default user profile. 2025-02-23 11:21:29 +05:30
KaranSalvi d53a4d6061 Removed navbar from dashboard. 2025-02-23 11:12:03 +05:30
KaranSalvi c839011847 Merged Ombase's changes. 2025-02-23 11:09:09 +05:30
atharvaombase 6df9befdd1 Fix:removed navbar and added space between components in dashboard 2025-02-23 11:05:12 +05:30
KaranSalvi aa97607ec4 Changed footer and testimonial. 2025-02-23 11:04:15 +05:30
atharvaombase 0048e9f462 Feat:Added Plant disease prediction 2025-02-23 10:52:31 +05:30
KaranSalvi 08fc0e790e Fixed cookie issue 2025-02-23 10:48:41 +05:30
KaranSalvi a1a0d6adc4 Made changes to honepage. 2025-02-23 10:47:58 +05:30
KaranSalvi 3aec29388b Added new icons for homepage. 2025-02-23 10:47:45 +05:30
atharvaombase dbbc0ce5f2 Feat:Added new Ai page for the Crop desies detection 2025-02-23 10:41:16 +05:30
atharvaombase 79c6c80636 Fix:Added new route for Ai 2025-02-23 10:40:40 +05:30
atharvaombase 9ac0294974 Image added 2025-02-23 10:27:07 +05:30
atharvaombase 870185001d Fix:Changed user profile 2025-02-23 10:26:41 +05:30
atharvaombase 34bdbf9f9c Fix:Fixed loader typo 2025-02-23 10:26:18 +05:30
atharvaombase a9d63abf9b Fix:Renamed this file and added the correct one
delete this file
2025-02-23 10:25:30 +05:30
atharvaombase 53b1e40d8f Fix:changed the Profile photo 2025-02-23 10:24:32 +05:30
atharvaombase c113a34f1f Fix:fixed loader typo 2025-02-23 10:23:46 +05:30
atharvaombase 9e04a4b734 Fix:fixed loader typo 2025-02-23 10:23:27 +05:30
notkshitij 3b21ab5b63 Removed useless node_modules folder and package-lock file. 2025-02-23 09:38:37 +05:30
notkshitij d431ff809e Merged frontend changes from frontend branch to main. 2025-02-23 09:37:59 +05:30
notkshitij dcc5ce361d Merged models folder from training branch. 2025-02-23 09:37:03 +05:30
notkshitij cc9c63d879 Merged bhakti's frontend changes. 2025-02-23 09:27:30 +05:30
notkshitij 4e6ce0e723 Merged Salvi's backend changes. 2025-02-23 09:26:44 +05:30
notkshitij c604fa308e Merged ombase's changes in bhakti's branch for karan to make changes to. 2025-02-23 09:16:48 +05:30
notkshitij a551e075b7 Added backend folder in Bhakti's branch for Salvi to make changes. 2025-02-23 09:15:03 +05:30
notkshitij 1966a696ab Merged backend changes made by salvi to crop controller.js 2025-02-23 09:14:01 +05:30
notkshitij 7da2809399 Added Salvi's backend folder from backend branch to allow ombase to continue testing. 2025-02-23 09:05:16 +05:30
notkshitij 3f9e6d3dee Deleted useless files such as backend, node_modules and package-lock. Modified readme. 2025-02-23 09:04:05 +05:30
notkshitij 7dd344f722 Deleted useless folders such as backend, node_modules, files such as package-lock. Also, modified readme. 2025-02-23 09:02:28 +05:30
KaranSalvi 283f62e1c2 feat:Make the server for the Prediction Model 2025-02-23 08:52:07 +05:30
Bhakti 54c7dbc940 Created component for Taking photo input for crop disease detection 2025-02-23 08:34:35 +05:30
notkshitij 4b27d1854e Added server.js for node server. References python app.py code, uses POST req. 2025-02-23 08:18:21 +05:30
notkshitij ac7ea72247 Changed the way we're specifying the path for image in app.py. Directly mention it while execting now. 2025-02-23 08:15:50 +05:30
atharvaombase 699bcb9d2c Fix:Fixed Fetch 2025-02-23 07:57:48 +05:30
atharvaombase 51eb7d8f47 still some errors 2025-02-23 07:34:46 +05:30
atharvaombase 54d90519cb Still some errors 2025-02-23 07:34:28 +05:30
atharvaombase d48736114b Feat:Added laoding animation 2025-02-23 07:34:05 +05:30
atharvaombase 36911b5701 Feat:Added loader animation 2025-02-23 07:33:20 +05:30
atharvaombase fcc52ed62a Feat:Added loader for loading animation throughout the webapp 2025-02-23 07:31:41 +05:30
atharvaombase 29e2d49ef6 Fix:Replaced Class with className 2025-02-23 07:30:54 +05:30
atharvaombase 92b647fa0e Fix:Replaced class with className 2025-02-23 07:30:14 +05:30
atharvaombase 7b2abd29b9 Fix:Replace class with className 2025-02-23 07:29:30 +05:30
atharvaombase 7f96da1555 Feat:Added Loading animation 2025-02-23 07:28:35 +05:30
atharvaombase ac723810c5 Fix:Added Create finanace and View Finance 2025-02-23 07:00:07 +05:30
Bhakti 3abcb355eb Added get started button functionality 2025-02-23 06:40:24 +05:30
Bhakti 71a951dce9 added loginbg 2025-02-23 05:43:06 +05:30
atharvaombase 04317cb9e9 Just order is changed 2025-02-23 04:45:25 +05:30
atharvaombase 7edab16bd3 Fix:Added EditFarm in the main.jsx 2025-02-23 04:44:16 +05:30
atharvaombase 86189b0f5b Feat:Added EditFarm MODAL From Flowbite for Farm deletion 2025-02-23 04:43:30 +05:30
atharvaombase 297b094de5 Fix:Changed icons and overall appearance 2025-02-23 04:42:43 +05:30
atharvaombase bcd600c766 Fix:Removed Console.log 2025-02-23 04:41:51 +05:30
atharvaombase 9293287566 Fix:Added logic to remove a crop from the database 2025-02-23 04:40:52 +05:30
atharvaombase 22533ee75d Fix:Added data for whole year instead of 5 months 2025-02-23 04:39:58 +05:30
atharvaombase f8e6efb5b3 Fix:Added EditFarm component Instead of <a> 2025-02-23 04:39:12 +05:30
atharvaombase a67e23fa6a Testing:Tested for the bakend data with console.log 2025-02-23 03:50:54 +05:30
atharvaombase 9f98ebd4c4 Fix:Added a div to keep navbar from overlapping the initial elements 2025-02-23 03:49:55 +05:30
notkshitij 1f0855c9f3 Merged all the changes from backend and frontend branch to main. Everything functional. 2025-02-23 03:38:45 +05:30
Bhakti f3d0fd7459 Merge branch 'bhakti' of https://git.kska.io/notkshitij/status200 into bhakti 2025-02-23 03:28:40 +05:30
notkshitij 0dbc742f42 Merged ombase's changes. 2025-02-23 03:25:29 +05:30
notkshitij 2be6de06d6 Merged Bhakti's changes. 2025-02-23 03:24:24 +05:30
atharvaombase 5cde4a3b45 Fix:Improved CSS of the side bar 2025-02-23 03:24:09 +05:30
notkshitij 228ce106b2 Merged Omabse's changes. 2025-02-23 03:23:20 +05:30
Bhakti 6d8d1ab5f8 Merge branch 'frontend' of https://git.kska.io/notkshitij/status200 into bhakti 2025-02-23 03:10:30 +05:30
notkshitij 928c3fbb12 Merged Bhakti's changes with Ombase's changes in frontend testing branch 2025-02-23 03:08:19 +05:30
Bhakti c4eb3e940e Changes made to Login and SignUp 2025-02-23 03:06:23 +05:30
Bhakti 43613b60ce landing successful 2025-02-23 03:05:24 +05:30
notkshitij 82f457406a Pulled Ombase's changes till now. 2025-02-23 03:01:52 +05:30
atharvaombase ec2f1a939b Fix:Changed the CropList to CropTable 2025-02-23 02:55:56 +05:30
atharvaombase 490668ff61 Feat:Added table to display crop details 2025-02-23 02:55:04 +05:30
atharvaombase 21a21303f8 Fix:Added Padding the select 2025-02-23 02:54:27 +05:30
atharvaombase 7edeef04f7 Fix:Added padding to select menu 2025-02-23 02:51:39 +05:30
atharvaombase 793a0867dd Fix:Added farmId as a prop and posted 2025-02-23 02:51:03 +05:30
atharvaombase a585ac58f6 Feat:Sent farmId prop to Farm.jsx 2025-02-23 02:27:21 +05:30
atharvaombase d16b59edc0 Feat:Sent props to AddCrop 2025-02-23 02:26:45 +05:30
atharvaombase 9e6ccc0343 Fix:changed fetch body for sending farm id 2025-02-23 02:25:26 +05:30
atharvaombase 3215da670e Fix:Removed overlapping svg 2025-02-23 02:24:37 +05:30
notkshitij 6e813383fb Updated readme file reflecting the purpose of this branch, i.e. main. 2025-02-23 01:44:57 +05:30
notkshitij 0758934b91 Added a bit more descriptive readme for training branch. 2025-02-23 01:42:07 +05:30
atharvaombase cbff64906b Fix:Replaced 'class' with 'className' in many files 2025-02-23 00:52:53 +05:30
atharvaombase 27955fc264 Feat:Added a form for new crops 2025-02-23 00:52:19 +05:30
atharvaombase ee59400d76 Feat:Created AddCrop component for adding more crops in a perticular Farm 2025-02-23 00:29:13 +05:30
atharvaombase 88d229cb2d Fix:Implemented AddCrop component 2025-02-23 00:28:20 +05:30
atharvaombase 79a29ad982 Fix:Added the well structured table 2025-02-23 00:27:11 +05:30
atharvaombase e98b39a9da Feat:Added loading text to be replaced with animation after 2025-02-23 00:26:27 +05:30
Bhakti f41d33625f Added animations to Landing page 2025-02-22 23:58:22 +05:30
atharvaombase ae9108769c Feat:Added the page to display the data of the farm using dynamic routing 2025-02-22 23:56:05 +05:30
atharvaombase 6d0813c8db Fix:Added new Field content Size of land 2025-02-22 23:54:56 +05:30
atharvaombase 1c7c9425bc Feat:Added a table for farm data on FarmPage 2025-02-22 23:54:14 +05:30
atharvaombase 341a3a127b Feat:Added new input Field for Size of Land 2025-02-22 23:53:13 +05:30
atharvaombase 66a6ac22d0 Fix: Added dynamic Routing For OnClick 2025-02-22 23:52:21 +05:30
atharvaombase 466d0b7abe Fix:Removed uneccesary useNavigate 2025-02-22 23:50:58 +05:30
atharvaombase 07d691ad4e Feat:Added new rout for the FarmPage.jsx(Dynamic routing) 2025-02-22 23:49:48 +05:30
atharvaombase 89af132577 Added Dynamic routing on the table name 2025-02-22 23:49:05 +05:30
notkshitij 5015db6edb Added dependencies in requirements.txt file. 2025-02-22 23:09:44 +05:30
notkshitij 19073e945b Moved test2.py to app-old. This implementation pulls model and stuff from hugging faces. 2025-02-22 23:08:33 +05:30
notkshitij 0ea087b5c1 Removed some unclear sample images and added new better ones. 2025-02-22 23:07:44 +05:30
notkshitij c254f356bf test2, i.e. vishnu is the chosen model. Shall be using that going forward. Perfectly working right now. Will be attempting to locally reference it now. 2025-02-22 22:55:33 +05:30
notkshitij f43890faab Added gitignore file excluding python venv folders. 2025-02-22 22:55:33 +05:30
notkshitij 559b806a59 Added sample crop images. 2025-02-22 22:55:33 +05:30
notkshitij 8830798bd4 Moved test1, test3 and test4 to archive folder. 2025-02-22 22:54:54 +05:30
atharvaombase 762e246ccd Fix:Corrected files structure 2025-02-22 22:41:24 +05:30
atharvaombase ddf28d9a46 Fix: Moved to Farm Folder 2025-02-22 22:38:33 +05:30
atharvaombase 586fd41133 Fix:Corrected the imports for the Farm Folder 2025-02-22 22:37:36 +05:30
atharvaombase 982fbba413 Fix:Made fully functional by fetching the data from backend 2025-02-22 22:36:01 +05:30
atharvaombase b805b8e34e Fix:Kept the original Navbar 2025-02-22 20:57:30 +05:30
Bhakti 956fb5604a added type writer effect and resolved visibility issue 2025-02-22 20:30:28 +05:30
atharvaombase 6dc57b28b1 Merged backend from Salvi 2025-02-22 20:19:36 +05:30
atharvaombase fdee1beb05 Added add farm option in dashboard and created add farm model. 2025-02-22 20:01:52 +05:30
notkshitij f11f46b3a5 Added test2 converted from python to js. Using vishnun0027's pretrained model. 2025-02-22 19:51:52 +05:30
notkshitij 9ef589d638 Added more class labels in test 3. 2025-02-22 19:34:37 +05:30
notkshitij 33a634ef7b Test 3 using TonyStarkD99 large model. Works like a charm. Need to increase the class labels. 2025-02-22 19:34:17 +05:30
Bhakti 58cd02b3a5 Glassmorphism added to all parts of landing page 2025-02-22 19:25:24 +05:30
notkshitij ba537242e8 Test 2, using vishnun0027 model. 2025-02-22 19:20:48 +05:30
atharvaombase bf03fa12f6 feat:Added forms to add,update,delete the farm 2025-02-22 19:16:35 +05:30
notkshitij 0b5ef59a62 Working python implementation for wambugu71 model. 2025-02-22 19:05:23 +05:30
atharvaombase c41d788328 feat:Added glass navbar and Dashboard components 2025-02-22 18:48:07 +05:30
Bhakti d5086e21ae converting all parts to glassmorphism 2025-02-22 18:42:03 +05:30
Bhakti 355f13b33d glassmorphism Navbar, bg photo for glassmorphism 2025-02-22 18:41:11 +05:30
Bhakti 68f3efc128 changed website's name in index.html, working on landing page 2025-02-22 17:34:21 +05:30
Bhakti 8db0eeba9a Added images/ logos 2025-02-22 17:33:04 +05:30
atharvaombase 439dbe51b6 fix:Chagned the navbar to default 2025-02-22 17:07:49 +05:30
atharvaombase 8ad01a5c50 feat:1.Added logo 2.changed color palet 2025-02-22 16:47:37 +05:30
atharvaombase d9c299a58f feat:Added total spent card and Removed some typos 2025-02-22 16:01:56 +05:30
notkshitij 33e352a1ef Added one line description in README. 2025-02-22 15:36:19 +05:30
atharvaombase f7cb1af2c4 feat:Added piechart in Dashboard 2025-02-22 15:35:48 +05:30
notkshitij 8438a9a2b7 Fix: Merged main.jsx changes from ombase's branch to bhakti's branch. 2025-02-22 13:29:49 +05:30
atharvaombase 357071b967 fix:main.jsx routing structure changed 2025-02-22 13:21:41 +05:30
notkshitij 75f31b5b93 Added frontend folder structure in Ombase's branch 2025-02-22 13:00:33 +05:30
KaranSalvi 15593af2a9 Added frontend folder structure. 2025-02-22 12:54:00 +05:30
notkshitij 33b5c9ccc8 Added Ombase's name in README file for his branch. 2025-02-22 12:52:15 +05:30
notkshitij 8f13ac6d4b Added Bhakti's name in README for her branch. 2025-02-22 12:50:21 +05:30
941 changed files with 218408 additions and 4858 deletions
+2
View File
@@ -0,0 +1,2 @@
package-lock.json
node_modules/
+2
View File
@@ -1,3 +1,5 @@
package-lock.json
# Logs
logs
*.log
+60
View File
@@ -1,6 +1,7 @@
const Crop = require("../Models/crop.model.js");
const Farm = require("../Models/farm.model.js");
const { uploadOnCloudinary } = require("../Utils/cloudinary.js");
const { run } = require("../Utils/model.js");
// Create a new crop
const createCrop = async (req, res) => {
@@ -145,6 +146,61 @@ const updateHealthStatus = async (req, res) => {
}
};
const cropHarvest = async (req, res) => {
try {
const crop = await Crop.findById(req.params.cropId).populate("farm");
console.log(crop);
const message = `My crop is ${crop.name}, given that I have planted it on ${crop.plantedDate}, suggest me a date as to when it will be harvested. Give output in the form: ${crop.name} will take .. months to harvest around (give month name and year).`; // for harvest expectation
const result = await run(message);
res.status(200).json({ message: result });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const suggestNextCrop = async (req, res) => {
try {
const crop = await Crop.findById(req.params.cropId).populate("farm");
console.log(crop);
const message = `Currently I have ${crop.name} in my field. Considering the best optimal time for its harvestation give my location, ${crop.farm.location} and water content of my field is ${crop.farm.waterContent}. Suggest next crop I should grow and give more suggestions around it. Don't tell me when to harvest ${crop.name}, only tell me next best crop to plant in my field and give suggestions around it.`; // for next sowing suggestion
const result = await run(message);
res.status(200).json({ message: result });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const suggestPesticides = async (req, res) => {
try {
const crop = await Crop.findById(req.params.cropId).populate("farm");
console.log(crop);
const message = `Considering I have grown ${crop.name} in my field located in ${crop.farm.location} and has water content of ${crop.farm.waterContent}. Suggest pesticides I should use on the crop and when to use it considering my sow date is ${crop.sowDate}. Give precautionary measures and suggestions around it.`; // for pesticides
const result = await run(message);
res.status(200).json({ message: result });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const suggestFertilizers = async (req, res) => {
try {
const crop = await Crop.findById(req.params.cropId).populate("farm");
console.log(crop);
const message = `Considering I have grown ${crop.name} in my field located in ${crop.farm.location} and has water content of ${crop.farm.waterContent}. Suggest fertilizers I should use on the crop and when to use it, i.e. after how many months after sowing considering sowing date is ${crop.sowDate} considering my sow date is ${crop.sowDate}. Give me precautionary measures.`; // for fertilizers
const result = await run(message);
res.status(200).json({ message: result });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
module.exports = {
createCrop,
@@ -154,4 +210,8 @@ module.exports = {
deleteCrop,
updateGrowthStage,
updateHealthStatus,
cropHarvest,
suggestNextCrop,
suggestPesticides,
suggestFertilizers,
};
+1
View File
@@ -39,6 +39,7 @@ const getUserFarms = async (req, res) => {
// Get a single farm by ID
const getFarmById = async (req, res) => {
try {
console.log("also i am clla ing", "My farm id is : ", req.params.farmId);
const farm = await Farm.findById(req.params.farmId)
.populate("crops")
.populate("finances");
+47 -1
View File
@@ -2,15 +2,55 @@ const Finance = require("../Models/finance.model.js");
const Farm = require("../Models/farm.model.js");
// Create finance record for a farm
// const createFinance = async (req, res) => {
// try {
// const { farm } = req.body;
// console.log("My farm id is which is going to be created : ", req.body);
// // Check if the farm exists
// const existingFarm = await Farm.findById(farm);
// if (!existingFarm)
// return res.status(404).json({ message: "Farm not found" });
// const finance = new Finance({
// farm,
// transactions: [],
// totalExpenses: 0,
// totalRevenue: 0,
// });
// await finance.save();
// // Link finance to farm
// existingFarm.finances = finance._id;
// await existingFarm.save();
// res.status(201).json(finance);
// } catch (error) {
// res.status(500).json({ message: error.message });
// }
// };
const createFinance = async (req, res) => {
try {
const { farm } = req.body;
console.log("My farm id is which is going to be created : ", farm);
// Check if the farm exists
const existingFarm = await Farm.findById(farm);
if (!existingFarm)
if (!existingFarm) {
return res.status(404).json({ message: "Farm not found" });
}
// Check if finance already exists for this farm
if (existingFarm.finances) {
return res
.status(400)
.json({ message: "Finance already exists for this farm" });
}
// Create finance entry
const finance = new Finance({
farm,
transactions: [],
@@ -50,6 +90,12 @@ const addTransaction = async (req, res) => {
try {
const { type, amount, description } = req.body;
console.log("My type is : ", type);
console.log("My amount is : ", amount);
console.log("My description is : ", description);
console.log("My finance id is : ", req.params.financeId);
const finance = await Finance.findById(req.params.financeId);
if (!finance)
return res.status(404).json({ message: "Finance record not found" });
+22 -7
View File
@@ -4,11 +4,28 @@ const { uploadOnCloudinary } = require("../Utils/cloudinary.js");
const sendEmail = require("../Utils/sendmail.js");
const crypto = require("crypto");
const jwt = require("jsonwebtoken");
const sha1 = require("sha1");
const axios = require("axios");
// Register or Sign up new User -- Done
const registerUser = catchAsyncErrors(async (req, res) => {
const { name, email, password, role } = req.body;
// Strong password policy
const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&]).{8,}$/;
if (!strongPasswordRegex.test(password)) {
return res.status(400).json({ success: false, message: "Password must be at least 8 characters long and include uppercase, lowercase, number, and special character." });
}
// Check for data breach with haveibeenpwned.com
const hashed = sha1(password).toUpperCase();
const prefix = hashed.slice(0, 5);
const suffix = hashed.slice(5);
const response = await axios.get(`https://api.pwnedpasswords.com/range/${prefix}`);
if (response.data.includes(suffix)) {
return res.status(400).json({ success: false, message: "This password has appeared in a data breach. Please choose a different one." });
}
const user = await User.create({
name,
email,
@@ -65,12 +82,12 @@ const loginUser = catchAsyncErrors(async (req, res) => {
return res
.status(200)
.cookie(process.env.TOKEN_NAME, token, {
.cookie("uid", token, {
httpOnly: true, // Prevent access from JavaScript (recommended for security)
secure: false, // ⚠️ Set to `false` for localhost
sameSite: "Lax", // Use "Lax" instead of "None" for better compatibility
path: "/",
sameSite: "None",
secure: process.env.NODE_ENV === "production",
httpOnly: true,
expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
})
.json({
success: true,
@@ -260,8 +277,6 @@ const resetPassword = catchAsyncErrors(async (req, res) => {
// get user personal details
const getUserDetails = catchAsyncErrors(async (req, res) => {
const user = await User.findById(req.user._id);
if (!user) {
+11 -7
View File
@@ -3,19 +3,23 @@ const catchAsyncErrors = require("../Middlewares/catchAsyncErrors.js");
const DB_connect = catchAsyncErrors(async () => {
try {
const connectionInstance = await mongoose.connect(
`${process.env.MONGODB_URI}/${process.env.DATABASE_NAME}`
);
const dbUri = `${process.env.MONGODB_URI}/${process.env.DATABASE_NAME}?authSource=admin`;
const connectionInstance = await mongoose.connect(dbUri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
if (!connectionInstance) {
console.log("MongoDB connection failed");
}
console.log(
"MongoDB connected Successfully on server : " +
} else {
console.log(
"MongoDB connected Successfully to:",
connectionInstance.connection.host
);
);
}
} catch (error) {
console.log("MongoDB connection failed due to some error :", error);
}
});
module.exports = DB_connect;
+1 -1
View File
@@ -2,7 +2,7 @@ const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./public/images");
cb(null, "./uploads");
},
filename: function (req, file, cb) {
+11
View File
@@ -0,0 +1,11 @@
const rateLimit = require("express-rate-limit");
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // limit each IP to 5 login requests per windowMs
message: "Too many login attempts. Try again in 15 minutes.",
standardHeaders: true,
legacyHeaders: false,
});
module.exports = { loginLimiter };
+9
View File
@@ -7,6 +7,10 @@ const {
deleteCrop,
updateHealthStatus,
updateGrowthStage,
cropHarvest,
suggestNextCrop,
suggestPesticides,
suggestFertilizers,
} = require("../Controllers/crop.controller.js");
const { checkAuthenticated } = require("../Middlewares/authentication.js");
const upload = require("../Middlewares/multer.js");
@@ -22,4 +26,9 @@ router.delete("/:cropId", checkAuthenticated, deleteCrop); // Delete a crop
router.put("/health/:cropId", checkAuthenticated, updateHealthStatus);
router.put("/growth/:cropId", checkAuthenticated, updateGrowthStage);
router.get("/harvest/:cropId", checkAuthenticated, cropHarvest);
router.get("/nextCrop/:cropId", checkAuthenticated, suggestNextCrop);
router.get("/pesticides/:cropId", checkAuthenticated, suggestPesticides);
router.get("/fertilizers/:cropId", checkAuthenticated, suggestFertilizers);
module.exports = router;
+3 -1
View File
@@ -19,11 +19,13 @@ const { checkAuthenticated } = require("../Middlewares/authentication.js");
const upload = require("../Middlewares/multer.js");
const { loginLimiter } = require("../Middlewares/rateLimiter");
const router = express.Router();
router.route("/register").post(registerUser);
router.route("/login").post(loginUser);
router.route("/login").post(loginLimiter, loginUser);
router.route("/password/forgot").post(forgetPassword);
+99
View File
@@ -272,6 +272,88 @@
// console.log(result.response.text());
// }
// const {
// GoogleGenerativeAI,
// HarmCategory,
// HarmBlockThreshold,
// } = require("@google/generative-ai");
// const apiKey = "AIzaSyDsXug23r4umgcJpj77KeqNyYW0hQnYDgg";
// const genAI = new GoogleGenerativeAI(apiKey);
// const model = genAI.getGenerativeModel({
// model: "gemini-2.0-flash",
// });
// const generationConfig = {
// temperature: 1,
// topP: 0.95,
// topK: 40,
// maxOutputTokens: 8192,
// responseMimeType: "text/plain",
// };
// async function run(message) {
// const chatSession = model.startChat({
// generationConfig,
// history: [
// {
// role: "user",
// parts: [
// {
// text: "AI Guidelines:\n- The AI must only provide answers related to farming, including crops, sowing, irrigation, harvesting, fertilizers, pesticides, soil health, and climate conditions. \n- The AI must not answer anything outside farming. \n- If asked an unrelated question, the AI must not respond. \n- If the query is unclear, the AI must default to farming-related guidance. \n- The AI must provide only one-line responses without extra details. \n- No harmful, hurtful, or controversial responses. \n- No advice on illegal, unsafe, or unethical farming practices.\n",
// },
// ],
// },
// {
// role: "model",
// parts: [
// {
// text: "Understood. I will only provide one-line responses directly related to farming.\n",
// },
// ],
// },
// {
// role: "user",
// parts: [
// {
// text: "you can also receive json or javascript object as an input ",
// },
// ],
// },
// {
// role: "model",
// parts: [
// {
// text: "Understood. I will process the JSON or JavaScript object only if it pertains to farming and respond with a single line.\n",
// },
// ],
// },
// {
// role: "user",
// parts: [
// {
// text: "Answer everything which falls under the farming and agriculture even if the prompt does not include any farm or agriculture word in it",
// },
// ],
// },
// {
// role: "model",
// parts: [
// {
// text: "Understood. I will assume all queries are related to farming and provide a one-line farming-related response.\n",
// },
// ],
// },
// ],
// });
// const result = await chatSession.sendMessage(message);
// console.log(result.response.text());
// return result.response.text();
// }
const {
GoogleGenerativeAI,
HarmCategory,
@@ -345,11 +427,28 @@ async function run(message) {
},
],
},
{
role: "user",
parts: [
{
text: "Give me a percise answer no matter what, dont give useless or incomplete answer \n",
},
],
},
{
role: "model",
parts: [
{
text: "Understood. I will strive to provide precise and complete one-line farming-related answers.\n",
},
],
},
],
});
const result = await chatSession.sendMessage(message);
console.log(result.response.text());
return result.response.text();
}
module.exports = { run };
+11 -2
View File
@@ -1,6 +1,7 @@
const express = require("express");
const cors = require("cors");
const cookieParser = require("cookie-parser");
const helmet = require("helmet");
const userRoute = require("./Routes/user.routes.js");
const farmRoute = require("./Routes/farm.routes.js");
@@ -17,6 +18,8 @@ dotenv.config({
const app = express();
app.use(helmet()); // Secure headers
const corsOptions = {
origin: process.env.FRONTEND_URI,
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
@@ -30,7 +33,7 @@ app.use(express.static("public"));
app.use(cookieParser());
app.get("/", (req, res) => {
return res.send("Hiddskpkpk...");
return res.send("Server is running...");
});
app.use("/api/v1", userRoute);
@@ -43,6 +46,12 @@ app.use("/api/v1/finance", financeRoute);
app.use("/api/v1/task", taskRoute);
// Redirect HTTP to HTTPS (works behind proxy)
app.use((req, res, next) => {
if (req.headers["x-forwarded-proto"] !== "https" && process.env.NODE_ENV === "production") {
return res.redirect(`https://${req.headers.host}${req.url}`);
}
next();
});
module.exports = app;
-4823
View File
File diff suppressed because it is too large Load Diff
+15 -14
View File
@@ -10,23 +10,24 @@
"license": "ISC",
"description": "",
"dependencies": {
"@google/generative-ai": "^0.22.0",
"@huggingface/transformers": "^3.3.3",
"@xenova/transformers": "^2.17.2",
"bcrypt": "^5.1.1",
"cloudinary": "^2.5.1",
"cookie-parser": "^1.4.6",
"@google/generative-ai": "^0.24.1",
"axios": "^1.6.8",
"bcrypt": "^6.0.0",
"cloudinary": "^2.7.0",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"jimp": "^1.6.0",
"dotenv": "^16.5.0",
"express": "^5.1.0",
"express-rate-limit": "^6.7.0",
"helmet": "^7.0.0",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.6.1",
"multer": "^1.4.5-lts.1",
"nodemailer": "^6.9.15",
"socket.io": "^4.7.5"
"mongoose": "^8.16.0",
"multer": "^2.0.1",
"nodemailer": "^7.0.3",
"sha1": "^1.1.1",
"socket.io": "^4.8.1"
},
"devDependencies": {
"nodemon": "^3.1.4"
"nodemon": "^3.1.10"
}
}
+1
View File
@@ -0,0 +1 @@
VITE_API_URL=http://localhost:8000
+25
View File
@@ -0,0 +1,25 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
package-lock.json
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+142
View File
@@ -0,0 +1,142 @@
{
"hash": "2bafedf9",
"configHash": "7e00041b",
"lockfileHash": "a954eb91",
"browserHash": "c3bc7b53",
"optimized": {
"react": {
"src": "../../node_modules/react/index.js",
"file": "react.js",
"fileHash": "902ee93a",
"needsInterop": true
},
"react-dom/client": {
"src": "../../node_modules/react-dom/client.js",
"file": "react-dom_client.js",
"fileHash": "cfbeda6d",
"needsInterop": true
},
"react-router-dom": {
"src": "../../node_modules/react-router-dom/dist/index.js",
"file": "react-router-dom.js",
"fileHash": "216229fd",
"needsInterop": false
},
"react-redux": {
"src": "../../node_modules/react-redux/dist/react-redux.mjs",
"file": "react-redux.js",
"fileHash": "b9f679da",
"needsInterop": false
},
"@reduxjs/toolkit": {
"src": "../../node_modules/@reduxjs/toolkit/dist/redux-toolkit.modern.mjs",
"file": "@reduxjs_toolkit.js",
"fileHash": "13da79f3",
"needsInterop": false
},
"socket.io-client": {
"src": "../../node_modules/socket.io-client/build/esm/index.js",
"file": "socket__io-client.js",
"fileHash": "ab2fcae8",
"needsInterop": false
},
"react-icons/io": {
"src": "../../node_modules/react-icons/io/index.mjs",
"file": "react-icons_io.js",
"fileHash": "fb80952c",
"needsInterop": false
},
"react-icons/fa6": {
"src": "../../node_modules/react-icons/fa6/index.mjs",
"file": "react-icons_fa6.js",
"fileHash": "da456fb8",
"needsInterop": false
},
"react-icons/ri": {
"src": "../../node_modules/react-icons/ri/index.mjs",
"file": "react-icons_ri.js",
"fileHash": "6e092d47",
"needsInterop": false
},
"react-icons/bs": {
"src": "../../node_modules/react-icons/bs/index.mjs",
"file": "react-icons_bs.js",
"fileHash": "c070a6ed",
"needsInterop": false
},
"react-icons/fa": {
"src": "../../node_modules/react-icons/fa/index.mjs",
"file": "react-icons_fa.js",
"fileHash": "aa81607f",
"needsInterop": false
},
"react-icons/md": {
"src": "../../node_modules/react-icons/md/index.mjs",
"file": "react-icons_md.js",
"fileHash": "60d442c6",
"needsInterop": false
},
"react-icons/io5": {
"src": "../../node_modules/react-icons/io5/index.mjs",
"file": "react-icons_io5.js",
"fileHash": "5d65fe60",
"needsInterop": false
},
"framer-motion": {
"src": "../../node_modules/framer-motion/dist/es/index.mjs",
"file": "framer-motion.js",
"fileHash": "05223771",
"needsInterop": false
},
"react-intersection-observer": {
"src": "../../node_modules/react-intersection-observer/dist/index.mjs",
"file": "react-intersection-observer.js",
"fileHash": "575187c6",
"needsInterop": false
},
"react-chartjs-2": {
"src": "../../node_modules/react-chartjs-2/dist/index.js",
"file": "react-chartjs-2.js",
"fileHash": "07d12b80",
"needsInterop": false
},
"chart.js": {
"src": "../../node_modules/chart.js/dist/chart.js",
"file": "chart__js.js",
"fileHash": "39dbe037",
"needsInterop": false
},
"react-apexcharts": {
"src": "../../node_modules/react-apexcharts/dist/react-apexcharts.min.js",
"file": "react-apexcharts.js",
"fileHash": "2bdb7b94",
"needsInterop": true
},
"react-typewriter-effect": {
"src": "../../node_modules/react-typewriter-effect/dist/index.js",
"file": "react-typewriter-effect.js",
"fileHash": "574603a4",
"needsInterop": true
}
},
"chunks": {
"chunk-UU7TO5PY": {
"file": "chunk-UU7TO5PY.js"
},
"chunk-2YIK36WJ": {
"file": "chunk-2YIK36WJ.js"
},
"chunk-UHINIFCJ": {
"file": "chunk-UHINIFCJ.js"
},
"chunk-SD42HLFO": {
"file": "chunk-SD42HLFO.js"
},
"chunk-W4EHDCLL": {
"file": "chunk-W4EHDCLL.js"
},
"chunk-EWTE5DHJ": {
"file": "chunk-EWTE5DHJ.js"
}
}
}
+100
View File
@@ -0,0 +1,100 @@
import {
Animation,
Animations,
ArcElement,
BarController,
BarElement,
BasePlatform,
BasicPlatform,
BubbleController,
CategoryScale,
Chart,
DatasetController,
DomPlatform,
DoughnutController,
Element,
Interaction,
LineController,
LineElement,
LinearScale,
LogarithmicScale,
PieController,
PointElement,
PolarAreaController,
RadarController,
RadialLinearScale,
Scale,
ScatterController,
Ticks,
TimeScale,
TimeSeriesScale,
_detectPlatform,
adapters,
animator,
controllers,
defaults,
elements,
index,
layouts,
plugin_colors,
plugin_decimation,
plugin_legend,
plugin_subtitle,
plugin_title,
plugin_tooltip,
plugins,
registerables,
registry,
scales
} from "./chunk-2YIK36WJ.js";
import "./chunk-EWTE5DHJ.js";
export {
Animation,
Animations,
ArcElement,
BarController,
BarElement,
BasePlatform,
BasicPlatform,
BubbleController,
CategoryScale,
Chart,
plugin_colors as Colors,
DatasetController,
plugin_decimation as Decimation,
DomPlatform,
DoughnutController,
Element,
index as Filler,
Interaction,
plugin_legend as Legend,
LineController,
LineElement,
LinearScale,
LogarithmicScale,
PieController,
PointElement,
PolarAreaController,
RadarController,
RadialLinearScale,
Scale,
ScatterController,
plugin_subtitle as SubTitle,
Ticks,
TimeScale,
TimeSeriesScale,
plugin_title as Title,
plugin_tooltip as Tooltip,
adapters as _adapters,
_detectPlatform,
animator,
controllers,
defaults,
elements,
layouts,
plugins,
registerables,
registry,
scales
};
//# sourceMappingURL=chart__js.js.map
+7
View File
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+45
View File
@@ -0,0 +1,45 @@
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __esm = (fn, res) => function __init() {
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
export {
__esm,
__commonJS,
__export,
__toESM,
__toCommonJS,
__publicField
};
//# sourceMappingURL=chunk-EWTE5DHJ.js.map
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}
+149
View File
@@ -0,0 +1,149 @@
import {
require_react
} from "./chunk-W4EHDCLL.js";
import {
__toESM
} from "./chunk-EWTE5DHJ.js";
// node_modules/react-icons/lib/iconBase.mjs
var import_react2 = __toESM(require_react(), 1);
// node_modules/react-icons/lib/iconContext.mjs
var import_react = __toESM(require_react(), 1);
var DefaultContext = {
color: void 0,
size: void 0,
className: void 0,
style: void 0,
attr: void 0
};
var IconContext = import_react.default.createContext && import_react.default.createContext(DefaultContext);
// node_modules/react-icons/lib/iconBase.mjs
var _excluded = ["attr", "size", "title"];
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
}
return target;
}
function _extends() {
_extends = Object.assign ? Object.assign.bind() : function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function ownKeys(e, r) {
var t = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var o = Object.getOwnPropertySymbols(e);
r && (o = o.filter(function(r2) {
return Object.getOwnPropertyDescriptor(e, r2).enumerable;
})), t.push.apply(t, o);
}
return t;
}
function _objectSpread(e) {
for (var r = 1; r < arguments.length; r++) {
var t = null != arguments[r] ? arguments[r] : {};
r % 2 ? ownKeys(Object(t), true).forEach(function(r2) {
_defineProperty(e, r2, t[r2]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) {
Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
});
}
return e;
}
function _defineProperty(obj, key, value) {
key = _toPropertyKey(key);
if (key in obj) {
Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true });
} else {
obj[key] = value;
}
return obj;
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function Tree2Element(tree) {
return tree && tree.map((node, i) => import_react2.default.createElement(node.tag, _objectSpread({
key: i
}, node.attr), Tree2Element(node.child)));
}
function GenIcon(data) {
return (props) => import_react2.default.createElement(IconBase, _extends({
attr: _objectSpread({}, data.attr)
}, props), Tree2Element(data.child));
}
function IconBase(props) {
var elem = (conf) => {
var {
attr,
size,
title
} = props, svgProps = _objectWithoutProperties(props, _excluded);
var computedSize = size || conf.size || "1em";
var className;
if (conf.className) className = conf.className;
if (props.className) className = (className ? className + " " : "") + props.className;
return import_react2.default.createElement("svg", _extends({
stroke: "currentColor",
fill: "currentColor",
strokeWidth: "0"
}, conf.attr, attr, svgProps, {
className,
style: _objectSpread(_objectSpread({
color: props.color || conf.color
}, conf.style), props.style),
height: computedSize,
width: computedSize,
xmlns: "http://www.w3.org/2000/svg"
}), title && import_react2.default.createElement("title", null, title), props.children);
};
return IconContext !== void 0 ? import_react2.default.createElement(IconContext.Consumer, null, (conf) => elem(conf)) : elem(DefaultContext);
}
export {
GenIcon
};
//# sourceMappingURL=chunk-SD42HLFO.js.map
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../node_modules/react-icons/lib/iconBase.mjs", "../../node_modules/react-icons/lib/iconContext.mjs"],
"sourcesContent": ["var _excluded = [\"attr\", \"size\", \"title\"];\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } } return target; }\nfunction _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport React from \"react\";\nimport { IconContext, DefaultContext } from \"./iconContext.mjs\";\nfunction Tree2Element(tree) {\n return tree && tree.map((node, i) => /*#__PURE__*/React.createElement(node.tag, _objectSpread({\n key: i\n }, node.attr), Tree2Element(node.child)));\n}\nexport function GenIcon(data) {\n return props => /*#__PURE__*/React.createElement(IconBase, _extends({\n attr: _objectSpread({}, data.attr)\n }, props), Tree2Element(data.child));\n}\nexport function IconBase(props) {\n var elem = conf => {\n var {\n attr,\n size,\n title\n } = props,\n svgProps = _objectWithoutProperties(props, _excluded);\n var computedSize = size || conf.size || \"1em\";\n var className;\n if (conf.className) className = conf.className;\n if (props.className) className = (className ? className + \" \" : \"\") + props.className;\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n stroke: \"currentColor\",\n fill: \"currentColor\",\n strokeWidth: \"0\"\n }, conf.attr, attr, svgProps, {\n className: className,\n style: _objectSpread(_objectSpread({\n color: props.color || conf.color\n }, conf.style), props.style),\n height: computedSize,\n width: computedSize,\n xmlns: \"http://www.w3.org/2000/svg\"\n }), title && /*#__PURE__*/React.createElement(\"title\", null, title), props.children);\n };\n return IconContext !== undefined ? /*#__PURE__*/React.createElement(IconContext.Consumer, null, conf => elem(conf)) : elem(DefaultContext);\n}", "import React from \"react\";\nexport var DefaultContext = {\n color: undefined,\n size: undefined,\n className: undefined,\n style: undefined,\n attr: undefined\n};\nexport var IconContext = React.createContext && /*#__PURE__*/React.createContext(DefaultContext);"],
"mappings": ";;;;;;;;AASA,IAAAA,gBAAkB;;;ACTlB,mBAAkB;AACX,IAAI,iBAAiB;AAAA,EAC1B,OAAO;AAAA,EACP,MAAM;AAAA,EACN,WAAW;AAAA,EACX,OAAO;AAAA,EACP,MAAM;AACR;AACO,IAAI,cAAc,aAAAC,QAAM,iBAA8B,aAAAA,QAAM,cAAc,cAAc;;;ADR/F,IAAI,YAAY,CAAC,QAAQ,QAAQ,OAAO;AACxC,SAAS,yBAAyB,QAAQ,UAAU;AAAE,MAAI,UAAU,KAAM,QAAO,CAAC;AAAG,MAAI,SAAS,8BAA8B,QAAQ,QAAQ;AAAG,MAAI,KAAK;AAAG,MAAI,OAAO,uBAAuB;AAAE,QAAI,mBAAmB,OAAO,sBAAsB,MAAM;AAAG,SAAK,IAAI,GAAG,IAAI,iBAAiB,QAAQ,KAAK;AAAE,YAAM,iBAAiB,CAAC;AAAG,UAAI,SAAS,QAAQ,GAAG,KAAK,EAAG;AAAU,UAAI,CAAC,OAAO,UAAU,qBAAqB,KAAK,QAAQ,GAAG,EAAG;AAAU,aAAO,GAAG,IAAI,OAAO,GAAG;AAAA,IAAG;AAAA,EAAE;AAAE,SAAO;AAAQ;AAC3e,SAAS,8BAA8B,QAAQ,UAAU;AAAE,MAAI,UAAU,KAAM,QAAO,CAAC;AAAG,MAAI,SAAS,CAAC;AAAG,WAAS,OAAO,QAAQ;AAAE,QAAI,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,GAAG;AAAE,UAAI,SAAS,QAAQ,GAAG,KAAK,EAAG;AAAU,aAAO,GAAG,IAAI,OAAO,GAAG;AAAA,IAAG;AAAA,EAAE;AAAE,SAAO;AAAQ;AACtR,SAAS,WAAW;AAAE,aAAW,OAAO,SAAS,OAAO,OAAO,KAAK,IAAI,SAAU,QAAQ;AAAE,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AAAE,UAAI,SAAS,UAAU,CAAC;AAAG,eAAS,OAAO,QAAQ;AAAE,YAAI,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,GAAG;AAAE,iBAAO,GAAG,IAAI,OAAO,GAAG;AAAA,QAAG;AAAA,MAAE;AAAA,IAAE;AAAE,WAAO;AAAA,EAAQ;AAAG,SAAO,SAAS,MAAM,MAAM,SAAS;AAAG;AAClV,SAAS,QAAQ,GAAG,GAAG;AAAE,MAAI,IAAI,OAAO,KAAK,CAAC;AAAG,MAAI,OAAO,uBAAuB;AAAE,QAAI,IAAI,OAAO,sBAAsB,CAAC;AAAG,UAAM,IAAI,EAAE,OAAO,SAAUC,IAAG;AAAE,aAAO,OAAO,yBAAyB,GAAGA,EAAC,EAAE;AAAA,IAAY,CAAC,IAAI,EAAE,KAAK,MAAM,GAAG,CAAC;AAAA,EAAG;AAAE,SAAO;AAAG;AAC9P,SAAS,cAAc,GAAG;AAAE,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AAAE,QAAI,IAAI,QAAQ,UAAU,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC;AAAG,QAAI,IAAI,QAAQ,OAAO,CAAC,GAAG,IAAE,EAAE,QAAQ,SAAUA,IAAG;AAAE,sBAAgB,GAAGA,IAAG,EAAEA,EAAC,CAAC;AAAA,IAAG,CAAC,IAAI,OAAO,4BAA4B,OAAO,iBAAiB,GAAG,OAAO,0BAA0B,CAAC,CAAC,IAAI,QAAQ,OAAO,CAAC,CAAC,EAAE,QAAQ,SAAUA,IAAG;AAAE,aAAO,eAAe,GAAGA,IAAG,OAAO,yBAAyB,GAAGA,EAAC,CAAC;AAAA,IAAG,CAAC;AAAA,EAAG;AAAE,SAAO;AAAG;AACtb,SAAS,gBAAgB,KAAK,KAAK,OAAO;AAAE,QAAM,eAAe,GAAG;AAAG,MAAI,OAAO,KAAK;AAAE,WAAO,eAAe,KAAK,KAAK,EAAE,OAAc,YAAY,MAAM,cAAc,MAAM,UAAU,KAAK,CAAC;AAAA,EAAG,OAAO;AAAE,QAAI,GAAG,IAAI;AAAA,EAAO;AAAE,SAAO;AAAK;AAC3O,SAAS,eAAe,GAAG;AAAE,MAAI,IAAI,aAAa,GAAG,QAAQ;AAAG,SAAO,YAAY,OAAO,IAAI,IAAI,IAAI;AAAI;AAC1G,SAAS,aAAa,GAAG,GAAG;AAAE,MAAI,YAAY,OAAO,KAAK,CAAC,EAAG,QAAO;AAAG,MAAI,IAAI,EAAE,OAAO,WAAW;AAAG,MAAI,WAAW,GAAG;AAAE,QAAI,IAAI,EAAE,KAAK,GAAG,KAAK,SAAS;AAAG,QAAI,YAAY,OAAO,EAAG,QAAO;AAAG,UAAM,IAAI,UAAU,8CAA8C;AAAA,EAAG;AAAE,UAAQ,aAAa,IAAI,SAAS,QAAQ,CAAC;AAAG;AAGvT,SAAS,aAAa,MAAM;AAC1B,SAAO,QAAQ,KAAK,IAAI,CAAC,MAAM,MAAmB,cAAAC,QAAM,cAAc,KAAK,KAAK,cAAc;AAAA,IAC5F,KAAK;AAAA,EACP,GAAG,KAAK,IAAI,GAAG,aAAa,KAAK,KAAK,CAAC,CAAC;AAC1C;AACO,SAAS,QAAQ,MAAM;AAC5B,SAAO,WAAsB,cAAAA,QAAM,cAAc,UAAU,SAAS;AAAA,IAClE,MAAM,cAAc,CAAC,GAAG,KAAK,IAAI;AAAA,EACnC,GAAG,KAAK,GAAG,aAAa,KAAK,KAAK,CAAC;AACrC;AACO,SAAS,SAAS,OAAO;AAC9B,MAAI,OAAO,UAAQ;AACjB,QAAI;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,OACJ,WAAW,yBAAyB,OAAO,SAAS;AACtD,QAAI,eAAe,QAAQ,KAAK,QAAQ;AACxC,QAAI;AACJ,QAAI,KAAK,UAAW,aAAY,KAAK;AACrC,QAAI,MAAM,UAAW,cAAa,YAAY,YAAY,MAAM,MAAM,MAAM;AAC5E,WAAoB,cAAAA,QAAM,cAAc,OAAO,SAAS;AAAA,MACtD,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,aAAa;AAAA,IACf,GAAG,KAAK,MAAM,MAAM,UAAU;AAAA,MAC5B;AAAA,MACA,OAAO,cAAc,cAAc;AAAA,QACjC,OAAO,MAAM,SAAS,KAAK;AAAA,MAC7B,GAAG,KAAK,KAAK,GAAG,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,IACT,CAAC,GAAG,SAAsB,cAAAA,QAAM,cAAc,SAAS,MAAM,KAAK,GAAG,MAAM,QAAQ;AAAA,EACrF;AACA,SAAO,gBAAgB,SAAyB,cAAAA,QAAM,cAAc,YAAY,UAAU,MAAM,UAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,cAAc;AAC3I;",
"names": ["import_react", "React", "r", "React"]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+172
View File
@@ -0,0 +1,172 @@
import {
__commonJS
} from "./chunk-EWTE5DHJ.js";
// node_modules/object-assign/index.js
var require_object_assign = __commonJS({
"node_modules/object-assign/index.js"(exports, module) {
"use strict";
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
function toObject(val) {
if (val === null || val === void 0) {
throw new TypeError("Object.assign cannot be called with null or undefined");
}
return Object(val);
}
function shouldUseNative() {
try {
if (!Object.assign) {
return false;
}
var test1 = new String("abc");
test1[5] = "de";
if (Object.getOwnPropertyNames(test1)[0] === "5") {
return false;
}
var test2 = {};
for (var i = 0; i < 10; i++) {
test2["_" + String.fromCharCode(i)] = i;
}
var order2 = Object.getOwnPropertyNames(test2).map(function(n) {
return test2[n];
});
if (order2.join("") !== "0123456789") {
return false;
}
var test3 = {};
"abcdefghijklmnopqrst".split("").forEach(function(letter) {
test3[letter] = letter;
});
if (Object.keys(Object.assign({}, test3)).join("") !== "abcdefghijklmnopqrst") {
return false;
}
return true;
} catch (err) {
return false;
}
}
module.exports = shouldUseNative() ? Object.assign : function(target, source) {
var from;
var to = toObject(target);
var symbols;
for (var s = 1; s < arguments.length; s++) {
from = Object(arguments[s]);
for (var key in from) {
if (hasOwnProperty.call(from, key)) {
to[key] = from[key];
}
}
if (getOwnPropertySymbols) {
symbols = getOwnPropertySymbols(from);
for (var i = 0; i < symbols.length; i++) {
if (propIsEnumerable.call(from, symbols[i])) {
to[symbols[i]] = from[symbols[i]];
}
}
}
}
return to;
};
}
});
// node_modules/prop-types/lib/ReactPropTypesSecret.js
var require_ReactPropTypesSecret = __commonJS({
"node_modules/prop-types/lib/ReactPropTypesSecret.js"(exports, module) {
"use strict";
var ReactPropTypesSecret = "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";
module.exports = ReactPropTypesSecret;
}
});
// node_modules/prop-types/lib/has.js
var require_has = __commonJS({
"node_modules/prop-types/lib/has.js"(exports, module) {
module.exports = Function.call.bind(Object.prototype.hasOwnProperty);
}
});
// node_modules/prop-types/checkPropTypes.js
var require_checkPropTypes = __commonJS({
"node_modules/prop-types/checkPropTypes.js"(exports, module) {
"use strict";
var printWarning = function() {
};
if (true) {
ReactPropTypesSecret = require_ReactPropTypesSecret();
loggedTypeFailures = {};
has = require_has();
printWarning = function(text) {
var message = "Warning: " + text;
if (typeof console !== "undefined") {
console.error(message);
}
try {
throw new Error(message);
} catch (x) {
}
};
}
var ReactPropTypesSecret;
var loggedTypeFailures;
var has;
function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
if (true) {
for (var typeSpecName in typeSpecs) {
if (has(typeSpecs, typeSpecName)) {
var error;
try {
if (typeof typeSpecs[typeSpecName] !== "function") {
var err = Error(
(componentName || "React class") + ": " + location + " type `" + typeSpecName + "` is invalid; it must be a function, usually from the `prop-types` package, but received `" + typeof typeSpecs[typeSpecName] + "`.This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`."
);
err.name = "Invariant Violation";
throw err;
}
error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
} catch (ex) {
error = ex;
}
if (error && !(error instanceof Error)) {
printWarning(
(componentName || "React class") + ": type specification of " + location + " `" + typeSpecName + "` is invalid; the type checker function must return `null` or an `Error` but returned a " + typeof error + ". You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument)."
);
}
if (error instanceof Error && !(error.message in loggedTypeFailures)) {
loggedTypeFailures[error.message] = true;
var stack = getStack ? getStack() : "";
printWarning(
"Failed " + location + " type: " + error.message + (stack != null ? stack : "")
);
}
}
}
}
}
checkPropTypes.resetWarningCache = function() {
if (true) {
loggedTypeFailures = {};
}
};
module.exports = checkPropTypes;
}
});
export {
require_object_assign,
require_ReactPropTypesSecret,
require_has,
require_checkPropTypes
};
/*! Bundled license information:
object-assign/index.js:
(*
object-assign
(c) Sindre Sorhus
@license MIT
*)
*/
//# sourceMappingURL=chunk-UU7TO5PY.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
{
"type": "module"
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+190
View File
@@ -0,0 +1,190 @@
import {
BarController,
BubbleController,
Chart,
DoughnutController,
LineController,
PieController,
PolarAreaController,
RadarController,
ScatterController
} from "./chunk-2YIK36WJ.js";
import {
require_react
} from "./chunk-W4EHDCLL.js";
import {
__toESM
} from "./chunk-EWTE5DHJ.js";
// node_modules/react-chartjs-2/dist/index.js
var import_react = __toESM(require_react());
var defaultDatasetIdKey = "label";
function reforwardRef(ref, value) {
if (typeof ref === "function") {
ref(value);
} else if (ref) {
ref.current = value;
}
}
function setOptions(chart, nextOptions) {
const options = chart.options;
if (options && nextOptions) {
Object.assign(options, nextOptions);
}
}
function setLabels(currentData, nextLabels) {
currentData.labels = nextLabels;
}
function setDatasets(currentData, nextDatasets) {
let datasetIdKey = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : defaultDatasetIdKey;
const addedDatasets = [];
currentData.datasets = nextDatasets.map((nextDataset) => {
const currentDataset = currentData.datasets.find((dataset) => dataset[datasetIdKey] === nextDataset[datasetIdKey]);
if (!currentDataset || !nextDataset.data || addedDatasets.includes(currentDataset)) {
return {
...nextDataset
};
}
addedDatasets.push(currentDataset);
Object.assign(currentDataset, nextDataset);
return currentDataset;
});
}
function cloneData(data) {
let datasetIdKey = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : defaultDatasetIdKey;
const nextData = {
labels: [],
datasets: []
};
setLabels(nextData, data.labels);
setDatasets(nextData, data.datasets, datasetIdKey);
return nextData;
}
function getDatasetAtEvent(chart, event) {
return chart.getElementsAtEventForMode(event.nativeEvent, "dataset", {
intersect: true
}, false);
}
function getElementAtEvent(chart, event) {
return chart.getElementsAtEventForMode(event.nativeEvent, "nearest", {
intersect: true
}, false);
}
function getElementsAtEvent(chart, event) {
return chart.getElementsAtEventForMode(event.nativeEvent, "index", {
intersect: true
}, false);
}
function ChartComponent(props, ref) {
const { height = 150, width = 300, redraw = false, datasetIdKey, type, data, options, plugins = [], fallbackContent, updateMode, ...canvasProps } = props;
const canvasRef = (0, import_react.useRef)(null);
const chartRef = (0, import_react.useRef)(null);
const renderChart = () => {
if (!canvasRef.current) return;
chartRef.current = new Chart(canvasRef.current, {
type,
data: cloneData(data, datasetIdKey),
options: options && {
...options
},
plugins
});
reforwardRef(ref, chartRef.current);
};
const destroyChart = () => {
reforwardRef(ref, null);
if (chartRef.current) {
chartRef.current.destroy();
chartRef.current = null;
}
};
(0, import_react.useEffect)(() => {
if (!redraw && chartRef.current && options) {
setOptions(chartRef.current, options);
}
}, [
redraw,
options
]);
(0, import_react.useEffect)(() => {
if (!redraw && chartRef.current) {
setLabels(chartRef.current.config.data, data.labels);
}
}, [
redraw,
data.labels
]);
(0, import_react.useEffect)(() => {
if (!redraw && chartRef.current && data.datasets) {
setDatasets(chartRef.current.config.data, data.datasets, datasetIdKey);
}
}, [
redraw,
data.datasets
]);
(0, import_react.useEffect)(() => {
if (!chartRef.current) return;
if (redraw) {
destroyChart();
setTimeout(renderChart);
} else {
chartRef.current.update(updateMode);
}
}, [
redraw,
options,
data.labels,
data.datasets,
updateMode
]);
(0, import_react.useEffect)(() => {
if (!chartRef.current) return;
destroyChart();
setTimeout(renderChart);
}, [
type
]);
(0, import_react.useEffect)(() => {
renderChart();
return () => destroyChart();
}, []);
return import_react.default.createElement("canvas", {
ref: canvasRef,
role: "img",
height,
width,
...canvasProps
}, fallbackContent);
}
var Chart2 = (0, import_react.forwardRef)(ChartComponent);
function createTypedChart(type, registerables) {
Chart.register(registerables);
return (0, import_react.forwardRef)((props, ref) => import_react.default.createElement(Chart2, {
...props,
ref,
type
}));
}
var Line = createTypedChart("line", LineController);
var Bar = createTypedChart("bar", BarController);
var Radar = createTypedChart("radar", RadarController);
var Doughnut = createTypedChart("doughnut", DoughnutController);
var PolarArea = createTypedChart("polarArea", PolarAreaController);
var Bubble = createTypedChart("bubble", BubbleController);
var Pie = createTypedChart("pie", PieController);
var Scatter = createTypedChart("scatter", ScatterController);
export {
Bar,
Bubble,
Chart2 as Chart,
Doughnut,
Line,
Pie,
PolarArea,
Radar,
Scatter,
getDatasetAtEvent,
getElementAtEvent,
getElementsAtEvent
};
//# sourceMappingURL=react-chartjs-2.js.map
File diff suppressed because one or more lines are too long
+39
View File
@@ -0,0 +1,39 @@
import {
require_react_dom
} from "./chunk-UHINIFCJ.js";
import "./chunk-W4EHDCLL.js";
import {
__commonJS
} from "./chunk-EWTE5DHJ.js";
// node_modules/react-dom/client.js
var require_client = __commonJS({
"node_modules/react-dom/client.js"(exports) {
var m = require_react_dom();
if (false) {
exports.createRoot = m.createRoot;
exports.hydrateRoot = m.hydrateRoot;
} else {
i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
exports.createRoot = function(c, o) {
i.usingClientEntryPoint = true;
try {
return m.createRoot(c, o);
} finally {
i.usingClientEntryPoint = false;
}
};
exports.hydrateRoot = function(c, h, o) {
i.usingClientEntryPoint = true;
try {
return m.hydrateRoot(c, h, o);
} finally {
i.usingClientEntryPoint = false;
}
};
}
var i;
}
});
export default require_client();
//# sourceMappingURL=react-dom_client.js.map
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../node_modules/react-dom/client.js"],
"sourcesContent": ["'use strict';\n\nvar m = require('react-dom');\nif (process.env.NODE_ENV === 'production') {\n exports.createRoot = m.createRoot;\n exports.hydrateRoot = m.hydrateRoot;\n} else {\n var i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n exports.createRoot = function(c, o) {\n i.usingClientEntryPoint = true;\n try {\n return m.createRoot(c, o);\n } finally {\n i.usingClientEntryPoint = false;\n }\n };\n exports.hydrateRoot = function(c, h, o) {\n i.usingClientEntryPoint = true;\n try {\n return m.hydrateRoot(c, h, o);\n } finally {\n i.usingClientEntryPoint = false;\n }\n };\n}\n"],
"mappings": ";;;;;;;;;AAAA;AAAA;AAEA,QAAI,IAAI;AACR,QAAI,OAAuC;AACzC,cAAQ,aAAa,EAAE;AACvB,cAAQ,cAAc,EAAE;AAAA,IAC1B,OAAO;AACD,UAAI,EAAE;AACV,cAAQ,aAAa,SAAS,GAAG,GAAG;AAClC,UAAE,wBAAwB;AAC1B,YAAI;AACF,iBAAO,EAAE,WAAW,GAAG,CAAC;AAAA,QAC1B,UAAE;AACA,YAAE,wBAAwB;AAAA,QAC5B;AAAA,MACF;AACA,cAAQ,cAAc,SAAS,GAAG,GAAG,GAAG;AACtC,UAAE,wBAAwB;AAC1B,YAAI;AACF,iBAAO,EAAE,YAAY,GAAG,GAAG,CAAC;AAAA,QAC9B,UAAE;AACA,YAAE,wBAAwB;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAjBM;AAAA;AAAA;",
"names": []
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+293
View File
@@ -0,0 +1,293 @@
"use client";
import {
require_react
} from "./chunk-W4EHDCLL.js";
import {
__toESM
} from "./chunk-EWTE5DHJ.js";
// node_modules/react-intersection-observer/dist/index.mjs
var React = __toESM(require_react(), 1);
var React2 = __toESM(require_react(), 1);
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
var observerMap = /* @__PURE__ */ new Map();
var RootIds = /* @__PURE__ */ new WeakMap();
var rootId = 0;
var unsupportedValue = void 0;
function defaultFallbackInView(inView) {
unsupportedValue = inView;
}
function getRootId(root) {
if (!root) return "0";
if (RootIds.has(root)) return RootIds.get(root);
rootId += 1;
RootIds.set(root, rootId.toString());
return RootIds.get(root);
}
function optionsToId(options) {
return Object.keys(options).sort().filter(
(key) => options[key] !== void 0
).map((key) => {
return `${key}_${key === "root" ? getRootId(options.root) : options[key]}`;
}).toString();
}
function createObserver(options) {
const id = optionsToId(options);
let instance = observerMap.get(id);
if (!instance) {
const elements = /* @__PURE__ */ new Map();
let thresholds;
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
var _a;
const inView = entry.isIntersecting && thresholds.some((threshold) => entry.intersectionRatio >= threshold);
if (options.trackVisibility && typeof entry.isVisible === "undefined") {
entry.isVisible = inView;
}
(_a = elements.get(entry.target)) == null ? void 0 : _a.forEach((callback) => {
callback(inView, entry);
});
});
}, options);
thresholds = observer.thresholds || (Array.isArray(options.threshold) ? options.threshold : [options.threshold || 0]);
instance = {
id,
observer,
elements
};
observerMap.set(id, instance);
}
return instance;
}
function observe(element, callback, options = {}, fallbackInView = unsupportedValue) {
if (typeof window.IntersectionObserver === "undefined" && fallbackInView !== void 0) {
const bounds = element.getBoundingClientRect();
callback(fallbackInView, {
isIntersecting: fallbackInView,
target: element,
intersectionRatio: typeof options.threshold === "number" ? options.threshold : 0,
time: 0,
boundingClientRect: bounds,
intersectionRect: bounds,
rootBounds: bounds
});
return () => {
};
}
const { id, observer, elements } = createObserver(options);
const callbacks = elements.get(element) || [];
if (!elements.has(element)) {
elements.set(element, callbacks);
}
callbacks.push(callback);
observer.observe(element);
return function unobserve() {
callbacks.splice(callbacks.indexOf(callback), 1);
if (callbacks.length === 0) {
elements.delete(element);
observer.unobserve(element);
}
if (elements.size === 0) {
observer.disconnect();
observerMap.delete(id);
}
};
}
function isPlainChildren(props) {
return typeof props.children !== "function";
}
var InView = class extends React.Component {
constructor(props) {
super(props);
__publicField(this, "node", null);
__publicField(this, "_unobserveCb", null);
__publicField(this, "handleNode", (node) => {
if (this.node) {
this.unobserve();
if (!node && !this.props.triggerOnce && !this.props.skip) {
this.setState({ inView: !!this.props.initialInView, entry: void 0 });
}
}
this.node = node ? node : null;
this.observeNode();
});
__publicField(this, "handleChange", (inView, entry) => {
if (inView && this.props.triggerOnce) {
this.unobserve();
}
if (!isPlainChildren(this.props)) {
this.setState({ inView, entry });
}
if (this.props.onChange) {
this.props.onChange(inView, entry);
}
});
this.state = {
inView: !!props.initialInView,
entry: void 0
};
}
componentDidMount() {
this.unobserve();
this.observeNode();
}
componentDidUpdate(prevProps) {
if (prevProps.rootMargin !== this.props.rootMargin || prevProps.root !== this.props.root || prevProps.threshold !== this.props.threshold || prevProps.skip !== this.props.skip || prevProps.trackVisibility !== this.props.trackVisibility || prevProps.delay !== this.props.delay) {
this.unobserve();
this.observeNode();
}
}
componentWillUnmount() {
this.unobserve();
}
observeNode() {
if (!this.node || this.props.skip) return;
const {
threshold,
root,
rootMargin,
trackVisibility,
delay,
fallbackInView
} = this.props;
this._unobserveCb = observe(
this.node,
this.handleChange,
{
threshold,
root,
rootMargin,
// @ts-ignore
trackVisibility,
// @ts-ignore
delay
},
fallbackInView
);
}
unobserve() {
if (this._unobserveCb) {
this._unobserveCb();
this._unobserveCb = null;
}
}
render() {
const { children } = this.props;
if (typeof children === "function") {
const { inView, entry } = this.state;
return children({ inView, entry, ref: this.handleNode });
}
const {
as,
triggerOnce,
threshold,
root,
rootMargin,
onChange,
skip,
trackVisibility,
delay,
initialInView,
fallbackInView,
...props
} = this.props;
return React.createElement(
as || "div",
{ ref: this.handleNode, ...props },
children
);
}
};
function useInView({
threshold,
delay,
trackVisibility,
rootMargin,
root,
triggerOnce,
skip,
initialInView,
fallbackInView,
onChange
} = {}) {
var _a;
const [ref, setRef] = React2.useState(null);
const callback = React2.useRef(onChange);
const [state, setState] = React2.useState({
inView: !!initialInView,
entry: void 0
});
callback.current = onChange;
React2.useEffect(
() => {
if (skip || !ref) return;
let unobserve;
unobserve = observe(
ref,
(inView, entry) => {
setState({
inView,
entry
});
if (callback.current) callback.current(inView, entry);
if (entry.isIntersecting && triggerOnce && unobserve) {
unobserve();
unobserve = void 0;
}
},
{
root,
rootMargin,
threshold,
// @ts-ignore
trackVisibility,
// @ts-ignore
delay
},
fallbackInView
);
return () => {
if (unobserve) {
unobserve();
}
};
},
// We break the rule here, because we aren't including the actual `threshold` variable
// eslint-disable-next-line react-hooks/exhaustive-deps
[
// If the threshold is an array, convert it to a string, so it won't change between renders.
Array.isArray(threshold) ? threshold.toString() : threshold,
ref,
root,
rootMargin,
triggerOnce,
skip,
trackVisibility,
fallbackInView,
delay
]
);
const entryTarget = (_a = state.entry) == null ? void 0 : _a.target;
const previousEntryTarget = React2.useRef(void 0);
if (!ref && entryTarget && !triggerOnce && !skip && previousEntryTarget.current !== entryTarget) {
previousEntryTarget.current = entryTarget;
setState({
inView: !!initialInView,
entry: void 0
});
}
const result = [setRef, state.inView, state.entry];
result.ref = result[0];
result.inView = result[1];
result.entry = result[2];
return result;
}
export {
InView,
defaultFallbackInView,
observe,
useInView
};
//# sourceMappingURL=react-intersection-observer.js.map
File diff suppressed because one or more lines are too long
+1119
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
import {
require_react
} from "./chunk-W4EHDCLL.js";
import "./chunk-EWTE5DHJ.js";
export default require_react();
//# sourceMappingURL=react.js.map
+7
View File
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+8
View File
@@ -0,0 +1,8 @@
# React + Vite
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+38
View File
@@ -0,0 +1,38 @@
import js from '@eslint/js'
import globals from 'globals'
import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
export default [
{ ignores: ['dist'] },
{
files: ['**/*.{js,jsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
settings: { react: { version: '18.3' } },
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...js.configs.recommended.rules,
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
]
+18
View File
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/images/logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Crop Compass</title>
<link
href="https://cdn.jsdelivr.net/npm/flowbite@2.5.1/dist/flowbite.min.css"
rel="stylesheet"
/>
</head>
<body>
<div id="root"></div>
<script src="https://cdn.jsdelivr.net/npm/flowbite@2.5.1/dist/flowbite.min.js"></script>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
+48
View File
@@ -0,0 +1,48 @@
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@reduxjs/toolkit": "^2.2.7",
"@splinetool/react-spline": "^4.0.0",
"apexcharts": "^4.5.0",
"chart.js": "^4.4.8",
"flowbite": "^2.5.1",
"framer-motion": "^12.4.7",
"react": "^18.3.1",
"react-apexcharts": "^1.7.0",
"react-chartjs-2": "^5.3.0",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
"react-intersection-observer": "^9.15.1",
"react-player": "^2.16.0",
"react-redux": "^9.1.2",
"react-router-dom": "^6.26.1",
"react-typewriter-effect": "^1.1.0",
"socket.io-client": "^4.7.5",
"axios": "^1.6.8",
"sha1": "^1.1.1"
},
"devDependencies": {
"@eslint/js": "^9.9.0",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.20",
"eslint": "^9.9.0",
"eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.9.0",
"postcss": "^8.4.45",
"tailwindcss": "^3.4.10",
"vite": "^5.4.1"
}
}
+6
View File
@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

+1
View File
@@ -0,0 +1 @@
<svg viewBox="-2.4 -2.4 28.80 28.80" xmlns="http://www.w3.org/2000/svg" fill="#000000" stroke="#000000"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round" stroke="#CCCCCC" stroke-width="3.2640000000000002"> <title></title> <g id="Complete"> <g id="add-square"> <g> <rect data-name="--Rectangle" fill="none" height="20" id="_--Rectangle" rx="2" ry="2" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.4" width="20" x="2" y="2"></rect> <line fill="none" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.4" x1="15.5" x2="8.5" y1="12" y2="12"></line> <line fill="none" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.4" x1="12" x2="12" y1="15.5" y2="8.5"></line> </g> </g> </g> </g><g id="SVGRepo_iconCarrier"> <title></title> <g id="Complete"> <g id="add-square"> <g> <rect data-name="--Rectangle" fill="none" height="20" id="_--Rectangle" rx="2" ry="2" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.4" width="20" x="2" y="2"></rect> <line fill="none" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.4" x1="15.5" x2="8.5" y1="12" y2="12"></line> <line fill="none" stroke="#ffffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.4" x1="12" x2="12" y1="15.5" y2="8.5"></line> </g> </g> </g> </g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+12
View File
@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
<defs>
</defs>
<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)" >
<path d="M 37.712 41.541 c -2.437 -10.14 2.919 -19.609 8.772 -25.137 c -6.221 11.54 -7.41 20.104 -3.461 33.177 l 2.29 -0.854 c -0.882 -2.464 -1.413 -4.873 -1.685 -7.241 c 8.23 -2.355 13.883 -7.209 15.231 -15.926 C 59.796 13.651 52.042 6.72 43.718 0.117 c 3.04 9.758 -11.581 17.964 -10.296 30.949 c 0.271 2.741 0.697 5.33 1.326 7.825" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(127,178,65); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
<path d="M 34.069 30.999 c 0.917 -12.923 13.599 -21.098 9.649 -30.883 c 1.394 8.216 -9.771 12.38 -12.663 22.195 c -1.575 5.836 -1.151 11.452 3.693 16.579 C 34.119 36.396 33.937 33.751 34.069 30.999 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(113,156,64); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
<polygon points="68.77,61.09 70.46,47.61 43.69,47.61 19.54,47.61 21.23,61.09 " style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(160,126,99); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) "/>
<polyline points="63.11,61.09 59.5,90 44.01,90 30.5,90 26.89,61.09 " style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(160,126,99); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) "/>
<polygon points="62.61,65.09 63.11,61.09 26.89,61.09 27.39,65.09 " style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(145,107,77); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 KiB

View File
+101
View File
@@ -0,0 +1,101 @@
import { useDispatch, useSelector } from "react-redux";
import "./App.css";
// import Navbar from "./components/Navbar";
import Navbar2 from "./components/Navbar2";
import { useEffect, useState } from "react";
import { userSliceActions } from "./store/userSlice";
import { Outlet } from "react-router-dom";
import { BACKEND_URL } from "./constants";
// Simple LanguageSwitcher component
function LanguageSwitcher({ language, setLanguage }) {
return (
<select
value={language}
onChange={(e) => {
setLanguage(e.target.value);
localStorage.setItem("language", e.target.value);
}}
className="absolute top-2 right-2 p-1 rounded border"
aria-label="Select language"
>
<option value="en">English</option>
<option value="hi">Hindi (ि)</option>
<option value="mr">Marathi (मर)</option>
<option value="fr">Français</option>
{/* Add more languages here */}
</select>
);
}
function App() {
const user = useSelector((store) => store.user);
const dispatch = useDispatch();
const loader = useSelector((store) => store.loader);
// Language state, initialized from localStorage or default to 'en'
const [language, setLanguage] = useState(
localStorage.getItem("language") || "en"
);
console.log("Current language:", language);
useEffect(() => {
async function initialiseUser() {
if (user.role === "unloggeduser") {
const responce = await fetch(`${BACKEND_URL}/api/v1/getuser`, {
method: "GET",
credentials: "include",
});
const userData = await responce.json();
dispatch(userSliceActions.addUser(userData.data));
}
}
initialiseUser();
}, []);
return (
<>
<div className="w-full h-auto flex-col relative">
{/* 2. Language Switcher visible on all pages */}
<LanguageSwitcher language={language} setLanguage={setLanguage} />
{/* 3. Pass language as prop to Navbar2 and Outlet if needed */}
<Outlet context={{ language }} />
<div
className={`${
loader ? "block" : "hidden"
} absolute w-full h-full bg-black opacity-50 top-0 left-0`}
>
<div className="text-center my-96">
<div role="status">
<svg
aria-hidden="true"
className="inline w-12 h-12 text-gray-200 animate-spin dark:text-gray-600 fill-blue-900"
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
fill="currentColor"
/>
<path
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
fill="currentFill"
/>
</svg>
<span className="sr-only">Loading...</span>
</div>
</div>
</div>
</div>
</>
);
}
export default App;
+13
View File
@@ -0,0 +1,13 @@
import React from "react";
const LanguageSwitcher = ({ currentLanguage, onChangeLanguage }) => (
<select value={currentLanguage} onChange={e => onChangeLanguage(e.target.value)}>
<option value="en">English</option>
<option value="hi">Hindi (ि)</option>
<option value="mr">Marathi (मर)</option>
<option value="fr">French (Français)</option>
{/* Add more languages as needed */}
</select>
);
export default LanguageSwitcher;
+11
View File
@@ -0,0 +1,11 @@
import React from "react";
const Container = ({ children }) => {
return (
<>
<div className="w-full max-h-screen">{children}</div>
</>
);
};
export default Container;

Some files were not shown because too many files have changed in this diff Show More