From 5bf9f1faff2e5ba990274e5868523e8d27a12da1 Mon Sep 17 00:00:00 2001 From: Abhijeet Shukla Date: Sat, 22 Feb 2025 00:50:24 +0530 Subject: [PATCH 1/2] inital mvp --- .DS_Store | Bin 0 -> 6148 bytes README.md | 2 + cal_predict/cal_api.py | 37 + cal_predict/calorie_model.pkl | Bin 0 -> 624 bytes cal_predict/dockerfile | 17 + cal_predict/requirements.txt | 6 + fit-bite-web/.eslintrc.js | 41 + fit-bite-web/.eslintrc.json | 3 + fit-bite-web/.gitignore | 36 + fit-bite-web/README.md | 34 + fit-bite-web/app/Checkout/page.jsx | 285 + fit-bite-web/app/Context/ChatContext.js | 22 + fit-bite-web/app/Context/SidebarContext.js | 84 + fit-bite-web/app/Context/ThemeContext.js | 58 + fit-bite-web/app/Context/UserProvider.js | 200 + fit-bite-web/app/account/[id]/page.jsx | 371 + fit-bite-web/app/account/page.jsx | 576 ++ fit-bite-web/app/add-restaurant/page.jsx | 348 + .../app/add-restaurant/restaurantTypeData.js | 117 + .../app/add-restaurant/useGeoLocationHook.jsx | 43 + fit-bite-web/app/admin/page.jsx | 250 + fit-bite-web/app/adminSignin/page.jsx | 315 + fit-bite-web/app/aiTrainer/page.jsx | 156 + .../app/api/account/[account]/route.js | 135 + fit-bite-web/app/api/add-product/route.js | 14 + fit-bite-web/app/api/admin/route.js | 63 + fit-bite-web/app/api/ai/route.js | 16 + fit-bite-web/app/api/desserts/route.js | 57 + fit-bite-web/app/api/ecommerce/route.js | 39 + fit-bite-web/app/api/item/route.js | 42 + fit-bite-web/app/api/largeCakes/route.js | 59 + fit-bite-web/app/api/login/route.js | 153 + fit-bite-web/app/api/orderCount/route.js | 39 + fit-bite-web/app/api/orders/[id]/route.js | 71 + fit-bite-web/app/api/orders/route.js | 100 + fit-bite-web/app/api/otherProducts/route.js | 28 + fit-bite-web/app/api/pastries/route.js | 79 + fit-bite-web/app/api/restaurants/route.js | 37 + fit-bite-web/app/api/signup/route.js | 47 + fit-bite-web/app/api/smallCakes/route.js | 58 + fit-bite-web/app/api/stripe/route.js | 219 + fit-bite-web/app/api/testML/route.js | 58 + fit-bite-web/app/api/uploadVideo/route.js | 22 + fit-bite-web/app/api/uploadVideoML/route.js | 63 + fit-bite-web/app/api/webhooks/stripe/route.js | 81 + fit-bite-web/app/chat/page.jsx | 58 + .../app/components/AppHeader copy.jsx | 180 + fit-bite-web/app/components/AppHeader.jsx | 180 + fit-bite-web/app/components/AppSidebar.jsx | 365 + fit-bite-web/app/components/Backdrop.jsx | 17 + fit-bite-web/app/components/CartLayout.jsx | 136 + .../app/components/Ecommerce/CountryMap.jsx | 123 + .../components/Ecommerce/DemographicCard.jsx | 131 + .../Ecommerce/MonthlySalesChart.jsx | 155 + .../components/Ecommerce/MonthlyTarget.jsx | 210 + .../app/components/Ecommerce/RecentOrders.jsx | 211 + .../components/Ecommerce/StatisticsChart.jsx | 150 + .../app/components/Ecommerce/page.jsx | 43 + .../app/components/EcommerceMetrics.jsx | 98 + fit-bite-web/app/components/Filter.jsx | 65 + .../components/FinalRestaurantCreation.jsx | 110 + fit-bite-web/app/components/Footer.jsx | 97 + fit-bite-web/app/components/Navbar.jsx | 379 + .../app/components/RestaurantType.jsx | 95 + .../app/components/RestaurantVerification.jsx | 345 + fit-bite-web/app/components/SidebarWidget.jsx | 25 + fit-bite-web/app/components/Tabs.jsx | 111 + .../app/components/common/ChartTab.jsx | 43 + .../app/components/common/ComponentCard.jsx | 40 + .../app/components/common/GridShape.jsx | 25 + .../app/components/common/PageBreadCrumb.jsx | 52 + .../components/common/ThemeToggleButton.jsx | 42 + fit-bite-web/app/components/form/Form.jsx | 23 + fit-bite-web/app/components/form/Label.jsx | 27 + .../app/components/form/MultiSelect.jsx | 166 + fit-bite-web/app/components/form/Select.jsx | 64 + .../form/example-form/BasicForm.jsx | 38 + .../form/example-form/ExampleFormOne.jsx | 81 + .../form/example-form/ExampleFormTwo.jsx | 166 + .../form/example-form/ExampleFormWithIcon.jsx | 86 + .../form/form-elements/CheckboxComponents.jsx | 37 + .../form/form-elements/DefaultInputs.jsx | 115 + .../form/form-elements/DropZone.jsx | 77 + .../form/form-elements/FileInputExample.jsx | 23 + .../form/form-elements/InputGroup.jsx | 57 + .../form/form-elements/InputStates.jsx | 70 + .../form/form-elements/RadioButtons.jsx | 43 + .../form/form-elements/SelectInputs.jsx | 55 + .../form/form-elements/TextAreaInput.jsx | 43 + .../form/form-elements/ToggleSwitch.jsx | 42 + .../form/group-input/PhoneInput.jsx | 141 + .../app/components/form/input/Checkbox.jsx | 43 + .../app/components/form/input/FileInput.jsx | 18 + .../app/components/form/input/InputField.jsx | 84 + .../app/components/form/input/Radio.jsx | 65 + .../app/components/form/input/RadioSm.jsx | 59 + .../app/components/form/input/TextArea.jsx | 63 + .../app/components/form/switch/Switch.jsx | 73 + .../header/NotificationDropdown.jsx | 384 + .../app/components/header/UserDropdown.jsx | 172 + fit-bite-web/app/components/icons/alert.svg | 15 + .../app/components/icons/angle-down.svg | 12 + .../app/components/icons/angle-left.svg | 0 .../app/components/icons/angle-right.svg | 0 .../app/components/icons/angle-up.svg | 13 + .../app/components/icons/arrow-down.svg | 15 + .../app/components/icons/arrow-right.svg | 15 + .../app/components/icons/arrow-up.svg | 16 + fit-bite-web/app/components/icons/audio.svg | 15 + fit-bite-web/app/components/icons/bell.svg | 14 + fit-bite-web/app/components/icons/bolt.svg | 15 + .../app/components/icons/box-cube.svg | 15 + .../app/components/icons/box-line.svg | 15 + fit-bite-web/app/components/icons/box.svg | 15 + .../app/components/icons/calendar.svg | 13 + .../app/components/icons/calender-line.svg | 3 + fit-bite-web/app/components/icons/chat.svg | 3 + .../app/components/icons/check-circle.svg | 15 + .../app/components/icons/check-line.svg | 15 + .../app/components/icons/chevron-down.svg | 6 + .../app/components/icons/chevron-left.svg | 16 + .../app/components/icons/chevron-up.svg | 3 + .../app/components/icons/close-line.svg | 14 + fit-bite-web/app/components/icons/close.svg | 15 + fit-bite-web/app/components/icons/copy.svg | 15 + fit-bite-web/app/components/icons/docs.svg | 15 + .../app/components/icons/dollar-line.svg | 15 + .../app/components/icons/download.svg | 15 + .../app/components/icons/envelope.svg | 15 + .../app/components/icons/eye-close.svg | 14 + fit-bite-web/app/components/icons/eye.svg | 14 + fit-bite-web/app/components/icons/file.svg | 15 + fit-bite-web/app/components/icons/folder.svg | 13 + fit-bite-web/app/components/icons/grid.svg | 15 + fit-bite-web/app/components/icons/group.svg | 15 + .../app/components/icons/horizontal-dots.svg | 15 + .../app/components/icons/index copy.jsx | 110 + fit-bite-web/app/components/icons/index.jsx | 110 + .../app/components/icons/info-hexa.svg | 15 + fit-bite-web/app/components/icons/info.svg | 15 + fit-bite-web/app/components/icons/list.svg | 15 + fit-bite-web/app/components/icons/lock.svg | 19 + .../app/components/icons/mail-line.svg | 15 + .../app/components/icons/more-dot.svg | 14 + fit-bite-web/app/components/icons/page.svg | 15 + .../app/components/icons/paper-plane.svg | 15 + fit-bite-web/app/components/icons/pencil.svg | 15 + .../app/components/icons/pie-chart.svg | 15 + fit-bite-web/app/components/icons/plug-in.svg | 15 + fit-bite-web/app/components/icons/plus.svg | 14 + .../app/components/icons/shooting-star.svg | 15 + fit-bite-web/app/components/icons/table.svg | 15 + .../app/components/icons/task-icon.svg | 15 + fit-bite-web/app/components/icons/task.svg | 1 + fit-bite-web/app/components/icons/time.svg | 15 + fit-bite-web/app/components/icons/trash.svg | 13 + .../app/components/icons/user-circle.svg | 6 + .../app/components/icons/user-line.svg | 15 + fit-bite-web/app/components/icons/videos.svg | 15 + .../app/components/ui/UserAddressCard.jsx | 134 + .../app/components/ui/badge/Badge.jsx | 62 + .../app/components/ui/button/Button.jsx | 55 + .../app/components/ui/dropdown/Dropdown.jsx | 46 + .../components/ui/dropdown/DropdownItem.jsx | 46 + .../app/components/ui/modal/index.jsx | 95 + fit-bite-web/app/components/ui/popover.jsx | 27 + .../app/components/ui/table/index.jsx | 64 + .../user-profile/UserAddressCard.jsx | 134 + .../components/user-profile/UserInfoCard.jsx | 189 + .../components/user-profile/UserMetaCard.jsx | 227 + fit-bite-web/app/dashboard/layout.jsx | 37 + fit-bite-web/app/dashboard/page.jsx | 43 + fit-bite-web/app/dishdata.js | 533 ++ fit-bite-web/app/dishes/[id]/page.jsx | 242 + .../app/dishes/cakes/large/[id]/page.jsx | 121 + fit-bite-web/app/dishes/cakes/large/page.jsx | 128 + fit-bite-web/app/dishes/cakes/page.jsx | 65 + .../app/dishes/cakes/small/[id]/page.jsx | 121 + fit-bite-web/app/dishes/cakes/small/page.jsx | 94 + .../app/dishes/desserts/[id]/page.jsx | 121 + fit-bite-web/app/dishes/desserts/page.jsx | 94 + fit-bite-web/app/dishes/meals/[id]/page.jsx | 226 + fit-bite-web/app/dishes/meals/page.jsx | 92 + fit-bite-web/app/dishes/others/[id]/page.jsx | 121 + fit-bite-web/app/dishes/others/page.jsx | 99 + fit-bite-web/app/dishes/page.jsx | 249 + .../app/dishes/pastries/[id]/page.jsx | 121 + fit-bite-web/app/dishes/pastries/page.jsx | 135 + fit-bite-web/app/dishes/test/page.jsx | 95 + fit-bite-web/app/error.jsx | 31 + fit-bite-web/app/functions/cart.js | 63 + fit-bite-web/app/functions/subtotal.js | 13 + fit-bite-web/app/globals.css | 475 ++ fit-bite-web/app/hooks/useGoBack.ts | 17 + fit-bite-web/app/hooks/useModal.ts | 12 + fit-bite-web/app/layout.jsx | 53 + fit-bite-web/app/loading.js | 14 + fit-bite-web/app/login/page.jsx | 320 + fit-bite-web/app/middlewares/mongoose.js | 9 + fit-bite-web/app/models/AdminModel.js | 16 + fit-bite-web/app/models/DessertModel.js | 12 + fit-bite-web/app/models/LargeCakesModel.js | 12 + fit-bite-web/app/models/OrderModel.js | 19 + fit-bite-web/app/models/OtherProductModel.js | 19 + fit-bite-web/app/models/PastriesModel.js | 12 + fit-bite-web/app/models/RestaurantModel.js | 33 + fit-bite-web/app/models/SmallCakesModel.js | 12 + fit-bite-web/app/models/UserModel.js | 21 + fit-bite-web/app/not-found.jsx | 14 + fit-bite-web/app/orders/page.jsx | 344 + fit-bite-web/app/output.json | 526 ++ fit-bite-web/app/page.jsx | 122 + .../Ghee Paratha with Dal Makhani.jpg | Bin 0 -> 120912 bytes ...rilled Chicken with Stir-Fried Veggies.jpg | Bin 0 -> 129637 bytes .../Moong Dal Chilla with Mint Chutney.jpg | Bin 0 -> 125294 bytes .../Paneer Bhurji with Multigrain Roti.jpg | Bin 0 -> 103848 bytes .../Peanut Butter Banana Smoothie.jpg | Bin 0 -> 104818 bytes .../Sprouts Salad with Lemon Dressing.jpg | Bin 0 -> 130011 bytes .../app/product-images/testimages.jpg | Bin 0 -> 1173 bytes fit-bite-web/app/profile/page.jsx | 28 + fit-bite-web/app/signup/page.jsx | 378 + fit-bite-web/app/test/page.jsx | 96 + fit-bite-web/app/testML/page.jsx | 63 + fit-bite-web/app/testUrl/page.jsx | 90 + fit-bite-web/components.json | 16 + fit-bite-web/jsconfig.json | 7 + fit-bite-web/lib/getStripe.js | 9 + fit-bite-web/lib/mongodb.js | 13 + fit-bite-web/lib/utils.js | 6 + fit-bite-web/next.config.js | 23 + fit-bite-web/package-lock.json | 6458 +++++++++++++++++ fit-bite-web/package.json | 64 + fit-bite-web/postcss.config.js | 6 + .../public/Ghee Paratha with Dal Makhani.jpg | Bin 0 -> 120912 bytes ...rilled Chicken with Stir-Fried Veggies.jpg | Bin 0 -> 129637 bytes .../Moong Dal Chilla with Mint Chutney.jpg | Bin 0 -> 125294 bytes .../Paneer Bhurji with Multigrain Roti.jpg | Bin 0 -> 103848 bytes .../public/Peanut Butter Banana Smoothie.jpg | Bin 0 -> 104818 bytes .../Sprouts Salad with Lemon Dressing.jpg | Bin 0 -> 130011 bytes fit-bite-web/public/alert.svg | 15 + fit-bite-web/public/angle-down.svg | 12 + fit-bite-web/public/angle-left.svg | 0 fit-bite-web/public/angle-right.svg | 0 fit-bite-web/public/angle-up.svg | 13 + fit-bite-web/public/arrow-down.svg | 15 + fit-bite-web/public/arrow-right.svg | 15 + fit-bite-web/public/arrow-up.svg | 16 + fit-bite-web/public/audio.svg | 15 + fit-bite-web/public/bell.svg | 14 + fit-bite-web/public/bolt.svg | 15 + fit-bite-web/public/box-cube.svg | 15 + fit-bite-web/public/box-line.svg | 15 + fit-bite-web/public/box.svg | 15 + fit-bite-web/public/calendar.svg | 13 + fit-bite-web/public/calender-line.svg | 3 + fit-bite-web/public/chat.svg | 3 + fit-bite-web/public/check-circle.svg | 15 + fit-bite-web/public/check-line.svg | 15 + fit-bite-web/public/chevron-down.svg | 6 + fit-bite-web/public/chevron-left.svg | 16 + fit-bite-web/public/chevron-up.svg | 3 + fit-bite-web/public/close-line.svg | 14 + fit-bite-web/public/close.svg | 15 + fit-bite-web/public/copy.svg | 15 + fit-bite-web/public/docs.svg | 15 + fit-bite-web/public/dollar-line.svg | 15 + fit-bite-web/public/download.svg | 15 + fit-bite-web/public/envelope.svg | 15 + fit-bite-web/public/eye-close.svg | 14 + fit-bite-web/public/eye.svg | 14 + fit-bite-web/public/favicon.ico | Bin 0 -> 16583 bytes fit-bite-web/public/file.svg | 15 + fit-bite-web/public/folder.svg | 13 + fit-bite-web/public/grid.svg | 15 + fit-bite-web/public/group.svg | 15 + fit-bite-web/public/horizontal-dots.svg | 15 + fit-bite-web/public/info-hexa.svg | 15 + fit-bite-web/public/info.svg | 15 + fit-bite-web/public/list.svg | 15 + fit-bite-web/public/lock.svg | 19 + fit-bite-web/public/logo.png | Bin 0 -> 16583 bytes fit-bite-web/public/mail-line.svg | 15 + fit-bite-web/public/more-dot.svg | 14 + fit-bite-web/public/next.svg | 1 + fit-bite-web/public/page.svg | 15 + fit-bite-web/public/paper-plane.svg | 15 + fit-bite-web/public/pencil.svg | 15 + fit-bite-web/public/pie-chart.svg | 15 + fit-bite-web/public/plug-in.svg | 15 + fit-bite-web/public/plus.svg | 14 + fit-bite-web/public/shooting-star.svg | 15 + fit-bite-web/public/table.svg | 15 + fit-bite-web/public/task-icon.svg | 15 + fit-bite-web/public/task.svg | 1 + fit-bite-web/public/testimages.jpg | Bin 0 -> 1173 bytes fit-bite-web/public/time.svg | 15 + fit-bite-web/public/trash.svg | 13 + fit-bite-web/public/user-circle.svg | 6 + fit-bite-web/public/user-line.svg | 15 + fit-bite-web/public/vercel.svg | 1 + fit-bite-web/public/videos.svg | 15 + fit-bite-web/tailwind.config.js | 229 + fit-bite-web/tsconfig.json | 38 + poseangle-app/PoseVideos/1.mov | Bin 0 -> 8355564 bytes poseangle-app/dockerfile | 25 + poseangle-app/poseangle.py | 123 + poseangle-app/requirements.txt | 2 + 307 files changed, 25655 insertions(+) create mode 100644 .DS_Store create mode 100644 README.md create mode 100755 cal_predict/cal_api.py create mode 100755 cal_predict/calorie_model.pkl create mode 100755 cal_predict/dockerfile create mode 100755 cal_predict/requirements.txt create mode 100644 fit-bite-web/.eslintrc.js create mode 100644 fit-bite-web/.eslintrc.json create mode 100644 fit-bite-web/.gitignore create mode 100644 fit-bite-web/README.md create mode 100644 fit-bite-web/app/Checkout/page.jsx create mode 100644 fit-bite-web/app/Context/ChatContext.js create mode 100644 fit-bite-web/app/Context/SidebarContext.js create mode 100644 fit-bite-web/app/Context/ThemeContext.js create mode 100644 fit-bite-web/app/Context/UserProvider.js create mode 100644 fit-bite-web/app/account/[id]/page.jsx create mode 100644 fit-bite-web/app/account/page.jsx create mode 100644 fit-bite-web/app/add-restaurant/page.jsx create mode 100644 fit-bite-web/app/add-restaurant/restaurantTypeData.js create mode 100644 fit-bite-web/app/add-restaurant/useGeoLocationHook.jsx create mode 100644 fit-bite-web/app/admin/page.jsx create mode 100644 fit-bite-web/app/adminSignin/page.jsx create mode 100644 fit-bite-web/app/aiTrainer/page.jsx create mode 100644 fit-bite-web/app/api/account/[account]/route.js create mode 100644 fit-bite-web/app/api/add-product/route.js create mode 100644 fit-bite-web/app/api/admin/route.js create mode 100644 fit-bite-web/app/api/ai/route.js create mode 100644 fit-bite-web/app/api/desserts/route.js create mode 100644 fit-bite-web/app/api/ecommerce/route.js create mode 100644 fit-bite-web/app/api/item/route.js create mode 100644 fit-bite-web/app/api/largeCakes/route.js create mode 100644 fit-bite-web/app/api/login/route.js create mode 100644 fit-bite-web/app/api/orderCount/route.js create mode 100644 fit-bite-web/app/api/orders/[id]/route.js create mode 100644 fit-bite-web/app/api/orders/route.js create mode 100644 fit-bite-web/app/api/otherProducts/route.js create mode 100644 fit-bite-web/app/api/pastries/route.js create mode 100644 fit-bite-web/app/api/restaurants/route.js create mode 100644 fit-bite-web/app/api/signup/route.js create mode 100644 fit-bite-web/app/api/smallCakes/route.js create mode 100644 fit-bite-web/app/api/stripe/route.js create mode 100644 fit-bite-web/app/api/testML/route.js create mode 100644 fit-bite-web/app/api/uploadVideo/route.js create mode 100644 fit-bite-web/app/api/uploadVideoML/route.js create mode 100644 fit-bite-web/app/api/webhooks/stripe/route.js create mode 100644 fit-bite-web/app/chat/page.jsx create mode 100644 fit-bite-web/app/components/AppHeader copy.jsx create mode 100644 fit-bite-web/app/components/AppHeader.jsx create mode 100644 fit-bite-web/app/components/AppSidebar.jsx create mode 100644 fit-bite-web/app/components/Backdrop.jsx create mode 100644 fit-bite-web/app/components/CartLayout.jsx create mode 100644 fit-bite-web/app/components/Ecommerce/CountryMap.jsx create mode 100644 fit-bite-web/app/components/Ecommerce/DemographicCard.jsx create mode 100644 fit-bite-web/app/components/Ecommerce/MonthlySalesChart.jsx create mode 100644 fit-bite-web/app/components/Ecommerce/MonthlyTarget.jsx create mode 100644 fit-bite-web/app/components/Ecommerce/RecentOrders.jsx create mode 100644 fit-bite-web/app/components/Ecommerce/StatisticsChart.jsx create mode 100644 fit-bite-web/app/components/Ecommerce/page.jsx create mode 100644 fit-bite-web/app/components/EcommerceMetrics.jsx create mode 100644 fit-bite-web/app/components/Filter.jsx create mode 100644 fit-bite-web/app/components/FinalRestaurantCreation.jsx create mode 100644 fit-bite-web/app/components/Footer.jsx create mode 100644 fit-bite-web/app/components/Navbar.jsx create mode 100644 fit-bite-web/app/components/RestaurantType.jsx create mode 100644 fit-bite-web/app/components/RestaurantVerification.jsx create mode 100644 fit-bite-web/app/components/SidebarWidget.jsx create mode 100644 fit-bite-web/app/components/Tabs.jsx create mode 100644 fit-bite-web/app/components/common/ChartTab.jsx create mode 100644 fit-bite-web/app/components/common/ComponentCard.jsx create mode 100644 fit-bite-web/app/components/common/GridShape.jsx create mode 100644 fit-bite-web/app/components/common/PageBreadCrumb.jsx create mode 100644 fit-bite-web/app/components/common/ThemeToggleButton.jsx create mode 100644 fit-bite-web/app/components/form/Form.jsx create mode 100644 fit-bite-web/app/components/form/Label.jsx create mode 100644 fit-bite-web/app/components/form/MultiSelect.jsx create mode 100644 fit-bite-web/app/components/form/Select.jsx create mode 100644 fit-bite-web/app/components/form/example-form/BasicForm.jsx create mode 100644 fit-bite-web/app/components/form/example-form/ExampleFormOne.jsx create mode 100644 fit-bite-web/app/components/form/example-form/ExampleFormTwo.jsx create mode 100644 fit-bite-web/app/components/form/example-form/ExampleFormWithIcon.jsx create mode 100644 fit-bite-web/app/components/form/form-elements/CheckboxComponents.jsx create mode 100644 fit-bite-web/app/components/form/form-elements/DefaultInputs.jsx create mode 100644 fit-bite-web/app/components/form/form-elements/DropZone.jsx create mode 100644 fit-bite-web/app/components/form/form-elements/FileInputExample.jsx create mode 100644 fit-bite-web/app/components/form/form-elements/InputGroup.jsx create mode 100644 fit-bite-web/app/components/form/form-elements/InputStates.jsx create mode 100644 fit-bite-web/app/components/form/form-elements/RadioButtons.jsx create mode 100644 fit-bite-web/app/components/form/form-elements/SelectInputs.jsx create mode 100644 fit-bite-web/app/components/form/form-elements/TextAreaInput.jsx create mode 100644 fit-bite-web/app/components/form/form-elements/ToggleSwitch.jsx create mode 100644 fit-bite-web/app/components/form/group-input/PhoneInput.jsx create mode 100644 fit-bite-web/app/components/form/input/Checkbox.jsx create mode 100644 fit-bite-web/app/components/form/input/FileInput.jsx create mode 100644 fit-bite-web/app/components/form/input/InputField.jsx create mode 100644 fit-bite-web/app/components/form/input/Radio.jsx create mode 100644 fit-bite-web/app/components/form/input/RadioSm.jsx create mode 100644 fit-bite-web/app/components/form/input/TextArea.jsx create mode 100644 fit-bite-web/app/components/form/switch/Switch.jsx create mode 100644 fit-bite-web/app/components/header/NotificationDropdown.jsx create mode 100644 fit-bite-web/app/components/header/UserDropdown.jsx create mode 100644 fit-bite-web/app/components/icons/alert.svg create mode 100644 fit-bite-web/app/components/icons/angle-down.svg create mode 100644 fit-bite-web/app/components/icons/angle-left.svg create mode 100644 fit-bite-web/app/components/icons/angle-right.svg create mode 100644 fit-bite-web/app/components/icons/angle-up.svg create mode 100644 fit-bite-web/app/components/icons/arrow-down.svg create mode 100644 fit-bite-web/app/components/icons/arrow-right.svg create mode 100644 fit-bite-web/app/components/icons/arrow-up.svg create mode 100644 fit-bite-web/app/components/icons/audio.svg create mode 100644 fit-bite-web/app/components/icons/bell.svg create mode 100644 fit-bite-web/app/components/icons/bolt.svg create mode 100644 fit-bite-web/app/components/icons/box-cube.svg create mode 100644 fit-bite-web/app/components/icons/box-line.svg create mode 100644 fit-bite-web/app/components/icons/box.svg create mode 100644 fit-bite-web/app/components/icons/calendar.svg create mode 100644 fit-bite-web/app/components/icons/calender-line.svg create mode 100644 fit-bite-web/app/components/icons/chat.svg create mode 100644 fit-bite-web/app/components/icons/check-circle.svg create mode 100644 fit-bite-web/app/components/icons/check-line.svg create mode 100644 fit-bite-web/app/components/icons/chevron-down.svg create mode 100644 fit-bite-web/app/components/icons/chevron-left.svg create mode 100644 fit-bite-web/app/components/icons/chevron-up.svg create mode 100644 fit-bite-web/app/components/icons/close-line.svg create mode 100644 fit-bite-web/app/components/icons/close.svg create mode 100644 fit-bite-web/app/components/icons/copy.svg create mode 100644 fit-bite-web/app/components/icons/docs.svg create mode 100644 fit-bite-web/app/components/icons/dollar-line.svg create mode 100644 fit-bite-web/app/components/icons/download.svg create mode 100644 fit-bite-web/app/components/icons/envelope.svg create mode 100644 fit-bite-web/app/components/icons/eye-close.svg create mode 100644 fit-bite-web/app/components/icons/eye.svg create mode 100644 fit-bite-web/app/components/icons/file.svg create mode 100644 fit-bite-web/app/components/icons/folder.svg create mode 100644 fit-bite-web/app/components/icons/grid.svg create mode 100644 fit-bite-web/app/components/icons/group.svg create mode 100644 fit-bite-web/app/components/icons/horizontal-dots.svg create mode 100644 fit-bite-web/app/components/icons/index copy.jsx create mode 100644 fit-bite-web/app/components/icons/index.jsx create mode 100644 fit-bite-web/app/components/icons/info-hexa.svg create mode 100644 fit-bite-web/app/components/icons/info.svg create mode 100644 fit-bite-web/app/components/icons/list.svg create mode 100644 fit-bite-web/app/components/icons/lock.svg create mode 100644 fit-bite-web/app/components/icons/mail-line.svg create mode 100644 fit-bite-web/app/components/icons/more-dot.svg create mode 100644 fit-bite-web/app/components/icons/page.svg create mode 100644 fit-bite-web/app/components/icons/paper-plane.svg create mode 100644 fit-bite-web/app/components/icons/pencil.svg create mode 100644 fit-bite-web/app/components/icons/pie-chart.svg create mode 100644 fit-bite-web/app/components/icons/plug-in.svg create mode 100644 fit-bite-web/app/components/icons/plus.svg create mode 100644 fit-bite-web/app/components/icons/shooting-star.svg create mode 100644 fit-bite-web/app/components/icons/table.svg create mode 100644 fit-bite-web/app/components/icons/task-icon.svg create mode 100644 fit-bite-web/app/components/icons/task.svg create mode 100644 fit-bite-web/app/components/icons/time.svg create mode 100644 fit-bite-web/app/components/icons/trash.svg create mode 100644 fit-bite-web/app/components/icons/user-circle.svg create mode 100644 fit-bite-web/app/components/icons/user-line.svg create mode 100644 fit-bite-web/app/components/icons/videos.svg create mode 100644 fit-bite-web/app/components/ui/UserAddressCard.jsx create mode 100644 fit-bite-web/app/components/ui/badge/Badge.jsx create mode 100644 fit-bite-web/app/components/ui/button/Button.jsx create mode 100644 fit-bite-web/app/components/ui/dropdown/Dropdown.jsx create mode 100644 fit-bite-web/app/components/ui/dropdown/DropdownItem.jsx create mode 100644 fit-bite-web/app/components/ui/modal/index.jsx create mode 100644 fit-bite-web/app/components/ui/popover.jsx create mode 100644 fit-bite-web/app/components/ui/table/index.jsx create mode 100644 fit-bite-web/app/components/user-profile/UserAddressCard.jsx create mode 100644 fit-bite-web/app/components/user-profile/UserInfoCard.jsx create mode 100644 fit-bite-web/app/components/user-profile/UserMetaCard.jsx create mode 100644 fit-bite-web/app/dashboard/layout.jsx create mode 100644 fit-bite-web/app/dashboard/page.jsx create mode 100644 fit-bite-web/app/dishdata.js create mode 100644 fit-bite-web/app/dishes/[id]/page.jsx create mode 100644 fit-bite-web/app/dishes/cakes/large/[id]/page.jsx create mode 100644 fit-bite-web/app/dishes/cakes/large/page.jsx create mode 100644 fit-bite-web/app/dishes/cakes/page.jsx create mode 100644 fit-bite-web/app/dishes/cakes/small/[id]/page.jsx create mode 100644 fit-bite-web/app/dishes/cakes/small/page.jsx create mode 100644 fit-bite-web/app/dishes/desserts/[id]/page.jsx create mode 100644 fit-bite-web/app/dishes/desserts/page.jsx create mode 100644 fit-bite-web/app/dishes/meals/[id]/page.jsx create mode 100644 fit-bite-web/app/dishes/meals/page.jsx create mode 100644 fit-bite-web/app/dishes/others/[id]/page.jsx create mode 100644 fit-bite-web/app/dishes/others/page.jsx create mode 100644 fit-bite-web/app/dishes/page.jsx create mode 100644 fit-bite-web/app/dishes/pastries/[id]/page.jsx create mode 100644 fit-bite-web/app/dishes/pastries/page.jsx create mode 100644 fit-bite-web/app/dishes/test/page.jsx create mode 100644 fit-bite-web/app/error.jsx create mode 100644 fit-bite-web/app/functions/cart.js create mode 100644 fit-bite-web/app/functions/subtotal.js create mode 100644 fit-bite-web/app/globals.css create mode 100644 fit-bite-web/app/hooks/useGoBack.ts create mode 100644 fit-bite-web/app/hooks/useModal.ts create mode 100644 fit-bite-web/app/layout.jsx create mode 100644 fit-bite-web/app/loading.js create mode 100644 fit-bite-web/app/login/page.jsx create mode 100644 fit-bite-web/app/middlewares/mongoose.js create mode 100644 fit-bite-web/app/models/AdminModel.js create mode 100644 fit-bite-web/app/models/DessertModel.js create mode 100644 fit-bite-web/app/models/LargeCakesModel.js create mode 100644 fit-bite-web/app/models/OrderModel.js create mode 100644 fit-bite-web/app/models/OtherProductModel.js create mode 100644 fit-bite-web/app/models/PastriesModel.js create mode 100644 fit-bite-web/app/models/RestaurantModel.js create mode 100644 fit-bite-web/app/models/SmallCakesModel.js create mode 100644 fit-bite-web/app/models/UserModel.js create mode 100644 fit-bite-web/app/not-found.jsx create mode 100644 fit-bite-web/app/orders/page.jsx create mode 100644 fit-bite-web/app/output.json create mode 100644 fit-bite-web/app/page.jsx create mode 100644 fit-bite-web/app/product-images/Ghee Paratha with Dal Makhani.jpg create mode 100644 fit-bite-web/app/product-images/Grilled Chicken with Stir-Fried Veggies.jpg create mode 100644 fit-bite-web/app/product-images/Moong Dal Chilla with Mint Chutney.jpg create mode 100644 fit-bite-web/app/product-images/Paneer Bhurji with Multigrain Roti.jpg create mode 100644 fit-bite-web/app/product-images/Peanut Butter Banana Smoothie.jpg create mode 100644 fit-bite-web/app/product-images/Sprouts Salad with Lemon Dressing.jpg create mode 100644 fit-bite-web/app/product-images/testimages.jpg create mode 100644 fit-bite-web/app/profile/page.jsx create mode 100644 fit-bite-web/app/signup/page.jsx create mode 100644 fit-bite-web/app/test/page.jsx create mode 100644 fit-bite-web/app/testML/page.jsx create mode 100644 fit-bite-web/app/testUrl/page.jsx create mode 100644 fit-bite-web/components.json create mode 100644 fit-bite-web/jsconfig.json create mode 100644 fit-bite-web/lib/getStripe.js create mode 100644 fit-bite-web/lib/mongodb.js create mode 100644 fit-bite-web/lib/utils.js create mode 100644 fit-bite-web/next.config.js create mode 100644 fit-bite-web/package-lock.json create mode 100644 fit-bite-web/package.json create mode 100644 fit-bite-web/postcss.config.js create mode 100644 fit-bite-web/public/Ghee Paratha with Dal Makhani.jpg create mode 100644 fit-bite-web/public/Grilled Chicken with Stir-Fried Veggies.jpg create mode 100644 fit-bite-web/public/Moong Dal Chilla with Mint Chutney.jpg create mode 100644 fit-bite-web/public/Paneer Bhurji with Multigrain Roti.jpg create mode 100644 fit-bite-web/public/Peanut Butter Banana Smoothie.jpg create mode 100644 fit-bite-web/public/Sprouts Salad with Lemon Dressing.jpg create mode 100644 fit-bite-web/public/alert.svg create mode 100644 fit-bite-web/public/angle-down.svg create mode 100644 fit-bite-web/public/angle-left.svg create mode 100644 fit-bite-web/public/angle-right.svg create mode 100644 fit-bite-web/public/angle-up.svg create mode 100644 fit-bite-web/public/arrow-down.svg create mode 100644 fit-bite-web/public/arrow-right.svg create mode 100644 fit-bite-web/public/arrow-up.svg create mode 100644 fit-bite-web/public/audio.svg create mode 100644 fit-bite-web/public/bell.svg create mode 100644 fit-bite-web/public/bolt.svg create mode 100644 fit-bite-web/public/box-cube.svg create mode 100644 fit-bite-web/public/box-line.svg create mode 100644 fit-bite-web/public/box.svg create mode 100644 fit-bite-web/public/calendar.svg create mode 100644 fit-bite-web/public/calender-line.svg create mode 100644 fit-bite-web/public/chat.svg create mode 100644 fit-bite-web/public/check-circle.svg create mode 100644 fit-bite-web/public/check-line.svg create mode 100644 fit-bite-web/public/chevron-down.svg create mode 100644 fit-bite-web/public/chevron-left.svg create mode 100644 fit-bite-web/public/chevron-up.svg create mode 100644 fit-bite-web/public/close-line.svg create mode 100644 fit-bite-web/public/close.svg create mode 100644 fit-bite-web/public/copy.svg create mode 100644 fit-bite-web/public/docs.svg create mode 100644 fit-bite-web/public/dollar-line.svg create mode 100644 fit-bite-web/public/download.svg create mode 100644 fit-bite-web/public/envelope.svg create mode 100644 fit-bite-web/public/eye-close.svg create mode 100644 fit-bite-web/public/eye.svg create mode 100644 fit-bite-web/public/favicon.ico create mode 100644 fit-bite-web/public/file.svg create mode 100644 fit-bite-web/public/folder.svg create mode 100644 fit-bite-web/public/grid.svg create mode 100644 fit-bite-web/public/group.svg create mode 100644 fit-bite-web/public/horizontal-dots.svg create mode 100644 fit-bite-web/public/info-hexa.svg create mode 100644 fit-bite-web/public/info.svg create mode 100644 fit-bite-web/public/list.svg create mode 100644 fit-bite-web/public/lock.svg create mode 100644 fit-bite-web/public/logo.png create mode 100644 fit-bite-web/public/mail-line.svg create mode 100644 fit-bite-web/public/more-dot.svg create mode 100644 fit-bite-web/public/next.svg create mode 100644 fit-bite-web/public/page.svg create mode 100644 fit-bite-web/public/paper-plane.svg create mode 100644 fit-bite-web/public/pencil.svg create mode 100644 fit-bite-web/public/pie-chart.svg create mode 100644 fit-bite-web/public/plug-in.svg create mode 100644 fit-bite-web/public/plus.svg create mode 100644 fit-bite-web/public/shooting-star.svg create mode 100644 fit-bite-web/public/table.svg create mode 100644 fit-bite-web/public/task-icon.svg create mode 100644 fit-bite-web/public/task.svg create mode 100644 fit-bite-web/public/testimages.jpg create mode 100644 fit-bite-web/public/time.svg create mode 100644 fit-bite-web/public/trash.svg create mode 100644 fit-bite-web/public/user-circle.svg create mode 100644 fit-bite-web/public/user-line.svg create mode 100644 fit-bite-web/public/vercel.svg create mode 100644 fit-bite-web/public/videos.svg create mode 100644 fit-bite-web/tailwind.config.js create mode 100644 fit-bite-web/tsconfig.json create mode 100755 poseangle-app/PoseVideos/1.mov create mode 100755 poseangle-app/dockerfile create mode 100755 poseangle-app/poseangle.py create mode 100755 poseangle-app/requirements.txt diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7683ef5555af20852c00c71b4b5850a2c45be69e GIT binary patch literal 6148 zcmeHKu};G<5IsXBDoUk}j1dDHLpL@;6~3Sg8#GNRNGT4qsAD~|GP3gpNNk7&7AF3v z?`(^@Dvip50NqKx=QwxH-Lq`xh)A_=vL;c3h^lCel})HGgx_;pkTpM22P!*9LD$ry zj4r6VU@Zf}fH3ge7~s8I!*1%7z`Ol#-)g9%tVVVKy{?fygk z{go3dv7e>3ihY>eZp(1obu5CWA=2s4CH1i^oL&c`MHo3v?ndR-VeCZa;Mgrn$@~L7 zi+(kaFn*f6aQq^Fh5_8!EY+Gr(ZYZ*APjsmz~@7R#u$4v4(-taWlI2H1;bX*=URe& zB9F00;}CBk%DDoatMVm=a_$(9yj|?kICSo$eDR_DmzA$jl>Iv9kE}VV*r8})Kp2>3 zVBI}7`2IgyUjNTK$&)Z34E!qwR3&LAEu`e{)`jHwu8q)6(OB5dIJ7QM{yMfDzKXZe atl(Y59boLyIK&7F;u0Zgkg5`lASg?8)s%C3l;QG zO>hvgPds?{;z7J9^VSc?wx8HGNbr zb$|-)bQm`~38N--9O6+4sPmW7%Xw%Ekdj3lSMkI>yn{uZYcWL_S0H@oD(vfVKk6pr z`tZcbV&qAz>4|P6nPNS_fiARws#pNwGz4i<3F<>U4!eotM*^HM?kGlupb6?JBEXNh zR3i43;na2-hNbK z1Dx#CG%BZRYuk^YMKG8O4i5DNg}>Du*4frSn$G^G$r@^^6nn|W?AkG>eEQk#=Z#F> zJ@xx4Hq)$ literal 0 HcmV?d00001 diff --git a/cal_predict/dockerfile b/cal_predict/dockerfile new file mode 100755 index 000000000..235c24d86 --- /dev/null +++ b/cal_predict/dockerfile @@ -0,0 +1,17 @@ +# Use an official Python runtime as a parent image +FROM python:3.10.0 + +# Set the working directory in the container +WORKDIR /app + +# Copy the current directory contents into the container at /app +COPY . /app + +# Install dependencies +RUN pip install --no-cache-dir -r requirements.txt + +# Expose the FastAPI default port +EXPOSE 8000 + +# Run the FastAPI application +CMD ["python", "cal_api.py"] diff --git a/cal_predict/requirements.txt b/cal_predict/requirements.txt new file mode 100755 index 000000000..c7fd83c42 --- /dev/null +++ b/cal_predict/requirements.txt @@ -0,0 +1,6 @@ +fastapi +uvicorn +numpy +pandas +pydantic +scikit-learn \ No newline at end of file diff --git a/fit-bite-web/.eslintrc.js b/fit-bite-web/.eslintrc.js new file mode 100644 index 000000000..620d5211e --- /dev/null +++ b/fit-bite-web/.eslintrc.js @@ -0,0 +1,41 @@ +module.exports = { + env: { + browser:true, + node: true, + es2021: true, + }, + extends: ["eslint:recommended", "plugin:react/recommended", "next/core-web-vitals"], + overrides: [ + { + env: { + node: true, + }, + files: [".eslintrc.{js,cjs}"], + parserOptions: { + sourceType: "script", + }, + }, + { + files: ["*.mjs"], + parserOptions: { + sourceType: "module", + }, + }, + ], + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + }, + plugins: [ + "react"], + rules: { + "react/prop-types": "off", + "react/react-in-jsx-scope": "off", + // allow jsx syntax in js files (for next.js project) + "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],}, + settings: { + react: { + version: "detect", + }, + }, +}; diff --git a/fit-bite-web/.eslintrc.json b/fit-bite-web/.eslintrc.json new file mode 100644 index 000000000..76a186db8 --- /dev/null +++ b/fit-bite-web/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["next/core-web-vitals", "plugin:react-hooks/recommended"] +} diff --git a/fit-bite-web/.gitignore b/fit-bite-web/.gitignore new file mode 100644 index 000000000..45c1abce8 --- /dev/null +++ b/fit-bite-web/.gitignore @@ -0,0 +1,36 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/fit-bite-web/README.md b/fit-bite-web/README.md new file mode 100644 index 000000000..e5f733efc --- /dev/null +++ b/fit-bite-web/README.md @@ -0,0 +1,34 @@ +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/fit-bite-web/app/Checkout/page.jsx b/fit-bite-web/app/Checkout/page.jsx new file mode 100644 index 000000000..8c24cf469 --- /dev/null +++ b/fit-bite-web/app/Checkout/page.jsx @@ -0,0 +1,285 @@ +"use client"; +import React from "react"; + +import "../globals.css"; +import { useState, useEffect } from "react"; +import { addtoCart, removeFromCart } from "../functions/cart"; +import { SubTotal } from "../functions/subtotal"; +import Head from "next/head"; + +import { ToastContainer, toast } from "react-toastify"; +import { useRouter } from "next/navigation"; +import getStripe from "@/lib/getStripe"; +import { UserContext } from "../Context/UserProvider"; +import Image from "next/image"; + +function Page() { + const router = useRouter(); + const [cartData, setcartData] = useState({}); + + const [count, setCount] = useState(0); + const { loggedIn, userData, contextLoading, setCountAgain, login } = + React.useContext(UserContext); + + let userId = userData._id; + + const initiatePayment = async () => { + + if (contextLoading == false) { + login() + if (!loggedIn) { + login() + router.replace("/login"); + } else { + toast.loading("Redirecting..."); + const stripe = await getStripe(); + try { + const response = await fetch("api/stripe", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ cartData, userId }), + }); + + let res = await response.json(); + // console.log(res); + stripe.redirectToCheckout({ + sessionId: res.id, + }); + } catch (e) { + console.log(e); + } + } + } + }; + + useEffect(() => { + if (contextLoading == false) { + login() + } + try { + if (localStorage.getItem("cart")) { + setcartData(JSON.parse(localStorage.getItem("cart"))); + saveCart(JSON.parse(localStorage.getItem("cart"))); + } + } catch (error) { + console.error(error); + localStorage.removeItem("cart"); + } + }, [contextLoading, loggedIn, userData, count, login]); + + const handleClick = () => { + setCount((prev) => prev + 1); + setCountAgain((prev) => prev + 1); + }; + + const saveCart = (myCart) => { + localStorage.setItem("cart", JSON.stringify(myCart)); + }; + // let Subtotal; + // { + // typeof window !== "undefined" && (Subtotal = SubTotal()); + // } + + function CartAmountToggle({ k, cartData }) { + return ( +
+ + + + + + {cartData[k].qty} + +
+ ); + } + + return ( +
+ + {/* {!loggedIn ? ( +
+ Loading... +
+ ) : ( + <> */} +
+ + + + + + + + + + + {Object.keys(cartData).map((k) => { + return ( + + + + + + + ); + })} + +
+ Product + + Qty + + Price +
+ + {cartData[k].productName}{" "} +

+ {" "} + {cartData[k].productName} +

+
+
+ + + ${cartData[k].price?.toFixed(2)} +
+
+
+
+

Subtotal

+

+ {" "} + + {" "} + {" "} + {" "} + {" "} + {" "} + +

+ {typeof window !== "undefined" && ( +

${SubTotal()}

+ )} +
+ +
+

Order Now

+

+ {" "} + + {" "} + {" "} + {" "} + +

+
+
+ {/* + )} */} +
+ ); +} + +export default Page; diff --git a/fit-bite-web/app/Context/ChatContext.js b/fit-bite-web/app/Context/ChatContext.js new file mode 100644 index 000000000..bcad73f3b --- /dev/null +++ b/fit-bite-web/app/Context/ChatContext.js @@ -0,0 +1,22 @@ +"use client"; +import { createContext, useContext, useState } from "react"; + +const ChatContext = createContext(); + +export const ChatProvider = ({ children }) => { + const [messages, setMessages] = useState([]); + + const addMessage = (text, sender) => { + setMessages((prev) => [...prev, { id: Date.now(), text, sender }]); + }; + + return ( + + {children} + + ); +}; + +export const useChat = () => { + return useContext(ChatContext); +}; diff --git a/fit-bite-web/app/Context/SidebarContext.js b/fit-bite-web/app/Context/SidebarContext.js new file mode 100644 index 000000000..1f81fc345 --- /dev/null +++ b/fit-bite-web/app/Context/SidebarContext.js @@ -0,0 +1,84 @@ +"use client"; +import React, { createContext, useContext, useState, useEffect } from "react"; + +// type SidebarContextType = { +// isExpanded: boolean; +// isMobileOpen: boolean; +// isHovered: boolean; +// activeItem: string | null; +// openSubmenu: string | null; +// toggleSidebar: () => void; +// toggleMobileSidebar: () => void; +// setIsHovered: (isHovered: boolean) => void; +// setActiveItem: (item: string | null) => void; +// toggleSubmenu: (item: string) => void; +// }; + +const SidebarContext = createContext(undefined); + +export const useSidebar = () => { + const context = useContext(SidebarContext); + if (!context) { + throw new Error("useSidebar must be used within a SidebarProvider"); + } + return context; +}; + +export const SidebarProvider= ({ + children, +}) => { + const [isExpanded, setIsExpanded] = useState(true); + const [isMobileOpen, setIsMobileOpen] = useState(false); + const [isMobile, setIsMobile] = useState(false); + const [isHovered, setIsHovered] = useState(false); + const [activeItem, setActiveItem] = useState(null); + const [openSubmenu, setOpenSubmenu] = useState(null); + + useEffect(() => { + const handleResize = () => { + const mobile = window.innerWidth < 768; + setIsMobile(mobile); + if (!mobile) { + setIsMobileOpen(false); + } + }; + + handleResize(); + window.addEventListener("resize", handleResize); + + return () => { + window.removeEventListener("resize", handleResize); + }; + }, []); + + const toggleSidebar = () => { + setIsExpanded((prev) => !prev); + }; + + const toggleMobileSidebar = () => { + setIsMobileOpen((prev) => !prev); + }; + + const toggleSubmenu = (item) => { + setOpenSubmenu((prev) => (prev === item ? null : item)); + }; + + return ( + + {children} + + ); +}; diff --git a/fit-bite-web/app/Context/ThemeContext.js b/fit-bite-web/app/Context/ThemeContext.js new file mode 100644 index 000000000..42fd8ba69 --- /dev/null +++ b/fit-bite-web/app/Context/ThemeContext.js @@ -0,0 +1,58 @@ +"use client"; + + +import { createContext, useState, useContext, useEffect } from "react"; + +// type Theme = "light" | "dark"; + +// type ThemeContextType = { +// theme: Theme; +// toggleTheme: () => void; +// }; + +const ThemeContext = createContext(undefined); + +export const ThemeProvider = ({ + children, +}) => { + const [theme, setTheme] = useState("light"); + const [isInitialized, setIsInitialized] = useState(false); + + useEffect(() => { + // This code will only run on the client side + const savedTheme = localStorage.getItem("theme"); + const initialTheme = savedTheme || "light"; // Default to light theme + + setTheme(initialTheme); + setIsInitialized(true); + }, []); + + useEffect(() => { + if (isInitialized) { + localStorage.setItem("theme", theme); + if (theme === "dark") { + document.documentElement.classList.add("dark"); + } else { + document.documentElement.classList.remove("dark"); + } + } + }, [theme, isInitialized]); + + const toggleTheme = () => { + setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light")); + }; + + return ( + + {children} + + ); +}; + +export const useTheme = () => { + const context = useContext(ThemeContext); + if (context === undefined) { + throw new Error("useTheme must be used within a ThemeProvider"); + } + return context; +}; diff --git a/fit-bite-web/app/Context/UserProvider.js b/fit-bite-web/app/Context/UserProvider.js new file mode 100644 index 000000000..edac7b3d2 --- /dev/null +++ b/fit-bite-web/app/Context/UserProvider.js @@ -0,0 +1,200 @@ +"use client"; +import React, { useCallback, useEffect, useState } from "react"; +var jwt = require("jsonwebtoken"); +const UserContext = React.createContext({ + loggedIn: true, + setLoggedIn: ()=>{}, + adminloggedIn: true, + setAdminLoggedIn: ()=>{}, + admin: null, + user: null, + contextLoading: true, + userData: "", + setCountAgain: () => {}, + cartData: 0, + // cart: null, + login: () => {}, + logout: () => {}, + adminlogin: () => {}, + adminlogout: () => {}, +}); +const UserProvider = ({ children }) => { + const [loggedIn, setLoggedIn] = useState(true); + const [adminloggedIn, setAdminLoggedIn] = useState(false); + const [contextLoading, setContextLoading] = useState(true); + const [user, setUser] = useState({ value: null }); + const [admin, setAdmin] = useState({ value: null }); + const [userData, setUserData] = useState({}); + const [countAgain, setCountAgain] = useState(0); + const [cartData, setcartData] = useState(0); + + + + + const getUser = useCallback(async(token)=> { + // if (loggedIn) { + if (token) { + setUser({ value: token }); + try { + let decodedToken = jwt.decode(token); + // console.log("decoded token", decodedToken); + return decodedToken; + } catch (e) { + console.log("token verification failed"); + setContextLoading(false); + } + } else { + + console.log("token not found"); + logout() + setContextLoading(false); + } + }, []) + const loginUser = useCallback(async(decodedToken) => { + try { + if (decodedToken) { + // console.log("token found", decodedToken.Email); + const response = await fetch( + `/api/login/?userEmail=${decodedToken.Email}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + let responseData = await response.json(); + // console.log("response data", responseData.result[0].Email); + if (response.status === 200) { + setUserData(responseData.result[0]); + setLoggedIn(true); + setContextLoading(false); + // if (decodedToken.Email === responseData.result[0].Email) { + // console.log("User found with that token. Verified"); + // setLoggedIn(true); + // // console.log("token found"); + // setContextLoading(false); + // } + } else { + console.log("User not found | Login Again"); + logout(); + + setContextLoading(false); + } + } + } catch (e) { + console.log("Error", e.message); + } + },[]) + // async function verifyToken(decodedToken) { + // if (decodedToken) { + // if (decodedToken.Email) { + // console.log("Token seems to be correct"); + // setLoggedIn(true); + // // console.log("token found"); + // setContextLoading(false); + // } else { + // logout(); + // setContextLoading(false); + // } + // if (decodedToken.Email === userEmail) { + // console.log("token verified successfully"); + // setLoggedIn(true); + // // console.log("token found"); + // setContextLoading(false); + // } else { + // // If no token in local storage, set loggedIn to false + // console.log("Will implement verification feature in the future"); + // setLoggedIn(true); + // setContextLoading(false); + // } + // } + // } +// const stableLoginUser = useCallback(loginUser, []); +// const stableGetUser = useCallback(getUser, []); + useEffect(() => { + if (window !== undefined) { + const token = localStorage.getItem("token"); + + const adminToken = localStorage.getItem("adminToken") || null; + + // console.log({ adminToken }); + if (adminToken) { + setAdmin({ value: adminToken }); + // console.log("admin logged in"); + setAdminLoggedIn(true); + setContextLoading(false); + } else { + // console.log("No admin Token found"); + setAdminLoggedIn(false); + setContextLoading(false); + } + getUser(token, adminToken).then((user) => { + loginUser(user); + }); + } + }, [loggedIn, adminloggedIn, loginUser, getUser]); + useEffect(() => { + // console.log("cart") + let keys = Object.keys(JSON.parse(localStorage.getItem("cart")) || {}); + if (keys.length > 0) { + setcartData( + Object.values(JSON.parse(localStorage.getItem("cart"))).reduce( + (acc, item) => acc + item.qty, + 0 + ) + ); + } + // let cartDataLength = keys.length; + // console.log({cartDataLength}); + // setcartData(cartDataLength); + }, [countAgain]); + + const login = useCallback(() => { + if (user.value) { + setLoggedIn(true); + // console.log("Token exists, user logged in"); + } + },[user.value]); + const adminlogin = () => { + if (admin.value != null) { + setAdminLoggedIn(true); + // console.log("Admin Token exists, Admin logged in"); + } else { + adminlogout(); + } + }; + + const adminlogout = () => { + setAdminLoggedIn(false); + localStorage.removeItem("adminToken"); + }; + const logout = () => { + localStorage.removeItem("token"); + setLoggedIn(false); + }; + + return ( + + {children} + + ); +}; +export { UserContext, UserProvider }; diff --git a/fit-bite-web/app/account/[id]/page.jsx b/fit-bite-web/app/account/[id]/page.jsx new file mode 100644 index 000000000..85870c0ca --- /dev/null +++ b/fit-bite-web/app/account/[id]/page.jsx @@ -0,0 +1,371 @@ +"use client"; +import React, { useEffect, useState } from "react"; +import { UserContext } from "@/app/Context/UserProvider"; +import { menuData } from "../../dishdata"; +import Link from "next/link"; +import { addtoCart } from "@/app/functions/cart"; +import { useRouter } from "next/navigation"; +import { ToastContainer, toast } from "react-toastify"; +import Image from "next/image"; +import "react-toastify/dist/ReactToastify.css"; +//when you place a order the dishes of different restaurant should be in order dashboard for those restaurants only +function page({ params }) { + const [slug, setSlug] = useState(params.id); + const [dish, setDish] = useState({}); + const { setCountAgain } = React?.useContext(UserContext); + const [itemData, setitemData] = useState([]); + const [submitted, setSubmitted] = useState(false); + const [errors, setErrors] = useState({ }); + + const [isChecked, setIsChecked] = useState({ checked: false }); + const [formData, setFormData] = useState({ + name: "", + Description: "", + Price: 0, + Carbohydrates:0, + Protein:0, + Fat: 0, + Calories:0, + restaurantId:slug, + type:"" + }); + let router = useRouter(); + // async function render() { + + // try { + // const response = await fetch(`/api/item?id=${slug}&dish=desserts`, { + // method: "GET", + // }); + // if (response) { + // setitemData(res.result); + // // console.log(res.result, "response orders"); + // } + // }catch (err) { + // console.log(err) + // } + // } + const handleInputChange = (e) => { + let name = e.target.name; + let value = e.target.value; + + setFormData((prevData) => ({ + ...prevData, + [name]: value, + restaurantId: slug, + image: "https://res.cloudinary.com/dkv7cimyy/image/upload/v1740123654/hack2/k7y0mnlaufgojdj3g47t.jpg", + + })); +} + + +// Handle form submission + const handleSubmit = async (e) => { + e.preventDefault(); + + // setActiveStep(2) + // Convert form data to JSON + // const jsonData = JSON.stringify(formData, null, 2); + setErrors({}) + const validationErrors = {}; + + if (!formData.name) { + validationErrors.name = "Please enter product name."; + } + + if (!formData.Description) { + validationErrors.Description = "Description is required."; + } + + + if (Object.keys(validationErrors).length > 0) { + setErrors(validationErrors); + } + + // { "username": "Abhi", + // "ContactNumber": 679234567890, + // "Email": "abhi2y@email.com", + // "Password": "abhi", + // "Address": "PNT Colony" + // } + // Log the JSON data (you can send it to a server or save it as needed) + + // Convert form data to JSON + const jsonDataFinal = JSON.stringify(formData, null, 2); + console.log("String form Data Final", jsonDataFinal); + // console.log("String form Data Final", jsonDataFinal); + if (Object.keys(validationErrors).length == 0) { + try { + const response = await fetch(`/api/add-product`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: jsonDataFinal, + }); + + if (response.status === 200) { + setSubmitted(true); + // console.log("Form data submitted successfully", formData); + toast.success("😎 Product created successfully!", { + position: "bottom-center", + autoClose: 5000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "dark", + }); + setTimeout(() => { + router.replace("/dishes"); + }, 3000); + setFormData({ + username: "", + ContactNumber: 0, + Address: "", + Email: "", + Password: "", + }); + } else { + console.error("Form submission failed"); + } + } catch (error) { + console.error("Error:", error); + }} + + + // console.log(formData); + }; + + return ( +
+

Add Product

+
+ +
+ Logo + {/*

+ Zomato +

*/} +
+
+
+
+ + + {errors.name && ( +

{errors.name}

+ )} + {/*

+ Please enter your desired Username +

*/} +
+ +
+ + + {errors.Description && ( +

{errors.Description}

+ )} + {/*

+ Please choose a password. +

*/} +
+ + + +
+ + + {errors.Price && ( +

{errors.Price}

+ )} + {/*

+ Please choose a password. +

*/} +
+
+ + + {errors.Protein && ( +

{errors.Protein}

+ )} + {/*

+ Please choose a password. +

*/} + + + + {errors.Calories && ( +

{errors.Calories}

+ )} + {/*

+ Please choose a password. +

*/} +
+
+ + + + {errors.Carbohydrates && ( +

{errors.Carbohydrates}

+ )} + {/*

+ Please choose a password. +

*/} + + + + {errors.Fat && ( +

{errors.Fat}

+ )} + {/*

+ Please choose a password. +

*/} +
+ + +
+ +

+ ©2023 Fit-Bite. All rights reserved. +

+
+
+
+ ); +} + +export default page; diff --git a/fit-bite-web/app/account/page.jsx b/fit-bite-web/app/account/page.jsx new file mode 100644 index 000000000..6ec8d6bb0 --- /dev/null +++ b/fit-bite-web/app/account/page.jsx @@ -0,0 +1,576 @@ +"use client"; +import React from "react"; +import { UserContext } from "../Context/UserProvider"; +import Image from "next/image"; +import { useState, useEffect, useCallback } from "react"; + +import "../globals.css"; +import { ToastContainer, toast } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; +import { useRouter } from "next/navigation"; + +function Page() { + // console.log(restaurantTypes.items[0]) + const { loggedIn, userData, contextLoading } = React.useContext(UserContext); + + let [toggleEdit, SetToggleEdit] = useState(false); + let [toggleRestaurants, SetToggleRestaurants] = useState(false); + const [errors, setErrors] = useState({ default: "default is required" }); + const [submitted, setSubmitted] = useState(false); + const [restaurantData, setRestaurantData] = useState({}); + + const router = useRouter(); + + // console.log(userData?.username, "above form"); + const [formData, setFormData] = useState({ + username: "", + ContactNumber: 0, + Address: "", + Email: "", + Password: "", + }); + + // Handle input changes and update state + const handleInputChange = (e) => { + let name = e.target.name; + let value = e.target.value; + + setFormData((prevData) => ({ + ...prevData, + [name]: value, + })); + //Validation Logic Here + const validationErrors = {}; + + if (formData.username.length > 0 && formData.username.length < 4) { + validationErrors.username = + "Username should have more than 4 characters."; + } + if (formData.Password.length > 0 && formData.Password.length < 5) { + validationErrors.Password = "Password should be atleast of 5 characters."; + } + console.log( + formData.Password.includes(formData.username), + formData.Password.length > 0 + ); + if ( + formData.Password.length > 0 && + formData.Password.includes(formData.username) + ) { + validationErrors.Password = "Username should not be used as a password."; + } + if (formData.Email.length > 1 && formData.Email.length < 10) { + validationErrors.Email = "Please enter correct E-mail id"; + } + if ( + formData.ContactNumber.length > 0 && + formData.ContactNumber.length < 10 && + formData.ContactNumber.length > 10 + ) { + validationErrors.ContactNumber = "Please enter correct Contact Number"; + } + + if (Object.keys(validationErrors).length > 0) { + setErrors(validationErrors); + } else { + setErrors(validationErrors); + } + }; + const isFormValid = () => { + // Check if there are any errors in the errors state + return Object.values(errors).every((error) => error === ""); + }; + // Handle form submission + const handleSubmit = async (id, e) => { + e.preventDefault(); + + const validationErrors = {}; + + if (formData.username.length > 0 && formData.username.length < 4) { + validationErrors.username = + "Username should have more than 4 characters."; + } + + if (formData.Password.length > 0 && formData.Password.length < 5) { + validationErrors.Password = "Password should be atleast of 5 characters."; + } + + if (formData.Password.includes(formData.username)) { + validationErrors.Password = "Username should not be used as a password."; + } + if (formData.Email.length > 1 && formData.Email.length < 10) { + validationErrors.Email = "Please enter correct E-mail id"; + } + if ( + formData.ContactNumber.length > 0 && + formData.ContactNumber.length < 10 && + formData.ContactNumber.length > 10 + ) { + validationErrors.ContactNumber = "Please enter correct Contact Number"; + } + + if (Object.keys(validationErrors).length > 0) { + setErrors(validationErrors); + } + + // { "username": "Abhi", + // "ContactNumber": 679234567890, + // "Email": "abhi2y@email.com", + // "Password": "abhi", + // "Address": "California" + // } + // Log the JSON data (you can send it to a server or save it as needed) + + // Convert form data to JSON + const jsonDataFinal = JSON.stringify(formData, null, 2); + // console.log("String form Data Final", jsonDataFinal); + try { + const response = await fetch(`/api/account/${id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: jsonDataFinal, + }); + let res = await response.json(); + if (response.status === 200) { + toast.success("😎 AccountInfo updated successfully!", { + position: "bottom-center", + autoClose: 5000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "dark", + }); + // console.log(res.token) + if (res.token) { + localStorage.setItem("token", res.token); + } + setSubmitted(true); + console.log("Account Information Successfully Updated", formData); + setTimeout(() => { + router.push("/"); + }, 3000); + setFormData({ + username: "", + ContactNumber: 0, + Address: "", + Email: "", + Password: "", + }); + } else { + toast.error("👹 Invalid Data! Try Again.", { + position: "bottom-center", + autoClose: 5000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "dark", + }); + console.error("Form submission failed"); + } + } catch (error) { + console.error("Error:", error); + } + // console.log(formData); + }; + // mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true }); + // setTimeout(() => { + // const decoded = jwt.decode(user.value); + + // if (loggedIn) { + // // let token = localStorage.getItem('token') + // console.log(decoded); + // } + // if (decoded.Email) { + + // const user = User.find({ + // Email: decoded.Email, + // }); + // console.log("user", user); + // } + // }, 5000); + const getRestaurant = useCallback(async() =>{ + try { + if (userData._id) { + // console.log("user ID found", userData._id); + const response = await fetch( + `/api/restaurants/?userId=${userData._id}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + let responseData = await response.json(); + // console.log("response data", responseData.result[0].Email); + if (response.status === 200) { + // console.log("response status", responseData.result[0].restaurantType.items) + // console.log(responseData.result, "response data result"); + // setRestaurantType(responseData.result[0].restaurantType); + setRestaurantData(responseData.result); + + // if (decodedToken.Email === responseData.result[0].Email) { + // console.log("User found with that token. Verified"); + // setLoggedIn(true); + // // console.log("token found"); + // setContextLoading(false); + // } + } else { + console.log("No restaurants found | Login Again"); + } + } + } catch (e) { + console.log("Error", e.message); + } + },[userData._id]) + useEffect(() => { + if (contextLoading == false) { + if (loggedIn) { + // console.log(userData?.username); + + getRestaurant(); + } + if (!loggedIn) { + console.log("else from orders page is getting triggered"); + + router.push("/login"); + } + } + }, [loggedIn, userData, submitted, contextLoading, getRestaurant, router]); + function editInfo() { + SetToggleEdit(!toggleEdit); + } + function restaurantInfo() { + SetToggleRestaurants(!toggleRestaurants); + } + + return ( +
+ +
+ Loading... +
+ +

Account Information

+
+ + {" "} + {" "} + {" "} + + + 🙅‍♂️ + +
+

+ {userData?.username}, How are you? +

+

+ Email: {userData?.Email} +

+

+ Contact Number:{" "} + {userData?.ContactNumber} +

+

+ Address:{" "} + {userData?.Address} +

+
+
+ {toggleEdit ? ( +
+
{ + handleSubmit(userData._id, e); + }} + action="/api/account" + method="PUT" + className="border + border-purple-400 rounded-xl px-8 pt-6 pb-8 mb-4" + > +
+
+ + + {errors.username && ( +

+ {errors.username} +

+ )} +
+
+ + + {errors.Email && ( +

+ {errors.Email} +

+ )} +
+
+ + + {errors.Password && ( +

+ {errors.Password} +

+ )} +
+
+ + + {errors.ContactNumber && ( +

+ {errors.ContactNumber} +

+ )} +
+ Logo +
+
+ + + {errors.Address && ( +

+ {errors.Address} +

+ )} + {/*

+ Please enter your Delivery Address. +

*/} +
+ +
+
+ ) : ( + "" + )} + + {/* RESTAURANT DATA */} +
restaurantInfo()} + className={`text-gray-600 body-font cursor-pointer p-6 m-8 ml-0 w-fit ${ + restaurantData && restaurantData.length > 0 ? "block" : "hidden" + }`} + > + {!toggleRestaurants ? "View" : "Hide"} Restaurants +
+ {toggleRestaurants ? ( +
+ {restaurantData && + restaurantData.map((item, index) => ( +
router.push(`/account/${item._id}`)} + > +

+ Restaurant Details +

+ {/*

+ Get ready with your menu card 🎉 +

*/} + +

+ Restaurant Name:{" "} + + {item.restaurantName} + {/* {console.log(item.restaurantName, "restaurantName")} */} + +

+

+ Contact Number:{" "} + + {item.restaurantContactNumber} + +

+

+ E-mail:{" "} + + {item.restaurantEmail} + +

+

+ Restaurant Address:{" "} + + {item.restaurantAddress} + +

+

+ Restaurant Latitude:{" "} + {item.restaurantLat} +

+

+ Restaurant Longitude:{" "} + {item.restaurantLng} +

+ {/*
    + {jsonDataObj.map((item) => ( +
  • +

    Name: {item.name}

    +

    Description: {item.description}

    +
  • + ))} +
*/} +

+ RestaurantType +

+ {/* //
*/} + + {/* {restaurantType && restaurantType.items && restaurantType.items.map((item, index) => ( */} + {/*
    */} + {item.restaurantType.items.map((item, index) => ( +
  • + + Name: {item.name} + +

    + Description:{" "} + + {item.description} + +

    +
  • + ))} + {/*
*/} + {/* ))} */} + + {/*

+ Our team will soon reach out to you! +

*/} +
+ ))} +
+ ) : ( + "" + )} +
+
+ ); +} + +export default Page; diff --git a/fit-bite-web/app/add-restaurant/page.jsx b/fit-bite-web/app/add-restaurant/page.jsx new file mode 100644 index 000000000..6150620a9 --- /dev/null +++ b/fit-bite-web/app/add-restaurant/page.jsx @@ -0,0 +1,348 @@ +"use client"; +import React, { useState, useEffect } from "react"; +import Tabs from "../components/Tabs"; +import RestaurantType from "../components/RestaurantType"; +import { UserContext } from "../Context/UserProvider"; +import useGeoLocation from "./useGeoLocationHook"; +import { useRouter } from "next/navigation"; +import { CldUploadWidget } from 'next-cloudinary'; +function CreateRestaurant() { + const location = useGeoLocation(); + const { loggedIn, contextLoading, userData, login } = + React.useContext(UserContext); + + let router = useRouter(); + + const [formData, setFormData] = useState({ + restaurantName: "", + restaurantContactNumber: 0, + restaurantEmail: "", + restaurantAddress: "", + restaurantLat: location.coordinates?.lat || "Not Available", + restaurantLng: location.coordinates?.lng || "Not Available", + restaurantType: { + items: [ + { + name: "", + description: "", + }, + ], + }, + }); + useEffect(() => { + if (contextLoading == false) { + login(); + setFormData((prevFormData) => ({ + ...prevFormData, + restaurantLat: location.coordinates?.lat || "", + restaurantLng: location.coordinates?.lng || "", + })); + if (!loggedIn) { + login(); + setTimeout(() => { + router.push("/login"); + }, 2000); + } + } + }, [loggedIn, contextLoading, userData, location, login, router]); + + const overlayStyles = { + // position: "absolute", + // top: 0, + // left: 0, + // right:0, + // bottom:0, + // marginLeft:"14px", + // width: "100%", + // height: "100%", + display: "none", + // justifyContent: "center", + // alignItems: "center", + // backgroundColor: "rgba(0, 0, 0, 0.5)", + // zIndex: 9999, + }; + + const [activeStep, setActiveStep] = useState(1); // Declare activeStep state + const [submitted, setSubmitted] = useState(false); + const [errors, setErrors] = useState({}); + //Handling form data + + // let lat = location.coordinates?.lat; + // let lng = location.coordinates?.lng; + + // setFormData((prevData) => ({ + // ...prevData, + // restaurantLat:lat, + + // restaurantLng:lng + // })); + + // Handle input changes and update state + const handleInputChange = (e) => { + let name = e.target.name; + let value = e.target.value; + + setFormData((prevData) => ({ + ...prevData, + [name]: value, + userId: userData._id, + })); + }; + + // Handle form submission + const handleSubmit = async (e) => { + e.preventDefault(); + + // Validation logic here + const validationErrors = {}; + + if (!formData.restaurantName) { + validationErrors.restaurantName = "Name is required."; + } + if (!formData.restaurantContactNumber) { + validationErrors.restaurantContactNumber = "Contact Number is required."; + } + if (!formData.restaurantEmail) { + validationErrors.restaurantEmail = "Restaurant Email is required."; + } + if (!formData.restaurantAddress) { + validationErrors.restaurantAddress = "Restaurant Address is required."; + } + + if ( + formData.restaurantEmail.length > 1 && + formData.restaurantEmail.length < 10 + ) { + validationErrors.restaurantEmail = "Please enter correct E-mail id"; + } + if (formData.restaurantEmail.length < 1) { + validationErrors.restaurantEmail = "Please enter E-mail id"; + } + if (formData.restaurantContactNumber.length < 9) { + validationErrors.restaurantContactNumber = + "Please enter correct Contact Number"; + } + + if (Object.keys(validationErrors).length > 0) { + setErrors(validationErrors); + } else { + setSubmitted(true); + setActiveStep(2); + } + // console.log(formData); + }; + // Conditionally set the overlay to be visible + if (location.coordinates && location.coordinates.lat) { + overlayStyles.display = "none"; + } else { + overlayStyles.display = "block"; + } + return ( +
+ + + + + {!loggedIn ? ( +
+ Loading... +
+ ) : ( + <> +
+

+ Turn on your GPS +

+
+
+
+
+ +
+
+

+ ADDRESS +

+

+ Please place the pin accurately at your outlet’s location + on the map +

+
+
+

+ EMAIL +

+

+ example@email.com +

+

+ PHONE +

+

123-456-7890

+
+
+
+
+

+ Restaurant Details +

+

+ Name, address and location +

+
+
+ + + {errors.restaurantName && ( +

{errors.restaurantName}

+ )} +
+
+ + + {errors.restaurantEmail && ( +

{errors.restaurantEmail}

+ )} +
+
+ + + {errors.restaurantAddress && ( +

{errors.restaurantAddress}

+ )} +
+ +
+
+
+ +
+
+
+
+ +
+
+
+ + +

+ Enter accurate address or your restaurant will not get sortlisted +

+
+ {submitted && ( +
+

Form submitted successfully!

+ +
+ )} +
+
+
+ + + + )} +
+ ); +} +export default CreateRestaurant; diff --git a/fit-bite-web/app/add-restaurant/restaurantTypeData.js b/fit-bite-web/app/add-restaurant/restaurantTypeData.js new file mode 100644 index 000000000..9741d3edf --- /dev/null +++ b/fit-bite-web/app/add-restaurant/restaurantTypeData.js @@ -0,0 +1,117 @@ +const restaurantTypeData = [ + { + index:0, + name: "Fine Dining Restaurant", + description: + "These restaurants offer high-quality cuisine and a formal dining experience. They often have an elegant ambiance, trained staff, and a wide selection of food..", + icon: ( + + + + ), + }, + { + index:1, + name: "Casual Dining Restaurant", + description: + "Customers can enjoy a variety of dishes at affordable prices, and they typically don't require reservations.", + icon: ( + + + + + + ), + }, + { + name: "Fast Food Restaurant", + description: + "Fast food restaurants serve quick, convenient, and affordable meals.", + icon: ( + + + + + ), + }, + { + name: "Café or Coffee Shop", + description: "Cafés are known for serving coffee, tea, and light meals.", + icon: ( + + + + ), + }, + + { + name: "Bistro", + description: + "A bistro is a small, cozy eatery that offers a mix of classic and contemporary dishes. It often has a European-inspired menu and a relaxed ambiance.", + icon: ( + + + + ), + }, + { + name: "Ethnic or Specialty Restaurant", + description: + "These restaurants focus on specific cuisines or dishes from around the world. Examples include Italian, Mexican, Thai, sushi bars, and seafood restaurants.", + icon: ( + + + + ), + }, +]; + +export default restaurantTypeData; diff --git a/fit-bite-web/app/add-restaurant/useGeoLocationHook.jsx b/fit-bite-web/app/add-restaurant/useGeoLocationHook.jsx new file mode 100644 index 000000000..6b9bd2214 --- /dev/null +++ b/fit-bite-web/app/add-restaurant/useGeoLocationHook.jsx @@ -0,0 +1,43 @@ +import { useState, useEffect } from "react"; + +const useGeoLocation = () => { + const [location, setLocation] = useState({ + loaded: false, + coordinates: { lat: "", lng: "" }, + }); + + const onSuccess = (location) => { + setLocation({ + loaded: true, + coordinates: { + lat: location.coords.latitude, + lng: location.coords.longitude, + }, + }); + }; + + const onError = (error) => { + setLocation({ + loaded: true, + error: { + code: error.code, + message: error.message, + }, + }); + }; + + useEffect(() => { + if (!("geolocation" in navigator)) { + onError({ + code: 0, + message: "Geolocation not supported", + }); + } + + navigator.geolocation.getCurrentPosition(onSuccess, onError); + }, []); + + return location; +}; + +export default useGeoLocation; \ No newline at end of file diff --git a/fit-bite-web/app/admin/page.jsx b/fit-bite-web/app/admin/page.jsx new file mode 100644 index 000000000..9d029ad3e --- /dev/null +++ b/fit-bite-web/app/admin/page.jsx @@ -0,0 +1,250 @@ +"use client"; +import React from "react"; +import { useState, useEffect } from "react"; +import { useRouter } from "next/navigation"; +import { UserContext } from "../Context/UserProvider"; +import Link from "next/link"; +// var jwt = require("jsonwebtoken"); +function Page() { + const [orders, setOrders] = useState([]); + const [counter, setCounter] = useState(0); + const [selectedStatus, setSelectedStatus] = useState({}); + const { contextLoading, adminloggedIn, adminlogout} = + React.useContext(UserContext); + const router = useRouter(); + const handleChange = (event, order) => { + // console.log(event, order.chargeId); + setSelectedStatus({ chargeId: order.chargeId, status: event }); + }; + + const handleUpdateStatus = async (order) => { + // console.log(order.chargeId); + // console.log(selectedStatus); + // console.log(order._id); + let jsonData = { + deliveryStatus: selectedStatus.status, + }; + const jsonDataFinal = JSON.stringify(jsonData, null, 2); + const response = await fetch(`/api/orders/${order._id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: jsonDataFinal, + }); + + // const data = await response.json(); + + if (response.status === 200) { + // Update UI to reflect successful update + console.log("Delivery status updated successfully!"); + setCounter((prev) => prev + 1); + } else { + // Handle error + console.error(response.message); + } + }; + async function render() { + try { + const response = await fetch("/api/orders", { + method: "GET", + }); + let res = await response.json(); + if (response.status === 200) { + setOrders(res.orders); + } + } catch (err) { + console.log(err); + } + } + + useEffect(() => { + if (typeof window !== "undefined") { + if (contextLoading == false) { + // console.log({adminloggedIn}, "adminlogged in"); + if (adminloggedIn) { + // adminlogin(); + render(); + // adminlogin(); + } + if (!adminloggedIn) { + + console.log("else from admin orders page is getting triggered"); + // Schedule the redirect after 3 seconds + setTimeout(() => { + router.push("/adminSignin"); + }, 1000); + } + } + } + // else { + // // Show the div first + + // // Schedule the redirect after 3 seconds + // setTimeout(() => { + // router.push("/login"); + // }, 3000); + // } + + // getUser().then(()=>{ + // console.log({decoded}); + // }) + + // cs_test_a1sBkOnJyyCv9FfZt5rogyFokDMk60s6SSVyrogePJGRyVE8u8I1c1vA2Y + }, [adminloggedIn, contextLoading, selectedStatus, counter, router]); + + return ( +
+

+ {" "} + {contextLoading || !adminloggedIn ? ( +
+ Loading... +
+ ) : orders.length > 0 ? ( + "Recent Orders" + ) : ( + "No Orders Found" + )} + {/* {orders.length > 0 ? "Recent Orders" : "Orders Found: NAN"} */} +

+ + {adminloggedIn ? ( +
+
+
+ {orders?.map((order) => ( + //

{order.chargeId, + // order.userId, + // order.orderStatus, + // order.amount, + // order.paymentMethod, + // order.billingEmail, + // order.cardBrand, + // order.last4Digits, + // order.receipt_url}

+ +
+ Order ID: {order.chargeId} +
+
+ {/* + + */} + + {" "} + {" "} + {" "} + + {/* */} +
+
+

+ Amount:{" "} + + {order.amount / 100} INR. + +

+

+ {order.orderStatus.toUpperCase()} +

+
+

+ Method: {order.paymentMethod} +

+

+ Billing Email: {order.billingEmail} +

+

+ Card Brand: {order.cardBrand} +

+

+ Last 4 Digits: {order.last4Digits} +

+
+
+

+ {order?.deliveryStatus + ? order.deliveryStatus === "Delivered" + ? "" + : "Delivery Status: " + : "Awaiting approval"} + + {order?.deliveryStatus} + +

+ + +
+ + {" "} + Invoice + + + + +
+
+
+ ))} +
+
+
+ ) : ( +
+ )} +
+ ); +} + +export default Page; diff --git a/fit-bite-web/app/adminSignin/page.jsx b/fit-bite-web/app/adminSignin/page.jsx new file mode 100644 index 000000000..e1993182a --- /dev/null +++ b/fit-bite-web/app/adminSignin/page.jsx @@ -0,0 +1,315 @@ +"use client"; +import React from "react"; +import { useState } from "react"; +import Image from "next/image"; +import Link from "next/link"; +import "../globals.css"; +import { ToastContainer, toast } from "react-toastify"; +// import { injectStyle } from "react-toastify/dist/inject-style"; +import "react-toastify/dist/ReactToastify.css"; +import { useRouter } from "next/navigation"; +import { UserContext } from "../Context/UserProvider"; +function LoginPage() { + const { setAdminLoggedIn } = React.useContext(UserContext); + const [submitted, setSubmitted] = useState(false); + const [errors, setErrors] = useState({ }); + + const [isChecked, setIsChecked] = useState({ checked: false }); + const [formData, setFormData] = useState({ + Email: "", + Password: "", + }); + let router = useRouter(); + const handleCheckboxChange = () => { + // Toggle the value of isChecked when the checkbox is clicked + setIsChecked({ checked: !isChecked.checked }); + }; + // IF REMEMBER ME IS CHECKED DO THIS + // if(isChecked.checked === true) { + + // console.log("Don't ask for password for this user again") + // } + + // Handle input changes and update state + const handleInputChange = (e) => { + let name = e.target.name; + let value = e.target.value; + + setFormData((prevData) => ({ + ...prevData, + [name]: value, + })); + //Validation Logic Here + // const validationErrors = {}; + + // if (!formData.Email) { + // validationErrors.Email = "Please enter your Email for future updates."; + // } + + // if (!formData.Password) { + // validationErrors.Password = "Password is required."; + // } + + // if (formData.Password.includes(formData.username)) { + // validationErrors.Password = "Username should not be used as a password."; + // } + // if (formData.Email.length > 1 && formData.Email.length < 10) { + // validationErrors.Email = "Please enter correct E-mail id"; + // } + // if (formData.Email.length < 1) { + // validationErrors.Email = "Please enter your Email for future updates."; + // } + + // if (Object.keys(validationErrors).length > 0) { + // setErrors(validationErrors); + + // // console.log(validationErrors) + // // setShouldSignup(false); + // } else { + // setErrors(validationErrors); + // } + }; + // const isFormValid = () => { + // // Check if there are any errors in the errors state + // return Object.values(errors).every((error) => error === ""); + // }; + // Handle form submission + const handleSubmit = async (e) => { + e.preventDefault(); + + // setActiveStep(2) + // Convert form data to JSON + // const jsonData = JSON.stringify(formData, null, 2); + setErrors({}) + const validationErrors = {}; + + if (!formData.Email) { + validationErrors.Email = "Please enter your Email for future updates."; + } + + if (!formData.Password) { + validationErrors.Password = "Password is required."; + } + + if (formData.Password.includes(formData.username)) { + validationErrors.Password = "Username should not be used as a password."; + } + if (formData.Email.length > 1 && formData.Email.length < 10) { + validationErrors.Email = "Please enter correct E-mail id"; + } + if (formData.Email.length < 1) { + validationErrors.Email = "Please enter your Email for future updates."; + } + + if (Object.keys(validationErrors).length > 0) { + setErrors(validationErrors); + } + + // { "username": "Abhi", + // "ContactNumber": 679234567890, + // "Email": "abhi2y@email.com", + // "Password": "abhi", + // "Address": "PNT Colony" + // } + // Log the JSON data (you can send it to a server or save it as needed) + + // Convert form data to JSON + const jsonDataFinal = JSON.stringify(formData, null, 2); + // console.log("String form Data Final", jsonDataFinal); + if (Object.keys(validationErrors).length == 0) { + try { + const response = await fetch("/api/admin", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: jsonDataFinal, + }); + // console.log(response.body); + if (response.status === 201) { + // Parse the JSON response and extract the token + const responseData = await response.json(); + const token = responseData.token; + + // Use the extracted token for further processing + // console.log("Token:", token); + // const token = response.cookies.get("token") + localStorage.setItem("adminToken", token); + setSubmitted(true); + // console.log("Form data submitted successfully", formData); + setAdminLoggedIn(true); + // adminlogin() + // setAdminEmail(formData.Email) + + toast.success("🎉 Signed In successfully! Redirecting 🤗", { + position: "bottom-center", + autoClose: 5000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "dark", + }); + setTimeout(() => { + router.push("/admin"); + }, 3000); + + setFormData({ + Email: "", + Password: "", + }); + } else { + console.error("Form submission failed"); + toast.error("👹 Admin Not Found!", { + position: "bottom-center", + autoClose: 5000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "dark", + }); + setFormData({ + Email: "", + Password: "", + }); + setIsChecked({ checked: false }); + } + } catch (error) { + console.error("Error:", error); + } + } + // console.log(formData); + }; + + return ( +
+ +
+ Logo + {/*

+ Zomato +

*/} +
+
+
+
+ + + {errors.Email && ( +

{errors.Email}

+ )} + {/*

+ Please enter your desired Username +

*/} +
+ +
+ + + {errors.Password && ( +

{errors.Password}

+ )} + {/*

+ Please choose a password. +

*/} +
+
+
+ + +
+ + Forgot Password? + +
+ + +
+
+

+ {`Don't`} have an account? + Contact Developer +

+
+

+ ©2023 Zomato. All rights reserved. +

+
+
+ ); +} + +export default LoginPage; diff --git a/fit-bite-web/app/aiTrainer/page.jsx b/fit-bite-web/app/aiTrainer/page.jsx new file mode 100644 index 000000000..f400c08c8 --- /dev/null +++ b/fit-bite-web/app/aiTrainer/page.jsx @@ -0,0 +1,156 @@ +"use client"; +import { useEffect, useRef, useState } from "react"; + +const VideoRecorder = () => { + const videoRef = useRef(null); + const mediaRecorderRef = useRef(null); + const [recording, setRecording] = useState(false); + const chunks = useRef([]); + const [selectedFile, setSelectedFile] = useState(null); + const [uploading, setUploading] = useState(false); + const [response, setResponse] = useState(null); + const handleFileChange = (e) => { + console.log(e.target.files[0]); + setSelectedFile(e.target.files[0],"from target"); + }; + + const handleUpload = async () => { + if (!selectedFile) { + alert("Please select a video file first."); + return; + } + + setUploading(true); + const formData = new FormData(); + formData.append("file", selectedFile, selectedFile.name); + + try { + const res = await fetch("/api/uploadVideoML", { + method: "POST", + body: formData, + }); + + const result = await res.json(); + console.log({ result }); + setResponse(result); + try { + const resFinal = await fetch("/api/ai", { + method: "POST", + body: JSON.stringify(result, 2), + }); + console.log({ resFinal }); + } catch (err) { + console.log(err, "gemini error"); + } + } catch (error) { + console.error("Upload failed:", error); + } + + setUploading(false); + }; + useEffect(() => { + async function getCameraStream() { + try { + const stream = await navigator.mediaDevices.getUserMedia({ + video: true, + audio: true, + }); + if (videoRef.current) { + videoRef.current.srcObject = stream; + } + } catch (error) { + console.error("Error accessing webcam:", error); + } + } + getCameraStream(); + }, []); + + const startRecording = () => { + if (!videoRef.current || !videoRef.current.srcObject) return; + + chunks.current = []; + const stream = videoRef.current.srcObject; + const mediaRecorder = new MediaRecorder(stream); + + mediaRecorder.ondataavailable = (event) => { + if (event.data.size > 0) { + chunks.current.push(event.data); + } + }; + + mediaRecorder.onstop = async () => { + const blob = new Blob(chunks.current, { type: "video/webm" }); + + // Convert Blob to File + const file = new File([blob], "recorded-video.webm", { + type: "video/webm", + }); + + // Upload video to API for saving + const formData = new FormData(); + formData.append("video", file); + + try { + const response = await fetch("/api/uploadVideo", { + method: "POST", + body: blob, // Send raw video data + }); + + const data = await response.json(); + // console.log(data.message, "Saved at:", data.filePath); + } catch (error) { + console.error("Error uploading video:", error); + } + }; + + mediaRecorderRef.current = mediaRecorder; + mediaRecorder.start(); + setRecording(true); + }; + + const stopRecording = () => { + if (mediaRecorderRef.current) { + mediaRecorderRef.current.stop(); + } + setRecording(false); + }; + + return ( +
+ {/*
+ ); +}; + +export default VideoRecorder; diff --git a/fit-bite-web/app/api/account/[account]/route.js b/fit-bite-web/app/api/account/[account]/route.js new file mode 100644 index 000000000..5470ee792 --- /dev/null +++ b/fit-bite-web/app/api/account/[account]/route.js @@ -0,0 +1,135 @@ +import User from "@/app/models/UserModel"; +import mongoose from "mongoose"; +import { NextResponse } from "next/server"; +var CryptoJS = require("crypto-js"); +var jwt = require("jsonwebtoken"); +await mongoose.connect(process.env.MONGODB_URI); + +export async function PUT(req, content) { + try { + console.log(content); + let userId = content.params.account; + let filter = { _id: userId }; + let payload = await req.json(); + console.log(payload); + + let modifypayload = Object.keys(payload); + for (var i = 0; i < modifypayload.length; i++) { + if (Object.values(payload)[i].length < 2) { + console.log("I am going to delete", modifypayload[i]); + delete modifypayload[i]; + } else if (typeof Object.values(payload)[i] === "number") { + if (Object.values(payload)[i].toString().length < 9) { + console.log("I am going to delete this number", modifypayload[i]); + delete modifypayload[i]; + } + } else { + console.log(modifypayload[i]); + } + } + const resultObject = modifypayload.reduce((obj, key) => { + if (key !== undefined) { + obj[key] = payload[key]; + } + return obj; + }, {}); + + console.log(resultObject, "resultObject"); + console.log(modifypayload, "modifyPayload"); + + let result; + if (resultObject.Password) { + console.log(resultObject.Password, "Password"); + if (resultObject.Password.toString().length > 2) { + resultObject.Password = CryptoJS.AES.encrypt( + resultObject?.Password, + "SecretKey" + ).toString(); + // let objWithPw = { + // username: payload?.username, + // ContactNumber: payload?.ContactNumber, + // Address: payload?.Address, + // Email: payload?.Email, + // Password: CryptoJS.AES.encrypt( + // payload?.Password, + // "SecretKey" + // ).toString(), + // }; + // { + // username: 'Abhijeet', + // ContactNumber: '1234567789', + // Address: '22/3 LA, USA', + // Email: 'abhijeet@mail.com', + // Password: 'kensis-tyddAf-6qormi' + // } + } + } + result = await User.findOneAndUpdate(filter, resultObject); + // else { + + // result = await User.findOneAndUpdate(filter,resultObject); + // } + if (result._id && resultObject.Email.length > 1) { + var token = jwt.sign( + { + Email: resultObject.Email, + }, + process.env.JWT_SECRET, + { expiresIn: "3d" } + ); + + console.log("Token", token); + return NextResponse.json({ result, token, success: true }); + } + + /// REVERT BACK /////////// + // let result; + // if (payload.Password.length> 2) { + // let objWithPw = { + // username: payload?.username, + // ContactNumber: payload?.ContactNumber, + // Address: payload?.Address, + // Email: payload?.Email, + // Password: CryptoJS.AES.encrypt( + // payload?.Password, + // "SecretKey" + // ).toString(), + // }; + // // { + // // username: 'Abhijeet', + // // ContactNumber: '1234567789', + // // Address: '22/3 LA, USA', + // // Email: 'abhijeet@mail.com', + // // Password: 'kensis-tyddAf-6qormi' + // // } + // result = await User.findOneAndUpdate(filter, objWithPw); + // } else { + // delete payload.Password + // result = await User.findOneAndUpdate(filter, payload); + // } + // if (result._id) { + // var token = jwt.sign( + // { + // Email: payload.Email, + // username: payload.username, + // ContactNumber: payload.ContactNumber, + // Address: payload.Address, + // }, + // process.env.JWT_SECRET, + // { expiresIn: "3d" } + // ); + + // console.log("Token", token); + // return NextResponse.json({ result, token, success: true }); + // } + /// REVERT BACK /////////// + + // order = await Order.findOne({ chargeId }); + // } else { + // order = await Order.findByIdAndUpdate(id, { deliveryStatus }); + + return NextResponse.json({ result, success: true }); + } catch (err) { + return NextResponse.json({ success: false }); + } +} diff --git a/fit-bite-web/app/api/add-product/route.js b/fit-bite-web/app/api/add-product/route.js new file mode 100644 index 000000000..05ed11aaa --- /dev/null +++ b/fit-bite-web/app/api/add-product/route.js @@ -0,0 +1,14 @@ +import mongoose from "mongoose"; +import OtherProduct from "@/app/models/OtherProductModel"; +import { NextResponse } from "next/server"; +var CryptoJS = require("crypto-js"); + + +export async function POST(req) { + const payload = await req.json(); + await mongoose.connect(process.env.MONGODB_URI); + const { name, Description, Price, image, Calories, Protein, Fat, Carbohydrates, restaurantId, type} = payload; + let user = new OtherProduct({ name, Description, Price, image, Calories, Protein, Fat, Carbohydrates, restaurantId, type}); + const result = await user.save(); + return NextResponse.json({ result, success: true }); + } \ No newline at end of file diff --git a/fit-bite-web/app/api/admin/route.js b/fit-bite-web/app/api/admin/route.js new file mode 100644 index 000000000..7bc23b1d4 --- /dev/null +++ b/fit-bite-web/app/api/admin/route.js @@ -0,0 +1,63 @@ +import mongoose from "mongoose"; +import Admin from "@/app/models/AdminModel"; +import { NextResponse } from "next/server"; +var jwt = require("jsonwebtoken"); +await mongoose.connect(process.env.MONGODB_URI); + +// export async function POST(req, res) { +// const payload = await req.json(); +// await mongoose.connect(process.env.MONGODB_URI); +// const { username, Email, Password } = payload; +// let user = new Admin({ username, Email, Password}); +// const result = await user.save(); +// return NextResponse.json({ result, success: true }); +// } +export async function POST(req) { + let success = true; + let message = "Successfully Logged in"; + let status = 201; + const payload = await req.json(); + + console.log(payload); + const user = await Admin.find({ + Email: payload.Email, + }); + console.log(user, "user found"); + + console.log(user.Password); + if (user.length !== 0) { + if ( + payload.Email === user[0].Email && + payload.Password === user[0].Password + ) { + console.log("Authenticated", user[0].Email, user[0].Password); + var token = jwt.sign( + { + Email: user[0].Email, + username: user[0].username, + }, + process.env.JWT_SECRET, + { expiresIn: "3d" } + ); + + console.log("Token", token); + // cookies().set('adminToken', token, { secure: true }) + return NextResponse.json( + { result: user, success, message, token: token }, + { status, headers: { "content-type": "application/json" } } + ); + } else { + console.log("Wrong password"); + return NextResponse.json( + { success: false, message: "Wrong Password" }, + { status: 401, headers: { "content-type": "application/json" } } + ); + } + } else if (user.length === 0) { + console.log("User not found"); + return NextResponse.json( + { result: user, success: false, message: "User not found" }, + { status: 200, headers: { "content-type": "application/json" } } + ); + } +} diff --git a/fit-bite-web/app/api/ai/route.js b/fit-bite-web/app/api/ai/route.js new file mode 100644 index 000000000..e887fadb3 --- /dev/null +++ b/fit-bite-web/app/api/ai/route.js @@ -0,0 +1,16 @@ +import { GoogleGenerativeAI } from "@google/generative-ai"; + +export async function POST(req) { + try { + const { prompt } = await req.json(); + const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY); + const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" }); + + const result = await model.generateContent(prompt); + const responseText = result.response.text(); +console.log({responseText}) + return Response.json({ text: responseText }); + } catch (error) { + return Response.json({ error: "Failed to generate response" }, { status: 500 }); + } +} diff --git a/fit-bite-web/app/api/desserts/route.js b/fit-bite-web/app/api/desserts/route.js new file mode 100644 index 000000000..8f2a37c91 --- /dev/null +++ b/fit-bite-web/app/api/desserts/route.js @@ -0,0 +1,57 @@ +import mongoose from "mongoose"; +// import User from '@/models/UserModel'; +import Dessert from '@/app/models/DessertModel'; +import { NextResponse } from "next/server"; + // const handler = async (req, res) =>{ + // const {name, email, password} = req.body + // const user = await User.create({ + // name, + // email, + // password + // }) + // res.status(201).json({ + // message: 'User Created Successfully', + // user + // }) + + export async function POST(req) { + const payload = await req.json(); + await mongoose.connect(process.env.MONGODB_URI); + let d = new Dessert(payload); + const result = await d.save(); + return NextResponse.json({ result, success: true }); + } + export async function GET() { + let desserts =[] + let success = true + try{ + await mongoose.connect(process.env.MONGODB_URI); + desserts= await Dessert.find(); + + console.log(desserts); + // if(user){ + // if (req.body.Email == user.Email && req.body.Password == user.Password){ + // // res.status(200).json({success: true}, {username:user.username, Email:user.Email }) + // return NextResponse.json({success: true, message: 'Successfully Logged in', username:user.username, Email:user.Email}) + // // username:user.username, Email:user.Email + // // return NextResponse.json(JSON.stringify({success: true, message: 'Successfully Loged in'}),{ status: 200, headers: { 'content-type': 'application/json' } }, {username:user.username, Email:user.Email }) + // } + + // } + }catch(e){ + desserts={result:"error"} + success=false + // console.log(e); + } + return NextResponse.json({result:desserts, success}); + // else { + // // If no user is found, send a different response (e.g., success: false) + // res.status(200).json({ success: false, message: "User not found" }); + // } + // const payload = await req.json(); + // await mongoose.connect(process.env.MONGODB_URI); + // let user = new User(payload); + // const result = await user.save(); + // return NextResponse.json({ result, success: true }); + } + // ex \ No newline at end of file diff --git a/fit-bite-web/app/api/ecommerce/route.js b/fit-bite-web/app/api/ecommerce/route.js new file mode 100644 index 000000000..a8b3103c3 --- /dev/null +++ b/fit-bite-web/app/api/ecommerce/route.js @@ -0,0 +1,39 @@ +import mongoose from "mongoose"; +// import User from '@/models/UserModel'; +import User from '@/app/models/UserModel'; +import { NextResponse } from "next/server"; + + export async function GET() { + let users =[] + let success = true + try{ + await mongoose.connect(process.env.MONGODB_URI); + users= await User.countDocuments(); + + console.log(users); + // if(user){ + // if (req.body.Email == user.Email && req.body.Password == user.Password){ + // // res.status(200).json({success: true}, {username:user.username, Email:user.Email }) + // return NextResponse.json({success: true, message: 'Successfully Logged in', username:user.username, Email:user.Email}) + // // username:user.username, Email:user.Email + // // return NextResponse.json(JSON.stringify({success: true, message: 'Successfully Loged in'}),{ status: 200, headers: { 'content-type': 'application/json' } }, {username:user.username, Email:user.Email }) + // } + + // } + }catch(e){ + users={result:"error"} + success=false + // console.log(e); + } + return NextResponse.json({result:users, success}); + // else { + // // If no user is found, send a different response (e.g., success: false) + // res.status(200).json({ success: false, message: "User not found" }); + // } + // const payload = await req.json(); + // await mongoose.connect(process.env.MONGODB_URI); + // let user = new User(payload); + // const result = await user.save(); + // return NextResponse.json({ result, success: true }); + } + // ex \ No newline at end of file diff --git a/fit-bite-web/app/api/item/route.js b/fit-bite-web/app/api/item/route.js new file mode 100644 index 000000000..e801bd48a --- /dev/null +++ b/fit-bite-web/app/api/item/route.js @@ -0,0 +1,42 @@ +import mongoose from "mongoose"; +import Pastries from "@/app/models/PastriesModel"; +import LargeCake from "@/app/models/LargeCakesModel"; +import smallCake from "@/app/models/SmallCakesModel"; +import Dessert from "@/app/models/DessertModel"; +import { NextResponse } from "next/server"; +import OtherProduct from "@/app/models/OtherProductModel"; +export async function GET(req) { + let dish = req.nextUrl.searchParams.get("dish") || 1; + console.log({dish}) + console.log(req.nextUrl.searchParams.get("id")) + let pastries; + let success = true; + console.log(req.url) +let model; +console.log(dish=='pastries') + if (dish == 'pastries') { + model = Pastries; + }else if (dish == "desserts") { + model = Dessert; + }else if(dish == "largeCakes"){ + model = LargeCake; + }else if(dish=="otherProducts"){ + model=OtherProduct; + } + + else{ + model = smallCake; + } + try { + await mongoose.connect(process.env.MONGODB_URI); + pastries = await model.find({ + _id: req.nextUrl.searchParams.get("id"), + }); + } catch (e) { + pastries = { result: "error" }; + success = false; + // console.log(e); + } + return NextResponse.json({ result: pastries[0], success }); + } + \ No newline at end of file diff --git a/fit-bite-web/app/api/largeCakes/route.js b/fit-bite-web/app/api/largeCakes/route.js new file mode 100644 index 000000000..b4e3771e6 --- /dev/null +++ b/fit-bite-web/app/api/largeCakes/route.js @@ -0,0 +1,59 @@ +import mongoose from "mongoose"; +// import User from '@/models/UserModel'; +import LargeCake from '@/app/models/LargeCakesModel'; +import { NextResponse } from "next/server"; +// import { largeCake } from '@/app/database/mongooseSchema'; + // const handler = async (req, res) =>{ + // const {name, email, password} = req.body + // const user = await User.create({ + // name, + // email, + // password + // }) + // res.status(201).json({ + // message: 'User Created Successfully', + // user + // }) + + export async function POST(req) { + const payload = await req.json(); + await mongoose.connect(process.env.MONGODB_URI); + let d = new LargeCake(payload); + const result = await d.save(); + return NextResponse.json({ result, success: true }); + } + + export async function GET() { + let LargeCakes =[] + let success = true + try{ + await mongoose.connect(process.env.MONGODB_URI); + LargeCakes= await LargeCake.find(); + + console.log(LargeCakes); + // if(user){ + // if (req.body.Email == user.Email && req.body.Password == user.Password){ + // // res.status(200).json({success: true}, {username:user.username, Email:user.Email }) + // return NextResponse.json({success: true, message: 'Successfully Logged in', username:user.username, Email:user.Email}) + // // username:user.username, Email:user.Email + // // return NextResponse.json(JSON.stringify({success: true, message: 'Successfully Loged in'}),{ status: 200, headers: { 'content-type': 'application/json' } }, {username:user.username, Email:user.Email }) + // } + + // } + }catch(e){ + LargeCakes={result:"error"} + success=false + // console.log(e); + } + return NextResponse.json({result:LargeCakes, success}); + // else { + // // If no user is found, send a different response (e.g., success: false) + // res.status(200).json({ success: false, message: "User not found" }); + // } + // const payload = await req.json(); + // await mongoose.connect(process.env.MONGODB_URI); + // let user = new User(payload); + // const result = await user.save(); + // return NextResponse.json({ result, success: true }); + } + // ex \ No newline at end of file diff --git a/fit-bite-web/app/api/login/route.js b/fit-bite-web/app/api/login/route.js new file mode 100644 index 000000000..15b59f700 --- /dev/null +++ b/fit-bite-web/app/api/login/route.js @@ -0,0 +1,153 @@ +"use server" +import mongoose from "mongoose"; +import User from "../../models/UserModel"; +import { NextResponse } from "next/server"; +var CryptoJS = require("crypto-js"); +var jwt = require("jsonwebtoken"); +import { cookies } from 'next/headers' + + +// String does not match expected pattern occurs on not parsing the response to JSON or fetching the wrong URL + + +// const handler = async (req, res) =>{ +// const {name, email, password} = req.body +// const user = await User.create({ +// name, +// email, +// password +// }) +// res.status(201).json({ +// message: 'User Created Successfully', +// user +// }) + +// export async function POST(req, res) { +// // let user = []; +// const payload = await req.json(); +// await mongoose.connect(process.env.MONGODB_URI); +// let user = await User.find({ +// Email: payload.Email, +// }); +// console.log(user); +// if (user) { +// if ( +// payload.Email === user[0].Email && +// payload.Password === user[0].Password +// ) { +// console.log("Authenticated"); +// // status; +// // res.status(200).json({success: true}, {username:user.username, Email:user.Email }) +// return NextResponse.json({success: true, message: 'Successfully Logged in', username:user.username, Email:user.Email}) +// // username:user.username, Email:user.Email +// // return NextResponse.json(JSON.stringify({success: true, message: 'Successfully Loged in'}),{ status: 200, headers: { 'content-type': 'application/json' } }, {username:user.username, Email:user.Email }) +// } else { +// // message = "Wrong username or Email address"; +// // success = false; +// // status = 401; +// return NextResponse.json({success: false, message: "Wrong username or Email address"}) +// } +// } +// } + +await mongoose.connect(process.env.MONGODB_URI); +export async function POST(req) { + // let user = []; + let success = true; + let message = "Successfully Logged in"; + let status = 201; + const payload = await req.json(); + + // console.log(payload.Email===undefined); + + // if(payload.Email===undefined) { + // message="User not found" + // } + // hhi@mail.com + // console.log(payload.Password) + // console.log(JSON.parse(encryptedPassword)) + console.log(payload) + const user = await User.find({ + Email: payload.Email, + }); + console.log(user); + + console.log(payload.Password); + if (user.length !== 0) { + let decryptedPassword = CryptoJS.AES.decrypt( + user[0].Password, + process.env.CRYPTO_JS_KEY + ).toString(CryptoJS.enc.Utf8); + console.log(decryptedPassword); + + + if ( + payload.Email === user[0].Email && + payload.Password === decryptedPassword + ) { + console.log("Authenticated", user[0].Email, user[0].Password); + var token = jwt.sign({Email:user[0].Email, username: user[0].username, ContactNumber: user[0].ContactNumber, Address: user[0].Address}, process.env.JWT_SECRET, { expiresIn: '3d' }); + + console.log("Token", token) + // var objToken = { + // token: token, + // } + //Save Cookies=> + // const response = NextResponse.json(token, {status:201} ); + // response.cookies.set("token", token,{ + // httpOnly: true + // }); + // return response; + + cookies().set('token', token, { secure: true, httpOnly: true }) + + return NextResponse.json( + { result: user, success, message,token: token }, + { status, headers: { "content-type": "application/json" } } + ); + } else { + console.log("Wrong password"); + return NextResponse.json( + { success: false, message: "Wrong Password" }, + { status: 401, headers: { "content-type": "application/json" } } + ); + } + } else if (user.length === 0) { + console.log("User not found"); + return NextResponse.json( + { result: user, success: false, message: "User not found" }, + { status: 200, headers: { "content-type": "application/json" } } + ); + } + + // user = { result: "Error" }; + // success = false; + // message = "Invalid Credientials"; + // status=200 + // console.log("Error is", e); + + // return NextResponse.json({result:user, success}) +} +// export async function gettingUserss(userEmail) { +// await mongoose.connect(process.env.MONGODB_URI); +// const user = await User.find({ +// Email: userEmail, +// }); +// console.log(user); +// // return user +// } + +export async function GET(req) { + try { + + let userEmail= req.nextUrl.searchParams.get("userEmail"); + console.log(userEmail); + const users = await User.find({Email:userEmail}); + + console.log(users, "from login"); + return NextResponse.json( { result: users}) + } catch (error) { + console.error('Error fetching users:', error); + NextResponse.json({ error: 'Internal Server Error' }); + } +} \ No newline at end of file diff --git a/fit-bite-web/app/api/orderCount/route.js b/fit-bite-web/app/api/orderCount/route.js new file mode 100644 index 000000000..f0e62d1f4 --- /dev/null +++ b/fit-bite-web/app/api/orderCount/route.js @@ -0,0 +1,39 @@ +import mongoose from "mongoose"; +// import User from '@/models/UserModel'; +import Order from "@/app/models/OrderModel"; +import { NextResponse } from "next/server"; + + export async function GET() { + let users =0; + let success = true + try{ + await mongoose.connect(process.env.MONGODB_URI); + users= await Order.countDocuments(); + + console.log(users); + // if(user){ + // if (req.body.Email == user.Email && req.body.Password == user.Password){ + // // res.status(200).json({success: true}, {username:user.username, Email:user.Email }) + // return NextResponse.json({success: true, message: 'Successfully Logged in', username:user.username, Email:user.Email}) + // // username:user.username, Email:user.Email + // // return NextResponse.json(JSON.stringify({success: true, message: 'Successfully Loged in'}),{ status: 200, headers: { 'content-type': 'application/json' } }, {username:user.username, Email:user.Email }) + // } + + // } + }catch(e){ + users={result:"error"} + success=false + // console.log(e); + } + return NextResponse.json({result:users, success}); + // else { + // // If no user is found, send a different response (e.g., success: false) + // res.status(200).json({ success: false, message: "User not found" }); + // } + // const payload = await req.json(); + // await mongoose.connect(process.env.MONGODB_URI); + // let user = new User(payload); + // const result = await user.save(); + // return NextResponse.json({ result, success: true }); + } + // ex \ No newline at end of file diff --git a/fit-bite-web/app/api/orders/[id]/route.js b/fit-bite-web/app/api/orders/[id]/route.js new file mode 100644 index 000000000..d2c6774fd --- /dev/null +++ b/fit-bite-web/app/api/orders/[id]/route.js @@ -0,0 +1,71 @@ +import Order from "@/app/models/OrderModel"; +import mongoose from "mongoose"; +import { NextResponse } from "next/server"; + + +await mongoose.connect(process.env.MONGODB_URI); + +export async function PUT(req, content) +{ + console.log(content) + let orderId = content.params.id + let filter = {_id:orderId}; + let payload = await req.json() + console.log(payload) + let result = await Order.findOneAndUpdate(filter, payload) + + + // order = await Order.findOne({ chargeId }); + // } else { + // order = await Order.findByIdAndUpdate(id, { deliveryStatus }); + + +return NextResponse.json({result, success: true}) +} + +// export async function POST(req, res) { +// const payload = await req.json(); +// console.log({ payload }); +// const { chargeId, deliveryStatus, id } = payload; +// // Establish a global connection outside the function + +// try { +// let order; +// // Find by chargeId first for better search performance +// if (chargeId) { +// order = await Order.findOne({ chargeId }); +// } else { +// order = await Order.findByIdAndUpdate(id, { deliveryStatus }); +// } + +// if (!order) { +// return NextResponse.json({ success: false, message: 'Order not found' }); +// } + +// // order.deliveryStatus = deliveryStatus; +// // await order.save(); +// console.log('updated'); +// return NextResponse.json({ order, success: true }); +// } catch (err) { +// console.error(err); // Log full error object +// return NextResponse.json({ success: false, message: 'Internal server error' }); +// } + +// // try{ +// // let order = await Order.find({ chargeId: orderId }); +// // console.log(order); +// // if (!order) { +// // return res.status(404).json({ message: 'Order not found' }); +// // } +// // if(order){ +// // order.deliveryStatus = deliveryStatus; +// // const result = await order.save(); +// // console.log("updated") +// // return NextResponse.json({ result, success: true }); +// // } + +// // }catch(err){ +// // return NextResponse.json({ success: false, message: err.message }); + +// // } +// } diff --git a/fit-bite-web/app/api/orders/route.js b/fit-bite-web/app/api/orders/route.js new file mode 100644 index 000000000..55e5e7969 --- /dev/null +++ b/fit-bite-web/app/api/orders/route.js @@ -0,0 +1,100 @@ +import Order from "@/app/models/OrderModel"; +import mongoose from "mongoose"; +import { NextResponse } from "next/server"; + + +export async function GET() { + + await mongoose.connect(process.env.MONGODB_URI); + + + const orders = await Order.find().sort({ createdAt: -1 }); + if(orders.length > 0){ + // console.log(orders); + return NextResponse.json({ orders, success: true }); + } + + return NextResponse.json({ success: true }); + + + +} + + +export async function POST(req) { + const payload = await req.json(); + // console.log(payload); + const { + deliveryStatus, + chargeId, + userId, + orderStatus, + amount, + paymentMethod, + billingEmail, + cardBrand, + last4Digits, + receipt_url, + } = payload; + console.log(userId, "from route"); + await mongoose.connect(process.env.MONGODB_URI); + // try{ +if(payload.deliveryStatus){ + let orders = await Order.find({ + userId + }).sort({ createdAt: -1 }); + try{ + let Orders = new Order({ + deliveryStatus, + chargeId, + userId, + orderStatus, + amount, + paymentMethod, + billingEmail, + cardBrand, + last4Digits, + receipt_url, + }); + const result = await Orders.save(); + return NextResponse.json({ result, orders, success: true }, {status: 201}); +} +catch(err){ + console.error(err); + console.log(orders, "form catch") + return NextResponse.json({ orders, success: true }, {status: 200}); +} + // if(orders.length > 0){ + // console.log(orders); + // } +} else{ + + let orders = await Order.find({ + userId + }).sort({ createdAt: -1 }); + if(orders.length > 0){ + console.log(orders, "from else block"); + return NextResponse.json({ orders, success: true }); + } +} + // return NextResponse.json({ orders:result, success: true }); +// }catch(err){ +// console.log(err); + // if(userId){ + // console.log(userId, "from catch"); + // const orders1 = await Order.find({ + // userId, + // }); + + // if(orders1.length > 0){ + // console.log(orders1, "from route"); + // return NextResponse.json({ orders:orders1 }); + // } + // } + + +// return NextResponse.json({ success: false }); + + +// } +} diff --git a/fit-bite-web/app/api/otherProducts/route.js b/fit-bite-web/app/api/otherProducts/route.js new file mode 100644 index 000000000..37e720f8a --- /dev/null +++ b/fit-bite-web/app/api/otherProducts/route.js @@ -0,0 +1,28 @@ +import mongoose from "mongoose"; +import OtherProduct from "@/app/models/OtherProductModel"; +import { NextResponse } from "next/server"; + + export async function GET() { + let desserts =[] + let success = true + try{ + await mongoose.connect(process.env.MONGODB_URI); + desserts= await OtherProduct.find(); + + console.log(desserts); + // if(user){ + // if (req.body.Email == user.Email && req.body.Password == user.Password){ + // // res.status(200).json({success: true}, {username:user.username, Email:user.Email }) + // return NextResponse.json({success: true, message: 'Successfully Logged in', username:user.username, Email:user.Email}) + // // username:user.username, Email:user.Email + // // return NextResponse.json(JSON.stringify({success: true, message: 'Successfully Loged in'}),{ status: 200, headers: { 'content-type': 'application/json' } }, {username:user.username, Email:user.Email }) + // } + + // } + }catch(e){ + desserts={result:"error"} + success=false + + } + return NextResponse.json({result:desserts, success}); + } diff --git a/fit-bite-web/app/api/pastries/route.js b/fit-bite-web/app/api/pastries/route.js new file mode 100644 index 000000000..3f766c194 --- /dev/null +++ b/fit-bite-web/app/api/pastries/route.js @@ -0,0 +1,79 @@ +import mongoose from "mongoose"; +// import User from '@/models/UserModel'; +import Pastries from "@/app/models/PastriesModel"; +import { NextResponse } from "next/server"; + +//Get pastries based on pagination +export async function GET(req) { + let page = req.nextUrl.searchParams.get("page") || 1; + let pageSize = 3; + let skip = (page - 1) * pageSize; + let pastries = []; + let success = true; + try { + await mongoose.connect(process.env.MONGODB_URI); + pastries = await Pastries.find().skip(skip).limit(pageSize); + + // console.log(pastries); + } catch (e) { + pastries = { result: "error" }; + success = false; + // console.log(e); + } + return NextResponse.json({ result: pastries, success }); +} + + + +export async function POST(req) { + const payload = await req.json(); + await mongoose.connect(process.env.MONGODB_URI); + let d = new Pastries(payload); + const result = await d.save(); + return NextResponse.json({ result, success: true }); +} +//Get all pastries +// export async function GET() { +// let pastries = []; +// let success = true; +// try { +// await mongoose.connect(process.env.MONGODB_URI); +// pastries = await Pastries.find(); + +// console.log(pastries); +// } catch (e) { +// pastries = { result: "error" }; +// success = false; +// } +// return NextResponse.json({ result: pastries, success }); +// } + +// if(user){ +// if (req.body.Email == user.Email && req.body.Password == user.Password){ +// // res.status(200).json({success: true}, {username:user.username, Email:user.Email }) +// return NextResponse.json({success: true, message: 'Successfully Logged in', username:user.username, Email:user.Email}) +// // username:user.username, Email:user.Email +// // return NextResponse.json(JSON.stringify({success: true, message: 'Successfully Loged in'}),{ status: 200, headers: { 'content-type': 'application/json' } }, {username:user.username, Email:user.Email }) +// } + +// } +// if(user){ +// if (req.body.Email == user.Email && req.body.Password == user.Password){ +// // res.status(200).json({success: true}, {username:user.username, Email:user.Email }) +// return NextResponse.json({success: true, message: 'Successfully Logged in', username:user.username, Email:user.Email}) +// // username:user.username, Email:user.Email +// // return NextResponse.json(JSON.stringify({success: true, message: 'Successfully Loged in'}),{ status: 200, headers: { 'content-type': 'application/json' } }, {username:user.username, Email:user.Email }) +// } + +// } +// console.log(e); +// else { +// // If no user is found, send a different response (e.g., success: false) +// res.status(200).json({ success: false, message: "User not found" }); +// } +// const payload = await req.json(); +// await mongoose.connect(process.env.MONGODB_URI); +// let user = new User(payload); +// const result = await user.save(); +// return NextResponse.json({ result, success: true }); +// ex diff --git a/fit-bite-web/app/api/restaurants/route.js b/fit-bite-web/app/api/restaurants/route.js new file mode 100644 index 000000000..521e63be3 --- /dev/null +++ b/fit-bite-web/app/api/restaurants/route.js @@ -0,0 +1,37 @@ +import Restaurant from "@/app/models/RestaurantModel"; +import mongoose from "mongoose"; +import { NextResponse } from "next/server"; + +export async function GET(req) { + try { + + let userId= req.nextUrl.searchParams.get("userId"); + console.log({userId}); + const Restaurants = await Restaurant.find({userId}); + + console.log(Restaurants, "from restaurants"); + return NextResponse.json( { result: Restaurants}) + } catch (error) { + console.error('Error fetching Restaurants:', error); + NextResponse.json({ error: 'Internal Server Error' }); + } +} +// export async function GET() { +// let data = {}; +// try { +// await mongoose.connect(process.env.MONGODB_URI); +// data = await Restaurant.find(); +// } catch (error) { +// data = { success: false }; +// } +// return NextResponse.json({ result: data, success: true }); +// } + + export async function POST(req) { + const payload = await req.json(); + console.log({payload}) + await mongoose.connect(process.env.MONGODB_URI); + let d = new Restaurant(payload); + const result = await d.save(); + return NextResponse.json({ result, success: true }); + } \ No newline at end of file diff --git a/fit-bite-web/app/api/signup/route.js b/fit-bite-web/app/api/signup/route.js new file mode 100644 index 000000000..3b6cc00a2 --- /dev/null +++ b/fit-bite-web/app/api/signup/route.js @@ -0,0 +1,47 @@ +import mongoose from "mongoose"; +import User from "@/app/models/UserModel"; +import { NextResponse } from "next/server"; +var CryptoJS = require("crypto-js"); +// const handler = async (req, res) =>{ +// const {name, email, password} = req.body +// const user = await User.create({ +// name, +// email, +// password +// }) +// res.status(201).json({ +// message: 'User Created Successfully', +// user +// }) +// await mongoose.connect(process.env.MONGODB_URI); +export async function POST(req) { + const payload = await req.json(); + await mongoose.connect(process.env.MONGODB_URI); + const { username, ContactNumber, Address, Email } = payload; + let user = new User({ username, ContactNumber, Address, Email, Password: CryptoJS.AES.encrypt(payload.Password, process.env.CRYPTO_JS_KEY).toString() }); + const result = await user.save(); + return NextResponse.json({ result, success: true }); +} +// export async function POST(req, res) { +// if(req.method === 'POST'){ +// console.log(req.body) +// let u = new User(req.body) +// console.log(req.body); + +// await u.save() +// return res.json({ success: true }); +// }else{ +// return res.json({ success: false, message:"faileddd"}); +// // return res.status(400).json({error: "Bad Request, Method not allowed"}) +// } +// } +// } +// export async function POST(req, res) { +// const payload = await req.json(); +// await mongoose.connect(process.env.MONGODB_URI); +// let d = new Restaurant(payload); +// const result = await d.save(); +// return NextResponse.json({ result, success: true }); +// } + +// export default connectDb(handler) diff --git a/fit-bite-web/app/api/smallCakes/route.js b/fit-bite-web/app/api/smallCakes/route.js new file mode 100644 index 000000000..a2448d366 --- /dev/null +++ b/fit-bite-web/app/api/smallCakes/route.js @@ -0,0 +1,58 @@ +import mongoose from "mongoose"; +// import User from '@/models/UserModel'; +import smallCake from '@/app/models/SmallCakesModel'; +import { NextResponse } from "next/server"; + // const handler = async (req, res) =>{ + // const {name, email, password} = req.body + // const user = await User.create({ + // name, + // email, + // password + // }) + // res.status(201).json({ + // message: 'User Created Successfully', + // user + // }) + + export async function POST(req) { + const payload = await req.json(); + await mongoose.connect(process.env.MONGODB_URI); + let d = new smallCake(payload); + const result = await d.save(); + return NextResponse.json({ result, success: true }); + } + + export async function GET() { + let smallCakes =[] + let success = true + try{ + await mongoose.connect(process.env.MONGODB_URI); + smallCakes= await smallCake.find(); + + console.log(smallCakes); + // if(user){ + // if (req.body.Email == user.Email && req.body.Password == user.Password){ + // // res.status(200).json({success: true}, {username:user.username, Email:user.Email }) + // return NextResponse.json({success: true, message: 'Successfully Logged in', username:user.username, Email:user.Email}) + // // username:user.username, Email:user.Email + // // return NextResponse.json(JSON.stringify({success: true, message: 'Successfully Loged in'}),{ status: 200, headers: { 'content-type': 'application/json' } }, {username:user.username, Email:user.Email }) + // } + + // } + }catch(e){ + smallCakes={result:"error"} + success=false + // console.log(e); + } + return NextResponse.json({result:smallCakes, success}); + // else { + // // If no user is found, send a different response (e.g., success: false) + // res.status(200).json({ success: false, message: "User not found" }); + // } + // const payload = await req.json(); + // await mongoose.connect(process.env.MONGODB_URI); + // let user = new User(payload); + // const result = await user.save(); + // return NextResponse.json({ result, success: true }); + } + // ex \ No newline at end of file diff --git a/fit-bite-web/app/api/stripe/route.js b/fit-bite-web/app/api/stripe/route.js new file mode 100644 index 000000000..cac2fb6d7 --- /dev/null +++ b/fit-bite-web/app/api/stripe/route.js @@ -0,0 +1,219 @@ +import Stripe from "stripe"; +import { NextResponse } from "next/server"; +const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET); + +export async function POST(req, res) { + + if (req.method === "POST") { + // let data = await req.json(); + // console.log(req.headers); + let passedValue = await req.text(); + // console.log(passedValue, "passed value"); + let valueToJson = JSON.parse(passedValue); + // console.log(valueToJson); + const cartData = valueToJson.cartData; + const userId = valueToJson.userId; + console.log(userId); + try { + const params = { + submit_type: "pay", + // payment_method_types: ["card"], + billing_address_collection: "auto", + shipping_options: [ + // { shipping_rate: "shr_1OKjBDSHh0F7a44U3SPgGKe2" }, + { shipping_rate: "shr_1OKjDRSHh0F7a44U2qOkHQc0" }, + ], + line_items: Object.keys(cartData).map((item) => { + const { price, productName, image, qty } = cartData[item]; + + console.log(productName); + console.log((price * 100).toFixed(0)); + console.log(image); + console.log(qty) + return { + price_data: { + currency: "inr", + product_data: { + name: productName, + images: [image], + }, + unit_amount: (price * 100).toFixed(0), + }, + adjustable_quantity: { + enabled: true, + minimum: 1, + }, + quantity: qty, + }; + }), + metadata: { + userId, + }, + + mode: "payment", + success_url: `http://localhost:3000/orders?success=true&session_id={CHECKOUT_SESSION_ID}`, + cancel_url: `http://localhost:3000/?canceled=true`, + }; + + const session = await stripe.checkout.sessions.create(params); +console.log({session},session.url) + return NextResponse.json(session); + } catch (err) { + console.log(err, "err"); + return NextResponse.json({ message: err.message }); + } + } else { + res.setHeader("Allow", "POST"); + res.status(405).end("Method Not Allowed"); + } +} + +// Comments Ahead + +// async function storeSession(ctx){ +// try { +// // Assuming the Checkout Session ID is sent as a parameter in the request +// const { sessionId } = ctx; +// const session = await stripe.checkout.sessions.retrieve(sessionId); +// console.log("my Session", session) +// }catch(err) { +// console.log(err, "err"); +// } +// } + +export async function GET() { + // console.log(sessionInfo); + // console.log({session}) + const session1 = await stripe.checkout.sessions.retrieve('cs_test_a1KBcWZXjvzS0FTR7Ktns0LfelGPcualxbryd1Cu3s4YIg1FNqhtjmUwiC'); + const paymentIntent = await stripe.paymentIntents.retrieve( + // "pi_3OLkg3SHh0F7a44U0iapBSkz" + session1.payment_intent + + ); + + // let subtotal = paymentIntent.amount; + console.log("payment Intent", paymentIntent); + const chargeId = paymentIntent.latest_charge; + + if (chargeId) { + const charge = await stripe.charges.retrieve(chargeId); + console.log("Charge", charge); + + const status = charge.status; // "succeeded" + const amount = charge.amount; // 11999 (in the smallest currency unit, e.g., cents) + const paymentMethod = charge.payment_method_details.type; // "card" + const billingEmail = charge.billing_details.email; + // Accessing card details + const cardBrand = charge.payment_method_details.card.brand; // "visa" + const last4Digits = charge.payment_method_details.card.last4; // "4242" + const receipt_url = charge.receipt_url + // Example: Log the details + console.log("Status:", status); + console.log("Invoice:", receipt_url); + console.log("Billing Email:", billingEmail); + console.log("Amount:", amount/100); + console.log("Payment Method:", paymentMethod); + console.log("Card Brand:", cardBrand); + console.log("Last 4 Digits:", last4Digits); + } + } + +// const invoiceId = charge.invoice; + +// if (invoiceId) { +// const invoice = await stripe.invoices.retrieve(invoiceId); +// console.log("Invoice", invoice); +// return NextResponse.json({ invoice: invoice }); +// } +// return NextResponse.json({ charge: charge}); +// } +// return NextResponse.json({ chargeid: chargeId }); +// } +// export async function GET(req, res) { +// // const transactions = await stripe.issuing.transactions.list({ +// // limit: 3, +// // }); +// const transaction = await stripe.issuing.transactions.retrieve( +// // 'pm_1OL1VfSHh0F7a44UD5SElQ6M' +// // 'pmc_1OL1gISHh0F7a44UgurHyeae' +// sessionInfo.id +// ); +// return NextResponse.json({transaction}); +// } + +// { +// id: 'cs_test_a1mGf6uPqe1hWjMzwVCFxbkles9LyWgvPEaV50XHhnUhijAlLnz3xFmISw', +// object: 'checkout.session', +// after_expiration: null, +// allow_promotion_codes: null, +// amount_subtotal: 1999, +// amount_total: 11999, +// automatic_tax: { enabled: false, status: null }, +// billing_address_collection: 'auto', +// cancel_url: 'http://localhost:3000/?canceled=true', +// client_reference_id: null, +// client_secret: null, +// consent: null, +// consent_collection: null, +// created: 1702036742, +// currency: 'inr', +// currency_conversion: null, +// custom_fields: [], +// custom_text: { +// shipping_address: null, +// submit: null, +// terms_of_service_acceptance: null +// }, +// customer: null, +// customer_creation: 'if_required', +// customer_details: null, +// customer_email: null, +// expires_at: 1702123141, +// invoice: null, +// invoice_creation: { +// enabled: false, +// invoice_data: { +// account_tax_ids: null, +// custom_fields: null, +// description: null, +// footer: null, +// metadata: {}, +// rendering_options: null +// } +// }, +// livemode: false, +// locale: null, +// metadata: {}, +// mode: 'payment', +// payment_intent: null, +// payment_link: null, +// payment_method_collection: 'if_required', +// payment_method_configuration_details: { id: 'pmc_1OL1gISHh0F7a44UgurHyeae', parent: null }, +// payment_method_options: {}, +// payment_method_types: [ 'card' ], +// payment_status: 'unpaid', +// phone_number_collection: { enabled: false }, +// recovered_from: null, +// setup_intent: null, +// shipping_address_collection: null, +// shipping_cost: { +// amount_subtotal: 10000, +// amount_tax: 0, +// amount_total: 10000, +// shipping_rate: 'shr_1OKjDRSHh0F7a44U2qOkHQc0' +// }, +// shipping_details: null, +// shipping_options: [ +// { +// shipping_amount: 10000, +// shipping_rate: 'shr_1OKjDRSHh0F7a44U2qOkHQc0' +// } +// ], +// status: 'open', +// submit_type: 'pay', +// subscription: null, +// success_url: 'http://localhost:3000/?success=true', +// total_details: { amount_discount: 0, amount_shipping: 10000, amount_tax: 0 }, +// ui_mode: 'hosted', +// url: 'https://checkout.stripe.com/c/pay/cs_test_a1mGf6uPqe1hWjMzwVCFxbkles9LyWgvPEaV50XHhnUhijAlLnz3xFmISw#fidkdWxOYHwnPyd1blpxYHZxWjA0T31QSUtWTW01QzJkMTFQNl89M1FcRHJoXWN3Z3VucmpNcnJQZHZ0TlVnXXdXNU1vaU58UFdTTkZqRHVyd3cySj1MQU1WUnF3an1uUGxXSTBGPE48bWRiNTVHfXRJbmZnaycpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBabHFgaCcpJ2BrZGdpYFVpZGZgbWppYWB3dic%2FcXdwYHgl' +// } diff --git a/fit-bite-web/app/api/testML/route.js b/fit-bite-web/app/api/testML/route.js new file mode 100644 index 000000000..767eb7e7d --- /dev/null +++ b/fit-bite-web/app/api/testML/route.js @@ -0,0 +1,58 @@ +// app/api/upload/route.js +import { NextResponse } from 'next/server'; +import formidable from 'formidable'; +import { createReadStream } from 'fs'; +import FormData from 'form-data'; +import axios from 'axios'; +import { unlink } from 'fs/promises'; + +export const config = { + api: { + bodyParser: false, + }, +}; + +export async function POST(request) { + try { + const formData = await new Promise((resolve, reject) => { + const form = new formidable.IncomingForm(); + form.parse(request, (err, fields, files) => { + if (err) reject(err); + resolve({ fields, files }); + }); + }); + + const file = formData.files.file?.[0]; + if (!file) { + return NextResponse.json( + { error: 'No file uploaded' }, + { status: 400 } + ); + } + + const forwardFormData = new FormData(); + const fileStream = createReadStream(file.filepath); + forwardFormData.append('file', fileStream, file.originalFilename); + + const response = await axios.post( + 'http://127.0.0.1:8000/upload_video', + forwardFormData, + { + headers: { + ...forwardFormData.getHeaders(), + }, + } + ); + + // Clean up temporary file + await unlink(file.filepath); + + return NextResponse.json(response.data); + } catch (error) { + console.error('Upload error:', error); + return NextResponse.json( + { error: error.message || 'Failed to upload video' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/fit-bite-web/app/api/uploadVideo/route.js b/fit-bite-web/app/api/uploadVideo/route.js new file mode 100644 index 000000000..0f979c5d6 --- /dev/null +++ b/fit-bite-web/app/api/uploadVideo/route.js @@ -0,0 +1,22 @@ +import { writeFile } from "fs/promises"; +import { join } from "path"; +import { NextResponse } from "next/server"; + +export async function POST(req) { + try { + // Read video file from request + const data = await req.arrayBuffer(); + const buffer = Buffer.from(data); + + // Define path to save the file + const videoPath = join(process.cwd(), "public", "uploads", `recorded-video-${Date.now()}.webm`); + + // Save the file locally + await writeFile(videoPath, buffer); + + return NextResponse.json({ message: "Video uploaded successfully!", path: videoPath }); + } catch (error) { + console.error("Error saving video:", error); + return NextResponse.json({ error: "Failed to save video" }, { status: 500 }); + } +} diff --git a/fit-bite-web/app/api/uploadVideoML/route.js b/fit-bite-web/app/api/uploadVideoML/route.js new file mode 100644 index 000000000..fd2f52a05 --- /dev/null +++ b/fit-bite-web/app/api/uploadVideoML/route.js @@ -0,0 +1,63 @@ +import axios from "axios"; + +export async function POST(req) { + try { + // ✅ Convert request to FormData + const formData = await req.formData(); + const file = formData.get("file"); // Extract file directly + console.log(file, "file received"); + if (!file) { + return new Response(JSON.stringify({ error: "No file provided" }), { status: 400 }); + } + // const fileBlob = await req.blob(); + // formData.append("file", fileBlob, "uploaded-video.mp4"); + + const backendFormData = new FormData(); + backendFormData.append("file", file, file.name); + + const newFile = backendFormData.get("file"); + + console.log("New file is ", newFile); + + // Send to FastAPI backend + const backendResponse = await axios.post("http://localhost:8000/upload_video", backendFormData, { + "Content-Type": "multipart/form-data;" + }); + // headers to pass to fetch API in post request when sending image/file in multi-form + // headers: { + // "Content-Type": "multipart/form-data", + // charset:'utf-8', + // boundary: Math.random().toString().substr(2) + + + + const data = await backendResponse.data; + console.log("Backend Response:", JSON.stringify(data)); + + return new Response(JSON.stringify(data), { status: backendResponse.status }); + } catch (error) { + console.error("Upload failed:", error); + return new Response(JSON.stringify({ error: "Internal server error" }), { status: 500 }); + } +} + + + +// export async function POST(req) { +// const formData = await req.formData(); +// const file = formData.get("file"); + +// if (!file) { +// return new Response(JSON.stringify({ error: "No file provided" }), { status: 400 }); +// } +// console.log(file) +// const backendResponse = await fetch("http://localhost:8000/upload_video", { +// method: "POST", +// body: {"file":file}, +// }); + +// const data = await backendResponse.json(); +// console.log(JSON.stringify(data)) +// return new Response(JSON.stringify(data), { status: backendResponse.status }); +// } + diff --git a/fit-bite-web/app/api/webhooks/stripe/route.js b/fit-bite-web/app/api/webhooks/stripe/route.js new file mode 100644 index 000000000..933b4510f --- /dev/null +++ b/fit-bite-web/app/api/webhooks/stripe/route.js @@ -0,0 +1,81 @@ +// import Order from "@/models/OrderModel"; +// import { headers } from "next/headers"; +// import { NextResponse } from "next/server"; +// import mongoose from "mongoose"; +// import Stripe from "stripe"; +// const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET); +// export async function POST(req, res) { +// let body = await req.text(); +// let valueToJson = JSON.parse(body); +// const sig = req.headers["stripe-signature"]; +// let event; + +// try { +// event = stripe.webhooks.constructEvent( +// valueToJson, +// sig, +// process.env.Stripe_Webhook_Secret +// ); +// } catch (err) { +// return new Response( +// `Webhook Error: ${err ? err.message : "Unknown Error"}` +// ); +// } +// let session = event.data.object; +// console.log(session, "session"); +// if (!session?.metadata?.userId) { +// return new Response(null, { status: 200 }); +// } + +// // Handle the event +// switch (event.type) { +// case "checkout.session.completed": +// await mongoose.connect(process.env.MONGODB_URI); +// const session1 = await stripe.checkout.sessions.retrieve(session.id); + +// // let session = event.data.object; +// let paymentIntentId = session1.payment_intent; +// const paymentIntent = await stripe.paymentIntents.retrieve( +// paymentIntentId +// ); +// // let subtotal = paymentIntent.amount; +// console.log("payment Intent", paymentIntent); +// let chargeId = paymentIntent.latest_charge; +// if (chargeId) { +// let charge = await stripe.charges.retrieve(chargeId); +// console.log("Charge", charge); + +// let orderStatus = charge.status; // "succeeded" +// let amount = charge.amount; // 11999 (in the smallest currency unit, e.g., cents) +// let paymentMethod = charge.payment_method_details.type; // "card" +// let billingEmail = charge.billing_details.email; +// // Accessing card details +// let cardBrand = charge.payment_method_details.card.brand; // "visa" +// let last4Digits = charge.payment_method_details.card.last4; // "4242" +// let receipt_url = charge.receipt_url; +// console.log(userId, +// orderStatus, +// amount, +// paymentMethod, +// billingEmail, +// cardBrand, +// last4Digits, +// receipt_url) +// // let order = new Order({ +// // userId, +// // orderStatus, +// // amount, +// // paymentMethod, +// // billingEmail, +// // cardBrand, +// // last4Digits, +// // receipt_url, +// // }); +// // await order.save(); +// } +// default: +// console.log(`Unhandled event type ${event.type}`); +// } + +// return new Response(null, { status: 200 }); +// } diff --git a/fit-bite-web/app/chat/page.jsx b/fit-bite-web/app/chat/page.jsx new file mode 100644 index 000000000..8769d7a6d --- /dev/null +++ b/fit-bite-web/app/chat/page.jsx @@ -0,0 +1,58 @@ +"use client"; +import { useState, useEffect, useRef } from "react"; +import { useChat } from "../Context/ChatContext"; + +const Chat = () => { + const { messages, addMessage } = useChat(); + const [input, setInput] = useState(""); + const chatEndRef = useRef(null); + + // Scroll to the latest message when new messages arrive + useEffect(() => { + chatEndRef.current?.scrollIntoView({ behavior: "smooth" }); + }, [messages]); + + const handleSend = () => { + if (!input.trim()) return; + + addMessage(input, "user"); + + // Simulate AI response + setTimeout(() => { + addMessage("Hello! How can I help you?", "ai"); + }, 1000); + + setInput(""); + }; + + return ( +
+
+ {messages.map((msg) => ( +
+
+ {msg.text} +
+
+ ))} +
+
+ +
+ setInput(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && handleSend()} + placeholder="Type your message..." + /> + +
+
+ ); +}; + +export default Chat; diff --git a/fit-bite-web/app/components/AppHeader copy.jsx b/fit-bite-web/app/components/AppHeader copy.jsx new file mode 100644 index 000000000..181652514 --- /dev/null +++ b/fit-bite-web/app/components/AppHeader copy.jsx @@ -0,0 +1,180 @@ +"use client"; +import { ThemeToggleButton } from "../components1/common/ThemeToggleButton"; +import NotificationDropdown from "../components1/header/NotificationDropdown"; +import UserDropdown from "../components1/header/UserDropdown"; +import { useSidebar } from "../Context/SidebarContext"; +import Image from "next/image"; +import Link from "next/link"; +import React, { useState ,useEffect,useRef} from "react"; + +const AppHeader= () => { + const [isApplicationMenuOpen, setApplicationMenuOpen] = useState(false); + + const { isMobileOpen, toggleSidebar, toggleMobileSidebar } = useSidebar(); + + const handleToggle = () => { + if (window.innerWidth >= 991) { + toggleSidebar(); + } else { + toggleMobileSidebar(); + } + }; + + const toggleApplicationMenu = () => { + setApplicationMenuOpen(!isApplicationMenuOpen); + }; + const inputRef = useRef(null); + + useEffect(() => { + const handleKeyDown = (event) => { + if ((event.metaKey || event.ctrlKey) && event.key === "k") { + event.preventDefault(); + inputRef.current?.focus(); + } + }; + + document.addEventListener("keydown", handleKeyDown); + + return () => { + document.removeEventListener("keydown", handleKeyDown); + }; + }, []); + + return ( +
+
+
+ + + + + Logo + Logo + + + + +
+
+
+ + + + + + + + +
+
+
+
+
+
+ {/* */} + + {/* */} + + + {/* */} +
+ {/* */} + +
+
+
+ ); +}; + +export default AppHeader; diff --git a/fit-bite-web/app/components/AppHeader.jsx b/fit-bite-web/app/components/AppHeader.jsx new file mode 100644 index 000000000..180232e42 --- /dev/null +++ b/fit-bite-web/app/components/AppHeader.jsx @@ -0,0 +1,180 @@ +"use client"; +import { ThemeToggleButton } from "./common/ThemeToggleButton"; +import NotificationDropdown from "./header/NotificationDropdown"; +import UserDropdown from "./header/UserDropdown"; +import { useSidebar } from "../Context/SidebarContext"; +import Image from "next/image"; +import Link from "next/link"; +import React, { useState ,useEffect,useRef} from "react"; + +const AppHeader= () => { + const [isApplicationMenuOpen, setApplicationMenuOpen] = useState(false); + + const { isMobileOpen, toggleSidebar, toggleMobileSidebar } = useSidebar(); + + const handleToggle = () => { + if (window.innerWidth >= 991) { + toggleSidebar(); + } else { + toggleMobileSidebar(); + } + }; + + const toggleApplicationMenu = () => { + setApplicationMenuOpen(!isApplicationMenuOpen); + }; + const inputRef = useRef(null); + + useEffect(() => { + const handleKeyDown = (event) => { + if ((event.metaKey || event.ctrlKey) && event.key === "k") { + event.preventDefault(); + inputRef.current?.focus(); + } + }; + + document.addEventListener("keydown", handleKeyDown); + + return () => { + document.removeEventListener("keydown", handleKeyDown); + }; + }, []); + + return ( +
+
+
+ + + + + Logo + Logo + + + + +
+
+
+ + + + + + + + +
+
+
+
+
+
+ {/* */} + + {/* */} + + + {/* */} +
+ {/* */} + +
+
+
+ ); +}; + +export default AppHeader; diff --git a/fit-bite-web/app/components/AppSidebar.jsx b/fit-bite-web/app/components/AppSidebar.jsx new file mode 100644 index 000000000..4aa306e87 --- /dev/null +++ b/fit-bite-web/app/components/AppSidebar.jsx @@ -0,0 +1,365 @@ +"use client" +import React, { useEffect, useRef, useState,useCallback } from "react"; +import Link from "next/link"; +import Image from "next/image"; +import { usePathname } from "next/navigation"; +import { useSidebar } from "../Context/SidebarContext"; +// import SidebarWidget from "./SidebarWidget"; +import { BoxCubeIcon, CalenderIcon, GridIcon, ListIcon, PageIcon, PieChartIcon, PlugInIcon, TableIcon, UserCircleIcon } from "./icons"; +function AppSidebar() { + +const navItems = [ + { + icon: icon, + name: "Dashboard", + subItems: [{ name: "Ecommerce", path: "/", pro: false }], + }, + { + icon: icon, + name: "Calendar", + path: "/calendar", + }, + { + icon:icon , + name: "User Profile", + path: "/profile", + }, + + { + name: "Forms", + icon: icon, + subItems: [{ name: "Form Elements", path: "/form-elements", pro: false }], + }, + { + name: "Tables", + icon: icon, + subItems: [{ name: "Basic Tables", path: "/basic-tables", pro: false }], + }, + { + name: "Pages", + icon: icon, + subItems: [ + { name: "Blank Page", path: "/blank", pro: false }, + { name: "404 Error", path: "/error-404", pro: false }, + ], + }, +]; + +const othersItems= [ + { + icon: icon, + name: "Charts", + subItems: [ + { name: "Line Chart", path: "/line-chart", pro: false }, + { name: "Bar Chart", path: "/bar-chart", pro: false }, + ], + }, + { + icon: icon, + name: "UI Elements", + subItems: [ + { name: "Alerts", path: "/alerts", pro: false }, + { name: "Avatar", path: "/avatars", pro: false }, + { name: "Badge", path: "/badge", pro: false }, + { name: "Buttons", path: "/buttons", pro: false }, + { name: "Images", path: "/images", pro: false }, + { name: "Videos", path: "/videos", pro: false }, + ], + }, + { + icon: icon, + name: "Authentication", + subItems: [ + { name: "Sign In", path: "/signin", pro: false }, + { name: "Sign Up", path: "/signup", pro: false }, + ], + }, +]; + +const { isExpanded, isMobileOpen, isHovered, setIsHovered } = useSidebar(); + const pathname = usePathname(); +// let menuType = "main" | "others" + const renderMenuItems = ( + navItems, + menuType + ) => ( +
    + {console.log({navItems})} + {navItems && navItems.map((nav, index) => ( +
  • + {nav.subItems ? ( + + ) : ( + nav.path && ( + + + {nav.icon} + + {(isExpanded || isHovered || isMobileOpen) && ( + {nav.name} + )} + + ) + )} + {nav.subItems && (isExpanded || isHovered || isMobileOpen) && ( +
    { + subMenuRefs.current[`${menuType}-${index}`] = el; + }} + className="overflow-hidden transition-all duration-300" + style={{ + height: + openSubmenu?.type === menuType && openSubmenu?.index === index + ? `${subMenuHeight[`${menuType}-${index}`]}px` + : "0px", + }} + > +
      + {nav.subItems.map((subItem) => ( +
    • + + {subItem.name} + + {subItem.new && ( + + new + + )} + {subItem.pro && ( + + pro + + )} + + +
    • + ))} +
    +
    + )} +
  • + ))} +
+ ); + const [openSubmenu, setOpenSubmenu] = useState(null); + const [subMenuHeight, setSubMenuHeight] = useState( + {} + ); + const subMenuRefs = useRef({}); + + // const isActive = (path: string) => path === pathname; + const isActive = useCallback((path) => path === pathname, [pathname]); + + useEffect(() => { + // Check if the current path matches any submenu item + let submenuMatched = false; + ["main", "others"].forEach((menuType) => { + const items = menuType === "main" ? navItems : othersItems; + items.forEach((nav, index) => { + if (nav.subItems) { + nav.subItems.forEach((subItem) => { + if (isActive(subItem.path)) { + setOpenSubmenu({ + type: menuType, + index, + }); + submenuMatched = true; + } + }); + } + }); + }); + + // If no submenu item matches, close the open submenu + if (!submenuMatched) { + setOpenSubmenu(null); + } + }, [pathname,isActive]); + + useEffect(() => { + // Set the height of the submenu items when the submenu is opened + if (openSubmenu !== null) { + const key = `${openSubmenu.type}-${openSubmenu.index}`; + if (subMenuRefs.current[key]) { + setSubMenuHeight((prevHeights) => ({ + ...prevHeights, + [key]: subMenuRefs.current[key]?.scrollHeight || 0, + })); + } + } + }, [openSubmenu]); +// let menuType1 = "main" | "others" + const handleSubmenuToggle = (index, menuType1) => { + setOpenSubmenu((prevOpenSubmenu) => { + if ( + prevOpenSubmenu && + prevOpenSubmenu.type === menuType1 && + prevOpenSubmenu.index === index + ) { + return null; + } + return { type: menuType1, index }; + }); + }; + + return ( + + ) +} + +export default AppSidebar \ No newline at end of file diff --git a/fit-bite-web/app/components/Backdrop.jsx b/fit-bite-web/app/components/Backdrop.jsx new file mode 100644 index 000000000..ecb9e3a69 --- /dev/null +++ b/fit-bite-web/app/components/Backdrop.jsx @@ -0,0 +1,17 @@ +import { useSidebar } from "../Context/SidebarContext"; +import React from "react"; + +const Backdrop= () => { + const { isMobileOpen, toggleMobileSidebar } = useSidebar(); + + if (!isMobileOpen) return null; + + return ( +
+ ); +}; + +export default Backdrop; diff --git a/fit-bite-web/app/components/CartLayout.jsx b/fit-bite-web/app/components/CartLayout.jsx new file mode 100644 index 000000000..14cbc56bb --- /dev/null +++ b/fit-bite-web/app/components/CartLayout.jsx @@ -0,0 +1,136 @@ +"use client"; + +import Image from "next/image"; +import React from "react"; +import { useState, useEffect } from "react"; + +function CartLayout() { + const [Cart, setCart] = useState({}); + // const [subTotal, setSubTotal] = useState(0); + + // const [shouldHideButtons, setShouldHideButtons] = useState(false); + + // Update state based on prop + // if (hideButtons) { + // setShouldHideButtons(true); + // } + useEffect(() => { + // console.log("use effect from cart hi"); + + try { + if (localStorage.getItem("cart")) { + setCart(JSON.parse(localStorage.getItem("cart"))); + saveCart(JSON.parse(localStorage.getItem("cart"))) + } + } catch (error) { + console.error(error); + localStorage.removeItem("cart"); + } + }, []); + const saveCart = (myCart) => { + localStorage.setItem("cart", JSON.stringify(myCart)); + // let subt = 0; + // let keys = Object.keys(myCart); + // for (let i = 0; i { + let newCart = Cart; + if (itemCode in Cart) { + newCart[itemCode].qty = Cart[itemCode].qty + qty; + } else { + newCart[itemCode] = { + qty: qty, + price: price, + productName: productName, + image: image, + }; + } + setCart(newCart); + saveCart(newCart); + }; + // const clearCart = () => { + // setCart({}); + // saveCart({}); + // }; + const removeFromCart = (itemCode, qty) => { + let newCart = Cart; + if (itemCode in Cart) { + newCart[itemCode].qty = Cart[itemCode].qty - qty; + } + if (newCart[itemCode].qty <= 0) { + delete newCart[itemCode]; + } + setCart(newCart); + saveCart(newCart); + }; + return ( +
+ + {Object.keys(Cart).length===0 &&
No items in the cart
} +
+ {Object.keys(Cart).map((k) => { + return
+ + +
+ {Cart[k].productName} +

+ {Cart[k].productName} +

+

{Cart[k].price}

+ {/*

${Cart[k].price.toFixed(2)}

*/} +
+{/* {Cart[k].description}: image url */} +
+ + {Cart[k].qty} + +
+
+
+ + +
; + })} +
+ +{/*

${subTotal.toFixed(2)}

*/} +{/* {!shouldHideButtons && ( */} +{/* {!shouldHideButtons && ( */} +{/*
+ + +
+)} */} + + + +
+ ) +} + +export default CartLayout \ No newline at end of file diff --git a/fit-bite-web/app/components/Ecommerce/CountryMap.jsx b/fit-bite-web/app/components/Ecommerce/CountryMap.jsx new file mode 100644 index 000000000..ce7c03843 --- /dev/null +++ b/fit-bite-web/app/components/Ecommerce/CountryMap.jsx @@ -0,0 +1,123 @@ +import React from "react"; +// import { VectorMap } from "@react-jvectormap/core"; +import { worldMill } from "@react-jvectormap/world"; +import dynamic from "next/dynamic"; + +const VectorMap = dynamic( + () => import("@react-jvectormap/core").then((mod) => mod.VectorMap), + { ssr: false } +); + +// // Define the component props +// interface CountryMapProps { +// mapColor?: string; +// } + +// type MarkerStyle = { +// initial: { +// fill: string; +// r: number; // Radius for markers +// }; +// }; + +// type Marker = { +// latLng: [number, number]; +// name: string; +// style?: { +// fill: string; +// borderWidth: number; +// borderColor: string; +// stroke?: string; +// strokeOpacity?: number; +// }; +// }; + +const CountryMap= ({ mapColor }) => { + return ( + + ); +}; + +export default CountryMap; diff --git a/fit-bite-web/app/components/Ecommerce/DemographicCard.jsx b/fit-bite-web/app/components/Ecommerce/DemographicCard.jsx new file mode 100644 index 000000000..5b0467a99 --- /dev/null +++ b/fit-bite-web/app/components/Ecommerce/DemographicCard.jsx @@ -0,0 +1,131 @@ +"use client"; +import Image from "next/image"; + +import CountryMap from "./CountryMap"; +import { useState } from "react"; +import { MoreDotIcon } from "../icons"; +import { Dropdown } from "../ui/dropdown/Dropdown"; +import { DropdownItem } from "../ui/dropdown/DropdownItem"; + +export default function DemographicCard() { + const [isOpen, setIsOpen] = useState(false); + + function toggleDropdown() { + setIsOpen(!isOpen); + } + + function closeDropdown() { + setIsOpen(false); + } + + return ( +
+
+
+

+ Customers Demographic +

+

+ Number of customer based on country +

+
+ +
+ + + + View More + + + Delete + + +
+
+
+
+ +
+
+ +
+
+
+
+ usa +
+
+

+ USA +

+ + 2,379 Customers + +
+
+ +
+
+
+
+

+ 79% +

+
+
+ +
+
+
+ france +
+
+

+ France +

+ + 589 Customers + +
+
+ +
+
+
+
+

+ 23% +

+
+
+
+
+ ); +} diff --git a/fit-bite-web/app/components/Ecommerce/MonthlySalesChart.jsx b/fit-bite-web/app/components/Ecommerce/MonthlySalesChart.jsx new file mode 100644 index 000000000..a9313c8b4 --- /dev/null +++ b/fit-bite-web/app/components/Ecommerce/MonthlySalesChart.jsx @@ -0,0 +1,155 @@ +"use client"; +import { ApexOptions } from "apexcharts"; +import dynamic from "next/dynamic"; +import { MoreDotIcon } from "../icons"; +import { DropdownItem } from "../ui/dropdown/DropdownItem"; +import { useState } from "react"; +import { Dropdown } from "../ui/dropdown/Dropdown"; +import Image from "next/image"; + +// Dynamically import the ReactApexChart component +const ReactApexChart = dynamic(() => import("react-apexcharts"), { + ssr: false, +}); + +export default function MonthlySalesChart() { + const options= { + colors: ["#465fff"], + chart: { + fontFamily: "Outfit, sans-serif", + type: "bar", + height: 180, + toolbar: { + show: false, + }, + }, + plotOptions: { + bar: { + horizontal: false, + columnWidth: "39%", + borderRadius: 5, + borderRadiusApplication: "end", + }, + }, + dataLabels: { + enabled: false, + }, + stroke: { + show: true, + width: 4, + colors: ["transparent"], + }, + xaxis: { + categories: [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ], + axisBorder: { + show: false, + }, + axisTicks: { + show: false, + }, + }, + legend: { + show: true, + position: "top", + horizontalAlign: "left", + fontFamily: "Outfit", + }, + yaxis: { + title: { + text: undefined, + }, + }, + grid: { + yaxis: { + lines: { + show: true, + }, + }, + }, + fill: { + opacity: 1, + }, + + tooltip: { + x: { + show: false, + }, + y: { + formatter: (val) => `${val}`, + }, + }, + }; + const series = [ + { + name: "Sales", + data: [168, 385, 201, 298, 187, 195, 291, 110, 215, 390, 280, 112], + }, + ]; + const [isOpen, setIsOpen] = useState(false); + + function toggleDropdown() { + setIsOpen(!isOpen); + } + + function closeDropdown() { + setIsOpen(false); + } + + return ( +
+
+

+ Monthly Sales +

+ +
+ + + + View More + + + Delete + + +
+
+ +
+
+ +
+
+
+ ); +} diff --git a/fit-bite-web/app/components/Ecommerce/MonthlyTarget.jsx b/fit-bite-web/app/components/Ecommerce/MonthlyTarget.jsx new file mode 100644 index 000000000..5ecf67119 --- /dev/null +++ b/fit-bite-web/app/components/Ecommerce/MonthlyTarget.jsx @@ -0,0 +1,210 @@ +"use client"; +// import Chart from "react-apexcharts"; +import { ApexOptions } from "apexcharts"; + +import dynamic from "next/dynamic"; +import { Dropdown } from "../ui/dropdown/Dropdown"; +import { MoreDotIcon } from "../icons"; +import { useState } from "react"; +import { DropdownItem } from "../ui/dropdown/DropdownItem"; +import Image from "next/image"; +// Dynamically import the ReactApexChart component +const ReactApexChart = dynamic(() => import("react-apexcharts"), { + ssr: false, +}); + +export default function MonthlyTarget() { + const series = [75.55]; + const options = { + colors: ["#465FFF"], + chart: { + fontFamily: "Outfit, sans-serif", + type: "radialBar", + height: 330, + sparkline: { + enabled: true, + }, + }, + plotOptions: { + radialBar: { + startAngle: -85, + endAngle: 85, + hollow: { + size: "80%", + }, + track: { + background: "#E4E7EC", + strokeWidth: "100%", + margin: 5, // margin is in pixels + }, + dataLabels: { + name: { + show: false, + }, + value: { + fontSize: "36px", + fontWeight: "600", + offsetY: -40, + color: "#1D2939", + formatter: function (val) { + return val + "%"; + }, + }, + }, + }, + }, + fill: { + type: "solid", + colors: ["#465FFF"], + }, + stroke: { + lineCap: "round", + }, + labels: ["Progress"], + }; + + const [isOpen, setIsOpen] = useState(false); + + function toggleDropdown() { + setIsOpen(!isOpen); + } + + function closeDropdown() { + setIsOpen(false); + } + + return ( +
+
+
+
+

+ Monthly Target +

+

+ Target you’ve set for each month +

+
+
+ + + + View More + + + Delete + + +
+
+
+
+ +
+ + + +10% + +
+

+ You earn $3287 today, it's higher than last month. Keep up your + good work! +

+
+ +
+
+

+ Target +

+

+ $20K + + + +

+
+ +
+ +
+

+ Revenue +

+

+ $20K + + + +

+
+ +
+ +
+

+ Today +

+

+ $20K + + + +

+
+
+
+ ); +} diff --git a/fit-bite-web/app/components/Ecommerce/RecentOrders.jsx b/fit-bite-web/app/components/Ecommerce/RecentOrders.jsx new file mode 100644 index 000000000..f7ec6538a --- /dev/null +++ b/fit-bite-web/app/components/Ecommerce/RecentOrders.jsx @@ -0,0 +1,211 @@ +import { + Table, + TableBody, + TableCell, + TableHeader, + TableRow, +} from "../ui/table"; +import Badge from "../ui/badge/Badge"; +import Image from "next/image"; + +// Define the TypeScript interface for the table rows +// interface Product { +// id: number; // Unique identifier for each product +// name: string; // Product name +// variants: string; // Number of variants (e.g., "1 Variant", "2 Variants") +// category: string; // Category of the product +// price: string; // Price of the product (as a string with currency symbol) +// // status: string; // Status of the product +// image: string; // URL or path to the product image +// status: "Delivered" | "Pending" | "Canceled"; // Status of the product +// } + +// Define the table data using the interface +const tableData = [ + { + id: 1, + name: "MacBook Pro 13”", + variants: "2 Variants", + category: "Laptop", + price: "$2399.00", + status: "Delivered", + image: "/images/product/product-01.jpg", // Replace with actual image URL + }, + { + id: 2, + name: "Apple Watch Ultra", + variants: "1 Variant", + category: "Watch", + price: "$879.00", + status: "Pending", + image: "/images/product/product-02.jpg", // Replace with actual image URL + }, + { + id: 3, + name: "iPhone 15 Pro Max", + variants: "2 Variants", + category: "SmartPhone", + price: "$1869.00", + status: "Delivered", + image: "/images/product/product-03.jpg", // Replace with actual image URL + }, + { + id: 4, + name: "iPad Pro 3rd Gen", + variants: "2 Variants", + category: "Electronics", + price: "$1699.00", + status: "Canceled", + image: "/images/product/product-04.jpg", // Replace with actual image URL + }, + { + id: 5, + name: "AirPods Pro 2nd Gen", + variants: "1 Variant", + category: "Accessories", + price: "$240.00", + status: "Delivered", + image: "/images/product/product-05.jpg", // Replace with actual image URL + }, +]; + +export default function RecentOrders() { + return ( +
+
+
+

+ Recent Orders +

+
+ +
+ + +
+
+
+ + {/* Table Header */} + + + + Products + + + Category + + + Price + + + Status + + + + + {/* Table Body */} + + + {tableData.map((product) => ( + + +
+
+ +
+
+

+ {product.name} +

+ + {product.variants} + +
+
+
+ + {product.price} + + + {product.category} + + + + {product.status} + + +
+ ))} +
+
+
+
+ ); +} diff --git a/fit-bite-web/app/components/Ecommerce/StatisticsChart.jsx b/fit-bite-web/app/components/Ecommerce/StatisticsChart.jsx new file mode 100644 index 000000000..a2b38d302 --- /dev/null +++ b/fit-bite-web/app/components/Ecommerce/StatisticsChart.jsx @@ -0,0 +1,150 @@ +"use client"; +import React from "react"; +// import Chart from "react-apexcharts"; +import { ApexOptions } from "apexcharts"; +import ChartTab from "../common/ChartTab"; +import dynamic from "next/dynamic"; + +// Dynamically import the ReactApexChart component +const ReactApexChart = dynamic(() => import("react-apexcharts"), { + ssr: false, +}); + +export default function StatisticsChart() { + const options= { + legend: { + show: false, // Hide legend + position: "top", + horizontalAlign: "left", + }, + colors: ["#465FFF", "#9CB9FF"], // Define line colors + chart: { + fontFamily: "Outfit, sans-serif", + height: 310, + type: "line", // Set the chart type to 'line' + toolbar: { + show: false, // Hide chart toolbar + }, + }, + stroke: { + curve: "straight", // Define the line style (straight, smooth, or step) + width: [2, 2], // Line width for each dataset + }, + + fill: { + type: "gradient", + gradient: { + opacityFrom: 0.55, + opacityTo: 0, + }, + }, + markers: { + size: 0, // Size of the marker points + strokeColors: "#fff", // Marker border color + strokeWidth: 2, + hover: { + size: 6, // Marker size on hover + }, + }, + grid: { + xaxis: { + lines: { + show: false, // Hide grid lines on x-axis + }, + }, + yaxis: { + lines: { + show: true, // Show grid lines on y-axis + }, + }, + }, + dataLabels: { + enabled: false, // Disable data labels + }, + tooltip: { + enabled: true, // Enable tooltip + x: { + format: "dd MMM yyyy", // Format for x-axis tooltip + }, + }, + xaxis: { + type: "category", // Category-based x-axis + categories: [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ], + axisBorder: { + show: false, // Hide x-axis border + }, + axisTicks: { + show: false, // Hide x-axis ticks + }, + tooltip: { + enabled: false, // Disable tooltip for x-axis points + }, + }, + yaxis: { + labels: { + style: { + fontSize: "12px", // Adjust font size for y-axis labels + colors: ["#6B7280"], // Color of the labels + }, + }, + title: { + text: "", // Remove y-axis title + style: { + fontSize: "0px", + }, + }, + }, + }; + + const series = [ + { + name: "Sales", + data: [180, 190, 170, 160, 175, 165, 170, 205, 230, 210, 240, 235], + }, + { + name: "Revenue", + data: [40, 30, 50, 40, 55, 40, 70, 100, 110, 120, 150, 140], + }, + ]; + return ( +
+
+
+

+ Statistics +

+

+ Target you’ve set for each month +

+
+
+ +
+
+ +
+
+ +
+
+
+ ); +} diff --git a/fit-bite-web/app/components/Ecommerce/page.jsx b/fit-bite-web/app/components/Ecommerce/page.jsx new file mode 100644 index 000000000..56800b81f --- /dev/null +++ b/fit-bite-web/app/components/Ecommerce/page.jsx @@ -0,0 +1,43 @@ +"use client" + +import React from "react"; +import EcommerceMetrics from "../components/EcommerceMetrics"; +import MonthlyTarget from "../components/Ecommerce/MonthlyTarget"; +import MonthlySalesChart from "../components/Ecommerce/MonthlySalesChart"; +import StatisticsChart from "../components/Ecommerce/StatisticsChart"; +import RecentOrders from "../components/Ecommerce/RecentOrders"; +import DemographicCard from "../components/Ecommerce/DemographicCard"; + +// export const metadata = { +// title: +// "Next.js E-commerce Dashboard | TailAdmin - Next.js Dashboard Template", +// description: "This is Next.js Home for TailAdmin Dashboard Template", +// }; + +export default function Ecommerce() { + return ( +
+
+ + + {/* */} +
+ +
+ {/* */} +
+ +
+ {/* */} +
+ +
+ {/* */} +
+ +
+ {/* */} +
+
+ ); +} diff --git a/fit-bite-web/app/components/EcommerceMetrics.jsx b/fit-bite-web/app/components/EcommerceMetrics.jsx new file mode 100644 index 000000000..c6f987ef0 --- /dev/null +++ b/fit-bite-web/app/components/EcommerceMetrics.jsx @@ -0,0 +1,98 @@ +"use client" +import React, { useState, useEffect } from 'react' +// import { GroupIcon } from './icons' +import Image from 'next/image' +import { ArrowDownIcon } from './icons' +import Badge from './ui/badge/Badge' +import { useRouter } from 'next/navigation' +function EcommerceMetrics() { + const [dessertData, setDessertData] = useState(0); + const [orderData, setorderData] = useState(0); + const router = useRouter(); + async function render() { + try { + const response = await fetch("/api/ecommerce", { + method: "GET", + }); + let res = await response.json(); + // console.log(res); + if (response.status === 200) { + setDessertData(res.result); + // console.log(res.result, "response orders"); + } + }catch (err) { + console.log(err) + } + } + async function render2() { + try { + const response = await fetch("/api/orderCount", { + method: "GET", + }); + let res = await response.json(); + // console.log(res); + if (response.status === 200) { + setorderData(res.result); + // console.log(res.result, "response orders"); + } + }catch (err) { + console.log(err) + } + } + + useEffect(() => { + render() + render2() + }, []); + return ( +
+ {/* */} +
+
+ {/* */} + Icon +
+ +
+
+ + Customers + +

+ {dessertData} +

+
+ + Icon + 11.01% + +
+
+ {/* */} + + {/* */} +
+
+ Icon +
+
+
+ + Orders + +

+ {orderData} +

+
+ + + 9.05% + +
+
+ {/* */} +
+ ) +} + +export default EcommerceMetrics \ No newline at end of file diff --git a/fit-bite-web/app/components/Filter.jsx b/fit-bite-web/app/components/Filter.jsx new file mode 100644 index 000000000..419c2b169 --- /dev/null +++ b/fit-bite-web/app/components/Filter.jsx @@ -0,0 +1,65 @@ +"use client" +import { useState } from "react"; + + + +const Filters = ({ onFilterChange }) => { + const [filters, setFilters] = useState({ + minCalories: "", + maxCalories: "", + minCarbs: "", + maxCarbs: "", + minFat: "", + maxFat: "", + minProtein: "", + maxProtein: "", + }); + + const handleChange = (e) => { + const { name, value } = e.target; + setFilters((prev) => ({ + ...prev, + [name]: value, + })); + }; + + const applyFilters = () => { + onFilterChange(filters); + }; + + return ( +
+

Filters

+
+ {["Calories", "Carbs", "Fat", "Protein"].map((nutrient) => ( +
+ + + + +
+ ))} +
+ +
+ ); +}; + +export default Filters; diff --git a/fit-bite-web/app/components/FinalRestaurantCreation.jsx b/fit-bite-web/app/components/FinalRestaurantCreation.jsx new file mode 100644 index 000000000..750033ad1 --- /dev/null +++ b/fit-bite-web/app/components/FinalRestaurantCreation.jsx @@ -0,0 +1,110 @@ +import React from "react"; + +function FinalRestaurantCreation({ + jsonData, + filteredItems, + activeStep, + setActiveStep, + setFormData0, +}) { + // const jsonDataObj = JSON.parse(jsonData); + // console.log(activeStep); + + const handleSubmit = () => { + // console.log("Hello", jsonData); + // console.log(filteredItems); + // console.log(activeStep); + setFormData0({ + restaurantName: "", + restaurantContactNumber: 0, + restaurantEmail: "", + restaurantAddress: "", + restaurantLat: 0, + restaurantLng: 0, + }); + setActiveStep(1); + // console.log(jsonDataObj.restaurantName) + }; + + return ( +
+
+
+

+ Get ready with your menu card 🎉 +

+

+ Submitted Successfully ❤ +

+ +

+ Restaurant Name:{" "} + {jsonData.restaurantName} +

+

+ Restaurant Contact Number:{" "} + + {jsonData.restaurantContactNumber} + +

+

+ Restaurant E-mail:{" "} + {jsonData.restaurantEmail} +

+

+ Restaurant Address:{" "} + {jsonData.restaurantAddress} +

+

+ Restaurant Latitude:{" "} + {jsonData.restaurantLat} +

+

+ Restaurant Longitude:{" "} + {jsonData.restaurantLng} +

+ {/*
    + {jsonDataObj.map((item) => ( +
  • +

    Name: {item.name}

    +

    Description: {item.description}

    +
  • + ))} +
*/} +

RestaurantType

+ {filteredItems.map((item, index) => ( +
    + {/* //
    */} +
  • +

    + Name: {item.name} +

    +

    + Description:{" "} + {item.description} +

    + {/*
  • */} + +
+ ))} + +

+ Our team will soon reach out to you! +

+
+
+
+ ); +} + +export default FinalRestaurantCreation; diff --git a/fit-bite-web/app/components/Footer.jsx b/fit-bite-web/app/components/Footer.jsx new file mode 100644 index 000000000..7318c663a --- /dev/null +++ b/fit-bite-web/app/components/Footer.jsx @@ -0,0 +1,97 @@ +import Image from "next/image"; +import Link from "next/link"; +import React from "react"; + +function Footer() { + return ( +
+
+ + logo + + FitBite + +

+ © 2023 FitBite — + + @Abhijeet + +

+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ); +} + +export default Footer; diff --git a/fit-bite-web/app/components/Navbar.jsx b/fit-bite-web/app/components/Navbar.jsx new file mode 100644 index 000000000..31150a46f --- /dev/null +++ b/fit-bite-web/app/components/Navbar.jsx @@ -0,0 +1,379 @@ +"use client"; +import Image from "next/image"; +import Link from "next/link"; +import React from "react"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "./ui/popover"; +// import { cartLength } from "../functions/cart"; +import { UserContext } from "../Context/UserProvider"; +import { useEffect, useState } from "react"; +function Navbar() { + const { loggedIn, login, logout, contextLoading, cartData } = + React.useContext(UserContext); + // if (!user.value) { + // // Render loading indicator or alternative content while user data is fetching + // return
; + // } + const [dropdown, setDropdown] = useState(false); + // const [userExists, setuserExists] = useState(); + + useEffect(() => { + // const token = localStorage.getItem("token"); + // console.log("token", token); + // if (token) { + // setuserExists({ value: token }); + // } + if (!contextLoading) { + login() + if (loggedIn) { + login(); + // console.log(user); + } else { + console.log("User is not logged in"); + // console.log(user); + } + } + }, [contextLoading, loggedIn, login]); + // console.log(userExists); + const toggleDropdown = () => { + // console.log(dropdown) + setDropdown(!dropdown); + }; + // // login() + // console.log('User:', user); + // console.log('Logged In:', loggedIn); + // console.log("User", user); + // console.log(loggedIn, login, logout, user) + // console.log(loggedIn, login, logout, user); + + return ( +
+
+ + logo + + FitBite + + + + + {/*
+ + +
+
    +
  • + Category 1= +
  • +
  • + Category 2 +
  • +
  • + Category 3 +
  • +
+
+ Home +
*/} + {/* Dishes */} + + {/* {user?.value ? ( + + {" "} + + ) : ( + <> + + + + + )} + */} + {/* {user.value ? ( + + + + {" "} + + ) : ( + + <> + + + + + )} */} + {/* items: {item.length} + {item.name} */} + + + + + + {" "} + {" "} + + + + + + Dishes + + + Add Restaurant + + {/* Login */} + + Create Account + + + + + + + + + + + {" "} + + + {/* {user?.value ? ( + + {" "} + + ) : ( + <> + + + + + )} */} + + {/*
*/} + + {/*
*/} + + {loggedIn ? ( + <> + + Account + + +
+ + Orders + +
+
+ + Logout + +
+ + ) : ( + + + + )} +
+ + + + + {" "} + {" "} + + + {cartData} + + + {/* + {} + */} + +
+ +
+ ); +} + +export default Navbar; diff --git a/fit-bite-web/app/components/RestaurantType.jsx b/fit-bite-web/app/components/RestaurantType.jsx new file mode 100644 index 000000000..99169efe8 --- /dev/null +++ b/fit-bite-web/app/components/RestaurantType.jsx @@ -0,0 +1,95 @@ +"use client"; +import React, { useState } from "react"; +import restaurantTypeData from "../add-restaurant/restaurantTypeData"; +import RestaurantVerification from "./RestaurantVerification"; + +function RestaurantType({ activeStep , formData, setActiveStep, setFormData}) { + // Create an array of states to track the clicked state for each container + + const [containerStates, setContainerStates] = useState( + new Array(6).fill(false) // Assuming you have 6 containers, initialize all to false + ); + const jsonData = JSON.stringify(formData, null, 2); + + // Function to handle the click event for a specific container + const handleContainerClick = (index) => { + // Create a copy of the containerStates array and toggle the state of the clicked container + const updatedStates = [...containerStates]; + updatedStates[index] = !updatedStates[index];//WIll set that thing to true + setContainerStates(updatedStates); + }; + // const [submitted, setSubmitted] = useState(false); + const trueIndices = containerStates + .map((value, index) => (value ? index : null)) + .filter((index) => index !== null); + // console.log(trueIndices); + + const filteredItems = trueIndices.map((index) => restaurantTypeData[index]); +// console.log(filteredItems) +const handleSubmit=()=>{ + setActiveStep(3) + // setSubmitted(true); + // setContainerStates(Array(6).fill(false)) + // console.log(filteredItems); + // console.log(jsonData) +} + return ( +
+ {/* Restaurant Type */} + +
+
+
+

+ Restaurant Type +

+

+ Please select from following types of restaurants. +

+
+
+ {restaurantTypeData.map((restaurantType, index) => ( +
handleContainerClick(index)} + > +
+
+ {restaurantType.icon} +
+

+ {restaurantType.name} +

+

+ {restaurantType.description} +

+
+
+ ))} +
+ + {/* {submitted && ( +
+

Submitted successfully!

+ +
+ )} */} +
+
+ + +
+ ); +} +export default RestaurantType; diff --git a/fit-bite-web/app/components/RestaurantVerification.jsx b/fit-bite-web/app/components/RestaurantVerification.jsx new file mode 100644 index 000000000..5e65aa0e7 --- /dev/null +++ b/fit-bite-web/app/components/RestaurantVerification.jsx @@ -0,0 +1,345 @@ + "use client" +import React, { useState } from "react"; +import FinalRestaurantCreation from "./FinalRestaurantCreation"; +import { ToastContainer, toast } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; +import { CldUploadWidget } from 'next-cloudinary'; +function RestaurantVerification({ + jsonData, + filteredItems, + activeStep, + setActiveStep, + setFormData0, +}) { + const jsonDataObj = JSON.parse(jsonData); + const [submitted, setSubmitted] = useState(false); + const [isClicked, setIsClicked] = useState(false); + const [fileUploaded, setFileUploaded] = useState(false); + const [file, setFile] = useState(""); + //Find filtered items + + const mappedItems = filteredItems.map((item) => { + // Here, you can access and manipulate each item as needed + // const itemName = item.name; + // const itemDescription = item.description; + + // Perform your desired operations on the item + // console.log( + // `Item ${index + 1}: Name - ${itemName}, Description - ${itemDescription}` + // ); + + // You can also return a modified version of the item + return { + ...item, + // Add or modify properties here + }; + }); +// console.log({mappedItems}) + // Output the mapped items + // console.log("Mapped items:", mappedItems); + // console.log(jsonDataObj); + const [formData, setFormData] = useState({ + restaurantName: "", + restaurantContactNumber: 0, + restaurantEmail: "", + restaurantAddress: "", + restaurantLat: 0, + restaurantLng: 0, + file:"", + restaurantType: { + items: [ + { + name: "", + description: "", + }, + { + name: "", + description: "", + }, + { + name: "", + description: "", + }, + { + name: "", + description: "", + }, + { + name: "", + description: "", + }, + { + name: "", + description: "", + }, + ], + }, + }); + + // console.log("filtereditems", filteredItems); + // console.log("Mapped items:", mappedItems[0]?.name); + // console.log(jsonDataObj.restaurantName); + + const set = () => { + console.log("set called") + console.log({file}) + setIsClicked(true); + setFormData({ + userId: jsonDataObj.userId, + restaurantName: jsonDataObj.restaurantName, + restaurantContactNumber: jsonDataObj.restaurantContactNumber, + restaurantEmail: jsonDataObj.restaurantEmail, + restaurantAddress: jsonDataObj.restaurantAddress, + restaurantLat: jsonDataObj.restaurantLat, + restaurantLng: jsonDataObj.restaurantLng, + restaurantImage:file, + restaurantType: { + items: mappedItems, + }, + }); + }; + const handleSubmit = async () => { + // console.log("Hello", jsonData); + // console.log(filteredItems); + // console.log(activeStep); + // console.log("Form Data original", formData); + // console.log(jsonDataObj.restaurantName); + + // setFormData1((prevData)=>({ + // // ...prevData, + // restaurantName: jsonDataObj.restaurantName, + // restaurantContactNumber: jsonDataObj.restaurantContactNumber, + // restaurantEmail: jsonDataObj.restaurantEmail, + // restaurantAddress: jsonDataObj.restaurantAddress, + // restaurantLat: jsonDataObj.restaurantLat, + // restaurantLng: jsonDataObj.restaurantLng, + // restaurantType: { + // items: [ + // { + // name: mappedItems[0]?.name, + // description: mappedItems[0]?.description, + // }, + // { + // name: mappedItems[1]?.name, + // description: mappedItems[1]?.description, + // }, + // { + // name: mappedItems[2]?.name, + // description: mappedItems[2]?.description, + // }, + // { + // name: mappedItems[3]?.name, + // description: mappedItems[3]?.description, + // }, + // { + // name: mappedItems[4]?.name, + // description: mappedItems[4]?.description, + // }, + // { + // name: mappedItems[5]?.name, + // description: mappedItems[5]?.description, + // }, + // ], + // }, + // })); + + //Submit Form Data + // Convert form data to JSON + const jsonDataFinal = JSON.stringify(formData, null, 2); + console.log({jsonDataFinal}, jsonDataObj) + // console.log("String form Data Final", jsonDataFinal); + try { + const response = await fetch("/api/restaurants", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: jsonDataFinal, + }); + + if (response.status === 200) { + console.log("Form data submitted successfully"); + toast.success("😎 Where is your menu card?🎉", { + position: "bottom-center", + autoClose: 5000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "dark", + }); + setSubmitted(true); + setActiveStep(4); + } else { + toast.error("👹 Invalid Data!", { + position: "bottom-center", + autoClose: 5000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "dark", + }); + console.error("Form submission failed"); + } + } catch (error) { + console.error("Error:", error); + } + }; + + return ( +
+ +
+
+ + + {/* { + // console.log("File added:", file); + console.log({results}, 'Results from callback func');//this works + console.log('Public ID', results.info.public_id); + results && results.info.public_id ? setFile(results.info.public_id):console.log('No file uploaded'); + setFileUploaded(true); + + className="text-gray-400 text-md mt-5" + }} > + + {({ open, results }) => { + console.log({results}, 'Results from render prop');//data.event.files[0].uploadInfo.public_id + return ; + }} + */} +

RestaurantVerification:

+

+ +

+ +

+ Verify Restaurant Details +

+

+ Restaurant Name:{" "} + {jsonDataObj.restaurantName} +

+

+ Restaurant Contact Number:{" "} + + {" "} + {jsonDataObj.restaurantContactNumber} + +

+

+ Restaurant E-mail:{" "} + {jsonDataObj.restaurantEmail} +

+

+ Restaurant Address:{" "} + + {jsonDataObj.restaurantAddress} + +

+

+ Restaurant Latitude:{" "} + {jsonDataObj.restaurantLat} +

+

+ Restaurant Longitude:{" "} + {jsonDataObj.restaurantLng} +

+ {/*
    + {jsonDataObj.map((item) => ( +
  • +

    Name: {item.name}

    +

    Description: {item.description}

    +
  • + ))} +
*/} +

RestaurantType

+ { + // console.log("File added:", file); + setFileUploaded(true); + console.log({results}, 'Results from callback func');//this works + console.log('Public ID', results.info.public_id); + let public_id = results.info.public_id; + results && results.info.public_id ? setFile(results.info.public_id):console.log('No file uploaded'); + setFile(public_id); + + + }} > + {/* UPLOAD */} + {({ open, results }) => { + console.log({results}, 'Results from render prop');//data.event.files[0].uploadInfo.public_id + + return ; + }} + + {filteredItems.map((item, index) => ( +
    +
  • +

    + Name: {item.name} +

    +

    + Description:{" "} + {item.description} +

    +
  • +
+ ))} + +
+ {submitted && ( +
+

Form submitted successfully!

+ +
+ )} +
+ +
+ ); +} + +export default RestaurantVerification; diff --git a/fit-bite-web/app/components/SidebarWidget.jsx b/fit-bite-web/app/components/SidebarWidget.jsx new file mode 100644 index 000000000..917908c90 --- /dev/null +++ b/fit-bite-web/app/components/SidebarWidget.jsx @@ -0,0 +1,25 @@ +import React from "react"; + +export default function SidebarWidget() { + return ( +
+

+ #1 Tailwind CSS Dashboard +

+

+ Leading Tailwind CSS Admin Template with 400+ UI Component and Pages. +

+ + Upgrade To Pro + +
+ ); +} diff --git a/fit-bite-web/app/components/Tabs.jsx b/fit-bite-web/app/components/Tabs.jsx new file mode 100644 index 000000000..f3b4ba1c2 --- /dev/null +++ b/fit-bite-web/app/components/Tabs.jsx @@ -0,0 +1,111 @@ +import React from "react"; +function Tabs({ activeStep, setActiveStep }) { + const handleStepClick = (step) => { + setActiveStep(step); + }; + return ( +
+ +
+
+
+

handleStepClick(1)} + > + + + + STEP 1 +

+ +

handleStepClick(2)} + > + + + + STEP 2 +

+ + +

+ + + + + STEP 3 +

+ + +

+ + + + + + STEP 4 +

+
+ {/* hero +
+

+ Master Cleanse Reliac Heirloom +

+

+ Whatever cardigan tote bag tumblr hexagon brooklyn asymmetrical + gentrify, subway tile poke farm-to-table. Franzen you probably + haven't heard of them man bun deep jianbing selfies heirloom prism + food truck ugh squid celiac humblebrag. +

+
*/} +
+
+
+ ); +} + +export default Tabs; diff --git a/fit-bite-web/app/components/common/ChartTab.jsx b/fit-bite-web/app/components/common/ChartTab.jsx new file mode 100644 index 000000000..c456e6203 --- /dev/null +++ b/fit-bite-web/app/components/common/ChartTab.jsx @@ -0,0 +1,43 @@ +import React, { useState } from "react"; + +const ChartTab = () => { + const [selected, setSelected] = useState("optionOne"); + + const getButtonClass = (option) => + selected === option + ? "shadow-theme-xs text-gray-900 dark:text-white bg-white dark:bg-gray-800" + : "text-gray-500 dark:text-gray-400"; + + return ( +
+ + + + + +
+ ); +}; + +export default ChartTab; diff --git a/fit-bite-web/app/components/common/ComponentCard.jsx b/fit-bite-web/app/components/common/ComponentCard.jsx new file mode 100644 index 000000000..6b2705f29 --- /dev/null +++ b/fit-bite-web/app/components/common/ComponentCard.jsx @@ -0,0 +1,40 @@ +import React from "react"; + +// interface ComponentCardProps { +// title: string; +// children: React.ReactNode; +// className?: string; // Additional custom classes for styling +// desc?: string; // Description text +// } + +const ComponentCard = ({ + title, + children, + className = "", + desc = "", +}) => { + return ( +
+ {/* Card Header */} +
+

+ {title} +

+ {desc && ( +

+ {desc} +

+ )} +
+ + {/* Card Body */} +
+
{children}
+
+
+ ); +}; + +export default ComponentCard; diff --git a/fit-bite-web/app/components/common/GridShape.jsx b/fit-bite-web/app/components/common/GridShape.jsx new file mode 100644 index 000000000..47a3c1e54 --- /dev/null +++ b/fit-bite-web/app/components/common/GridShape.jsx @@ -0,0 +1,25 @@ +import Image from "next/image"; +import React from "react"; + +export default function GridShape() { + return ( + <> +
+ grid +
+
+ grid +
+ + ); +} diff --git a/fit-bite-web/app/components/common/PageBreadCrumb.jsx b/fit-bite-web/app/components/common/PageBreadCrumb.jsx new file mode 100644 index 000000000..6ec84d89d --- /dev/null +++ b/fit-bite-web/app/components/common/PageBreadCrumb.jsx @@ -0,0 +1,52 @@ +import Link from "next/link"; +import React from "react"; + +// interface BreadcrumbProps { +// pageTitle: string; +// } + +const PageBreadcrumb = ({ pageTitle }) => { + return ( +
+

+ {pageTitle} +

+ +
+ ); +}; + +export default PageBreadcrumb; diff --git a/fit-bite-web/app/components/common/ThemeToggleButton.jsx b/fit-bite-web/app/components/common/ThemeToggleButton.jsx new file mode 100644 index 000000000..c08dfde66 --- /dev/null +++ b/fit-bite-web/app/components/common/ThemeToggleButton.jsx @@ -0,0 +1,42 @@ +import React from "react"; +import { useTheme } from "../../Context/ThemeContext"; + +export const ThemeToggleButton = () => { + const { toggleTheme } = useTheme(); + + return ( + + ); +}; diff --git a/fit-bite-web/app/components/form/Form.jsx b/fit-bite-web/app/components/form/Form.jsx new file mode 100644 index 000000000..f523a512a --- /dev/null +++ b/fit-bite-web/app/components/form/Form.jsx @@ -0,0 +1,23 @@ +import React, { FC, ReactNode, FormEvent } from "react"; + +// interface FormProps { +// onSubmit: (event: FormEvent) => void; +// children: ReactNode; +// className?: string; +// } + +const Form = ({ onSubmit, children, className }) => { + return ( +
{ + event.preventDefault(); // Prevent default form submission + onSubmit(event); + }} + className={` ${className}`} // Default spacing between form fields + > + {children} +
+ ); +}; + +export default Form; diff --git a/fit-bite-web/app/components/form/Label.jsx b/fit-bite-web/app/components/form/Label.jsx new file mode 100644 index 000000000..52a96ad13 --- /dev/null +++ b/fit-bite-web/app/components/form/Label.jsx @@ -0,0 +1,27 @@ +import React, { FC, ReactNode } from "react"; +import { twMerge } from "tailwind-merge"; + +// interface LabelProps { +// htmlFor?: string; +// children: ReactNode; +// className?: string; +// } + +const Label = ({ htmlFor, children, className }) => { + return ( + + ); +}; + +export default Label; diff --git a/fit-bite-web/app/components/form/MultiSelect.jsx b/fit-bite-web/app/components/form/MultiSelect.jsx new file mode 100644 index 000000000..c55fa1b1f --- /dev/null +++ b/fit-bite-web/app/components/form/MultiSelect.jsx @@ -0,0 +1,166 @@ +import React, { useState } from "react"; + +// interface Option { +// value: string; +// text: string; +// selected: boolean; +// } + +// interface MultiSelectProps { +// label: string; +// options: Option[]; +// defaultSelected?: string[]; +// onChange?: (selected: string[]) => void; +// disabled?: boolean; +// } + +const MultiSelect = ({ + label, + options, + defaultSelected = [], + onChange, + disabled = false, +}) => { + const [selectedOptions, setSelectedOptions] = + useState(defaultSelected); + const [isOpen, setIsOpen] = useState(false); + + const toggleDropdown = () => { + if (disabled) return; + setIsOpen((prev) => !prev); + }; + + const handleSelect = (optionValue) => { + const newSelectedOptions = selectedOptions.includes(optionValue) + ? selectedOptions.filter((value) => value !== optionValue) + : [...selectedOptions, optionValue]; + + setSelectedOptions(newSelectedOptions); + if (onChange) onChange(newSelectedOptions); + }; + + const removeOption = (index, value) => { + const newSelectedOptions = selectedOptions.filter((opt) => opt !== value); + setSelectedOptions(newSelectedOptions); + if (onChange) onChange(newSelectedOptions); + }; + + const selectedValuesText = selectedOptions.map( + (value) => options.find((option) => option.value === value)?.text || "" + ); + + return ( +
+ + +
+
+
+
+
+ {selectedValuesText.length > 0 ? ( + selectedValuesText.map((text, index) => ( +
+ {text} +
+
+ removeOption(index, selectedOptions[index]) + } + className="pl-2 text-gray-500 cursor-pointer group-hover:text-gray-400 dark:text-gray-400" + > + + + +
+
+
+ )) + ) : ( + + )} +
+
+ +
+
+
+ + {isOpen && ( +
e.stopPropagation()} + > +
+ {options.map((option, index) => ( +
+
handleSelect(option.value)} + > +
+
+ {option.text} +
+
+
+
+ ))} +
+
+ )} +
+
+
+ ); +}; + +export default MultiSelect; diff --git a/fit-bite-web/app/components/form/Select.jsx b/fit-bite-web/app/components/form/Select.jsx new file mode 100644 index 000000000..bd1b5d43c --- /dev/null +++ b/fit-bite-web/app/components/form/Select.jsx @@ -0,0 +1,64 @@ +import React, { useState } from "react"; + +// interface Option { +// value: string; +// label: string; +// } + +// interface SelectProps { +// options: Option[]; +// placeholder?: string; +// onChange: (value: string) => void; +// className?: string; +// defaultValue?: string; +// } + +const Select= ({ + options, + placeholder = "Select an option", + onChange, + className = "", + defaultValue = "", +}) => { + // Manage the selected value + const [selectedValue, setSelectedValue] = useState(defaultValue); + + const handleChange = (e) => { + const value = e.target.value; + setSelectedValue(value); + onChange(value); // Trigger parent handler + }; + + return ( + + ); +}; + +export default Select; diff --git a/fit-bite-web/app/components/form/example-form/BasicForm.jsx b/fit-bite-web/app/components/form/example-form/BasicForm.jsx new file mode 100644 index 000000000..a3bcf346c --- /dev/null +++ b/fit-bite-web/app/components/form/example-form/BasicForm.jsx @@ -0,0 +1,38 @@ +"use client"; +import React from "react"; +import ComponentCard from "../../common/ComponentCard"; +import Form from "../Form"; +import Input from "../input/InputField"; +import Button from "../../ui/button/Button"; + +export default function BasicForm() { + const handleSubmit = (e) => { + e.preventDefault(); + console.log("Form submitted:"); + }; + return ( + +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ ); +} diff --git a/fit-bite-web/app/components/form/example-form/ExampleFormOne.jsx b/fit-bite-web/app/components/form/example-form/ExampleFormOne.jsx new file mode 100644 index 000000000..5224c8c4e --- /dev/null +++ b/fit-bite-web/app/components/form/example-form/ExampleFormOne.jsx @@ -0,0 +1,81 @@ +"use client"; +import React, { useState } from "react"; +import ComponentCard from "../../common/ComponentCard"; +import Form from "../Form"; +import Label from "../Label"; +import Input from "../input/InputField"; +import Select from "../Select"; +import TextArea from "../input/TextArea"; +import Button from "../../ui/button/Button"; +import { PaperPlaneIcon } from "../../../icons"; + +export default function ExampleFormOne() { + const [message, setMessage] = useState(""); + const handleSubmit = (e) => { + e.preventDefault(); + console.log("Form submitted:"); + }; + const options = [ + { value: "marketing", label: "Option 1" }, + { value: "template", label: "Option 2" }, + { value: "development", label: "Option 3" }, + ]; + const handleSelectChange = (value) => { + console.log("Selected value:", value); + }; + + const handleTextareaChange = (value) => { + setMessage(value); + console.log("Message:", value); + }; + return ( + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ +