From 76f1ffa6b3658f8cedf50df3364bbb73f5fa6420 Mon Sep 17 00:00:00 2001 From: ziyaudheenms Date: Tue, 30 Jun 2026 11:53:01 +0530 Subject: [PATCH 1/3] feat: complete backend celery upload task and frontend integration --- .../Owner/__pycache__/tasks.cpython-311.pyc | Bin 0 -> 4006 bytes .../BackgroundWorker/Owner/tasks.py | 88 + .../bookmyvenue/BackgroundWorker/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 218 bytes .../__pycache__/main.cpython-311.pyc | Bin 0 -> 4721 bytes .../__pycache__/worker.cpython-311.pyc | Bin 0 -> 1004 bytes .../src/bookmyvenue/api/__init__.py | 0 .../api/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 205 bytes .../api/__pycache__/deps.cpython-311.pyc | Bin 0 -> 4025 bytes .../bookmyvenue/src/bookmyvenue/api/deps.py | 76 + .../src/bookmyvenue/api/v1/__init__.py | 0 .../v1/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 208 bytes .../src/bookmyvenue/api/v1/admin/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 214 bytes .../admin/__pycache__/admin.cpython-311.pyc | Bin 0 -> 4028 bytes .../src/bookmyvenue/api/v1/admin/admin.py | 61 + .../common/__pycache__/common.cpython-311.pyc | Bin 0 -> 4827 bytes .../src/bookmyvenue/api/v1/common/common.py | 98 + .../src/bookmyvenue/api/v1/owner/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 214 bytes .../owner/__pycache__/owner.cpython-311.pyc | Bin 0 -> 4547 bytes .../src/bookmyvenue/api/v1/owner/owner.py | 93 + .../src/bookmyvenue/api/v1/users/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 214 bytes .../users/__pycache__/users.cpython-311.pyc | Bin 0 -> 5804 bytes .../src/bookmyvenue/api/v1/users/users.py | 111 + .../src/bookmyvenue/core/__init__.py | 0 .../core/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 206 bytes .../core/__pycache__/config.cpython-311.pyc | Bin 0 -> 1731 bytes .../core/__pycache__/database.cpython-311.pyc | Bin 0 -> 848 bytes .../core/__pycache__/logging.cpython-311.pyc | Bin 0 -> 1838 bytes .../src/bookmyvenue/core/config.py | 35 + .../src/bookmyvenue/core/database.py | 12 + .../src/bookmyvenue/core/logging.py | 38 + .../__pycache__/logging.cpython-311.pyc | Bin 0 -> 1604 bytes .../bookmyvenue/core/middleware/logging.py | 23 + Backend/bookmyvenue/src/bookmyvenue/main.py | 94 + .../src/bookmyvenue/models/__init__.py | 14 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 648 bytes .../models/__pycache__/admin.cpython-311.pyc | Bin 0 -> 2860 bytes .../models/__pycache__/common.cpython-311.pyc | Bin 0 -> 6112 bytes .../models/__pycache__/owners.cpython-311.pyc | Bin 0 -> 3835 bytes .../models/__pycache__/user.cpython-311.pyc | Bin 0 -> 2770 bytes .../src/bookmyvenue/models/admin.py | 34 + .../src/bookmyvenue/models/common.py | 86 + .../src/bookmyvenue/models/owners.py | 46 + .../src/bookmyvenue/models/user.py | 41 + .../src/bookmyvenue/repositories/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 214 bytes .../repositories/admin/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 220 bytes .../__pycache__/repository.cpython-311.pyc | Bin 0 -> 6263 bytes .../repositories/admin/repository.py | 105 + .../repositories/common/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 221 bytes .../__pycache__/repository.cpython-311.pyc | Bin 0 -> 1691 bytes .../repositories/common/repository.py | 17 + .../repositories/owner/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 220 bytes .../__pycache__/repository.cpython-311.pyc | Bin 0 -> 7366 bytes .../repositories/owner/repository.py | 95 + .../__pycache__/repository.cpython-311.pyc | Bin 0 -> 4101 bytes .../repositories/users/repository.py | 52 + .../src/bookmyvenue/schema/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 208 bytes .../src/bookmyvenue/schema/admin/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 214 bytes .../admin/__pycache__/admin.cpython-311.pyc | Bin 0 -> 1428 bytes .../src/bookmyvenue/schema/admin/admin.py | 19 + .../src/bookmyvenue/schema/common/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 215 bytes .../common/__pycache__/common.cpython-311.pyc | Bin 0 -> 1606 bytes .../src/bookmyvenue/schema/common/common.py | 26 + .../src/bookmyvenue/schema/owner/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 214 bytes .../owner/__pycache__/owner.cpython-311.pyc | Bin 0 -> 948 bytes .../src/bookmyvenue/schema/owner/owner.py | 12 + .../__pycache__/responces.cpython-311.pyc | Bin 0 -> 4072 bytes .../bookmyvenue/schema/responce/responces.py | 64 + .../bookmyvenue/schema/responce/suiiii.html | 0 .../user/__pycache__/user.cpython-311.pyc | Bin 0 -> 3575 bytes .../src/bookmyvenue/schema/user/user.py | 50 + .../src/bookmyvenue/services/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 210 bytes .../__pycache__/adminService.cpython-311.pyc | Bin 0 -> 5062 bytes .../__pycache__/commonService.cpython-311.pyc | Bin 0 -> 2281 bytes .../__pycache__/ownerServices.cpython-311.pyc | Bin 0 -> 5813 bytes .../__pycache__/ownertask.cpython-311.pyc | Bin 0 -> 4254 bytes .../__pycache__/userServices.cpython-311.pyc | Bin 0 -> 4169 bytes .../src/bookmyvenue/services/adminService.py | 82 + .../src/bookmyvenue/services/commonService.py | 37 + .../src/bookmyvenue/services/ownerServices.py | 84 + .../src/bookmyvenue/services/userServices.py | 75 + .../src/bookmyvenue/utils/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 207 bytes .../__pycache__/image_kit.cpython-311.pyc | Bin 0 -> 431 bytes .../src/bookmyvenue/utils/image_kit.py | 7 + Backend/bookmyvenue/src/bookmyvenue/worker.py | 24 + Frontend/bookmyvenue/.dockerignore | 43 + Frontend/bookmyvenue/.gitignore | 37 + Frontend/bookmyvenue/.prettierignore | 7 + Frontend/bookmyvenue/.prettierrc | 11 + Frontend/bookmyvenue/README.md | 21 + Frontend/bookmyvenue/app/(admin)/add/page.tsx | 241 + .../app/(admin)/allTransactions/page.tsx | 174 + .../bookmyvenue/app/(admin)/allUsers/page.tsx | 147 + .../app/(admin)/allVenues/page.tsx | 112 + .../app/(admin)/bookmyvenue/page.tsx | 584 + Frontend/bookmyvenue/app/(admin)/layout.tsx | 37 + .../app/(auth)/complete-onboarding/page.tsx | 91 + .../app/(auth)/owner-onboarding/page.tsx | 166 + .../bookmyvenue/app/(auth)/sign-in/page.tsx | 38 + .../bookmyvenue/app/(auth)/sign-up/page.tsx | 29 + .../app/(owner)/Bookings/[id]/page.tsx | 138 + .../bookmyvenue/app/(owner)/create/page.tsx | 708 + .../app/(owner)/dashboard/page.tsx | 568 + .../app/(owner)/details/[id]/page.tsx | 163 + Frontend/bookmyvenue/app/(owner)/layout.tsx | 37 + .../app/(owner)/manager/[id]/page.tsx | 17 + .../app/(owner)/preview/[id]/page.tsx | 200 + .../app/(user)/booking/[id]/page.tsx | 14 + .../app/(user)/confirmation/[id]/page.tsx | 32 + .../app/(user)/filters/[id]/page.tsx | 159 + Frontend/bookmyvenue/app/(user)/layout.tsx | 37 + .../app/(user)/profile/[id]/page.tsx | 130 + .../app/(user)/venue/[id]/page.tsx | 194 + Frontend/bookmyvenue/app/favicon.ico | Bin 0 -> 15406 bytes Frontend/bookmyvenue/app/globals.css | 141 + Frontend/bookmyvenue/app/layout.tsx | 47 + Frontend/bookmyvenue/app/page.tsx | 169 + Frontend/bookmyvenue/components.json | 25 + Frontend/bookmyvenue/components/.gitkeep | 0 .../components/DynamicTabularIcons.tsx | 18 + Frontend/bookmyvenue/components/Footer.tsx | 12 + .../components/LocationSuggest.tsx | 113 + .../components/PaymentCancellation.tsx | 30 + .../bookmyvenue/components/PaymentPDF.tsx | 184 + Frontend/bookmyvenue/components/banner.tsx | 16 + .../bookmyvenue/components/calenderView.tsx | 57 + Frontend/bookmyvenue/components/cancel.tsx | 54 + Frontend/bookmyvenue/components/filters.tsx | 65 + Frontend/bookmyvenue/components/gallery.tsx | 58 + .../bookmyvenue/components/galleryViewAll.tsx | 54 + .../components/groupDatePicker.tsx | 33 + .../bookmyvenue/components/locationFinder.tsx | 43 + Frontend/bookmyvenue/components/offline.tsx | 133 + Frontend/bookmyvenue/components/payment.tsx | 51 + .../bookmyvenue/components/priceManager.tsx | 130 + Frontend/bookmyvenue/components/reject.tsx | 51 + .../bookmyvenue/components/revenueGraph.tsx | 227 + .../bookmyvenue/components/revenueStats.tsx | 70 + Frontend/bookmyvenue/components/review.tsx | 69 + Frontend/bookmyvenue/components/seasonal.tsx | 77 + .../bookmyvenue/components/theme-provider.tsx | 71 + .../bookmyvenue/components/topRatedVenues.tsx | 57 + Frontend/bookmyvenue/components/ui/alert.tsx | 76 + Frontend/bookmyvenue/components/ui/badge.tsx | 49 + Frontend/bookmyvenue/components/ui/button.tsx | 67 + .../bookmyvenue/components/ui/calendar.tsx | 222 + Frontend/bookmyvenue/components/ui/card.tsx | 103 + .../bookmyvenue/components/ui/carousel.tsx | 240 + Frontend/bookmyvenue/components/ui/chart.tsx | 373 + Frontend/bookmyvenue/components/ui/dialog.tsx | 168 + .../components/ui/dropdown-menu.tsx | 269 + Frontend/bookmyvenue/components/ui/field.tsx | 238 + .../bookmyvenue/components/ui/input-group.tsx | 156 + Frontend/bookmyvenue/components/ui/input.tsx | 19 + Frontend/bookmyvenue/components/ui/label.tsx | 24 + Frontend/bookmyvenue/components/ui/navbar.tsx | 62 + .../bookmyvenue/components/ui/popover.tsx | 89 + Frontend/bookmyvenue/components/ui/select.tsx | 192 + .../bookmyvenue/components/ui/separator.tsx | 28 + Frontend/bookmyvenue/components/ui/slider.tsx | 59 + Frontend/bookmyvenue/components/ui/sonner.tsx | 49 + .../bookmyvenue/components/ui/spinner.tsx | 10 + Frontend/bookmyvenue/components/ui/table.tsx | 116 + .../bookmyvenue/components/ui/textarea.tsx | 18 + Frontend/bookmyvenue/components/upComing.tsx | 129 + .../bookmyvenue/components/venueLister.tsx | 194 + .../bookmyvenue/components/venueSearch.tsx | 88 + Frontend/bookmyvenue/components/weekly.tsx | 70 + Frontend/bookmyvenue/dockerfile | 12 + Frontend/bookmyvenue/eslint.config.mjs | 18 + .../features/venueCreateFeatureSlice.ts | 147 + Frontend/bookmyvenue/hooks/.gitkeep | 0 Frontend/bookmyvenue/lib/.gitkeep | 0 Frontend/bookmyvenue/lib/redux/hooks.ts | 8 + Frontend/bookmyvenue/lib/redux/provider.tsx | 9 + Frontend/bookmyvenue/lib/utils.ts | 6 + Frontend/bookmyvenue/middleware.ts | 26 + Frontend/bookmyvenue/next.config.mjs | 21 + Frontend/bookmyvenue/package-lock.json | 12616 ++++++++++++++++ Frontend/bookmyvenue/package.json | 50 + Frontend/bookmyvenue/postcss.config.mjs | 8 + Frontend/bookmyvenue/public/.gitkeep | 0 Frontend/bookmyvenue/public/1.png | Bin 0 -> 208488 bytes Frontend/bookmyvenue/public/2.png | Bin 0 -> 124722 bytes Frontend/bookmyvenue/public/3.png | Bin 0 -> 154905 bytes Frontend/bookmyvenue/public/banner.png | Bin 0 -> 1044333 bytes Frontend/bookmyvenue/public/banner3.png | Bin 0 -> 891684 bytes Frontend/bookmyvenue/public/banner4.png | Bin 0 -> 618861 bytes Frontend/bookmyvenue/public/brand2.png | Bin 0 -> 106430 bytes Frontend/bookmyvenue/public/logo.png | Bin 0 -> 42826 bytes Frontend/bookmyvenue/public/payment.png | Bin 0 -> 75605 bytes Frontend/bookmyvenue/store/store.ts | 15 + Frontend/bookmyvenue/tsconfig.json | 34 + 206 files changed, 23967 insertions(+) create mode 100644 Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/Owner/__pycache__/tasks.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/Owner/tasks.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/__pycache__/main.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/__pycache__/worker.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/__pycache__/deps.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/deps.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/__pycache__/admin.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/admin.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/common/__pycache__/common.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/common/common.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/owner/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/owner/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/owner/__pycache__/owner.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/owner/owner.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/users/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/users/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/users/__pycache__/users.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/api/v1/users/users.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/core/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/core/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/core/__pycache__/config.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/core/__pycache__/database.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/core/__pycache__/logging.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/core/config.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/core/database.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/core/logging.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/core/middleware/__pycache__/logging.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/core/middleware/logging.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/main.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/models/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/admin.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/common.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/owners.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/user.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/models/admin.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/models/common.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/models/owners.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/models/user.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/admin/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/admin/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/admin/__pycache__/repository.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/admin/repository.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/common/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/common/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/common/__pycache__/repository.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/common/repository.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/owner/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/owner/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/owner/__pycache__/repository.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/owner/repository.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/users/__pycache__/repository.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/repositories/users/repository.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/admin/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/admin/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/admin/__pycache__/admin.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/admin/admin.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/common/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/common/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/common/__pycache__/common.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/common/common.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/owner/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/owner/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/owner/__pycache__/owner.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/owner/owner.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/responce/__pycache__/responces.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/responce/responces.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/responce/suiiii.html create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/user/__pycache__/user.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/schema/user/user.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/services/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/services/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/services/__pycache__/adminService.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/services/__pycache__/commonService.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/services/__pycache__/ownerServices.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/services/__pycache__/ownertask.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/services/__pycache__/userServices.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/services/adminService.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/services/commonService.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/services/ownerServices.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/services/userServices.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/utils/__init__.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/utils/__pycache__/__init__.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/utils/__pycache__/image_kit.cpython-311.pyc create mode 100644 Backend/bookmyvenue/src/bookmyvenue/utils/image_kit.py create mode 100644 Backend/bookmyvenue/src/bookmyvenue/worker.py create mode 100644 Frontend/bookmyvenue/.dockerignore create mode 100644 Frontend/bookmyvenue/.gitignore create mode 100644 Frontend/bookmyvenue/.prettierignore create mode 100644 Frontend/bookmyvenue/.prettierrc create mode 100644 Frontend/bookmyvenue/README.md create mode 100644 Frontend/bookmyvenue/app/(admin)/add/page.tsx create mode 100644 Frontend/bookmyvenue/app/(admin)/allTransactions/page.tsx create mode 100644 Frontend/bookmyvenue/app/(admin)/allUsers/page.tsx create mode 100644 Frontend/bookmyvenue/app/(admin)/allVenues/page.tsx create mode 100644 Frontend/bookmyvenue/app/(admin)/bookmyvenue/page.tsx create mode 100644 Frontend/bookmyvenue/app/(admin)/layout.tsx create mode 100644 Frontend/bookmyvenue/app/(auth)/complete-onboarding/page.tsx create mode 100644 Frontend/bookmyvenue/app/(auth)/owner-onboarding/page.tsx create mode 100644 Frontend/bookmyvenue/app/(auth)/sign-in/page.tsx create mode 100644 Frontend/bookmyvenue/app/(auth)/sign-up/page.tsx create mode 100644 Frontend/bookmyvenue/app/(owner)/Bookings/[id]/page.tsx create mode 100644 Frontend/bookmyvenue/app/(owner)/create/page.tsx create mode 100644 Frontend/bookmyvenue/app/(owner)/dashboard/page.tsx create mode 100644 Frontend/bookmyvenue/app/(owner)/details/[id]/page.tsx create mode 100644 Frontend/bookmyvenue/app/(owner)/layout.tsx create mode 100644 Frontend/bookmyvenue/app/(owner)/manager/[id]/page.tsx create mode 100644 Frontend/bookmyvenue/app/(owner)/preview/[id]/page.tsx create mode 100644 Frontend/bookmyvenue/app/(user)/booking/[id]/page.tsx create mode 100644 Frontend/bookmyvenue/app/(user)/confirmation/[id]/page.tsx create mode 100644 Frontend/bookmyvenue/app/(user)/filters/[id]/page.tsx create mode 100644 Frontend/bookmyvenue/app/(user)/layout.tsx create mode 100644 Frontend/bookmyvenue/app/(user)/profile/[id]/page.tsx create mode 100644 Frontend/bookmyvenue/app/(user)/venue/[id]/page.tsx create mode 100644 Frontend/bookmyvenue/app/favicon.ico create mode 100644 Frontend/bookmyvenue/app/globals.css create mode 100644 Frontend/bookmyvenue/app/layout.tsx create mode 100644 Frontend/bookmyvenue/app/page.tsx create mode 100644 Frontend/bookmyvenue/components.json create mode 100644 Frontend/bookmyvenue/components/.gitkeep create mode 100644 Frontend/bookmyvenue/components/DynamicTabularIcons.tsx create mode 100644 Frontend/bookmyvenue/components/Footer.tsx create mode 100644 Frontend/bookmyvenue/components/LocationSuggest.tsx create mode 100644 Frontend/bookmyvenue/components/PaymentCancellation.tsx create mode 100644 Frontend/bookmyvenue/components/PaymentPDF.tsx create mode 100644 Frontend/bookmyvenue/components/banner.tsx create mode 100644 Frontend/bookmyvenue/components/calenderView.tsx create mode 100644 Frontend/bookmyvenue/components/cancel.tsx create mode 100644 Frontend/bookmyvenue/components/filters.tsx create mode 100644 Frontend/bookmyvenue/components/gallery.tsx create mode 100644 Frontend/bookmyvenue/components/galleryViewAll.tsx create mode 100644 Frontend/bookmyvenue/components/groupDatePicker.tsx create mode 100644 Frontend/bookmyvenue/components/locationFinder.tsx create mode 100644 Frontend/bookmyvenue/components/offline.tsx create mode 100644 Frontend/bookmyvenue/components/payment.tsx create mode 100644 Frontend/bookmyvenue/components/priceManager.tsx create mode 100644 Frontend/bookmyvenue/components/reject.tsx create mode 100644 Frontend/bookmyvenue/components/revenueGraph.tsx create mode 100644 Frontend/bookmyvenue/components/revenueStats.tsx create mode 100644 Frontend/bookmyvenue/components/review.tsx create mode 100644 Frontend/bookmyvenue/components/seasonal.tsx create mode 100644 Frontend/bookmyvenue/components/theme-provider.tsx create mode 100644 Frontend/bookmyvenue/components/topRatedVenues.tsx create mode 100644 Frontend/bookmyvenue/components/ui/alert.tsx create mode 100644 Frontend/bookmyvenue/components/ui/badge.tsx create mode 100644 Frontend/bookmyvenue/components/ui/button.tsx create mode 100644 Frontend/bookmyvenue/components/ui/calendar.tsx create mode 100644 Frontend/bookmyvenue/components/ui/card.tsx create mode 100644 Frontend/bookmyvenue/components/ui/carousel.tsx create mode 100644 Frontend/bookmyvenue/components/ui/chart.tsx create mode 100644 Frontend/bookmyvenue/components/ui/dialog.tsx create mode 100644 Frontend/bookmyvenue/components/ui/dropdown-menu.tsx create mode 100644 Frontend/bookmyvenue/components/ui/field.tsx create mode 100644 Frontend/bookmyvenue/components/ui/input-group.tsx create mode 100644 Frontend/bookmyvenue/components/ui/input.tsx create mode 100644 Frontend/bookmyvenue/components/ui/label.tsx create mode 100644 Frontend/bookmyvenue/components/ui/navbar.tsx create mode 100644 Frontend/bookmyvenue/components/ui/popover.tsx create mode 100644 Frontend/bookmyvenue/components/ui/select.tsx create mode 100644 Frontend/bookmyvenue/components/ui/separator.tsx create mode 100644 Frontend/bookmyvenue/components/ui/slider.tsx create mode 100644 Frontend/bookmyvenue/components/ui/sonner.tsx create mode 100644 Frontend/bookmyvenue/components/ui/spinner.tsx create mode 100644 Frontend/bookmyvenue/components/ui/table.tsx create mode 100644 Frontend/bookmyvenue/components/ui/textarea.tsx create mode 100644 Frontend/bookmyvenue/components/upComing.tsx create mode 100644 Frontend/bookmyvenue/components/venueLister.tsx create mode 100644 Frontend/bookmyvenue/components/venueSearch.tsx create mode 100644 Frontend/bookmyvenue/components/weekly.tsx create mode 100644 Frontend/bookmyvenue/dockerfile create mode 100644 Frontend/bookmyvenue/eslint.config.mjs create mode 100644 Frontend/bookmyvenue/features/venueCreateFeatureSlice.ts create mode 100644 Frontend/bookmyvenue/hooks/.gitkeep create mode 100644 Frontend/bookmyvenue/lib/.gitkeep create mode 100644 Frontend/bookmyvenue/lib/redux/hooks.ts create mode 100644 Frontend/bookmyvenue/lib/redux/provider.tsx create mode 100644 Frontend/bookmyvenue/lib/utils.ts create mode 100644 Frontend/bookmyvenue/middleware.ts create mode 100644 Frontend/bookmyvenue/next.config.mjs create mode 100644 Frontend/bookmyvenue/package-lock.json create mode 100644 Frontend/bookmyvenue/package.json create mode 100644 Frontend/bookmyvenue/postcss.config.mjs create mode 100644 Frontend/bookmyvenue/public/.gitkeep create mode 100644 Frontend/bookmyvenue/public/1.png create mode 100644 Frontend/bookmyvenue/public/2.png create mode 100644 Frontend/bookmyvenue/public/3.png create mode 100644 Frontend/bookmyvenue/public/banner.png create mode 100644 Frontend/bookmyvenue/public/banner3.png create mode 100644 Frontend/bookmyvenue/public/banner4.png create mode 100644 Frontend/bookmyvenue/public/brand2.png create mode 100644 Frontend/bookmyvenue/public/logo.png create mode 100644 Frontend/bookmyvenue/public/payment.png create mode 100644 Frontend/bookmyvenue/store/store.ts create mode 100644 Frontend/bookmyvenue/tsconfig.json diff --git a/Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/Owner/__pycache__/tasks.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/Owner/__pycache__/tasks.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..59b0b1f6469b49df3583c2bddac48cf3726cc4b8 GIT binary patch literal 4006 zcmb6bTWlN0aqo^t9^aHiJ#C5fQOV#}!{SC-|-^(#RMwgkmnQIzf>?;S0R zAPb|&2W<$j>K}h30rce}us@r^C|V$BKP>;91Oh%BAV5G7p!uWg1TgZ|*`p|uQi`g} zv$%kog#I;||FwyJ9XI=OsaQ$J{pVlsvLG=CyH`db4BUH~n zx3f2o=2^=AGJmdZ5O+D%9{ACNg>SjC}(7 zJhgSAE8uuebcp;HENDdUYENrCi$OP#2L3<*04O2=RQZGM?X}Xn`^4#qF3}a+WI;Ak`w*U z0*$8@+xVkeh0M%Nh z#Mb&)f*5S8uGEjaV^BGN1nGk{j-!a2D){$dciS#o_e7xB-k^{F_mE%<{@?i*nMHJ$ z`!!l*l(9W$|E%B#%{yxP)Ue%}??cCqpL(VFpU}jO_WNc zW*;Clxn)AVpo?qBp3?d_%Q2IY;7ke=v`ARa8C4Q7$sNI&HOonoim1w#i;fvZC+(EU2}K(#qUE*Sk+2;~XpOL(DOHv;y5+ujH-#5; zsP~pYR7sjnrsn$sgjN}Hk^;(2Xz8$6aoUQevV>qoPuRhhn8A8#7Q!b%^~EwQSiHSr z1?x^sfCDYxwi76!S%He$@F7yUYYu#AaTz&nwKc9JwzpXf)@ay88`_TxqaVa?X_#p7 zOTUU=Rqz;r=Mf*n+PtnV#HZyu@ex&>|9I&W`rQ&A0ps90;?poEFWHL5HIizeDNhJ@EpVae*K=vUD@p{tckg?B-I4(ic*sr?Hc!aek@J9NKux%1vg zIdGnD+3Y|4^|7zcKRf@be|V#R_;1<2-d%ftKuz~P6dnloJ*v?VUy64^HF`KJ-5D8sTx{ zX55&SOSAc+cU>rygn}Uy%Fd`eyxDX73*}YMnT?(^W^2^!?lrn5pnvWBQ{egSZ(7$+ zjh9Z1SLV$2XxW7#XI~>nB=9{2#i_Cng?dWCLuJJJ-`fneJ@!8G8V5($rb<_SYs_n9 zgg#;~vftC;CcEN&jZo7qN&*0 z!p6x9X6Hfk@HKFMCkO$YV!<&tpO5H6d6V9~WLjt^0BEg-IZa90c! zJ#UL_eNX|Xb_*hYdsW9Y?E28b8OJeMNei=qBYUEEq15BOSy zgZZ_?%)~HSJK~u*%B>B&I}zbtMtHzq9_3*E<#5~OFxS^cpp-zS)^w6h>5wcfr@piR z*@nbjGajn^wrzRxNSGrqMbVk{jj$@X{;wIxt>Jmgo7p%$aat| zIWW#n9ABX~u!P9_0DctCfwox*50gtk(t4%+8$g+37{)~Yd-iV&g^X%9QM=LDw@{DK z*iF=JGsUv77GhVrR+Sz3z^b+>v|EvJGY3zd**p?Ee6l?b>+& literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/Owner/tasks.py b/Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/Owner/tasks.py new file mode 100644 index 000000000..57840ab37 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/Owner/tasks.py @@ -0,0 +1,88 @@ +import random + +import structlog +from typing import List + +from celery import shared_task +from sqlalchemy import select +from src.bookmyvenue.models.common import Venue +from src.bookmyvenue.core.database import session +from src.bookmyvenue.utils.image_kit import imagekit +from src.bookmyvenue.worker import app +logger = structlog.get_logger() + + +@app.task +def upload_media_to_imagekit(venue_id:int,cover_image,gallery:List,venue_name:str): + db = session() + + #we need to get the venue record first + #update its status to uploading + #start the image uploads to imagekit + #on success update the status to uploaded + + try: + current_venue_fetching_statement = select(Venue).where(Venue.id == venue_id) + venue = db.execute(current_venue_fetching_statement).scalar_one_or_none() #scalar is uses=d to return as python object + + if not venue: + logger.error("venue not found for the given id" , venueid = venue_id) + return { + "status_code":400, + "message": "venue not found" + } + + venue.task_status = 'Uploading' + + cover_image_url = '' + gallery_urls = [] + #First we upload the images to the imagekit storage and then return the urls to the route control + + logger.info("trying to upload the cover image through imagekit" , venueid = venue_id, task_id = venue.celery_task_ID) + + + try: + uploaded_media = imagekit.files.upload( + file=cover_image, + file_name=f'{venue_name}-cover-{random.randint(0,10000)}', + folder='/covers' + ) + + if uploaded_media.url: + logger.info("successfully uploaded the cover image" , url = uploaded_media.url, venueid = venue_id, task_id = venue.celery_task_ID) + cover_image_url = uploaded_media.url + + idx=0 + for img in gallery: + uploaded_media_gallery = imagekit.files.upload( + file=img, + file_name= f'{venue_name}-gallery-idx', + folder='/gallery' + ) + if uploaded_media_gallery.url: + logger.info("successfully uploaded the gallery image" , url = uploaded_media_gallery.url, venueid = venue_id, task_id = venue.celery_task_ID) + gallery_urls.append(uploaded_media_gallery.url) ## appending the gallery urls back. + + idx += 1 + + venue.cover_image = cover_image_url + venue.gallery = gallery_urls + venue.task_status = 'Completed' + db.commit() + + except Exception as e: + logger.info("Can't upload the media", venueid = venue_id, task_id = venue.celery_task_ID) + venue.task_status = "Failed" + raise e + + + + except Exception as e: + db.rollback() + logger.info("owner media upload task error", venueid = venue_id) + raise e + finally: + db.close() #closing the opened connection + + + diff --git a/Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/BackgroundWorker/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..367622a9d9e4ab8e51f8a8eccf9fe0c06bcbbaf0 GIT binary patch literal 218 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 Zr9~YfRG9es-1@l!`%wpvvH=!O{{xV%p=JO8 literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/__pycache__/worker.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/__pycache__/worker.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bda456b2150976171b87255cc11195f763841cf3 GIT binary patch literal 1004 zcmZ8fy>HV%6u*nzB>iv-rL=0ph6D;y)0Tcggb-gpsgA#S&r`-96NTna}tuN zLP)G^tepy|otXI}A{H#KOl+>o#Kd#bpoC}N@7}w6@9y{ByHAodfz_%K3dd?veG*nL7M*Wt`LuA4@~W|g_cm6gTi zrDUzj9hJXI>UL^%Y3*S`@S1!+}bM=eqQ!V}BfwmgY*Q_(1M6h>e3MA(~vYYoL=;HLlu=1}5|ch)#% zx@zhzxcNGx9FkZ1mSU==(W;|pw&hUE@nT()N{v$m?(lAQDyLjg?k(>mqFz|*6rBaH z!HfT&ie@vKghP+?5)%Ut0qWpQs5QriPH1+WG9{qLJu&d|!nG<<9r^`b20i^#*htBH zK$FYc&*Z#CGfb~jIYYVO*j2e$smtro-duA(Xs;a94GJpv)lvpR12%LisA#qMC;F&j zlbT5%vp8H8JWu`&z!xyaE}Cf%{w`W*5B`1_MWo{+SDN)hXe=87lr}?tM2v(k5Ww#M zjs-u4u=oQ_eMeJnY_%<|`2xbz7bt|m1HkV<6rA2g-;ci?cclpC4{eCphyr5;12?ufdu{na@Hv; literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/api/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/api/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9288bc49578918bc6474d17f1e430665a69eb0fc GIT binary patch literal 205 zcmZ3^%ge<81n-M9vq1D?5CH>>P{wCAAY(d13PUi1CZpdgnq6^l5K^SQz##`t1cXJ|oJZ;zz z?RBfGU%z_w-m9v9zj{^QWHLzv<==n)&H6Vfg#Jz&of2&`FYj;&-A5YII0H%kmyxVN=Y*%rIJ;44K2yFyoWPK66AGVSLKiZyt~ia43Xu>=8`)X=nb3$+93v z>jyhRE&T{q^AujcY-fUPX%zIi^+TQhphxMjCfq@isAX|d>%)=tcRG64BUi+# z*F#!A@JGNCkHw(>>m0Kkz!|U@yc3mfSx%lPvOwjD2KJBm}W!7_ds+cxw88=W;UxdF_e zQgPOB$Eu|hDB=`7UF52fD-yhq@Dc^Ak9i06IebR&mQFgBYgfi}=* z=sw56_hFA77`IE%g5u{g4DfTcZ=o;3*U&BQ3AZ>NB5CmHMODMHF{~k^6>U1C_~Xj# zxs|InCicqtODjtyJV*4Kcx4XTHyo?HQZ#R_%vjcqi`CC?se)H#6!iu~Zlwq^vwD-s zY@!C*N?BjgaM>=Dt6u*qc4P>atQF;UB*`$0n}^r_Es%f0Q%BDeeP52;8>!Figu>B* zme9Aw)8_@B{EENJf0?|O++xqGtx&Jv)vH%_0-XFY@*dhAnhu4%cpD8~j9{liN^0+a zrFm@?}4xy9v@-*4Vr%!$$UtOHOdgc7m@`5x!=f%rPm8Pfh2n(r~ zX+uc% zKIg|;;-q`{%uYCzNPdri{6NX~(P%#Q0|HXNxFewSNHcY82Sua9&xHejiZ$Pzb3avG zL2C$FQ_x&qd$Ip`bN`90Y^(pBhsT=z?{39g*`Y0gh%h3d`%LWy9~yMh3}Al+CYYZ# z&^8x@&SuEzLIt7Sow31fgo2QuLANKJE@%*XNJo0DXaJV&aL|@R4vky8I5bhU%Pz>Y z$aXYn1t9ccM(E*JoBYTkMP1WyNo)t~J<%!|RZ%ev>lR??xG2?{N~x_49sr?`0LzvRoBIfiJkGNq69ITH-^l@N6uDSsDDYy2 zwYrLl7X?IEqz97yZAebYA1y7W#FScRGB1hh*PLsYfil;r8>+^f)I%Q&2984y` z;6r%rA`r-{!r0?USD0uB6HQ^F{_*pi*vx(SEqQjlk(+7eX6m23Nac4>D0-WF&I@0q z@21`SqI>OkTj>U`GF&p`Hnfv+=NXuJhq?D}Bu z0*su5NYqYr&D+RotNko!Wx<0tM4`p3;Krj`M5E|hm?IO=NlsJJ&2;3K(0l`qeCs#i z$nWXF(G+-?f%m6yH2Ey_Y_gG?ZRTdXINI37(UL1E6i3A-Uv&B6E{>UZ~trZf{h`u>rRy&G@kh1 z6$(zZjBWoY8il)2q35ntfWYB`rZ`Gbf$hxhWC!=^m~hY;uxgrnNQO@5{k{{dJJ(_U{h07D< zA35|g^dtW(SVhIaza~r2q?arECD5HP$8jx`sI#Yq`rJ-!A<+%i7CPhxYYR=eZ>udd z<_2pE9dU#8bw4fiu^X&AF~ps6(FeV?g$i!4w$OqbtZ$N}>Z#vn?quqj7wO#A`~&?# z@oW8YwsGi8^UxVLeYTN4+f1LWCt8Wot&wJ8w2?U6OdPJqb|O)308ai6>EpN~50CF4 z_&i?QE-_{=5d?0S>cD3&If_nCeLLw+U2IG&HYXN$5YG)U@?e#H9)m?k)Whxj-^{wM H7%2V&<4F8J literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/deps.py b/Backend/bookmyvenue/src/bookmyvenue/api/deps.py new file mode 100644 index 000000000..639060539 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/api/deps.py @@ -0,0 +1,76 @@ +import os +import structlog +import redis.asyncio as aioredis +from dotenv import load_dotenv +from fastapi import Depends, HTTPException, Request, status +from sqlalchemy.orm import Session +from clerk_backend_api import Clerk +from clerk_backend_api.security import authenticate_request +from clerk_backend_api.security.types import AuthenticateRequestOptions + + +from src.bookmyvenue.core.database import session +from src.bookmyvenue.models.admin import Admin +from src.bookmyvenue.repositories.admin.repository import adminRepository +from src.bookmyvenue.repositories.owner.repository import ownerRepository +load_dotenv() + +clerk_SDK = Clerk(bearer_auth=os.getenv("CLERK_API_KEY")) +logger = structlog.get_logger() + +def get_the_db_Session(): + db = session() #generating the new sectio + try: + yield db #yield is used to get the current session pause the function pass the session to the respective function calling the db session and once it completes the job the contol comes back here and closes the connection + finally: + db.close() + + +def get_the_redis_client(request: Request) -> aioredis.Redis: + return request.app.state.redis #accessing the redis client stored in the app.state of the request. + + + + +# this function is used to check the incoming request with siginied in or not +def get_the_current_user(request: Request): + + request_state = clerk_SDK.authenticate_request( + request, + AuthenticateRequestOptions( + authorized_parties=['http://localhost:3000'] + ) + ) + + if not request_state.is_signed_in: + raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED,detail="user is not signed in") + else: + request_payload = request_state.payload + user_id = request_payload['sub'] # user ID + return user_id + + +# Role based checking of the Admin +def admin_only_route(request: Request,db:Session = Depends(get_the_db_Session)): + user_id = get_the_current_user(request=request) #passing the request to the function + admin_user = adminRepository.get_the_admin_by_user(db,user_id) + + if not admin_user: + logger.error("Forbidden request, only allowed for the admin to access" ,clerk_id=user_id) + raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,detail="Forbidden, only admin can access this endpoint") + + return admin_user + + +#Role based check for owner +def owner_only_route(request: Request,db:Session = Depends(get_the_db_Session)): + user_id = get_the_current_user(request=request) #passing the request to the function + owner_user = ownerRepository.get_owner_record_by_ID(db,user_id) + + if not owner_user: + logger.error("Forbidden request, only allowed for the owners to access" ,clerk_id=user_id) + raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,detail="Forbidden, only owners can access this endpoint") + + return owner_user + + diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/v1/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/api/v1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/v1/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/api/v1/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b8324c9c13830639787e0d3405001bbb09141eaa GIT binary patch literal 208 zcmZ3^%ge<81Wd)6Ss?l`h=2h`DC095kTIPhg&~+hlhJP_LlF~@{~09tE7{p9CbT%U zs5r(WAjUs0)ukx2EH%a@wK%&ZzaSa#b-ukodsN$jJDC K0Y(%t1H}Lb4LCCZ literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b7c5737c74eb7f0eff6b7c5438c1788fff0843ba GIT binary patch literal 214 zcmZ3^%ge<81k)cGW`XF(AOZ#$p^VRLK*n^26oz01O-8?!3`I;p{%4TnuS{pFn9$e#HSdbZ0W*C#0lAD2KczG$)vkyYXfw!d#r#0x R12ZEd;|B&9QN#=s0{~{GJBk1R literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/__pycache__/admin.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/__pycache__/admin.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..55a35226c9a078730e2190f36e7274a856a18c1b GIT binary patch literal 4028 zcmeHKO>ErO5q{+UaaXIAtRGvlVvCV0sfz+D#VOEMh}FoJ8n?AwRg#^A-Grvdw-P0C zxq0NuS=DKcq-X?Rd`yo%IWX))kW-EU3KTBT0~g?7LBN24URt0B8BQ)fb>{7IrIn?+ zXb-)VewsIL-pss@+?jdf&%3)b1fD;C`Gbwmf%_{iqKEIm;@Lk0LOvq~F$9a)f+7gW zilCyi19=liR<+7x8 z%G(+Q`v9qlacUPDN*xB%}9t zi34a)ABpN%r|16?RUgeAiK_nvRHKHtO!5PNN9cJWj9)Tc?@B%%rso!ay5v+n%EHt< zt>topP9TJW>v}}6RUDnsBt%bc8G>@)1 z%xp_?ElI7Z0p^K0!#2^lS3^d1%2rKfczD>iMm^PAr>e24whjpgA{nEG>8iSA(y|9` zvfSFGY|GT?c5;d@L7uEIS~5S}PEYAgEVWQ-bE2^tW}3%V!8A;8r+Pg4DPczb6Zm^p zf)M*T5g;|ZcCZn$(dKUoH_3(=Sw0l*0so-A{wRJk&ffNt(LNz}_n*=h8{$oIBM~hh z#yY(SHW;&_5W6&^ZP){?h z?K}YXWZkhV7WL?Xli{Td6H^f(Y|pulO=ZfM!(7?X^(sWNtd$LX=YuZrMZivWO0XN{ zXCa?u7#WyIhT4+XSRaa#mb117=@B=}B_~W_s;H)cFcBBSfMh9D?8O?Po}GS8y|A<} zx3VxFCOD*UfNy+%dRjd{H?J-&{POC;@=89z-SZF6zaSe#C!^8fYV?Mxrf-&=8x}R7 zym&6A2ak^Dr3*8~tANHWUR*5xqD<$RxkZcf)ZO%)N)djJ;(5o}yj;6R%T-!j1vd~$ z#Z{2mwJk1lnclJ1DrRx(wIUCgCM{HI3~M_l$AEGF1mth(!j7#5_qyjhRNUhaUMMB~X9D@V%}*3*5Z=gt4D^t5rcD^C|zo~F3Q zz6%)GX(XdaWF)U5X;&LIhRZWZz5@iR3Ae#AzOR~`ZaI8uF<}#E_`QhafpPx`q@C## zXM^!`U-vz_@t5EF<7$0e4aQYJKK3Lv-kIlbJo;I1>3z&|HIP(aQrmf6sOP4F+>|dJ zGNM$4JpbWgsk$%EXCG|@SFU54Yk{Qsk`~!QnqNE2mQBKYLS=i6j3J$ZGgvQ;xQ7UL|t*o1HB}9y*nGW9y z$Dpzn_Ep+~%Ui+%udGeVu=`-xSTO7d!dDKO*l-zIZc90fDnkcV0CmBj6_<6Rn;a7C zb;9w3imlGDQN zj+g1r`lMq#NuSyo4$`OU>CqrPdMnvT_w5Wfy83rxVn%#QfP91GR&rM&qV(y=$0Iwx zstdz`Fx;43_-f7n$vgGgcZ1n?{c;t?E+IFBx4@1#!bPy;69_eNUEG^Y@gr2x#NVI_ zPP?REfC~?ZFHiINi?^D~(q?OqEQ;@-`l9&$K6SqNG)BaefM{1lFNFxFQWu5-VW=@P z_tm6-ex*KhHJG{TZ+rj)u(-kn1hFa1qgR|j_?~F&o2XbrmG{JLRKcl*1&;Ycne$(y j_~fsywYJD5aRs$6!GEatv^j?`;lm9zVYc6xhuc2^29^PL literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/admin.py b/Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/admin.py new file mode 100644 index 000000000..ae32b5044 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/api/v1/admin/admin.py @@ -0,0 +1,61 @@ +from typing import List + +import structlog +from fastapi import APIRouter, Depends, HTTPException, status +from sqlalchemy.orm import Session +import redis.asyncio as aioredis +from src.bookmyvenue.schema.admin.admin import AmenitesSchema, CategoriesSchema, CategorySchema +from src.bookmyvenue.models.admin import Admin +from src.bookmyvenue.api.deps import admin_only_route, get_the_db_Session, get_the_redis_client +from src.bookmyvenue.services.adminService import adminservice + +logger = structlog.get_logger() +router = APIRouter( + prefix='/admin' +) + +@router.post('/category') +async def add_category(category:CategoriesSchema,db:Session = Depends(get_the_db_Session), admin_user:Admin = Depends(admin_only_route), redis:aioredis.Redis = Depends(get_the_redis_client)): + """ + this endpoint is protected with the role based access such that only admins can access this route. + """ + + category_addition_acknowledment = adminservice.add_category(db=db, categories=category.category) + + if category_addition_acknowledment: + logger.info("successfully created the categories...." , admin_user = admin_user.user_id) + await redis.delete('bmv:categories:all') + raise HTTPException( + status_code=status.HTTP_201_CREATED, + detail=f"successfully created the categories" + ) + else: + logger.error("cant complete the categories addition...." , admin_user = admin_user.user_id) + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=f"some errors occured and cant complete the creation of categories." + ) + + + +@router.post('/amenity') +async def add_amenity(amenity:AmenitesSchema,db:Session = Depends(get_the_db_Session), admin_user:Admin = Depends(admin_only_route), redis:aioredis.Redis = Depends(get_the_redis_client)): + """ + this endpoint is protected with the role based access such that only admins can access this route. + """ + + amenity_addition_acknowledment = adminservice.add_amenity(db=db, amenities=amenity.amenity) + + if amenity_addition_acknowledment: + logger.info("successfully created the amenities...." , admin_user = admin_user.user_id) + await redis.delete('bmv:amenities:all') + raise HTTPException( + status_code=status.HTTP_201_CREATED, + detail=f"successfully created the amenities" + ) + else: + logger.error("cant complete the amenitiy addition...." , admin_user = admin_user.user_id) + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=f"some errors occured and cant complete the creation of amenities." + ) \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/v1/common/__pycache__/common.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/api/v1/common/__pycache__/common.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb98be9f8d6fb22a7f6fc4e8821903e093dd861e GIT binary patch literal 4827 zcmc&&TW{M&79L8}jf!lEmaU5|-;-9^SV7|0aolWb`BFP^l5OL(Km-EXclcYDA2sMD6*(unr+ZN^atz@$Rla6FhOhp14V)DKB-9ilBYdGnUd(sZgw}o z(xbzfGau*7?VNAMe+dLA1kc~7vDJUHBJ=|;SdV)@^WqtS&}WE6EWx7;emi(VaAX_= z&O3RhKxRlYPw=jc%fz__PsVHNNZuz<8A|YH{ASt3pAZ6>fSGsmEkbLiRS0H+X4%7s z1Uf?tZJ9P9oCyo7sVsvV%Rr1=s-RUG1@O%Ou=RJJ$T4^A4@EtWauZ{#hXdOAg|{o8Q%WenUc(jNr&M}zkBso zaSaNFXPPT<1y%x(XMvNXe6aw4Kw97mdAYohyUPiT(K5xz+)7d0FDFT(V;}GiCj*4N z#Yv@NA;%dJ3wf}j-GbO#?y%I>cQuR91$u>(v+`Xo%PwX2J7$C}oyf6yDVyW-TmcU+ zkShv8v9Q32>-ikF;Xj+J^*7JqakYqM?<6iO6j_cp9PEt{fb*`xScawzp3p=!w74dLvhHvz~9gc7NUU0Qy7&)5ujk_I9_M=AwaOeRkBQ z_Z514Xr5tJTN-UPauug-1t8kio{HCQ)jp=?wTIY;*T!9&^(1w3gI*HW#~b^3oZNNb4%*botT;MB) zM*u6#3TKckBQqNV&Ddk?-hN6Lt=M*!k!3Nz1W`tM=~|PQhsKgY5j&2EJwn9GV>rQ~ z4L4t0S%FYQ<_pV3gItx01;fP`8CEg^>kOX<(_9v7#UTEs9vB*9HCpSqQdzzW-}~4# zp=5q!xLM8|i&FwyF07Z5K9Rne6<`9V28;A)9TW47%1L zo2`W*JT(T@RNq!AvrIwG=bAtA;}K*fn3BSZfEiN&+dl0b~mp~_!*G-)y=4@rAlwVvww^$2{ z`>#}~ES|)p#v%kiiGlF;clg^vzfvfE@~hk5pPtZ8rq$S_7MoPaj=kXE)>XZG;LH3M z`LBIy_j#@Ryb?W>$adWmts;+$dhTuc)c?@0gr`;SjOLwDyfe=eeUCHBo0rtYxRw}K zyz#xxZas2Y51-l%U)Tv>P)26e@SGN&t9r;FRYf)7qke5cbdMG~_g%jl8qq={Ti2eG z)W`E5&MUzYl^oT`QH30>x>4uQZv662{Ic$)^=Mbsg*t!xGjevif5Ac_Bh?nvc5;_a z?a(RZ?4(LhY4p@CeQk%n_UxicFKG0_*8GoF%M&V@*2uI%rgf_I)8xbCqpN?GA8&m9 z8?|Rt>lsz4iyC!NA&*GVlW3>jHl_#TFpv{&7>Frc?iVoAXoEV-n2ZXHbTsMw_5Vyd zKpstW@T!CZfe_Q?q35;G+X0G%9@YaYLaX)O9zky;>jIjY^BkOS zdvP;;Sm0y3*pI~k7K2!rd=jz_mG!p8Q@HXCEZ)Q-iN$FUHr@!;@fK}}X8>aa_X(q3 zEvB&AS1%iMogeBt@f=|6v>=`bl{jjNw=m#-bHt7fel`7l@`^V2wi=z#q7w?)z84&T zhz+sp%)>K}$|}{TQGE(|M5+hV3o1FHks}H@q9^*lyz|AK?XsFUrzOrQkwb|L>z>HJ z3G`!X;*yrQ)D-AX?uLhV!o$jichvB#7M?vA=qVKH)`DlhbEv^#EjYY&buV^$H#WW# z8`r&|T1=0>1u;F2V|pB7dIyf_gS+(54n3r#CR94D(dk`!Zik+G7E$TT7a(|7QWfl&MA27KSkzTo4)YUdl@cpYdm*FoQEoW zH5CH>>P{wCAAY(d13PUi1CZpdD{KVtyd; Rftit!@dE>lC}IYR0RRk;J23zN literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/v1/owner/__pycache__/owner.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/api/v1/owner/__pycache__/owner.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3437dbf6a9e090bcc4cbe3f026c9bb4b6dc8b970 GIT binary patch literal 4547 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 X=+-*6nCkg+(52#`40JmNSbF>q^W~$U literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/v1/owner/owner.py b/Backend/bookmyvenue/src/bookmyvenue/api/v1/owner/owner.py new file mode 100644 index 000000000..3bd1085d2 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/api/v1/owner/owner.py @@ -0,0 +1,93 @@ +from typing import List + +from pydantic import Json, ValidationError + +from src.bookmyvenue.models.owners import Owner +from src.bookmyvenue.schema.common.common import VenueSchema +from fastapi import APIRouter, Depends, Form, File, HTTPException, UploadFile, status +from sqlalchemy.orm import Session +from dotenv import load_dotenv +import structlog +from src.bookmyvenue.services import commonService +from src.bookmyvenue.schema.owner.owner import OwnerOnboardingSchema +from src.bookmyvenue.schema.responce.responces import CreatedVenueResponce, UserCreatedResponce, UserUpdatedResponce +from src.bookmyvenue.api.deps import get_the_current_user, get_the_db_Session, owner_only_route +from src.bookmyvenue.services.ownerServices import ownerservice +from src.bookmyvenue.services.adminService import adminservice + + +load_dotenv() +logger = structlog.get_logger() + + +router = APIRouter( + prefix='/owner' #the prefix that joins `api/v1` prefix with api/v1/user + / => api/v1/user/ +) #this is used to create the routes with reference of app in the main.py of src folder + +@router.get('/check') +def check_owner_profile( + db:Session = Depends(get_the_db_Session), + current_user_id:str = Depends(get_the_current_user) +): + + ownerservice.get_owner_record(db,current_user_id) + logger.info(f"Owner has onboarded!" , clerk_id=current_user_id) + return UserUpdatedResponce(status_code=200,message="Owner has onboarded!") + + + + + + +@router.post('/onboarding') +def complete_onboarding( + onboard:OwnerOnboardingSchema, + db:Session = Depends(get_the_db_Session), + current_user_id:str = Depends(get_the_current_user) +): + + ownerservice.complete_owner_onboarding(db,current_user_id,onboard) + logger.info(f"onboarded the owner successfully" , clerk_id=current_user_id) + return UserUpdatedResponce(status_code=200,message="successfully updated the profile") + + +@router.post('/venue' , response_model=CreatedVenueResponce) +async def create_venue_lisiting( + payload: str = Form(...), + cover_image: UploadFile = File(...), + gallery: List[UploadFile] = File(...), + db:Session = Depends(get_the_db_Session), + owner:Owner = Depends(owner_only_route) +): + + + try: + payload_data =VenueSchema.model_validate_json(payload) + except ValidationError as e: + # If there are any field typos or missing items, this will catch them + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=e.errors() + ) + + #first create a venue table with metadata , along with task_status = 'pending' + #call the media upload task + #save the task id in the venue table + #return added to queue responce + + + + created_venue_instance = ownerservice.create_new_venue(db=db,owner_user=owner, payload=payload_data, cover_image=cover_image, gallery=gallery) + + if not created_venue_instance: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="cant create new venue instance" + ) + + return { + "status_code": 200, + "message": "Successfully added the venue to the queue", + "data": f"{created_venue_instance.name}-{created_venue_instance.task_status}" + } + \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/v1/users/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/api/v1/users/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/v1/users/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/api/v1/users/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..afb1030c443145a9543ef0a120df7832f4a4ef86 GIT binary patch literal 214 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 literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/api/v1/users/users.py b/Backend/bookmyvenue/src/bookmyvenue/api/v1/users/users.py new file mode 100644 index 000000000..a2e2867cf --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/api/v1/users/users.py @@ -0,0 +1,111 @@ +import os +from fastapi import APIRouter, Depends, HTTPException, Request, Header, status +from sqlalchemy.orm import Session +from dotenv import load_dotenv +from svix.webhooks import Webhook, WebhookVerificationError +import structlog +from src.bookmyvenue.schema.responce.responces import UserCreatedResponce, UserUpdatedResponce +from src.bookmyvenue.schema.user.user import ClerkWebhookEvent, PhoneOnboardingSchema, UserSchema +from src.bookmyvenue.api.deps import admin_only_route, get_the_current_user, get_the_db_Session +from src.bookmyvenue.services.userServices import userservice + + +load_dotenv() +logger = structlog.get_logger() +WEBHOOK_CLERK_SECRET = os.getenv('CLERK_WEBHOOK_SECRET') or '' + +router = APIRouter( + prefix='/user' #the prefix that joins `api/v1` prefix with api/v1/user + / => api/v1/user/ +) #this is used to create the routes with reference of app in the main.py of src folder + + +@router.get("/") +def home(): + logger.info( + "Attempting to sync Clerk user to database", + clerk_id=1, + email="test@gmail" + ) + return UserUpdatedResponce( + status_code=201, + message="new user generated successfully", + ) + + +@router.get("/test") +def test(): + logger.info( + "Attempting to sync Clerk user to database", + clerk_id=1, + email="test@gmail" + ) + return UserUpdatedResponce( + status_code=201, + message="new user generated successfully", + ) + + +@router.post('/webhook/create-user') #this route is used to register the user with the weebhook comming from clerk +async def clerk_webhook_handler( + request: Request, + db: Session = Depends(get_the_db_Session), + svix_id: str = Header(None, alias="svix-id"), + svix_signature: str = Header(None, alias="svix-signature"), + svix_timestamp: str = Header(None, alias="svix-timestamp"), +): #Dependency injection in which the DB session is been needed for thos endpoimt + + + if not svix_id or not svix_signature or not svix_timestamp: + logger.error("Missing required Svix headers") + raise HTTPException(status_code=400, detail="Missing required Svix headers") + + payload = await request.body() #getting the webhook data that is been send + payload_str = payload.decode("utf-8") #stringfiying it + + try: + wh = Webhook(WEBHOOK_CLERK_SECRET) + headers = { + "svix-id": svix_id, + "svix-signature": svix_signature, + "svix-timestamp": svix_timestamp, + } + # This will raise an exception if the signature is invalid or forged + wh.verify(payload_str, headers) + except WebhookVerificationError as e: + logger.error("Invalid signature validation failed") + raise HTTPException(status_code=401, detail="Invalid signature validation failed") + + try: + event = ClerkWebhookEvent.model_validate_json(payload_str) #used to validate the incoming json with the pydantic model we defined + except Exception as e: + logger.error(f"Unparseable Clerk event data: {str(e)}") + raise HTTPException(status_code=422, detail=f"Unparseable Clerk event data: {str(e)}") + + if event.type == "user.created": + new_user = userservice.register_user(db=db,clerk_user=event.data) + validated_user = UserSchema.model_validate(new_user) #used to look on the given databade object , check wheter it matches with the schema and picks the required user fields and converts into pydantic model instance + + return UserCreatedResponce( + status_code=201, + message="new user generated successfully", + data=validated_user + ) + elif event.type == "user.deleted": + is_deleted = userservice.delete_user(db=db,clerk_user=event.data) + if not is_deleted: + raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,detail="cant delete the user.") + + return UserUpdatedResponce(status_code=200,message="successfully deleted the user") + + +@router.post('/onboarding') +def complete_onboarding( + phone:PhoneOnboardingSchema, + db:Session = Depends(get_the_db_Session), + current_user_id:str = Depends(admin_only_route) +): + + userservice.complete_user_onboarding(db=db,phone=phone,current_user_id=current_user_id) + logger.info(f"onboarded the user successfully" , clerk_id=current_user_id) + return UserUpdatedResponce(status_code=200,message="successfully updated the profile") + \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/core/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/core/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/core/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/core/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..774ba9abef90e74766f3554687cef51dd026a62d GIT binary patch literal 206 zcmZ3^%ge<81nuRTSs?l`h=2h`DC095kTIPhg&~+hlhJP_LlF~@{~09tE7931CbT%U zs5r(WAjUs0)ukx2EH%a@wK%&ZzaSlIY~;;_lhPbtkwwJTx;+6Zz}F+Y&_z|6?V_<;dN I6fpzE0PR0G1^@s6 literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/core/__pycache__/config.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/core/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..45a0b31e323916a40439467123fc80b827e05d46 GIT binary patch literal 1731 zcmZt`O-~y~bap+q*WNXbAt6vjP!y=3s9ahuQA%rLH=uw)7$S9LX|?PO#9_Vb&aP33 zQpuG#5Qzgl1*xi(LzT8_&sBdx)#F;?V9h0#svdeXN=`ZT%{qoS>CBrq^WNKe-#b60 zQb`2kn~}u_pGFb-TM)egbU0r83ELAy5Rq(Dm2^oGXW5o@8TN=BsbU?6JZwj+F+CQZ zqjtQi=t?!ACnO{zil2d&U%MIshdlW~Xk9Q#?3n~|Slv;RNL*KCbO#aT5Rn8`o<%?o zt2=a!N+e0O9hsngA*;D4Nt&iiz?t4(BLI z2p)v0JxKK~lH@ySRP}+-QZm%1QT2QDgRG}RUh1`mD`bGA$(7$SZzVZH6iC`2S9)=C zHRrl}s|WX}Q>R?XuCE)#>}r80Ys@8e%dfc3OoXe1?o->XRjK3ixaXU@kUcg4PI9$S zytlluR$MIVo7vKmu~En`myE^2N@3$mkyMrd@xut&p5@nG zb2kd5t(8q9mtDMDDCQsHIVc>DRdyYh(J#OQ1!!ZZVpATaU;E7D0~XZL@TlWe{K`HR zF&TzqR;gj|q+wLSdt00}!}zLh+Fc0~dF2t$XFP2frsKH2DMIuNgJnR(M19$y_y}*i zuFW-K`sTK;;r(QN10b% zS}(6TG|#}@a-Mp7zFRAASNF?rRG^$Qtv%|HkXJp}7gZ^H%qoL7dp+8MoRqsp=4uB_ z74`)Z%ljQr9` zH1TkIe73Q2a`O~__hEo%0h)NWJ^9ho+>gt_+){IL`D}7Im|Xj7BfvLKL3vNj#Qf7o z!Nj}(JbLQ#&B0<5#Rp6EWb2 z&A}$bXA9bC4XuMSQmljCMMsa$1^4Bp p=mR9H9a)lwPwsaRY?tUf0;0pwP}otBHga_P@xt*!LlHAf`+xH}z`pHV%6u+}w$99v3sRALkEU8e$h!84DNC^WJL|X>Sl6CRDwr+fOd*@V&#E^lZ z6JqO%gj7If;7?#=Or;LdO_i9~iptc9yL_}1c=zu4y?5{4``vr~P%3#yQS;lvR*n(+ zu8k?pOq8=XO4&ygQJf%#eT=nkBnC5mlUcqsvdv_M*}jdDfm(=KuMwRA>%c_lQ0+1K z1+cfAskM!%?K=hn49;%&Q)HM7N`U6XZNoh9`#mGb@qo2tzubP7sGI;OOo-)Cv>JWo|A|7f;9nL1dpEw&r)b|g&}By z=;YaU&}O?qBg;BZdoLmFLeL;l2T~fem5=pyM?S%$D|VD|2q?)(TcN3K_qgumNEDPJ z%1ZPv*3feLO4&!UX6IG3*0*ORW;lvX=V>2h^edSWLbNwf*9$MxLg z+@+(IamFp3Q2!b7rh-@d18z;jQzBiDH@JOKx7e(&)*JPerEu-V6KRjk|_Z0mr_8$Dy-d~qT zHoA8GxLg^O7d{&O;?SMnyY=?fky|--D}8(D&F|fQxAbN8t3B{qM_%jLYxN6yjUMqE DZ8YSo literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/core/__pycache__/logging.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/core/__pycache__/logging.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7be194f0b0aa4a03af6964ef424ac2945940a1c4 GIT binary patch literal 1838 zcma)6%}*Og6rZ)d%NS$xm4I-PLaQWVtJbAK5mIS5BtT1)KopW3kR^B79lLAx!6#nq5T7Tv(ZYRk&uvj>dh6&C8xewSj(#rspIvVH*em1zxUp} znP0NmUIgQ>$DdbMRfPVQi)bXynbTXq{D>@MDGpjYo0T;sTqo8NFejX(n_5dL$WpD; z_o+42QdW_!{UaSL>x#gPaBh1QCNxTToqFcE>u~A;nuP!94}b_b%1gw%_Nz*?s74XR z_oZz(s;P*J*?0DLAj5ZumDo@20>)kk=RMZiyS51Jf^e_1aj|7pW*Cl&`cm0K^wyTL zgCkk@e6jsbx?3mWX_5p;5Tc~K;7=0htd%PxNcvu65^Pnn()y*28agfUo&oa0w2gqF&N$$h#hvfojo zRs(_Q7>tQA(=fj!rE?|UE0t}^c&X0Fi_DEl7n~RsqBA`yw6afKgA0vuN(@)14rvfa zza-KisGA&Ih>YoboIK|Z1CR$@LMx=yC8DxxMAon@30Mjph|Ck)C9B+UAt*5jjJdJo zmHo%Wvj_!I{~2zHJU2@=YzR%p?^&Yn{_4tdM=fcQhUmZNd(3x8N16uovR$cDB8DDO z+v5+yYAl`?>XKieEn}u6Sgg+6_{iCv1cJwc@(l zDBkt`jfb1hh*u}YyO2HPR$K>}yV(e3jGD2v=~GfXkF8LH6NRU&UJH*9qNO(gSKe+m z4)7f8$3-D*hcrd_M1N`wBbBHGo@Z_&gn|QK?rvp44i3A;1ewyZ~XUxga%qG<@xNbRrm?ZjIg!MsFXF zj0YpLe}47HgVxAWFtT*?(am;RRkeR12JN*ZG8*ko4yk?8y8r5N|In)!$GOX|oOVx2 zDgt>eNjpwXp-xCoP Settings: + return Settings() + +# Instantiate for easy structural access across your app components +settings = get_settings() \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/core/database.py b/Backend/bookmyvenue/src/bookmyvenue/core/database.py new file mode 100644 index 000000000..a18513ff2 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/core/database.py @@ -0,0 +1,12 @@ + +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker, DeclarativeBase + +from src.bookmyvenue.core.config import settings +#Just a common base class +class Base(DeclarativeBase): + pass + +DATABASE_URL = settings.DATABASE_URL or '' +engine = create_engine(DATABASE_URL) +session = sessionmaker(autocommit = False, autoflush=True, bind=engine) \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/core/logging.py b/Backend/bookmyvenue/src/bookmyvenue/core/logging.py new file mode 100644 index 000000000..2becb4cea --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/core/logging.py @@ -0,0 +1,38 @@ +import logging +import sys +# import os +import structlog +from src.bookmyvenue.core.config import settings + +def setup_logging() -> None: + + is_production = False #this is used to track whether the + + processors = [ + structlog.contextvars.merge_contextvars, # Pulls metadata like request_id automatically + structlog.processors.add_log_level, # Adds "level": "INFO" + structlog.processors.TimeStamper(fmt="iso"), # Adds ISO 8601 UTC timestamp + structlog.processors.StackInfoRenderer(), # Captures call stack on errors + structlog.processors.format_exc_info, # Gracefully serializes traceback objects + ] + + if is_production: + # Production Pipeline: Stream pure JSON strings + processors.append(structlog.processors.JSONRenderer()) + else: + # Development Pipeline: Stream colored, readable lines + processors.append(structlog.dev.ConsoleRenderer(colors=True)) + + + structlog.configure( + processors=processors, + logger_factory=structlog.PrintLoggerFactory(), + wrapper_class=structlog.make_filtering_bound_logger(logging.INFO), + cache_logger_on_first_use=True, + ) + + logging.basicConfig( + format="%(message)s", + stream=sys.stdout, #output the log in the terminal + level=logging.INFO, + ) \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/core/middleware/__pycache__/logging.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/core/middleware/__pycache__/logging.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5c9d1a64dec5e60c10a3c9cedc8780bb4f45dc44 GIT binary patch literal 1604 zcmZ`(&1)M+6rcT&w2~bh#fVsTo36i977VjNki*~vMemCov}W=+Er#| z-O5$KkWl;w7+iYt$!&4zy^#D5vJpfq^iXP6N}R#5 zXaM6PI=uwLJ|f7FFfwE;848w(x*=obiE1RU3Kt~8na})kx$2c~`W`3W@{!K%T1E%D z<@zPt)$7B%bnfdm=eASP1Fs53>9lW}&Z+Hef-3#a3e%&*Vyo-wu3y&cgfY8Jm~OMC z=TxZg`2lmA#b{rc8t8C_5dhm$&>urTy)GfNh9q#NCDlOCrvs3_OIYG@Heitp9RsSV zF?R^eQ9MD1pyz0)>kz_s6o(K!Qh1d0{^nXTK6LPw-dKjvxLygJaaJ3h7;!BHd`rjk z+VED8PQ=n*P!=j>!b62|8md768xsOQ3ezA791dv>C!BuWY}v3q z>$t?G*4v`&)Bt&CfluLaSTETp?_e`wg>H-!hkdfAenh0r3K2E<;HY51S>B)tg(9 zj8SK7?)a3LqXIXwVvD(95tO-Z*0bJw=kFE}GbhzAl<;kGC%Rq&?oc b=zKeFJvA$VFYiM8gT)s@{PKU+BBR~_^d^tT literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/core/middleware/logging.py b/Backend/bookmyvenue/src/bookmyvenue/core/middleware/logging.py new file mode 100644 index 000000000..4edee9851 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/core/middleware/logging.py @@ -0,0 +1,23 @@ +import uuid +from fastapi import Request +from starlette.middleware.base import BaseHTTPMiddleware +import structlog + +class LoggingContextMiddleware(BaseHTTPMiddleware): + """ + Global middleware to attach unique request tracking IDs + to all log messages asynchronously. + """ + async def dispatch(self, request: Request, call_next): + request_id = request.headers.get("X-Request-ID", str(uuid.uuid4())) + + + structlog.contextvars.clear_contextvars() + structlog.contextvars.bind_contextvars( + request_id=request_id, + path=request.url.path, + method=request.method, + ) + + response = await call_next(request) + return response \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/main.py b/Backend/bookmyvenue/src/bookmyvenue/main.py new file mode 100644 index 000000000..0f0ed3152 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/main.py @@ -0,0 +1,94 @@ +import os +import structlog + +from contextlib import asynccontextmanager +from fastapi import FastAPI, HTTPException, Request, Response +from fastapi.responses import JSONResponse +from fastapi.middleware.cors import CORSMiddleware +from upstash_redis.asyncio import Redis + +from src.bookmyvenue.schema.responce.responces import HealthStatusResponce +from src.bookmyvenue.core.logging import setup_logging +from src.bookmyvenue.core.middleware.logging import LoggingContextMiddleware +from src.bookmyvenue.api.v1.users import users +from src.bookmyvenue.api.v1.owner import owner +from src.bookmyvenue.api.v1.admin import admin +from src.bookmyvenue.api.v1.common import common + +setup_logging() +logger = structlog.get_logger() + +UPSTASH_REDIS_REST_URL = os.getenv('UPSTASH_REDIS_REST_URL') or "" +UPSTASH_REDIS_REST_TOKEN = os.getenv('UPSTASH_REDIS_REST_TOKEN') or "" + +@asynccontextmanager +async def lifespan(app: FastAPI): + """ + this lifespan function is used to initialize a open connection when the app is up and will close that connection once the app stops running + """ + logger.info("App has started, setting up the redis client") + app.state.redis = Redis(url=UPSTASH_REDIS_REST_URL, token=UPSTASH_REDIS_REST_TOKEN) #app.state is used to pass this variable to anywhree in the program. + yield + + logger.info("Detected that App has been closed, closing the initialized redis.........") + await app.state.redis.close() + + +app = FastAPI(lifespan=lifespan) #initializing the app with the lifespan + +origins = [ + "http://localhost:3000", +] +app.add_middleware( + CORSMiddleware, + allow_origins=origins, + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) +app.add_middleware(LoggingContextMiddleware) + + + +@app.exception_handler(HTTPException) +async def custom_http_exception_handler(request: Request, exc: HTTPException): + + origin = request.headers.get("origin") + + response = JSONResponse( + status_code=exc.status_code, + content={ + "status_code": exc.status_code, + "message": exc.detail, + "data": None + } + ) + + # Manually re-attach headers so the browser doesn't block the error message + if origin: + response.headers["Access-Control-Allow-Origin"] = origin + response.headers["Access-Control-Allow-Credentials"] = "true" + response.headers["Access-Control-Allow-Methods"] = "*" + response.headers["Access-Control-Allow-Headers"] = "*" + + return response + + + +@app.get('/health-check') +def start(): + logger.info("the server is running strong") + return HealthStatusResponce(message=" well!" , status_code=200) + +#Including the apis used in the project +app.include_router(users.router , prefix='/api/v1') +app.include_router(owner.router , prefix='/api/v1') +app.include_router(admin.router , prefix='/api/v1') +app.include_router(common.router , prefix='/api/v1') + +def main(): + print("Hello from bookmyvenue!") + + +if __name__ == "__main__": + main() diff --git a/Backend/bookmyvenue/src/bookmyvenue/models/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/models/__init__.py new file mode 100644 index 000000000..d39477928 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/models/__init__.py @@ -0,0 +1,14 @@ +# src/models/__init__.py + +#when the src.model is called all the imports listed here will get grouped together and can access them easily, (MOST NEEDED FOR DB MIGRATIONS) + + + +# Import every model class here so they register with the central Base +from src.bookmyvenue.models.user import User +from src.bookmyvenue.models.owners import Owner, PriceManager +from src.bookmyvenue.models.admin import Admin, Category, Amenity +from src.bookmyvenue.models.common import Venue + +# Package them up cleanly +__all__ = ["User", "Owner", "Admin", "Category", "Amenity", "PriceManager", "Venue"] \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e56d3fba41622a92004a29224aa814a0823b8085 GIT binary patch literal 648 zcmZ`#O-sW-5S?v4TP=uJ70&^UcTu6X2NBu|ejLI=NRy?+W|OjME4leEyn7MeUNXb(n>X{;Y&HPn&}~2VY5*T9`3cOcSYG4j1tN$@0-Sh+sQ+40 z>&-P5aFOAKy$Cbv9`+n!z3^rX%kUW338BIA{KTakGSj`gWz9U}GnoC&8Ujs8>0 zgxtOnamczs8Vs?lNuw3PS6jTkho|bO%{B;>Ao|ba@uBBzLE1ppuXW8%|`(TE6O_B<22wgMl*p$HYd}FylN+ zD|^!N{UAwv{~ea74_{&Xl&Zz#^y-H8Q`QmjjL{CuN0V$!2Yf~^agc6NZGc_|;fSRX z{WTm#himz2SnB&RZqN7Kaq(rJVR4$U3$cqm3BGxbw9p74iya`xB^>?69L~%CFo#yT Z8FM%(*Re2R>z7fK6yCMh>-BFaqzNSkLJbiHVM-4@APON#1O16XamZn@v^d@=EZ$w4S)1ZY zm3-*Iha7yU1gAEYsx(n^;K;F3Rf*%S1C^HrbY7l+3$KTQF6g2uSfVOg0W~0^9x#KJq)Jvu z4Oy}(^R}QFwiH$2vSdcAs2a6mYRrnOaZv~eR|GxuwV=yHSq=)qPw@CfO>kQnY|1WM zlG`F+i|(=w=&`(zi9f?(G6AMstJaK)T{M~Wnc>tjK^C2^P-5J+KP3$&=WEokZ!>9* zJg8+vCQTF_0zUFgv05cMOIZA^l`3Z4vRRxGvxvhvcZ_POyHfs=yUO#QL3k(-K^1jD z4cve;QiB13NO}N%K|Qc0ElaRZc>JP9Npd-7;(zD&lKydR1bvDmAPkZD?gUw~%4$ zFX>Oh2G$ zMcb~_{QpYRC{mZcjSxdPh=5dE6`lhMFK$hqFW^d?!qw}AYc`pp#(h$lB2KwhsTLNj z`-O>0r99J^Cw83_CSVW5)(Z>JW;O2fHiwq_bXYtwodQ3DFafb|V$mk3i&54%Wau#E*WI**KV}0c0qYqaOtsHv%iI=(5 z$z1YA#ycb9%`2_>_T=JCR~m=vN#h$Q&Mg(zhmULq17q@*0I-eFoNA4=4?Y^}ymhP- zeRop`gk%oj(UrJLM`4Y8#d{MSqW3=~I)=+yc*muHbdU9sR{6VN*>emGg8nfg-7yk+ z6oMwU9Dsm>$1iFU{0H=SZ`Pg!L6hJ?lY}d0fGLx}>Dv|BV9}B<8N`{JrUQ7ANYQ6H zz-oZWb=$aCCv-okEMk-@Hm5z4kkf3CGfL|Y(eT+0y&?_)PaR^A4q?X-XCsrjyOUep zM{#BJ5W)yT3ZXwf=wWO-f`C^RJqf^qPL0wGsysTfDB%S~k0OjB979OIgaaTrzX0@e zc(ggQ{-zvGWgg9}jIE44KCpUv?KE)yhMUTJseC7uZ+_hRyq#YxyHXyiC*{|NkGH>C znqQhz9-J`K6UId3@E8O{NlhuXo#5m(AV^`zWJ`s~sL_xyGDmg%M~FKus9+FBz$K(*-ljn&ZyL%Gw zJjr=J06gEv!k6KaH);(Q0lI>)ljZz29z(Jqz32%9q!&BjGu!XgB{n^c<}(OLyc|7? z;tuA$k8KFZYv)&he&!whH_Y3=dTQ;|lewoKxv5z%HQPze_Lw*8O0%9c`;VBnDGSHn zL+)L3wYzS*?4`?{ba@B&fYoJBLWJsb5BHUWW0h--DtwIa#Khx|MV)(Q(Jb8|R>MzW zJZ8h-&kjSv$-a_+vL*Pc$?8Q&jqnLW74%8=x@RlY;tA5f4|tsOl*D72A8-GWzfdmt z`S&6{4`bo?hZ6$a42q(-E*x|BsvE*t_w{u{$h!S?UAXAJzHZ8j2&ri|w5GPOb-QO8 klto+I6!ykeZHrsBU$yTGizf8g8(aDow`{-0&i}W+0Bg^}H~;_u literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/common.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/common.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..70016323ff4ae3702437a020cc469d808c04a0bf GIT binary patch literal 6112 zcmb_gOH3O{8gAqE17q_vm}iW^Au%S-g9P#-GuY;tAt6J;?lweL$6X{H+_ux*CV|OF zKFonb4xSa#TAEqOBaO0-h66_~D{;)RTk1orPb2MRvnNK$X)e2ebz_V%lilpDDgUmj z{_Fc6^;i9W^B0%PLBQv)p~%yJG!Vq!@SyamJLtUsqlqB?L@)$nN)VihGMR9{CQ-wg zDKke>q&_w$ES#0HayH7w*(p0$OVx4?%E8r9b)1uOaxTin)l>Cc1J%GaQjPi=GSS2} zQ_Wlp)xxo54rc6(9jJq;eGU5k1YhIB zIJWCvn_&jN#z*IM>b$Oh$NQRumGCt_R0phbG4=nGO!0_)oV<=a03sJMI z&Y?`*MuWKNp;A?!SI^cIQM^;pWH&H% zmGM?Nq8h8Tc9tZA++(MNYC=|~zCu>R5n0X5@z^$RHyyLO1?0Ia5SmK};MJCG_c8v~ zD*akZ{9xUGBC)MXV%sMoc&ZRQpNP<2h0y+q2pv@j9VGL;jW%`2AJ>odC3*BfaxHU}xwd`%n5Lt^f0emW*0tP&6L=G^ zWyX+urG~ln4M|;NK7;DxbIr1dv$$q8lJ)(`0LkO>OtY{_2EEYi$xI@lCw3Q|5mRh3 z&LhaoqE^E)P^r`kD4t3(kk_^PM|6BOmQJNJP&Xh!vqugJ1I7ziGJHa-V~`N%S-tey2t5(S zv~d0W`RC7{hdBCil3iirp?HcrzlP#siWlG)ym#(VDz%F1th#t=4e>E3bRI*U#D}n+ z&N!WnBXA-Xp?QvuVrj(3!I{9V)q{2ji7}dCcq9n#4h+K(hIOqRn`F5R7ZVaGF~(&0 zlK^pn7E7=kD{3w=CDMr)kJec9TwwnWhfu3~k^&poVG?$*0qQ+IwFW%cAsInyAKpW(R(1ijlJP=an|m0g(p##KdS3Hh31h(w<6Y(zp)Q z9L6txs9E$q*k}gSp`R>wAK0=Gb=K3L741A;4Q0VP%hjL`cl9l5^z0GuE!PtPykO`<5zuA${9 z5>~}jdifEzwhYz(>fE{xyc~wp2Ai{tLyue6U9c?h@rp5*0(S_@5U*S+8A`8f_89DJ znvcac>UES*X?zzn5WGOLgxYW;AN_txYPbQd7~P&RdYIa8yayKIPT)F5!ZyWXnj;ni zIhh3RJ7ckD89H(B#1%8%35+4%3`-5;o1mweSsa707@bT)pz3cLpiK*AYQtmz6Z{Ux zcVdD!fXA=7d;pUmCQeMSCp9yi9{xNYUclrcCYLZ7#-tvT%a~ljWCRmE3AQ}lS zOz>Cn_!=fRFu}JaKZeOIOg_Wpb4c`);talehL%(@}ZFle9KJZaV;i|c+#9q zJ?C%Zp&OGqOzvTVql;ez@`m7lhx-pO=_wHpbOaihvPb?@cXxK~=eGVFx8vSr-Xe*4 zBDJw{8>_Uj+3==yQ+QP;kt{TsWYyqk@uu25pnAOf7W0tx7Xru!OtP~%YfjA1DxNb+ zW{0t6H`d{6U$Otr<7u8Hi_ z=3*}LYDpp|pvmNfip?o9fYuw4dm~D3q-;(J%{!F;x_BR);tk8*u;LA8Z|B zQw~{fehHyE1pRw5dCw5k^!9-iT#$ncN^s$bDCjT9|Aan-@gSgGtgvmM#YBj+}{J=%*x(b#XDQJdR8K5WpY;aUo6b+ zo_>2;^3TiudBs1Uy_;LiN4J(GavqvY&g(2Y{yn$kpOpQRiXXPzom<-VxW7cG0KIQU~gYEwtfz19A0=T;|} zgE4`CITe_d_Be^rh-oLGdQPd0eo$l-D>8}|8MW#$aJFzu>Aa-03?J9VX|mkR_wN(% z^P9xDeeuP6C(x}y9jX5(PQTnWtGJ$qvc*V6_{P>8!m|XOh(AHxx_;{$xx@~Sj7wk7 zQhIjK6O;=-&{GinZ}uQ1)R!SbDW2nTMl=$no&a&4(0U-9hmNFos5^NSg7Sxc1pj{H zTQQHFLn4i*jGU=wN+rJ<(>g`5Oj561NXZp(h-H4}tjHQ9{*f@eRR@JQdne*u!xF%tj) literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/owners.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/owners.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc7a3753cd108dfe866b1349b843fa16daa37fbc GIT binary patch literal 3835 zcmd57&-6<(4{a>XA}vK7geD3OvJ$5d>(sogY9Y(+nmOiQMm!j4gFXe`#;kxgrV znAxRm5iP(&4m$Y200KfFX`z!#Av);jqmMc60$YGs^bjpIeQT#DRaGSTN~n(;gAwX$wF-1Ul4 z)>Ki>gd8p>8suhKAx>moqojOST_mec=!QYd>RpGuNgf#vyIfUEPWY;7kh_FtSSM5v zD-|L+am9TLB~7j>s*}i(k}OiuC_f-GqE4I`B{GyWRlirRWPA>bweaR77}S74ORv}9 zzCy1HFSD?=Zy3VxK8fM|pF?E%fS)0(6_wX_B5bqd2vg?6#zrj9n#6Eh!-hae@ z&k_6Bu05>;NueJpP2$UbY4j_WPfKHP!pEK9^@l2< zPDsO-esg{^;6y95tcY|~Sb-zWsa07P@5sc7i&aA_t0hVlq8g6BEY-NG4xO@P$qAz- zl%?kq43qKEet0>N3e}d0uER-o!k{ZtTs3i&fch;tz;gCAuI31p#*?v4BVddv0BQK;830HDzCSYe zLGzw(Apt;n&;DB=uRjOjQ?X06$R+n!1c8zY6@*&1JI(BFc?@Qtrvd6rJF(czeRsu7EP`z3?2B`r zipVX#1RG{4Gm5TMQ6YlhL<9i_s>-Ox1mVl7D8Fur3xa|B(ks#!boEvr1zO@{sk^$Q5cb^(3qDs1=qfxmWNvR?SHf4re=_dR>p{6o>~ zzisv3w)=0_XVyY%`s1j{-UhMQ+wGw<&C9L9*5LMnmHE`pd}<9%*+WzHD{HqJvyZ

n~PhE;B_Q#jpXf-e0`x2YUu0WG7n<0dCz6v)1WytX$?)< zLzDa7CQWwIVkg_Fv&}!XZa&SKsc9=UZKtN|i;ezfV13ABr$H=sx}83^5pONGmbY(g zu57J5n={i3R(iosFVwF!PB)LQzi+Y&AQrpO9?fnHw;n$0HAiQy(OG+Rwq9s_*c@N~ z#AIhdEOxd%{;Q44+XK%&FvsVt@i}{Zu7167t2w(4E1Uzd*tz!D`HgdJu4j#Fo-(#1hB|;(2=(0B z>BfoXX}fpSj*RUve(VJR7NCWg^PjZjAKo*0)y!&ERE)*1#p6HUHPAI+<}18Snp=PZru=7iBL&!T`y(2>4(_(TZE4geuvOW zT=ZkC`vk!ys~OZ>a+yUfhcJn-PbgDZL_i|aHvu{cW&A%Tlw_t^Xic;xw!g3@rtOJo zD>-8)XX^R2<;IQ2D<(SwVzD#rVq-Q!IbDxHY_r7X&&dqi3F_}7hz z%iS(xBZay=4S9dhGOJOAViNE|8%GTz=nO*&%N|H+*%JKcl7*{)cnAK!pb0c|8QrDm zDJ*t|`e*Kvmy9OqRcOV`ss{mg0zRLw&5W9Fk{_A8`QJ#J`Mvo|(q^(|r?i=2vr~3L lgFfVfH{)9Fh1>G#VEd(zZwY$585L$x+DMq literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/user.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/models/__pycache__/user.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a843314607fa6fb03701a4e0164a4f03d3c93119 GIT binary patch literal 2770 zcmbVOO-vhC5MJB6_TnE5gqS}QQ-KhUz-rpG5iLXtb=njJX-U$<%F=4_KFWsuao(;; zuu{o~9603QNJvGhDsiZ2s&JrE4@m7H#~jy{57wR{^^_YCIpx%uT^wU*QYnwOvor6_ zd^2x$-r!$ju`mN;;mU>Ee+L=n9~2scJ7NwgFh4RfBl}cF^9ep5@_yB?1%!ac3arKn zoVylKgIY)kX}rK|Z9hyIj=sY1RqOON9cFotWmn z#k`>wHQkA4NnVwxWGQQ8Mly*Lr9=hE(9IR40O%~Pq8AyEEkMp6h2g#+DegFY>c=Dy zM)1ju;J*dQ5CVRNu(BWi0Th7{X45<^c+1Y9h_+7WpG|s*Q%#((|>~@_vRX2D#+k$@P{n6j) zx%))^6Q?|%J@VWmC*+>p-V>4bVov0~W~@yP>ZSjkwtcScK+~ehfo&3Pgq(h|bOHzJSEEt6%Gz4Ngp}b_~C7C$f^}9M| z$?#rRWKGc>PI6yCN~|K)^KUL9_{L6&-Rp1+2y{x{edacB-uMX`1jujnK@R-P!N*`1 zO7SVo-B=?@(ham_?q3G&_$^Asr$rnDPL2#6CFA=1!k31>Z$RqANI0OuiB}(YHF^Q znk&y$5?g`I0h^tJS!L(y$@JFz=eu@JLRg@`Hl^KYsBVL zRX$bYQ}v!y#oE00sI*x+-~uDTmkf|sNXoO7VC7z|W9Wbha6y;ACU876a$$S=9YFQY zzDoCI@1y?B{(}&Um_S}3Iflt1CJ@*JF3OBu+`eD$8LW4VKpbNj#~8*j7Cbu4rCQf; zEi!U4nDBcW`nWmY*6;y??{`zLny`=-(s3tftry@|i(8vc*u0}kYJP=i>t3C@rR)}K zdvhyeP|dvw-o *Pending , *Uploading, *Completed, *Failed + celery_task_ID: Mapped[str] = mapped_column(Text, nullable=True) + overall_rating: Mapped[Decimal] = mapped_column( + Numeric(precision=5,scale=2), #precision refers with the total numbers exist with scale which determines no of digits after decimal point + default=Decimal("0.00"), + nullable=False, + ) + gallery: Mapped[List[str]] = mapped_column(ARRAY(String), default=list, nullable=False) + created_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now() # when a user is created add the server's that respective time in the created_at column + ) + updated_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now(), # when a user is created add the server's that respective time in the created_at column + onupdate=func.now() # when a user updates the exisiting model + ) + + price_manager: Mapped[Optional['PriceManager']] = relationship( + back_populates='venue', + cascade="all, delete-orphan" + ) + + + def __repr__(self) -> str: + return f"" + + + + + + \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/models/owners.py b/Backend/bookmyvenue/src/bookmyvenue/models/owners.py new file mode 100644 index 000000000..26be2a8f3 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/models/owners.py @@ -0,0 +1,46 @@ +from typing import List, Optional + +from sqlalchemy import DateTime, ForeignKey, String, Text, func, Integer +from sqlalchemy.orm import Mapped , mapped_column , DeclarativeBase, relationship +from src.bookmyvenue.core.database import Base #Importing the unified Base from the main database.py file +from datetime import datetime + + +class Owner(Base): + __tablename__ = "owners" + + id: Mapped[int] = mapped_column( primary_key=True , nullable=False , autoincrement=True) + user_id: Mapped[int] = mapped_column(ForeignKey('users.id')) #go to users table, pick it's ID and place it in this column as foreign key relation + profession: Mapped[str] = mapped_column(String(100), nullable=False) + promise: Mapped[str] = mapped_column(Text, nullable=False) + intro_descp: Mapped[str] = mapped_column(Text, nullable=True) + organization: Mapped[str] = mapped_column(String(200), nullable=False) + venues_listed: Mapped[int] = mapped_column(Integer , default=0) + overall_ratting: Mapped[int] = mapped_column(Integer , default=0) + joined_on: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now() # when a user is created add the server's that respective time in the created_at column + ) + updated_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now(), # when a user is created add the server's that respective time in the created_at column + onupdate=func.now() # when a user updates the exisiting model + ) + user: Mapped[Optional["User"]] = relationship( + back_populates="owner" + ) + venues: Mapped[Optional[List['Venue']]] = relationship(back_populates='owner',cascade="all, delete-orphan") + + def __repr__(self) -> str: + return f"" + + + +class PriceManager(Base): + __tablename__ = "price_manager" + + id: Mapped[int] = mapped_column( primary_key=True , nullable=False , autoincrement=True) + venue_id: Mapped[int] = mapped_column(ForeignKey('venues.id')) + venue:Mapped['Venue'] = relationship(back_populates="price_manager") + standerd_price: Mapped[int] = mapped_column(default=1000, nullable=False) + \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/models/user.py b/Backend/bookmyvenue/src/bookmyvenue/models/user.py new file mode 100644 index 000000000..da88ce0a7 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/models/user.py @@ -0,0 +1,41 @@ +from typing import Optional + +from sqlalchemy import DateTime, String, func +from sqlalchemy.orm import Mapped , mapped_column , DeclarativeBase, relationship +from src.bookmyvenue.core.database import Base #Importing the unified Base from the main database.py file +from datetime import datetime + + + + +class User(Base): + __tablename__ = "users" + + id: Mapped[int] = mapped_column( primary_key=True , index=True , nullable=False , autoincrement=True) + clerkUserID: Mapped[str] = mapped_column( index=True , nullable=False ) + username: Mapped[str] = mapped_column(String(50), unique=True, nullable=False) + email: Mapped[str] = mapped_column(nullable=False , unique=True) + fullname: Mapped[str] = mapped_column(nullable=False) + phone: Mapped[Optional[str]] = mapped_column(String(10)) #we need phone number which only contains 10 digits + created_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now() # when a user is created add the server's that respective time in the created_at column + ) + updated_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + server_default=func.now(), # when a user is created add the server's that respective time in the created_at column + onupdate=func.now() # when a user updates the exisiting model + ) + + owner: Mapped[Optional["Owner"]] = relationship( + back_populates="user", + cascade="all, delete-orphan" + ) + + admin: Mapped[Optional["Admin"]] = relationship( + back_populates="user", + cascade="all, delete-orphan" + ) + + def __repr__(self) -> str: + return f"" \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/repositories/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/repositories/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4a425983a0b6447a415f596d08390987125942fd GIT binary patch literal 214 zcmZ3^%ge<81g#P}Ss?l`h=2h`DC095kTIPhg&~+hlhJP_LlF~@{~09tE7RF3CbT%U zs5r(WAjUs0)ukx2EH%a@wK%&ZzaSlIY~;;_lhPbtkwwJTx;+6;1AF+Y&_ Qz|6?V_<;dN6fpzE0MlSQF8}}l literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/admin/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/repositories/admin/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/admin/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/repositories/admin/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d3a4e6d7bc936e7fdb9d822e6e4c998434fb01b GIT binary patch literal 220 zcmZ3^%ge<81a7{DSs?l`h=2h`DC095kTIPhg&~+hlhJP_LlF~@{~09tE8p2FCbT%U zs5r(WAjUs0)ukx2EH%a@wK%&ZzaSAI*-JfJ4j@|Z~z7V zc8YCEG^xw!l;zR%gg&K37|SE4Gzsf~@q?Fp zI+WzNq|TnhIF0+DnX5$8KTO~T?j6S_2(#`!Yv zh6cvdDXBkoJ)OX!oEozkf#4d3F(XdP-65)S%JSwrvV4UulKG|4k2ha2ca}>egY;mDL+48PM6o~7_1InB>Lcd0E3PZ`P_dHgD|SBiRPepQis9J2 zeIT7R^pJ>%c6ZI4n1Zi>rDPh5LMp8bqv@%X2oMV(_Q@L{*246-q>lsFxb(I*E(x+G zB#2x`7~BB!o@=08l-kNEq3i4;hgD-MVLX`@CCej9dO{`|<|6EofaSh9CE;02Hq!Es z%8D-G`1M)KJt||+Nsp2q8t zE=^KKaXn!r6SD%gG?MW&(pG@<@@D6WkzrCZa$#VkKP7cx`Ia=&C22SG^yJ8O_14JQ zboxf`>{Tf>C5>E9ByUJ5apXGGsk66eoraTTWn9n!S<*)6&WseRW}}m{R%lGpJFeYG{8pw11_|2<^{=I?Yh$ zYN$IK>du5NnW0OIfgB%RM-IQlJZJ0f_uTCQ2;&s(Tg?a6-%-P}MHevW?-Y)m?)~l5;^!+(!8@=eacJK z4MF+5L75zV$)aU~5y+54_FilU@BodWdGx;jHt75Wl~9nI|WFg zgDudZwiUnvG8&KBc`5l>{lms$5$^?Z#DmGiF@zGx^4R)__mP5APQ@)}LQx_v+)P-g zhP4tBR~R`?mZKH5j4s34_Ftwt_ty7V*JcSCd{Mk_G7vpD}1& zKKfbf!+kamuuOW1wZsPqAfk(ZLcmV}l!@+PsId6rnOBwFtyN?7^)z- zbn;)xFy&16j2S+&@L@r6r!!oW$u+HVd$Zi$-%tN;ezo;zw)N-=pJ}~dwqD3^-6q$) z%JpWs-VE1oa{Y$4pDw%1-jdLR+S@y?geHo?pXk(g z6gVIdtq96~i#~Tec9pO9BZ%#9dp__?Gt+3s`ExYQh;HyDp1wy8+uHi&WI9Dfa_)qd zRw44DA()iXg=w57(U`1{3lL2}5JoN?LVA>zN=`Tm>E+=eoJeVjB)JX=qY!yXqL6^V zZaSd}(3gxQWfsD|TM!6IVpO0vq7wops~n2(w)VUO1zEv$<-=)3A>k5kA`AinL{99etsx(^9f+Up=!#!CcX{~S;E?6ibR6+kI+ZP= zoYadx4UBSJPebS=!tEk|1GD^;Mb;(NVkC`Rph#>7$#y(-z)d}5X;bE!E0y+D9x`X` z-vAcSdI0TiF?>yHjm_)G?LR`n;)S*Fu7^8vJNKG953IYLVQw7(SnOW+q2QiXwmr+X zFCWjahfVgdLG!wY_w#EkcmLwui_dE}gNv#a%vvE=+xm^$8RWi20H6;50Tkr#ci-*) z_|m;gi}3sIIlprqdHs9|$7gbZ`7=f6P!V8nXp(i!BxgS7640m!!w)ix~ZFUaXXIoZ*UzHSe6 z);YgE)Di9sI{y@OL*YkL^M7M%@JTr5x#Qo*x)hxyF)sKNv@bIimXBDiKH$Qq3GEC4 z)KE}|+(C-OO5n2uR51{^lMuQ9l-UF7sY6uRi!;bu1AL6MI8VR@0IwQ>O$7xnww&Ab zIvY@AA@kGz1%R4>UAqn6jc|sXrR`jR6=IJYTp$ZHL?uI4ch0ls><(he{hvLR%=pX7TK^H^# zkJ9R|#Fcl`P?3*XqS+ku6=?fwIOwppfKhWouc!g?T4FyE*#?Dd6GZi7iltY{ z3K@IpJ84VvDI5oO5(jH70N0%i!{kt#Q7z}t4x>EhP`go{bEwuR%RLeQkY?S9U z)MHf3Ids-2&pEWuD9<_6VZ1)C`FAXaP5+LJzsdABEqK-)Lkt6QSsi{u>%ZMdz2!jl U&A)s*Q@7i!+r7Y(AC<=c03lAgumAu6 literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/admin/repository.py b/Backend/bookmyvenue/src/bookmyvenue/repositories/admin/repository.py new file mode 100644 index 000000000..f34bd2880 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/repositories/admin/repository.py @@ -0,0 +1,105 @@ +from fastapi import HTTPException,status +from sqlalchemy import insert +from sqlalchemy.exc import SQLAlchemyError +import structlog +from typing import List, Optional +from sqlalchemy.orm import Session + +from src.bookmyvenue.schema.admin.admin import AmenitySchema, CategorySchema +from src.bookmyvenue.schema.user.user import PhoneOnboardingSchema +from src.bookmyvenue.models.user import User +from src.bookmyvenue.models.admin import Admin, Amenity, Category + +logger = structlog.get_logger() +class AdminRepository: + def get_the_admin_by_user(self, db:Session, clerk_id:str) -> Optional[Admin]: + clerk_user = db.query(User).filter_by(clerkUserID=clerk_id).first() #filter based search is fast for getting a spevific element + if not clerk_user: + logger.error("user record not found for checking whether he/she is admin" ,clerk_id=clerk_id) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,detail="user not found in DB") + return db.query(Admin).filter_by(user=clerk_user).first() + + def check_the_existing_category(self, db:Session, categories:List[CategorySchema]): + category_names = [cat.name for cat in categories] #collecting all the category names first + + return db.query(Category).filter(Category.name.in_(category_names)).all() # .in_ checks with the entire data present in the DB with the given names + + def check_the_existing_amenity(self, db:Session, amenities:List[AmenitySchema]): + amenities_names = [amenity.name for amenity in amenities] #collecting all the category names first + + return db.query(Amenity).filter(Amenity.name.in_(amenities_names)).all() # .in_ checks with the entire data present in the DB with the given names + + def add_the_categories(self, db:Session, categories:List[CategorySchema]) -> bool: + #performing bulk insert in the db + + #convert the categories into plain list of dicts + + dict_categoryies_to_add = [] + + for category in categories: + dict_item = { + "name" : category.name, + "icon_name" : category.icon_name + } + dict_categoryies_to_add.append(dict_item) + + # this execute is used to bulk add the categories + try: + + db.execute( + insert(Category), + dict_categoryies_to_add + ) + + db.commit() + except SQLAlchemyError as e: + db.rollback() # is used to roll back the updates if any problem with the bulk addition + + logger.error("something went wrong with the adding of the categories....") + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=f"Transaction failed and was entirely reversed. Error: {str(e)}" + ) + + return True + + def add_the_amenities(self, db:Session, amenities:List[AmenitySchema]) -> bool: + #performing bulk insert in the db + + #convert the categories into plain list of dicts + + dict_amenities_to_add = [] + + for amenity in amenities: + dict_item = { + "name" : amenity.name, + "icon_name" : amenity.iconName + } + dict_amenities_to_add.append(dict_item) + + # this execute is used to bulk add the categories + try: + + db.execute( + insert(Amenity), + dict_amenities_to_add + ) + + db.commit() + except SQLAlchemyError as e: + db.rollback() # is used to roll back the updates if any problem with the bulk addition + + logger.error("something went wrong with the adding of the amenities....") + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=f"Transaction failed and was entirely reversed. Error: {str(e)}" + ) + + return True + + + + + + +adminRepository = AdminRepository() \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/common/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/repositories/common/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/common/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/repositories/common/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6749fe2cb0d616b57a0bad2a1ced3e122c63a777 GIT binary patch literal 221 zcmZ3^%ge<81iSwlXMyO)AOZ#$p^VRLK*n^26oz01O-8?!3`I;p{%4TnuL5VQn9$e!clv5w+peWEdMLncWP$xw}5G82xEYs#gK2nAm z6orQjMVD^PR3MWZBTL2%9`Ywh0f7iN73kDWg)?Q!cSk*J$3e!P?!NmTKi+-c@9y;1 z)Km#Un=O92H76qU4>N{M9w^6ufbtNz$Q67P2!;@dhA1#w^d&=rS@PvTF_b_xRPLAk zLZBHM*A>4Ql#Eg^VN3`}L|EFI9Byy`%9Ejij42U)i(K^qatjBL%M%!RGp6CY=`(2E z71vN*`+_V{Jorr3bQ6IDyl~ z(Xj?N8E{2cfl^djUXFqw3cts#DE1P_g^KPvRS8boBy>h}z=qOb92-2ZpM^&-zul4( z-y8@)DU7^5IuRNA5IRlq8afnK>k?IV+L)xI2skR)zJCau#@OE=>>y*dP^I#kEMGV8 z#hAqA${q7|h;I^a7n?V6yq!cXb3NEKZ$#1dcj*r}Y-96=?QG-FHP^uxq`TY~6X%po zhBSCMHXY84Ir62AR!V0#aN=xQkdl>bV#~=-5a9RgXPIog3(9M#Kn?q-r(gJe@3*}_ zwXQy&>GLo3>I=Qv)oYnv>u9xOz@Y!*5Qq*N*CkShiD*n*VB!N11M&6ccy7;{nR>Xl5dywn$7=nGwaG1C`2+9LT7K&$l<)hsK7&n=6VEGvlI zw$JoQ%i3w%ejXtOz!LV5h{6QBM&uF`yp~ze4iR6Fmq8|2hzU00EfD*oUtbiIrN^~C zg6Zkzv*h{8(J$HOtK2>-WI?GtzRbL}r$0V(pMP-_WS`yQ_B%zM2HUt^riBd~{zO_H zVULZ-AZRg8NZU#Ls7ci%ZFylcuZdMhr{f*p_MJ@}q>YFKyl#30Zgu0tEpGrx*pC~w z8+c*P0Do7dCQd9^w}}Z=^O=)C%lXY8|0j?uEFE?LoUhl~mpSiWkt+Du1CNhD^d&(M zdT6P0UhkoDXV`mazH?shp-(!e``_q#=e*umQR(Af=d$8Q-Qv}(cy(Xx%d!Bc^tSkq Z`Cg3!lj!0?XXaXWrkc%EM=9~@-T((+mx}-Z literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/common/repository.py b/Backend/bookmyvenue/src/bookmyvenue/repositories/common/repository.py new file mode 100644 index 000000000..b665a8290 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/repositories/common/repository.py @@ -0,0 +1,17 @@ +from fastapi import HTTPException,status +import structlog +from typing import List, Optional +from sqlalchemy.orm import Session + +from src.bookmyvenue.models.admin import Amenity, Category + + +logger = structlog.get_logger() + +class CommonRepository: + def fetch_all_the_categories(self, db:Session) -> Optional[List[Category]]: + return db.query(Category).all() + def fetch_all_the_amenities(self, db:Session) -> Optional[List[Amenity]]: + return db.query(Amenity).all() + +commonRepository = CommonRepository() \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/owner/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/repositories/owner/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/owner/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/repositories/owner/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae04b9ebf5340fd67f70f25b584f8ddf72177d12 GIT binary patch literal 220 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 literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/owner/repository.py b/Backend/bookmyvenue/src/bookmyvenue/repositories/owner/repository.py new file mode 100644 index 000000000..ed0705863 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/repositories/owner/repository.py @@ -0,0 +1,95 @@ +from fastapi import File, HTTPException, UploadFile,status +from pydantic import Json +from sqlalchemy import Select +import structlog +from typing import List, Optional +from sqlalchemy.orm import Session + +from src.bookmyvenue.models.admin import Amenity, Category +from src.bookmyvenue.schema.common.common import ImageKitVenueUrls, VenueSchema +from src.bookmyvenue.models.common import Venue +from src.bookmyvenue.schema.owner.owner import OwnerOnboardingSchema +from src.bookmyvenue.schema.responce.responces import UserNotFoundResponce +from src.bookmyvenue.schema.user.user import PhoneOnboardingSchema +from src.bookmyvenue.models.user import User +from src.bookmyvenue.models.owners import Owner + +logger = structlog.get_logger() + +class OwnerRepository: + def get_owner_record_by_ID(self, db:Session, current_user_id:str) -> Optional[Owner]: + return db.query(Owner).join(User).filter(User.clerkUserID == current_user_id).first() + + def onboard_owner(self, db:Session,clerk_user:User, onboard:OwnerOnboardingSchema) -> Owner: + logger.info("creating the owner record forthe user" , userid = clerk_user.id) + owner = Owner( + user = clerk_user, + profession = onboard.profession, + promise = onboard.promise, + intro_descp = onboard.self_info, + organization = onboard.organization + ) + db.add(owner) + db.commit() + db.refresh(owner) + return owner + + def duplicate_venue_checker(self, db:Session, owner:Owner, name:str, city:str, street_address:str) -> bool: + duplicate_venue = db.query(Venue).filter( + Venue.owner == owner, + Venue.name.ilike(name), + Venue.city.ilike(city), + Venue.street_address.ilike(street_address), + ).first() + + if duplicate_venue: + logger.info("already an venue exists with same name in same city at same location for the same owner.", owner = owner.user_id, venue_name = name, venue_city = city, venue_street_address = street_address) + raise HTTPException(status_code=status.HTTP_409_CONFLICT , detail="already an venue exists with same name in same city at same location") + + return False + def create_venue_record(self, db:Session, owner:Owner, payload:Json[VenueSchema]) -> Venue: + # we have to decode the categories and amenities first sice we have to apply relation with them + + category_command = Select(Category).where(Category.id.in_(payload.categories)) + categories_instances =db.execute(category_command) + list_of_categories = categories_instances.scalars().all() #returns the instance as a python list + logger.info("collecting the categories" , ids = payload.categories) + + amenities_command = Select(Amenity).where(Amenity.id.in_(payload.amenities)) + amenities_instances = db.execute(amenities_command) + list_of_amenities = amenities_instances.scalars().all() #returns the instance as a python list + logger.info("collecting the amenities" , ids = payload.amenities) + + # now we are creating the venue listings with the collected documents. + logger.info("creating the venue with the details" , owner = owner.user_id, venue_name = payload.name, venue_city = payload.city, venue_street_address = payload.street_address) + venue_instance = Venue( + categories = list_of_categories, + amenities = list_of_amenities, + owner = owner, + name = payload.name, + max_capacity = payload.max_capacity, + street_address = payload.street_address, + city = payload.city, + district = payload.district, + state = payload.state, + country = payload.country, + location_url = payload.location_url, + description = payload.description, + cancellation_percentage = payload.cancellation_percentage, + minimum_slot_duration = payload.minimum_slot_duration, + cancellation_time_limit = payload.cancellation_time_limit, + hourly_rent = payload.hourly_rent, + task_status = "Pending" + ) + + db.add(venue_instance) + db.commit() + logger.info("commiting the venue in the db" , owner = owner.user_id, venue_name = payload.name, venue_city = payload.city, venue_street_address = payload.street_address) + db.refresh(venue_instance) + + return venue_instance + + + + +ownerRepository = OwnerRepository() \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/users/__pycache__/repository.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/repositories/users/__pycache__/repository.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc1cfb411dc465a92c03bb4ff5f39804c7a2129e GIT binary patch literal 4101 zcmc&1TWA~E_0Cf>k}SoFZN+h&$m`uEVpDr5DQUO6g(S9PQe*=?&D23d1u%aJtB zol#;7#h7J36ceyp3NEDu(^9t~DfrVLrDT6fJ_;QLLBvo)p!B1EUa}v{e)Zft)<|+3 zSo+heJLjBx?z!*t(jU9J{0Pe5{yMTyR1o?XZ8VE`K)l)pViV~|=kln)rMLp0;yK#p z^Fm4hEab(4l#&=v%*zE|%ExFauN2gj%4j+7F9cEnM*H%?LRYGbLp;L5La4bQUFUJL zfl^@}T|v6?Dbm$#9(v$&OX?VmJ9bFATj!@y-2Wdc66c++tG8}VjxS~KqLnj>j%-?K zt7InPoTDTeE1d`0H;qjb`ho2E$iyUJSQAF6s83;Y(I{px@OvlcjUrAKXN@$`bH%yo z%seinp+lqtG6!2?D0t9#br*Ti31npW zd`wo(2I25xO7Z$ttil{}R?+>y_cML~+M*tWc0lif3kW$Oy00m`XqY+6Aj=M~&pJvb zkI8Kbag>&5aO0HJLT9t1wOY_;_?c?ebbC)^>q z_EkN>&WD6E@QFv96JT4WXSp^O7ai$N36o`_!YD`0=JFOM+U&9;Wpl)|;({ZZIG-i- z1xObFldcqt#lE_8`TZF>i8*t1awb{CVTr!N?H;Wn?OFP$_j|zC$NUMV%sFB zQ=2%d&24*bN&ZiJk>0Qu8MIbTlzR!D%bB2>;3s0%JdV-Fh{buPl7w1*TqNCq7)=H! zbrL}NM8+r-a#qJM%ZQC#D)(gwPFq-SO_wVIKQ23R-k6)i#1V7Ftl=7lkk-M%-MJhe z!C8XM`M8ht(uF+Ra2KcRvK=@+eKxs(GnVNC7T63eqz`DP+g)69y$3x^Id({yUy}&K zK=XG1R?(gkS`VxR?4EabmY(%i12rXCSCY1p+>7)zPQ)6KXrp%!>b@!+_kWH6d_h6g zw;x1mU|n95tM?v+ABL-8Z>Evmv(LuqOjC7b%2uWtiho^QQy&B#2C4zt@UQtdF4UBP zx-wuZ1KzlEyUMe7=(x$cGHEN5jc{KzL{88{N{iINXWEsC(#%|b&CKQh>k#jY716w4 zL3D1GqZL}`!Ql#>krE7ydc%Wad65>O1#doGd?Iy@`h=?p3)IuHQV}(e?$`y(9GX&1 ztjkC30&XzSlxW9C7;7_#wu_;Pc-V1NL@+sDf*b?6axb$pf-?ruV@1P?WoZz9#4)=o z_pn}%9diwccLHuspk)jlJF<=~@TBG8BP`MIf`5z|WxR_-U|D8!R6)4w(>x z5UM?ds*w|+iHLUoz4KZkc}tr}ev}v^Z`0mW6vQYP0uYxDTPYQCf|(K_xah_clRC0C z^Xw}v>fjsPSku~M`JF>HdbAi_-=ygl1fFRB=F%^g{viH*<(DfjqNC5Fqr3BVbhH+| zQjcDF5xx05db1Wy)}zU4un`{EN4$!;yoc{Af z{oJ^HGh;{eT12l$bUUcO9DM6HKdT1o%E^B>y~6jN{)Ad&qOK%tC2^!Be^66mbtPsi zF<2Jt*|k`I%O7>*G4#Hf+5R1fuN&nSyxaw%9nh^blS3+v9!Ezq{xyaCn(;^%rqM96 z+KlIIL<0APpF%=?Usw@zP;8gF$K69qz`w`Er9`=3$9dctA+p3MKrA5NgyY_th|5d^ zUA>|~hUzp7fe1t!s+SBy3~B|0Z_z#uoAmCeYPpU-0M-CwnP!zw9#W^azIS1ic?Uq7 zvmf1kzyAFnwfX3MUQ+uT!O;4(wQCy-wct=aIAjNh4mc04KfGSO-Z&oJIRE8d_{2Wq z)czJ|96zz~o#yXLDEk8R12*Xie;>aXLZ5~F7l(z$b`N-G*u}eNpPv8Ah)W*<nPsld>)3`6#e=3;%G;ltom zK>Eg?U`ar`up%IPJmq2yW`Oo#aMCCB|LVv42+&RsLvIA`!Rb-s5yzKJgTq|RwfQy` zZm^WGAQ5q7Yk3jU7j~ac$h?zJ=jk7%Kv6cHsX4%V4rB literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/repositories/users/repository.py b/Backend/bookmyvenue/src/bookmyvenue/repositories/users/repository.py new file mode 100644 index 000000000..a9348c6fa --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/repositories/users/repository.py @@ -0,0 +1,52 @@ +from fastapi import HTTPException,status +import structlog +from typing import Optional +from sqlalchemy.orm import Session + +from src.bookmyvenue.schema.responce.responces import UserNotFoundResponce +from src.bookmyvenue.schema.user.user import PhoneOnboardingSchema +from src.bookmyvenue.models.user import User + +logger = structlog.get_logger() +class UserRepository: + def get_user_by_id(self, db:Session, clerk_id:str) -> Optional[User]: + return db.query(User).filter_by(clerkUserID=clerk_id).first() #filter based search is fast for getting a spevific element + + def create_clerk_user(self, db:Session, clerk_id:str, email:str, fullname:str, username:str) -> User: + logger.info("registering the user " , clerk_id=clerk_id, email = email) + dbOject = User( + clerkUserID=clerk_id, + email=email, + username=username, + fullname=fullname, + ) + db.add(dbOject) + logger.info("commiting the user to DB" , clerk_id=clerk_id, email = email) + db.commit() + db.refresh(dbOject) + logger.info("created the user in DB" , clerk_id=clerk_id, email = email) + return dbOject + + def update_user_onboarding(self, db:Session, clerk_id:str, phone:PhoneOnboardingSchema) -> User: + current_user = db.query(User).filter_by(clerkUserID = clerk_id).first() + if not current_user: + logger.error("user record not found" ,clerk_id=clerk_id) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,detail="user not found in DB") + + current_user.phone = phone.phone + + logger.info("commiting the user onboarding to DB" , clerk_id=clerk_id) + db.commit() + db.refresh(current_user) + return current_user + + def detele_user(self, db:Session, clerk_user:User): + logger.info("deleting the user from DB" , clerk_id=clerk_user.clerkUserID) + try: + db.delete(clerk_user) + db.commit() + return True + except Exception as e: + return False + +userRepository = UserRepository() \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/schema/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/schema/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7fbde45afaf103d9992eb8611bb30425217f790d GIT binary patch literal 208 zcmZ3^%ge<81Zu^aSs?l`h=2h`DC095kTIPhg&~+hlhJP_LlF~@{~09tE7{p9CbT%U zs5r(WAjUs0)ukx2EH%a@wK%&ZzaSB^G=4F<|$LkeT{^GF7%}*)KNwq6t1=fQXoRONF7?YTio0%6AAD@|*SrQ+wS5Wzj!zMRBr8Fniu80+AGstbl{6OLZ QGb1D82L>2X#0(Sz0KC^c82|tP literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/admin/__pycache__/admin.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/schema/admin/__pycache__/admin.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..32dd8cc36917fc43f20ebb2948a8295cb2361045 GIT binary patch literal 1428 zcmb7E&ubGw6rS1LB%8FGv?=0`gJ`Ql4tf=&6l{wcu&Yoi7#5c8&RExGcjNA+u(uTY z2Lvzu50v6RlR^(=52ASTmXhM3C*PY*tjWehC$nF^c`t9~n{OujMbkg{Tn=*i zOfD~S1<0wHTtVcDkSk?!Dx29Pwb@^|M2#lOODBwKQc_&CLcZZM-b`}O9NuL1P=xpz zNgCXP;UVFqK^bXCTZGG8VRRXyf=S4j3=1epdCiLWjvvIE_IvJHiQ-u4`5-92N~_jfnqH{5G;W81QKxyOuch`I5eh=qYYJ{D>X zi@A=M;-gj^6kss{c_4#DfX+Xk(~{Pyck27~(@M3Ycl3RDI(jfaDw^))14vJLc@tu3 zoySc*6(4M;7bE4tJ2vn3)1keK%G^zFm#t_O#77)Z%Ff?7t zm5eQ?V*c7%fLn*+{^zQYGtJdos0;x;&bq42cORZ;cX|r;V}U@@tzea2D<=6UZaLnL zIKD(}#mw>|#|{*n8Q&=Bk&5FJGQ^VOhkKzer~jjs;5Jmidx?ZU0Qxee^psrhjrZ^5 zes5au=Owz(Ct2veJ;UhvWlE)VsZX-djn6Q8ewk9U(}^Xz^(k}S#W^PdSBEIhIhhhp F{sE`9Gg$xt literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/admin/admin.py b/Backend/bookmyvenue/src/bookmyvenue/schema/admin/admin.py new file mode 100644 index 000000000..4684dd952 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/schema/admin/admin.py @@ -0,0 +1,19 @@ +from typing import List + +from pydantic import BaseModel, Field + + +class CategorySchema(BaseModel): + name: str + icon_name: str # this field validation helps to match the 'icon_name' column of the Category table to map 'iconName' coming from frontend + +class CategoriesSchema(BaseModel): + category: List[CategorySchema] + + +class AmenitySchema(BaseModel): + name: str + icon_name: str + +class AmenitesSchema(BaseModel): + amenity: List[AmenitySchema] \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/common/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/schema/common/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/common/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/schema/common/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..716033fc5eaa5d59e361ef7806747c5875f2ecf4 GIT binary patch literal 215 zcmZ3^%ge<81m;CHSs?l`h=2h`DC095kTIPhg&~+hlhJP_LlF~@{~09tE6dp`CbT%U zs5r(WAjUs0)ukx2EH%a@wK%&ZzaSlIY~;;_lhPbtkwwJTx;S`BhsF+Y&_ Qz|6?V_<;dN6fpzE03gvjdH?_b literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/common/__pycache__/common.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/schema/common/__pycache__/common.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd16e1c733749d5ecc4735424276225f36425efb GIT binary patch literal 1606 zcmZ`(y>H}16d&8O-yiuPn*?&ZeR{O#HEoy%Fvl ziGqS6#fiIuf(nHAM=0$IYea!WMVBL2UB#Q(jguw8e)IEh=FPk}@68+k+-lVkJpcUm z(U(L==r7s1dP;M0c?9G+qKIlP8p*HjYMwsQJ!52OvTwN9D~(DT($U9=;%^WwvC>Zl zLcc+@Shg znZNu4y3Y|qBaNbweu$XCFx4KxsA77-jDq2Ul?qlaSfyZ9#Y$kWrdXL(-YoV2qxE8D zqhQT~wImy(QI*yHv#veY)Ng5))anY@UY3lmKyp?^<8$Uu*@1n`JWF8T@|b9P*4MfGqI-V1WI{0VffIBP{ zH3-0WB1s#^0qiIy9Ng^p8=^{x437{|C&UZr)RnwR$X8R#oofu(idZ7V^8En9gs4K8 zgO7s1_a-^D5Jf@HXx-|#te&bJ{p73tmg^Lu*uC&Da}c>D`ExO402mBKalvq P%*e?2fdNJoF$2W_Xl6Qz literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/owner/__pycache__/owner.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/schema/owner/__pycache__/owner.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1f9fca893ffcbe632bca42eac600f27b8217bcea GIT binary patch literal 948 zcmah|Uu#n_6wkdkx4o^c8_N6xg2IYW5I=wp!EXMUbgM8X5-xK1-FLq2CIz_!TP%r#&bhQpmsX;Vbk(8yTyeLH{=`JPh%tUuMNz%1UnecAH zQfeb%GtrrWxjVQm1}19tvP24!wx^5d)6rH3k1gE+3?PpJ*o0K{BU{u#cuHK)dip3T^@@oo$ykD2PFsjDdicTb2MN1g4GVAg~^fMQkN{XzXQ;3 rE$j!L=Z(S4Fz?^M&Cy9R2G>R>$$kNPwS90Lc9(xT>#zT~@?3udF%kX) literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/owner/owner.py b/Backend/bookmyvenue/src/bookmyvenue/schema/owner/owner.py new file mode 100644 index 000000000..49d008150 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/schema/owner/owner.py @@ -0,0 +1,12 @@ +import datetime + +from pydantic import BaseModel, ConfigDict, EmailStr, Field +from typing import List, Dict, Any, Optional + + +class OwnerOnboardingSchema(BaseModel): + organization: str + profession: Optional[str] = None + promise: str + self_info: Optional[str] = None + diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/responce/__pycache__/responces.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/schema/responce/__pycache__/responces.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..78d64eaed1b419fb6e5e7e3c3124984d128884e7 GIT binary patch literal 4072 zcmcgvTW{1x6dtd=H}5UUZZ2FxQGlR@cBu*~5(QcaN{Jwws*p-utz`k(^6DX*4#$V3NcV==fGslzPOC_1W zWBvWjPjeYU{=&}SNr%GruL2>DiAFS`OAMhU2q>qzDMM_DhSZXHU+kuhOe@1>shc%& zt(=i><#|8dm5oBHAdnRKmS~yZh?b?|Q<0G8@CHw-$hjPF`50H?oD5tc#+5l&1g=Dj zku@uvD+5=FaU+}?0d6$LjdE@bxN3|W<6I56@fcU-+yrowF|NkBDc}ypxN*)M2JT3V zo6wHlA@%837^b@5OSg5~si*w>b=9VemPWh2JZG8r^wk@B#{q@H57g|@JDvN~P(iPB z&7h|4tOo;rc}{ics>Q-S=*!DCWdYj>bHRTNGP8Xdx{nDZEkPr#)H39dikk3e>M87s z=kNwkOQLC-(L~gyS&$@@v^3bB@ki0v@2S0JnH@UURc-t3Gr_OiW0s+)j>GhooFieYKJF3Lqk`MIZd1BT&l^@~8#E-Zin z@kQNq{EDKerfI>-x@FohO|%{MjBKOXZ;iQ2ZS>!6-~6tsdC628cBaS z1c04_NzHn0fB!{L2zF{x5KbeDfL_>N0=z2-Wv_DTg*@v?*fu$W5QG93`VT`f5$@HG zi3H!aNs*|7?F<3m_l?BK7xF1j!nVl~gdh^QNOB}T_!QK_6Ts{C@G%H?!2zdW61_`u z`z#U&4R~!7-n9Y3(uD;q@D(Q|`-&xG?*Y(+mPp~Fs-<`}7U6VD!RcOJgM+-gx%~<_ zX!Tf!hJ;^Y;nzoT*4N+znu+fCbMUv=zHWYoECPn##!WEf=2YEXe00K->d-bhf)IFz zlajr|BeT~#3chIqdIr}9X~@UgO{#XC`*-+VV30dj231x8Xx3xyj3dVr#(j#^F7$#S z;E9d9bHFDSCndY{UdgIqDQ;TMywx*zN|B!%j4;eXlVLH9mRr0TFodt*jhj3*6J%h< zlV&z0L})<YG8GyABj znxUHwjx37{=TQ6jKH5FVWdkAjNEUDcztiv{iQAih8hBOYHG-cYzVCP@c|0O{ew(`- zTxPE_{QTiv+Fnc%vLy}wo;v&+dT;WVm7 z!8>*iRZpX8$bsrCsz$+^ZlLNcs)ih>mQghd-jPpHwT!AEmlK3DTO%jHrS q)HsBzLR5D+SrAU(s!`yoFpR5)92fu&#=$#r;WZAUYE*&Og?|9qNq0X0 literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/responce/responces.py b/Backend/bookmyvenue/src/bookmyvenue/schema/responce/responces.py new file mode 100644 index 000000000..4d4e19f1e --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/schema/responce/responces.py @@ -0,0 +1,64 @@ + +from typing import List + +from pydantic import BaseModel, ConfigDict + + +from src.bookmyvenue.schema.common.common import VenueSchema +from src.bookmyvenue.schema.admin.admin import AmenitySchema, CategorySchema +from src.bookmyvenue.schema.user.user import UserSchema + + +class BaseResponceClass(BaseModel): + model_config = ConfigDict(from_attributes=True) + + status_code:int + message:str + + +class ResponceCategorySchema(BaseModel): + model_config = ConfigDict(from_attributes=True) + id:int + name: str + icon_name: str + +class ResponceAmenitySchema(BaseModel): + model_config = ConfigDict(from_attributes=True) + id:int + name: str + icon_name: str + +class UserCreatedResponce(BaseResponceClass): + model_config = ConfigDict(from_attributes=True) + data: UserSchema + + +class CategoryFetchedResponce(BaseResponceClass): + model_config = ConfigDict(from_attributes=True) + data: List[ResponceCategorySchema] + + +class AmenityFetchedResponce(BaseResponceClass): + model_config = ConfigDict(from_attributes=True) + data: List[ResponceAmenitySchema] + + +class CreatedVenueResponce(BaseResponceClass): + model_config = ConfigDict(from_attributes=True) + data: str + +class UserUpdatedResponce(BaseResponceClass): + responce_type:str = "ResourceUpdated" + + +class HealthStatusResponce(BaseResponceClass): + status_code:int + message:str + + +class UserNotFoundResponce(BaseResponceClass): + responce_type:str = "NotFound" + + +class UserNotAuthenticatedResponce(BaseResponceClass): + responce_type:str = "Unauthorized" \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/responce/suiiii.html b/Backend/bookmyvenue/src/bookmyvenue/schema/responce/suiiii.html new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/schema/user/__pycache__/user.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/schema/user/__pycache__/user.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e95efe66de5f89930892be2da8e682749c6d2ed8 GIT binary patch literal 3575 zcmai0O>7&-72cmAxm=Q>7)h}zB@V5h)`U}~wVNVIO&77{$f~2C)=pb22rO3Ip+$R_ zWM`L#CDgzQ$Uz4mcnA;yZ2%t%H${BuEyo;+o|k|Q#GC>YD3BWs>6BC7o25*VRO;c( zw=?hC9nQ>q@7w)*CZkJGrvJTk|DQ2Q`VS6H3XDZL`Y&8Qmu$(F9m&9};>fOID6VR# zE-{E3Gh#B@RVVHyjD)KhnwvC|u5ReEq)020O+JmQT!}S~W zTBUk#xmxzQcGI=0&K;le*hf|B*l;KLxa#?w2wMHHw!^iJhF`7MET`PtsJNVL`)C1% zpG#CSWLq+nPb8{RV#`;-N@LJduxG2V7{YTm9LgSuzx>d)8TCA#p|}9k>J62uyx0ri1;oY5u8cIT6FqpFC@tR;^a|EnJ}o_o$xF{vjO!Cw*_<_@MNO zN10c;wOQJz(PdVBNK4Dqd*Ig_r7ibi>3Y5XU~T93wAQ4h>sI*zt=Xk5u(>-Ah0SB- z!Et#T)>~@Aqym;2J1h-zn9K;H^_Z~{ zCMg)*$O1Dyu(p(7(nd}MP$rrI!e)$*i?I0v-P#7%EL*^vMk{RsHBD{g{Cc=4yw-E9GoIve$KLb_;H2Imz(Aax#8&71VzANrw#h>0{9JHrf4k*9aYHf(wN2(aZ_Nj*`;QLPCyzri54BC^&$KOF4#^t_+fTi} z!o$$N+$NVhKe-f=sn(;X>SypY^e?r^rOuldf|dPSt-DXwLvjIXn_TGR&IKRsUkS-M zsBMAJi8hRTJv%LyfO(bL2;GU2fItAndb-mKpqr4|pl>$D5uP(A{!W8}>J0l*9JuhM z@am8|Fwq&pIcOd(Yrq})Oh~Y{$xJ7m4Q>aw_ilIeOt2cP?m-JyqmAMO0~;k^z;d(= z@BAqLk==?!<95uBKTkYU;Ozu0DhBAqkQzi;8iONBat(zN-w`}jMv=zh z>aqw{9uq0TwMx?w;=BGGhG0R#tf*K`$LG3hJu)3yyXSB7SYx|hqlM(~arRRq22V3o zOZGDakt9Q>TR;KOJ{dayxy#~AnX+b=4w;=Ouh1Fft@_km_YWma@%E|RI%mHc! z1lOAlm?P@P8TFg2R(`o1SUx%n58~(|0DLydf0pn#qVgBTR$%<{ei*A?U_g=e-Knen zObt)dtmS?DW_#MD#gPG>;M1QiS6C);_ zhte5Ho$TgQ|8I}O>?YK2$iMWchp24|_pTRGLlManrfJv9FdHTvPs4Wxb#{j3JwW}yGtt%nKrOETH55Ba+i7V}iD~A(T zf{(v_Dcs}JhvTS?J$W1)c8MJOt$Z-wmGJuiF$!l~&)MOO%;|83P*!dExiS>W1mq>& z`A8jzy?#fzXMzjWZN-tOysbHFj*P=2y!MBUrdud^U>Z z@Hpr`Y$AF;W2Uksf{-Kex)v`0RA`|@!ogyJL+<}xyBd9>USrqcW(;4?2JEV`EO(@A zAb#IUzY1SfJJQ?Xt7?}havGv(1P+of(0bgbG+mzVN~6%)d4bmBJ~gAtV_j(!a89ru z_o;MDzSfmSVISrM>v5kNOUW3hXJc#ng str: + return f"" + +class PhoneOnboardingSchema(BaseModel): + phone: str = Field(max_length=10) \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/services/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/services/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/services/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/services/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..deff0d8d5cf1840147dfe8899bae89afa8b792e4 GIT binary patch literal 210 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 ByvhIo literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/services/__pycache__/ownertask.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/services/__pycache__/ownertask.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b16e708502a9eb56fa2d11e792f0720a143dd43d GIT binary patch literal 4254 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 A4FCWD literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/services/__pycache__/userServices.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/services/__pycache__/userServices.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db19005fbc2121021afd44396a90858d36f5a32c GIT binary patch literal 4169 zcmahMOKcm*b(YH|mp@TnS`sBu5f%SR*H%zFPHaaBT7MeFb|lx5KOmHDDeg$5wETE> zDOm(n7(oiKhJoZzz;2BcI=M2egO3T207j96(9_abz{COu4754;#=z;tr@ooxZ{-AC zt!Cc7dGF1e_Z|Kt6!If@?tMGH^v3`~|E3?U$K3>8{vCijNI?pxq9mPNDwlI5U7U^M zlRV&f)twWP0>imgPtKe4GFVW>oG0Vi)U}7aZ%3}@__KpU`?|@_hk(e zK=qVhzJ!YfEvpyE8erTMlWy+ACb9YPG6TRJgi(@HP|~Gvm{(lby(F}V6&`yQJc|1> zchdX%>VjJlU`1pr9_&-Rz{_k-`5CXMh(Hlgd~goG6`(rKV6u`;W6Pz?TmH0)$+Aop zv^)gsC6Z6`t<7Qf!ax0f`5!P8b<;XuaV@n8&Y(|**WDHO64ye(YTKmC3?e>QZ_8Zg zIh5ya$11!w*e!`j-Cqhf*b<1kd4cPM-ZCCgY_tv4CI>)qfvmPhTfEcJ9MVG_YQ^16 zdk-nXm;8O;ec0yzl+(i<`la^n6|S3e%j4W-U8o4;s6$s@M@k1$yxmeN{FZnhZ1u2h zFVMEHi`u97w*txSTK8A{kR*{QLc_K^L~|mZNv+^`z7WT`R920r z6oo*(Kj19U&YP@K4xFYL6lc`s7%*s*ekG-56(`sD0~evWNvQqGhZw_ZR?o!s42~~m zS8$#Q$)|ESULZ|gd?TyrTEfMcEP<)<;;#^!ggVC(7fPy1Rk1|64}}taR+#NCH_d=G z%av8EXpv-dDY7Oz7G+ooIWU$-Ei5iVoe?l01!DQHq|_2VOJU-nd-g11omC=vevPub zv-yPrp_yR$7qUdtWu}l%O*KIhqiceulWY;DqMFsA)|P-(pyS&XpTRe*U1@?-I+nXC zouC$0p;iYhw}#aP`|LD>tdQd@md`#wVSWkDLOqeqFWR+IUJUL%`#6XRx-c7m9Q9xs|z7g~Ia3Ygcf-gy&AB(#trn z%*_KXw+5jBIE|#8-*y?-=BR^anjhoEH7i8$BIt?<)1*8|w{5PEJC=GuN9}6}rkm(_ zG*%7O2ltqRM;nOu^|PV+Q9T^JUAbE}M^8NopK2gisJ|XhnDKYN2-SQ0z7QG$U>bhZ zJJLX$Z<5;>GRNMt!Fp`J8GGl^bu)ItjD1-B_<1-6{Jv}4v!L|(g@gx88@zerwWIQ@Uydum0DA1`n9gV_!*+m%hsx(b-yb){M?p zL(cSd{&G{Q3ia@y8Qx=r6C0%Ju17}9$o{HW?;kcId*QvS*z?oK!6%V}wa6he za>$5GJPKCD=ivc*xd!=~v>Q|9HrV7P3)#q-(`o#tfo z*=XI?S_n3?HrtW%dYf%GC1}ZTQ`y-fp|N&r*WM4b+aU|evUiHma4jF9(H{T5byF$e zyxuH`gf=)rdrNuGPjN%#1ahrKPiSXJcv(#%dnxN1bQq(;U;g< z1y#G-@+1@0tUE@xQ5O{U#zAsDGV_RwI2dk^ot z_t0As=<1A*bs-AzorsFOO#nB zlx52=%ejJ5f;g0|pe$c6rC8IJWkTIY=;gdU4fMaX-UfQJ@l z^KQF{K4?s5(VvlKO5@OqmIhA3Mk-N_3pB-$q zsm6(3au6oVy8!(Z=BF1S`?6$5Gd+S8pxeSrf4h-M zz;wLwN}RC6-~;kISfDAX{S$@;&v9HG1#Ysx=V;7uzID`VwB9;;({R4fAi2W^I@JBv z(WK#g>rMh720s5A)j`uYQuB?PzR{bWhWi8u?f>=R2a5Z#vv7k$;i2mCpL4f!w$AK~ F{{si_7s&ts literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/services/adminService.py b/Backend/bookmyvenue/src/bookmyvenue/services/adminService.py new file mode 100644 index 000000000..c53ee81aa --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/services/adminService.py @@ -0,0 +1,82 @@ +from typing import List, Optional +import uuid + +from fastapi import File, HTTPException, UploadFile, status +import structlog +from sqlalchemy.orm import Session + + +from src.bookmyvenue.schema.common.common import ImageKitVenueUrls +from src.bookmyvenue.utils.image_kit import imagekit +from src.bookmyvenue.schema.admin import admin +from src.bookmyvenue.models.owners import Owner +from src.bookmyvenue.models.user import User +from src.bookmyvenue.repositories.users.repository import userRepository +from src.bookmyvenue.repositories.owner.repository import ownerRepository +from src.bookmyvenue.repositories.admin.repository import adminRepository +from src.bookmyvenue.schema.user import user +from src.bookmyvenue.schema.owner import owner + + +logger = structlog.get_logger() + +class AdminService: + def add_category(self, db:Session, categories: List[admin.CategorySchema]) : + #check if that same category exists , if so raise error + + existing_categories = adminRepository.check_the_existing_category(db, categories) + if existing_categories: + logger.error("some of the categories already exists" ,exisiting_categories=existing_categories) + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,detail="some of the categories already exists") + + return adminRepository.add_the_categories(db, categories) + + def add_amenity(self, db:Session, amenities: List[admin.AmenitySchema]): + #check if that same category exists , if so raise error + + existing_categories = adminRepository.check_the_existing_amenity(db, amenities) + if existing_categories: + logger.error("some of the amenities already exists" ,exisiting_categories=existing_categories) + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,detail="some of the amenities already exists") + + return adminRepository.add_the_amenities(db, amenities) + + async def upload_venue_images(self,cover_image: UploadFile = File(...),gallery: List[UploadFile] = File(...)) -> ImageKitVenueUrls: + cover_image_url = '' + gallery_urls = [] + #First we upload the images to the imagekit storage and then return the urls to the route control + try: + logger.info("trying to upload the cover image") + cover_image_data = await cover_image.read() + uploaded_media = imagekit.files.upload( + file=cover_image_data, + file_name=cover_image.filename or '', + folder='/covers' + ) + if uploaded_media.url: + logger.info("successfully uploaded the cover image" , url = uploaded_media.url) + cover_image_url = uploaded_media.url + + + for img in gallery: + img_bytes = await img.read() + uploaded_media_gallery = imagekit.files.upload( + file=img_bytes, + file_name=img.filename or '', + folder='/gallery' + ) + if uploaded_media_gallery.url: + logger.info("successfully uploaded the cover image" , url = uploaded_media_gallery.url) + gallery_urls.append(uploaded_media_gallery.url) ## appending the gallery urls back. + + except Exception as e: + logger.error("some error occured while dealing with image upload" , e) + + return ImageKitVenueUrls( + cover_image_url=cover_image_url, + gallery_images=gallery_urls, + ) + + + +adminservice = AdminService() \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/services/commonService.py b/Backend/bookmyvenue/src/bookmyvenue/services/commonService.py new file mode 100644 index 000000000..ca5894ee2 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/services/commonService.py @@ -0,0 +1,37 @@ +from typing import List, Optional +import uuid + +from fastapi import HTTPException, status +import structlog +from sqlalchemy.orm import Session + +from src.bookmyvenue.repositories.common.repository import commonRepository +from src.bookmyvenue.models.admin import Amenity, Category + + + + +logger = structlog.get_logger() + +class CommonService: + def get_the_categories(self, db:Session) -> List[Category]: + categories_list = commonRepository.fetch_all_the_categories(db) + if not categories_list: + logger.error("the categories table is empty , no category to show") + raise HTTPException(status.HTTP_404_NOT_FOUND ,detail="categories are not found in the database") + return categories_list + + def get_the_amenities(self, db:Session) -> List[Amenity]: + amenity_list = commonRepository.fetch_all_the_amenities(db) + if not amenity_list: + logger.error("the amenity table is empty , no category to show") + raise HTTPException(status.HTTP_404_NOT_FOUND ,detail="amenities are not found in the database") + return amenity_list + + + + + + + +commonService = CommonService() \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/services/ownerServices.py b/Backend/bookmyvenue/src/bookmyvenue/services/ownerServices.py new file mode 100644 index 000000000..b8855daf6 --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/services/ownerServices.py @@ -0,0 +1,84 @@ + +import base64 +from typing import Optional,List +import uuid + +from fastapi import File, HTTPException, UploadFile, status +from pydantic import Json +import structlog +from sqlalchemy.orm import Session + + +from src.bookmyvenue.models.common import Venue +from src.bookmyvenue.schema.common.common import ImageKitVenueUrls, VenueSchema +from src.bookmyvenue.models.owners import Owner +from src.bookmyvenue.models.user import User +from src.bookmyvenue.repositories.users.repository import userRepository +from src.bookmyvenue.repositories.owner.repository import ownerRepository +from src.bookmyvenue.schema.user import user +from src.bookmyvenue.schema.owner import owner +from src.bookmyvenue.BackgroundWorker.Owner.tasks import upload_media_to_imagekit + +logger = structlog.get_logger() + +class OwnerService: + + def get_owner_record(self, db:Session, current_user_id:str) -> Optional[Owner]: + owner_profile = ownerRepository.get_owner_record_by_ID(db, current_user_id) + if not owner_profile: + logger.info(f"Owner Profile Not Found!" , clerk_id=current_user_id) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,detail="Owner Profile not found!") + return owner_profile + + + def complete_owner_onboarding(self, db:Session, current_user_id:str, onboard:owner.OwnerOnboardingSchema) -> Owner: + logger.info("trying to onboard owner" , clerk_id = current_user_id) + current_user = userRepository.get_user_by_id(db, current_user_id) + if not current_user: + logger.error("user record not found" ,clerk_id=current_user_id) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,detail="user not found in DB") + owner_record = ownerRepository.get_owner_record_by_ID(db, current_user_id) + if owner_record: + logger.error("owner has already onboarded" ,clerk_id=current_user_id) + raise HTTPException(status_code=status.HTTP_201_CREATED,detail="Owner onboadred completed!") + + owner_record = ownerRepository.onboard_owner(db,current_user,onboard) + + return owner_record + + def create_new_venue(self, db:Session, owner_user:Owner,payload:Json[VenueSchema],cover_image: UploadFile = File(...), gallery: List[UploadFile] = File(...)) -> Venue: + #if a vnue with same name , city and same location exists alreday for the respective owner + + duplicate_checker = ownerRepository.duplicate_venue_checker(db=db, owner=owner_user, city=payload.city, street_address=payload.street_address, name=payload.name) + + venue_instance = ownerRepository.create_venue_record(db=db, owner=owner_user, payload=payload) + + if not venue_instance: + logger.error("cant create the venue for the owner" , ownerId = owner_user.id) + raise HTTPException( + status_code=status.HTTP_409_CONFLICT, + detail="cant able to create the venue for the given data" + ) + + cover_bytes = cover_image.file.read() + cover_base64 = base64.b64encode(cover_bytes).decode('utf-8') + + gallery_base64_list = [ + base64.b64encode(file.file.read()).decode('utf-8') for file in gallery + ] + + celery_queue_worker = upload_media_to_imagekit.delay(venue_instance.id, cover_base64, gallery_base64_list, venue_instance.name) + venue_instance.celery_task_ID = celery_queue_worker.id + db.commit() + db.refresh(venue_instance) + + return venue_instance + + + + + + + + +ownerservice = OwnerService() \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/services/userServices.py b/Backend/bookmyvenue/src/bookmyvenue/services/userServices.py new file mode 100644 index 000000000..c6dc76dbd --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/services/userServices.py @@ -0,0 +1,75 @@ +import uuid + +from fastapi import HTTPException +import structlog +from sqlalchemy.orm import Session + + +from src.bookmyvenue.models.user import User +from src.bookmyvenue.repositories.users.repository import userRepository +from src.bookmyvenue.schema.user import user + + +logger = structlog.get_logger() + +class UserService: + def register_user(self, db: Session, clerk_user: user.ClerkWebhookData) -> User: + + primary_email = None + for email_obj in clerk_user.email_addresses: + if email_obj.id == clerk_user.primary_email_address_id: + primary_email = email_obj.email_address + break + + # Fallback if primary ID matches nothing, grab the first available email + if not primary_email and clerk_user.email_addresses: + primary_email = clerk_user.email_addresses[0].email_address + + if not primary_email: + logger.error("user have no email address" , clerk_id=clerk_user.id) + raise ValueError(f"Clerk user {clerk_user.id} has no valid email address.") + + # 2. Check if the user already exists locally (idempotency check) + existing_user = userRepository.get_user_by_id(db=db, clerk_id=clerk_user.id) + + if existing_user: + logger.info("user with the given username or email exists" , clerk_id=clerk_user.id, email = primary_email) + raise HTTPException(status_code=409, detail=f"user with same ID exists") + + # 3. Formulate full name + first = clerk_user.first_name or "" + last = clerk_user.last_name or "" + username = clerk_user.username + fullname = f"{first} {last}".strip() or "Clerk User" + + if not username: + username = f"{primary_email.split('@')[0]}_{uuid.uuid4().hex[:4]}" + + new_user = userRepository.create_clerk_user( + db=db, + clerk_id=clerk_user.id, + email=primary_email.lower(), + fullname=fullname, + username=username + ) + + return new_user + + def delete_user(self, db: Session, clerk_user: user.ClerkWebhookData): + existing_user = userRepository.get_user_by_id(db=db, clerk_id=clerk_user.id) + + if not existing_user: + logger.info("user with the given username or email doent exists" , clerk_id=clerk_user.id) + raise HTTPException(status_code=409, detail=f"user with the given ID doesnt exist") + + return userRepository.detele_user(db, existing_user) + + + + def complete_user_onboarding(self, db:Session, current_user_id:str, phone:user.PhoneOnboardingSchema) -> User: + logger.info("trying to onboard user" , clerk_id = current_user_id) + updated_user = userRepository.update_user_onboarding(db=db,clerk_id=current_user_id,phone=phone) + return updated_user + + +userservice = UserService() \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/utils/__init__.py b/Backend/bookmyvenue/src/bookmyvenue/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Backend/bookmyvenue/src/bookmyvenue/utils/__pycache__/__init__.cpython-311.pyc b/Backend/bookmyvenue/src/bookmyvenue/utils/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8388cbc083c0de21d20b8922aea5419ebfda0285 GIT binary patch literal 207 zcmZ3^%ge<81fSCFvq1D?5CH>>P{wCAAY(d13PUi1CZpdI&j){-Y%*!l^kJl@x{Ka9Do1apelWJGQ3bYdBsA7H~@qw9cR?wK%&ZzaS$AImL2f9G7pz;@oO>TZlX-=wL z5iihAkl%}afW!x8Mn=XP44e&Mc!NRy0xJ5z#=s-eVR1u1asty7&I?io7X=Kj2pE1~ WX5wM`$N(h1fQSYT5G>*b8VCUIMs<$> literal 0 HcmV?d00001 diff --git a/Backend/bookmyvenue/src/bookmyvenue/utils/image_kit.py b/Backend/bookmyvenue/src/bookmyvenue/utils/image_kit.py new file mode 100644 index 000000000..112bd31ad --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/utils/image_kit.py @@ -0,0 +1,7 @@ +import os +from imagekitio import ImageKit + +#initializing the imageKit instance +imagekit = ImageKit( + private_key=os.getenv("IMAGEKIT_PRIVATE_KEY") +) \ No newline at end of file diff --git a/Backend/bookmyvenue/src/bookmyvenue/worker.py b/Backend/bookmyvenue/src/bookmyvenue/worker.py new file mode 100644 index 000000000..65923377e --- /dev/null +++ b/Backend/bookmyvenue/src/bookmyvenue/worker.py @@ -0,0 +1,24 @@ +import os +from celery import Celery +from src.bookmyvenue.core.config import settings + + +app = Celery( + app_name="bookmyvenue", + broker=os.environ.get("UPSTASH_REDIS_CELERY_URL"), + backend=settings.CELERY_RESULT_BACKEND +) + +#auto-discover is used to look into the tasks.py files present inside the src.bookmyvenue package which may contain many other sub modules. +app.autodiscover_tasks( + packages=['src.bookmyvenue.BackgroundWorker.Owner'] +) + +app.conf.update( + task_track_started=True, + task_serializer="json", + result_serializer="json", + accept_content=["json"], + broker_use_ssl={"ssl_cert_reqs": 0}, + redis_backend_use_ssl={"ssl_cert_reqs": 0}, +) \ No newline at end of file diff --git a/Frontend/bookmyvenue/.dockerignore b/Frontend/bookmyvenue/.dockerignore new file mode 100644 index 000000000..6650cbe8a --- /dev/null +++ b/Frontend/bookmyvenue/.dockerignore @@ -0,0 +1,43 @@ + + +# Next.js build output and cache +.next/ + +# Logs and OS files +npm-debug.log* +.DS_Store + +# Source Control +.git +.github +.gitignore + +# Dependencies (Let Docker install these inside the container) +node_modules/ +bower_components/ +vendor/ + +# Build Outputs +dist/ +build/ +out/ +*.exe +*.dll + +# Environment & Secrets +.env +.env.* +*.pem +*.key +aws_credentials + +# Debug & Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.logs/ +*.swp + +# OS Metadata +.DS_Store +Thumbs.db \ No newline at end of file diff --git a/Frontend/bookmyvenue/.gitignore b/Frontend/bookmyvenue/.gitignore new file mode 100644 index 000000000..f5ebfc60f --- /dev/null +++ b/Frontend/bookmyvenue/.gitignore @@ -0,0 +1,37 @@ +# dependencies +.env +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# env files +.env*.local + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/Frontend/bookmyvenue/.prettierignore b/Frontend/bookmyvenue/.prettierignore new file mode 100644 index 000000000..461b00841 --- /dev/null +++ b/Frontend/bookmyvenue/.prettierignore @@ -0,0 +1,7 @@ +dist/ +node_modules/ +.next/ +.turbo/ +coverage/ +pnpm-lock.yaml +.pnpm-store/ \ No newline at end of file diff --git a/Frontend/bookmyvenue/.prettierrc b/Frontend/bookmyvenue/.prettierrc new file mode 100644 index 000000000..a8a2054a1 --- /dev/null +++ b/Frontend/bookmyvenue/.prettierrc @@ -0,0 +1,11 @@ +{ + "endOfLine": "lf", + "semi": false, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "es5", + "printWidth": 80, + "plugins": ["prettier-plugin-tailwindcss"], + "tailwindStylesheet": "app/globals.css", + "tailwindFunctions": ["cn", "cva"] +} diff --git a/Frontend/bookmyvenue/README.md b/Frontend/bookmyvenue/README.md new file mode 100644 index 000000000..1e66186df --- /dev/null +++ b/Frontend/bookmyvenue/README.md @@ -0,0 +1,21 @@ +# Next.js template + +This is a Next.js template with shadcn/ui. + +## Adding components + +To add components to your app, run the following command: + +```bash +npx shadcn@latest add button +``` + +This will place the ui components in the `components` directory. + +## Using components + +To use the components in your app, import them as follows: + +```tsx +import { Button } from "@/components/ui/button"; +``` diff --git a/Frontend/bookmyvenue/app/(admin)/add/page.tsx b/Frontend/bookmyvenue/app/(admin)/add/page.tsx new file mode 100644 index 000000000..070353a61 --- /dev/null +++ b/Frontend/bookmyvenue/app/(admin)/add/page.tsx @@ -0,0 +1,241 @@ +"use client" +import React, { useState } from 'react' +import { Badge } from '@/components/ui/badge' +import { IconCategory, IconHeartPlus, IconIcons } from '@tabler/icons-react' +import { + InputGroup, + InputGroupAddon, + InputGroupButton, + InputGroupInput, + InputGroupText, + InputGroupTextarea, +} from "@/components/ui/input-group" +import { Label } from '@/components/ui/label' +import { Button } from '@/components/ui/button' +import { toast } from 'sonner' +import { useAuth } from '@clerk/nextjs' +import axios from 'axios' + + +interface categoriesProp { + name: string + icon_name: string +} + +interface Amenities { + name: string + icon_name: string +} + +function page() { + const [active, setActive] = useState('category') + const [name, setName] = useState("") + const [icon, setIcon] = useState("") + const [categories, setCategories] = useState([]) + const [amenities, setAmenities] = useState([]) + + const { getToken } = useAuth() + const HandleAddCategories = () => { + if (name == "" || icon == "") { + toast.info("add the required details") + } + else { + let cate = { + name: name, + icon_name: icon + } + + setCategories(prevCategories => [...prevCategories, cate]) + setName('') + setIcon('') + } + + } + + const HandleAddAmenities = () => { + if (name == "" || icon == "") { + toast.info("add the required details") + } + else { + let amenity = { + name: name, + icon_name: icon + } + + setAmenities(prevCategories => [...prevCategories, amenity]) + setName('') + setIcon('') + } + + } + + + const HandleCategorySubmisssion = async () => { + const jwtToken = await getToken() + axios.post(`${process.env.NEXT_PUBLIC_DOMAIN}/api/v1/admin/category`, { + category: categories + }, { + headers: { + // Headers are nested under the 'headers' key + authorization: `Bearer ${jwtToken}`, + 'Content-Type': 'application/json' + }, + }) + .then((res) => { + console.log(res) + if (res.data.status_code == 201) { + toast.success("successfully created the categories") + } + + setCategories([]) + }) + .catch((err) => { + console.log(err.response.data) + if (err.response.data.status_code == 400) { + toast.error(err.response.data.message) + } + }) + } + + const HandleAmenitySubmisssion = async () => { + const jwtToken = await getToken() + axios.post(`${process.env.NEXT_PUBLIC_DOMAIN}/api/v1/admin/amenity`, { + amenity: amenities + }, { + headers: { + // Headers are nested under the 'headers' key + authorization: `Bearer ${jwtToken}`, + 'Content-Type': 'application/json' + }, + }) + .then((res) => { + console.log(res) + if (res.data.status_code == 201) { + toast.success("successfully created the amenities") + } + + setCategories([]) + }) + .catch((err) => { + console.log(err.response.data) + if (err.response.data.status_code == 400) { + toast.error(err.response.data.message) + } + }) + } + + return ( +

+
+
+

Admin Control Panel

+

create the categories and amenities that servers the venues

+
+ Admin Panel +
+
+
{ + setName('') + setIcon('') + setActive('category') + }}> + + Add Category +
+
{ + setName('') + setIcon('') + setActive('amenity') + }}> + + Add amenity +
+
+ { + active == 'category' ? ( +
+
+ + { + setName(e.target.value) + }} /> + + + + +
+
+ + { + setIcon(e.target.value) + }} /> + + + + + +
+
+ { + categories.map(category => { + return ( + + {category.name} + + ) + }) + } +
+
+ + +
+
+ ) : ( +
+
+ + { + setName(e.target.value) + }} /> + + + + +
+
+ + { + setIcon(e.target.value) + }} /> + + + + + +
+
+ { + amenities.map(amenity => { + return ( + + {amenity.name} + + ) + }) + } +
+
+ + +
+
+ ) + } + + +
+ ) +} + +export default page \ No newline at end of file diff --git a/Frontend/bookmyvenue/app/(admin)/allTransactions/page.tsx b/Frontend/bookmyvenue/app/(admin)/allTransactions/page.tsx new file mode 100644 index 000000000..2d7909a68 --- /dev/null +++ b/Frontend/bookmyvenue/app/(admin)/allTransactions/page.tsx @@ -0,0 +1,174 @@ +import { Badge } from '@/components/ui/badge' +import React from 'react' +import { + Table, + TableBody, + TableCaption, + TableCell, + TableFooter, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table" +import { IconBuilding, IconCashBanknoteHeart, IconCashBanknoteMinus, IconCategoryMinus, IconTicket, IconUser } from '@tabler/icons-react' +import { Button } from '@/components/ui/button' +import { Alert } from '@/components/ui/alert' + +const invoices = [ + { + invoice: "INV001", + guest: "john Deo", + owner: "ziyau", + type: "Refund", + totalAmount: "$250.00", + refundAmount: "$34.00", + commision: "$5.00", + paymentMethod: "Dodo Payments", + confrormTicket: "kjgg", + }, + { + invoice: "INV002", + guest: "john Deo", + owner: "ziyau", + type: "Refund", + totalAmount: "$250.00", + refundAmount: "$34.00", + commision: "$5.00", + paymentMethod: "Dodo Payments", + confrormTicket: "kjgg", + }, + { + invoice: "INV003", + guest: "john Deo", + owner: "ziyau", + type: "Refund", + totalAmount: "$250.00", + refundAmount: "-", + commision: "$5.00", + paymentMethod: "Dodo Payments", + confrormTicket: "kjgg", + }, + { + invoice: "INV004", + guest: "john Deo", + owner: "ziyau", + type: "Refund", + totalAmount: "$250.00", + refundAmount: "$34.00", + commision: "$5.00", + paymentMethod: "Dodo Payments", + confrormTicket: "kjgg", + }, + { + invoice: "INV005", + guest: "john Deo", + owner: "ziyau", + type: "Refund", + totalAmount: "$250.00", + refundAmount: "$34.00", + commision: "$5.00", + paymentMethod: "Dodo Payments", + confrormTicket: "kjgg", + }, + { + invoice: "INV006", + guest: "john Deo", + owner: "ziyau", + type: "Refund", + totalAmount: "$250.00", + refundAmount: "$34.00", + commision: "-", + paymentMethod: "Dodo Payments", + confrormTicket: "kjgg", + }, + { + invoice: "INV007", + guest: "john Deo", + owner: "ziyau", + type: "Refund", + totalAmount: "$250.00", + refundAmount: "-", + commision: "$5.00", + paymentMethod: "Dodo Payments", + confrormTicket: "kjgg", + }, +] + + +function page() { + return ( +
+
+
+

Transactions Through BMV

+

Track the transactions and revenue generations

+
+ 1202 transactions +
+
+ + A list of your recent invoices. + + + Invoice + +
+ Guest +
+
+ +
+ Owner +
+
+ +
+ Type +
+
+ +
+ Amount Paid +
+
+ +
+ + + Refund Amount +
+
+ +
+ + + Confirmation +
+
+ Commision +
+
+ + {invoices.map((invoice) => ( + + {invoice.invoice} + {invoice.guest} + {invoice.owner} + {invoice.type} + {invoice.totalAmount} + {invoice.refundAmount} + + Confirmation Ticket + + {invoice.commision} + + ))} + + +
+
+
+ ) +} + +export default page \ No newline at end of file diff --git a/Frontend/bookmyvenue/app/(admin)/allUsers/page.tsx b/Frontend/bookmyvenue/app/(admin)/allUsers/page.tsx new file mode 100644 index 000000000..0674ff493 --- /dev/null +++ b/Frontend/bookmyvenue/app/(admin)/allUsers/page.tsx @@ -0,0 +1,147 @@ +'use client' +import { Badge } from '@/components/ui/badge' +import { Button } from '@/components/ui/button' +import { IconUserCancel, IconUserDown, IconUsers, IconSearch, IconUser, IconBuilding, IconTicket } from '@tabler/icons-react' +import React, { useState } from 'react' +import { + InputGroup, + InputGroupAddon, + InputGroupButton, + InputGroupInput, + InputGroupText, + InputGroupTextarea, +} from "@/components/ui/input-group" +function page() { + const [searchQuery, setSearchQuery] = useState('') + + return ( +
+
+
+ + + + + + +
+
+
+
+

All The Users Signed Through BMV

+ 144 users +
+
+
+ All + Users + Owners +
+ +
+
+
+
+ +
+
+

Ziyaudheen MS

+
BMV Guest
+

since 3 years

+
+
+ + +
+
+
+
+ +
+
+

Ziyaudheen MS

+
BMV Guest
+

since 3 years

+
+
+ + +
+
+
+
+ +
+
+

Ziyaudheen MS

+
BMV Guest
+

since 3 years

+
+
+ + +
+
+
+
+ +
+
+

Ziyaudheen MS

+
BMV Guest
+

since 3 years

+
+
+ + +
+
+
+
+ +
+
+

Ziyaudheen MS

+
BMV Guest
+

since 3 years

+
+
+ + +
+
+
+
+ +
+
+

Ziyaudheen MS

+
BMV Guest
+

since 3 years

+
+
+ + +
+
+
+
+ +
+
+

Ziyaudheen MS

+
BMV Guest
+

since 3 years

+
+
+ + +
+
+
+
+
+ ) +} + +export default page \ No newline at end of file diff --git a/Frontend/bookmyvenue/app/(admin)/allVenues/page.tsx b/Frontend/bookmyvenue/app/(admin)/allVenues/page.tsx new file mode 100644 index 000000000..b035872b2 --- /dev/null +++ b/Frontend/bookmyvenue/app/(admin)/allVenues/page.tsx @@ -0,0 +1,112 @@ +'use client' +import { Badge } from '@/components/ui/badge' +import { Button } from '@/components/ui/button' +import { IconUserCancel, IconUserDown, IconUsers, IconSearch, IconUser, IconBuilding, IconTicket, IconX, IconStarFilled } from '@tabler/icons-react' +import React, { useState } from 'react' +import { + InputGroup, + InputGroupAddon, + InputGroupButton, + InputGroupInput, + InputGroupText, + InputGroupTextarea, +} from "@/components/ui/input-group" +import { Filters } from '@/components/filters' +import { Card, CardHeader } from '@/components/ui/card' +import Image from 'next/image' +import { VenueLister } from '@/components/venueLister' +function page() { + const [searchQuery, setSearchQuery] = useState('') + const [rating, setRating] = useState(0) + return ( +
+
+
+ + + + + + + +
+ +
+
+
+

All The Venues Listed

+ 144 venues +
+ +
+
+ All + Approved + Waiting +
+
+ {Array.from({ length: 5 }, (_, index) => { + const starValue = index + 1 + return ( + + ) + })} +
+
+ + +
+
+ ) +} + +export default page \ No newline at end of file diff --git a/Frontend/bookmyvenue/app/(admin)/bookmyvenue/page.tsx b/Frontend/bookmyvenue/app/(admin)/bookmyvenue/page.tsx new file mode 100644 index 000000000..2f94b583a --- /dev/null +++ b/Frontend/bookmyvenue/app/(admin)/bookmyvenue/page.tsx @@ -0,0 +1,584 @@ +'use client' + +import React, { useState } from 'react' +import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card" +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import { + IconBuilding, + IconCash, + IconClock, + IconCheck, + IconStarFilled, + IconCalendar, + IconTrendingUp, + IconUsers, + IconArrowUpRight, + IconChevronRight, + IconSearch, + IconMapPin, + IconCreditCard, + IconPlus, + IconAlertCircle, + IconHistory, + IconUser, + IconSquareRoundedCheckFilled +} from '@tabler/icons-react' +import { VenueLister } from '@/components/venueLister' +import { UpComing } from '@/components/upComing' +import { Review } from '@/components/review' +import { Cancel } from '@/components/cancel' +import { Reject } from '@/components/reject' + +// --- Mock Data --- + +const MOCK_LISTED_VENUES = [ + { + id: 101, + name: "Al Saj Convention Center (Arena)", + location: "Kazhakkoottam, Trivandrum", + rating: 4.5, + cats: ["Wedding", "Conference", "Exhibition"], + image: "https://www.alsajconventioncenter.com/wp-content/uploads/2023/07/Arena.png", + status: "Active", + bookingsThisMonth: 14, + revenueThisMonth: 12400, + revenueThisYear: 88000, + }, + { + id: 102, + name: "Grand Palace Orchid Gardens", + location: "Nemom, Trivandrum", + rating: 4.2, + cats: ["Birthday", "Workshop", "Meetup"], + image: "https://images.unsplash.com/photo-1519167758481-83f550bb49b3?auto=format&fit=crop&q=80&w=600", + status: "Active", + bookingsThisMonth: 8, + revenueThisMonth: 7200, + revenueThisYear: 45000, + }, + { + id: 103, + name: "Whispering Palms Resort Hall", + location: "Varkala Beach, Trivandrum", + rating: 4.7, + cats: ["Wedding", "Party", "Conference"], + image: "https://images.unsplash.com/photo-1542314831-068cd1dbfeeb?auto=format&fit=crop&q=80&w=600", + status: "Active", + bookingsThisMonth: 12, + revenueThisMonth: 9500, + revenueThisYear: 68000, + }, + { + id: 104, + name: "Lakeside Open Turf & Banquet", + location: "Akkulam, Trivandrum", + rating: 4.6, + cats: ["Sport", "Birthday", "Meetup"], + image: "https://images.unsplash.com/photo-1527529482837-4698179dc6ce?auto=format&fit=crop&q=80&w=600", + status: "Active", + bookingsThisMonth: 18, + revenueThisMonth: 5800, + revenueThisYear: 39000, + } +]; + +const MOCK_PENDING_APPROVAL_VENUES = [ + { + id: 201, + name: "Golden Pavilion Banquet Hall", + location: "Pattom, Trivandrum", + cats: ["Wedding", "Conference"], + submissionDate: "2026-05-28", + status: "Document Verification", + completionPercentage: 65, + notes: "Awaiting verification of the local building license certificate." + }, + { + id: 202, + name: "The Hive Rooftop & Cafe Workspace", + location: "Vazhuthacaud, Trivandrum", + cats: ["Workshop", "Meetup"], + submissionDate: "2026-06-02", + status: "Physical Inspection", + completionPercentage: 35, + notes: "Site inspection scheduled for tomorrow at 11:00 AM." + }, + { + id: 203, + name: "Coral Cove Beachfront Gardens", + location: "Kovalam, Trivandrum", + cats: ["Wedding", "Party"], + submissionDate: "2026-06-03", + status: "Admin Approval Sign-off", + completionPercentage: 90, + notes: "Inspection passed. Final approval from regional lead pending." + } +]; + +// Graph mock data matching filters +const MONTH_DATA = [ + { label: "W1", amount: 6200 }, + { label: "W2", amount: 8400 }, + { label: "W3", amount: 11200 }, + { label: "W4", amount: 9100 }, +]; + +const YEAR_DATA = [ + { label: "Jan", amount: 18000 }, + { label: "Feb", amount: 22000 }, + { label: "Mar", amount: 25000 }, + { label: "Apr", amount: 29000 }, + { label: "May", amount: 34900 }, + { label: "Jun", amount: 41000 }, + { label: "Jul", amount: 38000 }, + { label: "Aug", amount: 45000 }, + { label: "Sep", amount: 49000 }, + { label: "Oct", amount: 56000 }, + { label: "Nov", amount: 52000 }, + { label: "Dec", amount: 68000 }, +]; + +function Page() { + const [timeFilter, setTimeFilter] = useState<'month' | 'year'>('month'); + const [hoveredPoint, setHoveredPoint] = useState<{ index: number; x: number; y: number } | null>(null); + + // Derive stats based on filter + const totalListedVenues = MOCK_LISTED_VENUES.length; + const pendingApprovalsCount = MOCK_PENDING_APPROVAL_VENUES.length; + + const totalMoney = timeFilter === 'month' + ? MOCK_LISTED_VENUES.reduce((acc, curr) => acc + curr.revenueThisMonth, 0) + : MOCK_LISTED_VENUES.reduce((acc, curr) => acc + curr.revenueThisYear, 0); + + const totalBookings = timeFilter === 'month' + ? MOCK_LISTED_VENUES.reduce((acc, curr) => acc + curr.bookingsThisMonth, 0) + : MOCK_LISTED_VENUES.reduce((acc, curr) => acc + (curr.bookingsThisMonth * 10), 0); // Mock year bookings + + const graphData = timeFilter === 'month' ? MONTH_DATA : YEAR_DATA; + + // SVG Chart Config + const chartHeight = 220; + const chartWidth = 720; + const paddingX = 40; + const paddingY = 30; + + const maxVal = Math.max(...graphData.map(d => d.amount)) * 1.1; // 10% headroom + const minVal = 0; + + // Calculate coordinates + const points = graphData.map((d, index) => { + const x = paddingX + (index / (graphData.length - 1)) * (chartWidth - paddingX * 2); + const y = chartHeight - paddingY - ((d.amount - minVal) / (maxVal - minVal)) * (chartHeight - paddingY * 2); + return { x, y, label: d.label, amount: d.amount }; + }); + + // SVG path definitions + const linePath = points.length > 0 + ? points.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`).join(' ') + : ''; + + const areaPath = points.length > 0 + ? `${linePath} L ${points[points.length - 1].x} ${chartHeight - paddingY} L ${points[0].x} ${chartHeight - paddingY} Z` + : ''; + + return ( +
+ + {/* Header and Filter bar */} +
+
+

+ Admin Panel +

+

+ Manage your venues, monitor bookings, trace the financial trajectory and feel the beat of BMV +

+
+ +
+ + {/* Stats Cards Section */} +
+ {/* Total Money Card */} + +
+ + No Of Venues Listed +
+ +
+
+ +
+ ${totalMoney.toLocaleString('en-US', { minimumFractionDigits: 0 })} +
+
+ + +12.4% + + + vs last {timeFilter === 'month' ? 'month' : 'year'} + +
+
+
+ + {/* Listed Venues Card */} + +
+ + Users Registered Through BMV +
+ +
+
+ +
+ {totalListedVenues} +
+

+ 34 owners and 290 guests. +

+
+
+ + {/* Bookings Card */} + +
+ + Transactions Through BMV +
+ +
+
+ +
+ {totalBookings} +
+
+ + 5% + + + commision fees + +
+
+
+ + {/* Pending Approvals Card */} + +
+ + {/* Trajectory Graph & Approval Queue section */} +
+ + {/* Trajectory Graph Container (2 Cols) */} +
+ + +
+
+ Transaction Trajectory + Visualizing revenue flows and scaling trends +
+ + Active Flow + +
+
+ + + {/* Custom SVG Line Chart */} +
+ + + {/* Shadow / Area gradient */} + + + + + + + {/* Horizontal grid lines */} + {[0, 0.25, 0.5, 0.75, 1].map((ratio, i) => { + const y = paddingY + ratio * (chartHeight - paddingY * 2); + const val = maxVal - ratio * (maxVal - minVal); + return ( + + + + ${Math.round(val).toLocaleString()} + + + ); + })} + + {/* Area fill */} + {points.length > 0 && ( + + )} + + {/* Line stroke */} + {points.length > 0 && ( + + )} + + {/* Axis labels & interactive markers */} + {points.map((p, index) => { + const isHovered = hoveredPoint?.index === index; + return ( + + {/* Vertical highlight line on hover */} + {isHovered && ( + + )} + + {/* X Axis labels */} + + {p.label} + + + {/* Data point circle */} + + + ); + })} + + {/* Invisible broad hover columns for smooth interactivity */} + {points.map((p, index) => { + const widthPerCol = (chartWidth - paddingX * 2) / (points.length - 1 || 1); + const rectX = p.x - widthPerCol / 2; + return ( + setHoveredPoint({ index, x: p.x, y: p.y })} + onMouseLeave={() => setHoveredPoint(null)} + /> + ); + })} + +
+ + {/* Floating Tooltip details */} +
+ {hoveredPoint ? ( +
+ {points[hoveredPoint.index].label}: + ${points[hoveredPoint.index].amount.toLocaleString()} +
+ ) : ( + + Hover over data points to inspect detailed value logs + + )} +
+ +
+
+
+ + {/* Approval Queue Section (1 Col) */} + +
+ + Revenue Made By BMV +
+ +
+
+ +
+ {totalBookings} +
+
+ + 5% + + + commision fees + +
+
+
+ +
+ + {/* Existing Listed Venues Section */} +
+
+
+

+ Venues Waiting Approval +

+

Go through the venues , approve them and earn through it.

+
+ + {totalListedVenues} Total + +
+ +
+
+
+
+
+
+ +
+
+ +
+

Al Saj Arena, nemom, tvm, kerala

+

ziya123@gmail.com

+ +
+
+
+
+ + +
+
+
+
+
+ +
+
+ +
+

Al Saj Arena, nemom, tvm, kerala

+

ziya123@gmail.com

+ +
+
+
+
+ + +
+
+
+
+
+ +
+
+ +
+

Al Saj Arena, nemom, tvm, kerala

+

ziya123@gmail.com

+ +
+
+
+
+ + +
+
+
+
+
+ +
+
+ +
+

Al Saj Arena, nemom, tvm, kerala

+

ziya123@gmail.com

+ +
+
+
+
+ + +
+
+
+
+
+ +
+
+ +
+

Al Saj Arena, nemom, tvm, kerala

+

ziya123@gmail.com

+ +
+
+
+
+ + +
+
+
+ + +
+
+
+
+ ); +} + +export default Page \ No newline at end of file diff --git a/Frontend/bookmyvenue/app/(admin)/layout.tsx b/Frontend/bookmyvenue/app/(admin)/layout.tsx new file mode 100644 index 000000000..db9882857 --- /dev/null +++ b/Frontend/bookmyvenue/app/(admin)/layout.tsx @@ -0,0 +1,37 @@ +import { Geist, Geist_Mono, Figtree, Roboto } from "next/font/google" + +import "../globals.css" +import { ThemeProvider } from "@/components/theme-provider" +import { cn } from "@/lib/utils"; +import { Footer } from "@/components/Footer"; +import { Navbar } from "@/components/ui/navbar"; + +const robotoHeading = Roboto({subsets:['latin'],variable:'--font-heading'}); + +const figtree = Figtree({subsets:['latin'],variable:'--font-sans'}) + +const fontMono = Geist_Mono({ + subsets: ["latin"], + variable: "--font-mono", +}) + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode +}>) { + return ( + + + + + {children} + + + + ) +} diff --git a/Frontend/bookmyvenue/app/(auth)/complete-onboarding/page.tsx b/Frontend/bookmyvenue/app/(auth)/complete-onboarding/page.tsx new file mode 100644 index 000000000..f208e0a06 --- /dev/null +++ b/Frontend/bookmyvenue/app/(auth)/complete-onboarding/page.tsx @@ -0,0 +1,91 @@ +"use client" +import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' +import { Navbar } from '@/components/ui/navbar' +import { IconCompassFilled, IconDashboard, IconPhone } from '@tabler/icons-react' +import { useAuth } from '@clerk/nextjs' +import React, { useState } from 'react' +import axios from 'axios' +import { toast } from 'sonner' +import { Spinner } from '@/components/ui/spinner' +import { useRouter } from 'next/navigation' + +function page() { + + const router = useRouter() + const [phone, setPhone] = useState('') + const { getToken } = useAuth() + const [loading ,setLoading] =useState(false) + const HandleUserOnboarding = async () => { + setLoading(true) + console.log("uploading.........") + const jwtToken = await getToken() + axios + .post(`${process.env.NEXT_PUBLIC_DOMAIN}/api/v1/user/onboarding`, { + phone: phone, + }, { + headers: { + // Headers are nested under the 'headers' key + authorization: `Bearer ${jwtToken}`, + 'Content-Type': 'application/json' + }, + }) + .then((res) => { + console.log(res) + if (res.data.status_code == 200) { + toast.success("completed the owner onboarding...") + router.push('/') + } + if (res.data.status_code == 201) { + toast.success("you have onboarded already!") + router.push('/') + } + }) + .catch((err) => { + console.log(err.response.data) //contains the details of the error + if (err.response && err.response.status === 404) { + toast.info(err.response.message) + } + if (err.response && err.response.status === 403) { + // toast.info(err.response.data) + } + }) + .finally(() => { + setLoading(false) + }) + + } + + + + return ( +
+ +

Complete Your Onboadring

+

Experience the smoothness we BMV offers!

+
+
+

Phone Number

+ setPhone(e.target.value)} /> +

We collect your numbers just for the onboarding process and will not use it for any personal data leakage problems and will only share it with the venued where you have booked

+
+
+ +
+ +
+
+ ) +} + +export default page \ No newline at end of file diff --git a/Frontend/bookmyvenue/app/(auth)/owner-onboarding/page.tsx b/Frontend/bookmyvenue/app/(auth)/owner-onboarding/page.tsx new file mode 100644 index 000000000..e322f52d7 --- /dev/null +++ b/Frontend/bookmyvenue/app/(auth)/owner-onboarding/page.tsx @@ -0,0 +1,166 @@ +"use client" +import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' +import { IconBriefcase, IconBuilding, IconCompassFilled, IconHeart, IconSpeakerphone } from '@tabler/icons-react' +import React, { useEffect, useState } from 'react' +import { useAuth } from '@clerk/nextjs' +import axios from 'axios' +import { toast } from 'sonner' +import { Spinner } from "@/components/ui/spinner" +import { useRouter } from 'next/navigation' +function page() { + const router = useRouter() + const [org, setOrg] = useState("") + const [profession, setProfession] = useState("") + const [promise, setPromise] = useState("") + const [info, setInfo] = useState("") + const { getToken } = useAuth() + const [loading, setLoading] = useState(false) + const [checking, setChecking] = useState(false) + + + const checkOwnerStaus = async () => { + setChecking(true) + const jwtToken = await getToken() + axios + .get(`${process.env.NEXT_PUBLIC_DOMAIN}/api/v1/owner/check`, { + headers: { + // Headers are nested under the 'headers' key + authorization: `Bearer ${jwtToken}`, + 'Content-Type': 'application/json' + }, + }) + .then((res) => { + console.log(res) + if (res.data.status_code == 200) { + toast.success("Owner has onboarded!...") + router.push('/dashboard') + } + if (res.data.status_code == 201) { + toast.success("you have onboarded already!") + router.push('/dashboard') + } + }) + .catch((err) => { + console.log(err) + if (err.response && err.response.status_code === 404) { + toast.info(err.response.message) + } + }) + .finally(() => { + setChecking(false) + }) + } + + + const handleOnBoarding = async () => { + setLoading(true) + console.log("uploading.........") + const jwtToken = await getToken() + axios + .post(`${process.env.NEXT_PUBLIC_DOMAIN}/api/v1/owner/onboarding`, { + organization: org, + profession: profession, + promise: promise, + self_info: info + }, { + headers: { + // Headers are nested under the 'headers' key + authorization: `Bearer ${jwtToken}`, + 'Content-Type': 'application/json' + }, + }) + .then((res) => { + console.log(res) + if (res.data.status_code == 200) { + toast.success("completed the owner onboarding...") + router.push('/dashboard') + } + if (res.data.status_code == 201) { + toast.success("you have onboarded already!") + router.push('/dashboard') + } + }) + .catch((err) => { + console.log(err) + if (err.response && err.response.status_code === 404) { + toast.info(err.response.message) + router.push('/') + } + }) + .finally(() => { + setLoading(false) + }) + + } + + + useEffect(() => { + checkOwnerStaus() + }, []) + + + if (checking) { + return ( +
+
+ +

Checking Owner Profile

+

Please wait while we verify your owner status...

+
+
+ ) + } + + + return ( + <> +
+
+

Become An Owner

+

Get Your Venues Listed , Start Earning As a Owner

+
+
+

Name Of The Organization

+ setOrg(e.target.value)} /> +
+
+

Your Profession

+ setProfession(e.target.value)} /> +
+
+

Your Guarenty For Guests

+ setPromise(e.target.value)} /> +

Lets guests find it secure , express what your organization can do for them and will ensure them

+
+
+

Share Who You Are

+ +
+
+
+ + + + + + + + + ) +} + +export { Offline } \ No newline at end of file diff --git a/Frontend/bookmyvenue/components/payment.tsx b/Frontend/bookmyvenue/components/payment.tsx new file mode 100644 index 000000000..2564f6594 --- /dev/null +++ b/Frontend/bookmyvenue/components/payment.tsx @@ -0,0 +1,51 @@ +import { IconCash } from '@tabler/icons-react' +import React from 'react' +import { Button } from './ui/button' +import Image from 'next/image' + +function Payment() { + return ( +
+
+
+

Payment Details

+

Detailed calculation of what we charge you and what you pay for

+
+
+
Rent For One Hour :
+

$10.00

+
+
+
Platform Charge :
+

$3.00

+
+
+
GST :
+

$4.00

+
+
+
Total Rent (4 hours):
+

$40.00

+
+
+
Total Price:
+

$57.00

+
+
+
+
+
+ Payment +

Pay It With 100% Security!

+

BMV have a secured payment gateway, pay it, experience the moment

+
+
+
+
+ +
+
+ ) +} + +export { Payment } \ No newline at end of file diff --git a/Frontend/bookmyvenue/components/priceManager.tsx b/Frontend/bookmyvenue/components/priceManager.tsx new file mode 100644 index 000000000..ef22b2796 --- /dev/null +++ b/Frontend/bookmyvenue/components/priceManager.tsx @@ -0,0 +1,130 @@ +import React from 'react' +import { InputGroup, InputGroupAddon, InputGroupInput } from './ui/input-group' +import { IconBriefcase, IconCash, IconPlus, IconX } from '@tabler/icons-react' +import { Button } from './ui/button' +import { Badge } from './ui/badge' +import { Seasonal } from './seasonal' +import { Weekly } from './weekly' + +function PriceManager() { + return ( +
+
+

Standerd rent

+ + + + + + +
+
+
+

Seasonal Pay

+ +
+
+
+

Onam

+ 22-05-2026 to 05-06-2026 +
+
+ + + + + + + +
+
+
+
+

Onam

+ 22-05-2026 to 05-06-2026 +
+
+ + + + + + + +
+
+
+
+

Onam

+ 22-05-2026 to 05-06-2026 +
+
+ + + + + + + +
+
+
+
+
+

Weekly Pay

+ +
+
+
+

Saturday

+ +
+
+ + + + + + + +
+
+
+
+

Sunday

+ +
+
+ + + + + + + +
+
+
+ +
+ ) +} + +export { PriceManager } \ No newline at end of file diff --git a/Frontend/bookmyvenue/components/reject.tsx b/Frontend/bookmyvenue/components/reject.tsx new file mode 100644 index 000000000..76685cecf --- /dev/null +++ b/Frontend/bookmyvenue/components/reject.tsx @@ -0,0 +1,51 @@ +import React from 'react' +import { Button } from "@/components/ui/button" +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" + +import { IconCash, IconCross, IconLocationCheck, IconWriting, IconX } from '@tabler/icons-react' +import { Input } from './ui/input' +import { PaymentCancellation } from './PaymentCancellation' +function Reject() { + return ( + +
+ + + + + + This Venue Has Rejected + + + Share Why This venue failed to showcase. + +
+
+
What made as to take this call :
+ +
+
+ + + + + + + +
+ +
+
+ ) +} + +export {Reject} \ No newline at end of file diff --git a/Frontend/bookmyvenue/components/revenueGraph.tsx b/Frontend/bookmyvenue/components/revenueGraph.tsx new file mode 100644 index 000000000..41066d182 --- /dev/null +++ b/Frontend/bookmyvenue/components/revenueGraph.tsx @@ -0,0 +1,227 @@ +"use client" + +import * as React from "react" +import { CartesianGrid, Line, LineChart, XAxis } from "recharts" + +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card" +import { + ChartContainer, + ChartTooltip, + ChartTooltipContent, + type ChartConfig, +} from "@/components/ui/chart" + +export const description = "An interactive line chart" + +const chartData = [ + { date: "2024-04-01", desktop: 222, mobile: 150 }, + { date: "2024-04-02", desktop: 97, mobile: 180 }, + { date: "2024-04-03", desktop: 167, mobile: 120 }, + { date: "2024-04-04", desktop: 242, mobile: 260 }, + { date: "2024-04-05", desktop: 373, mobile: 290 }, + { date: "2024-04-06", desktop: 301, mobile: 340 }, + { date: "2024-04-07", desktop: 245, mobile: 180 }, + { date: "2024-04-08", desktop: 409, mobile: 320 }, + { date: "2024-04-09", desktop: 59, mobile: 110 }, + { date: "2024-04-10", desktop: 261, mobile: 190 }, + { date: "2024-04-11", desktop: 327, mobile: 350 }, + { date: "2024-04-12", desktop: 292, mobile: 210 }, + { date: "2024-04-13", desktop: 342, mobile: 380 }, + { date: "2024-04-14", desktop: 137, mobile: 220 }, + { date: "2024-04-15", desktop: 120, mobile: 170 }, + { date: "2024-04-16", desktop: 138, mobile: 190 }, + { date: "2024-04-17", desktop: 446, mobile: 360 }, + { date: "2024-04-18", desktop: 364, mobile: 410 }, + { date: "2024-04-19", desktop: 243, mobile: 180 }, + { date: "2024-04-20", desktop: 89, mobile: 150 }, + { date: "2024-04-21", desktop: 137, mobile: 200 }, + { date: "2024-04-22", desktop: 224, mobile: 170 }, + { date: "2024-04-23", desktop: 138, mobile: 230 }, + { date: "2024-04-24", desktop: 387, mobile: 290 }, + { date: "2024-04-25", desktop: 215, mobile: 250 }, + { date: "2024-04-26", desktop: 75, mobile: 130 }, + { date: "2024-04-27", desktop: 383, mobile: 420 }, + { date: "2024-04-28", desktop: 122, mobile: 180 }, + { date: "2024-04-29", desktop: 315, mobile: 240 }, + { date: "2024-04-30", desktop: 454, mobile: 380 }, + { date: "2024-05-01", desktop: 165, mobile: 220 }, + { date: "2024-05-02", desktop: 293, mobile: 310 }, + { date: "2024-05-03", desktop: 247, mobile: 190 }, + { date: "2024-05-04", desktop: 385, mobile: 420 }, + { date: "2024-05-05", desktop: 481, mobile: 390 }, + { date: "2024-05-06", desktop: 498, mobile: 520 }, + { date: "2024-05-07", desktop: 388, mobile: 300 }, + { date: "2024-05-08", desktop: 149, mobile: 210 }, + { date: "2024-05-09", desktop: 227, mobile: 180 }, + { date: "2024-05-10", desktop: 293, mobile: 330 }, + { date: "2024-05-11", desktop: 335, mobile: 270 }, + { date: "2024-05-12", desktop: 197, mobile: 240 }, + { date: "2024-05-13", desktop: 197, mobile: 160 }, + { date: "2024-05-14", desktop: 448, mobile: 490 }, + { date: "2024-05-15", desktop: 473, mobile: 380 }, + { date: "2024-05-16", desktop: 338, mobile: 400 }, + { date: "2024-05-17", desktop: 499, mobile: 420 }, + { date: "2024-05-18", desktop: 315, mobile: 350 }, + { date: "2024-05-19", desktop: 235, mobile: 180 }, + { date: "2024-05-20", desktop: 177, mobile: 230 }, + { date: "2024-05-21", desktop: 82, mobile: 140 }, + { date: "2024-05-22", desktop: 81, mobile: 120 }, + { date: "2024-05-23", desktop: 252, mobile: 290 }, + { date: "2024-05-24", desktop: 294, mobile: 220 }, + { date: "2024-05-25", desktop: 201, mobile: 250 }, + { date: "2024-05-26", desktop: 213, mobile: 170 }, + { date: "2024-05-27", desktop: 420, mobile: 460 }, + { date: "2024-05-28", desktop: 233, mobile: 190 }, + { date: "2024-05-29", desktop: 78, mobile: 130 }, + { date: "2024-05-30", desktop: 340, mobile: 280 }, + { date: "2024-05-31", desktop: 178, mobile: 230 }, + { date: "2024-06-01", desktop: 178, mobile: 200 }, + { date: "2024-06-02", desktop: 470, mobile: 410 }, + { date: "2024-06-03", desktop: 103, mobile: 160 }, + { date: "2024-06-04", desktop: 439, mobile: 380 }, + { date: "2024-06-05", desktop: 88, mobile: 140 }, + { date: "2024-06-06", desktop: 294, mobile: 250 }, + { date: "2024-06-07", desktop: 323, mobile: 370 }, + { date: "2024-06-08", desktop: 385, mobile: 320 }, + { date: "2024-06-09", desktop: 438, mobile: 480 }, + { date: "2024-06-10", desktop: 155, mobile: 200 }, + { date: "2024-06-11", desktop: 92, mobile: 150 }, + { date: "2024-06-12", desktop: 492, mobile: 420 }, + { date: "2024-06-13", desktop: 81, mobile: 130 }, + { date: "2024-06-14", desktop: 426, mobile: 380 }, + { date: "2024-06-15", desktop: 307, mobile: 350 }, + { date: "2024-06-16", desktop: 371, mobile: 310 }, + { date: "2024-06-17", desktop: 475, mobile: 520 }, + { date: "2024-06-18", desktop: 107, mobile: 170 }, + { date: "2024-06-19", desktop: 341, mobile: 290 }, + { date: "2024-06-20", desktop: 408, mobile: 450 }, + { date: "2024-06-21", desktop: 169, mobile: 210 }, + { date: "2024-06-22", desktop: 317, mobile: 270 }, + { date: "2024-06-23", desktop: 480, mobile: 530 }, + { date: "2024-06-24", desktop: 132, mobile: 180 }, + { date: "2024-06-25", desktop: 141, mobile: 190 }, + { date: "2024-06-26", desktop: 434, mobile: 380 }, + { date: "2024-06-27", desktop: 448, mobile: 490 }, + { date: "2024-06-28", desktop: 149, mobile: 200 }, + { date: "2024-06-29", desktop: 103, mobile: 160 }, + { date: "2024-06-30", desktop: 446, mobile: 400 }, +] + +const chartConfig = { + views: { + label: "Page Views", + }, + desktop: { + label: "Desktop", + color: "var(--chart-1)", + }, + mobile: { + label: "Mobile", + color: "var(--chart-2)", + }, +} satisfies ChartConfig + +export function RevenueGraph() { + const [activeChart, setActiveChart] = + React.useState("desktop") + + const total = React.useMemo( + () => ({ + desktop: chartData.reduce((acc, curr) => acc + curr.desktop, 0), + mobile: chartData.reduce((acc, curr) => acc + curr.mobile, 0), + }), + [] + ) + + return ( + + +
+ Line Chart - Interactive + + Showing total visitors for the last 3 months + +
+
+ {["desktop", "mobile"].map((key) => { + const chart = key as keyof typeof chartConfig + return ( + + ) + })} +
+
+ + + + + { + const date = new Date(value) + return date.toLocaleDateString("en-US", { + month: "short", + day: "numeric", + }) + }} + /> + { + return new Date(value).toLocaleDateString("en-US", { + month: "short", + day: "numeric", + year: "numeric", + }) + }} + /> + } + /> + + + + +
+ ) +} diff --git a/Frontend/bookmyvenue/components/revenueStats.tsx b/Frontend/bookmyvenue/components/revenueStats.tsx new file mode 100644 index 000000000..d44c51c02 --- /dev/null +++ b/Frontend/bookmyvenue/components/revenueStats.tsx @@ -0,0 +1,70 @@ +import { IconAnalyze } from '@tabler/icons-react' +import React from 'react' +import { RevenueGraph } from './revenueGraph' + +function RevenueStats() { + const activityData = [ + { month: 'Jan', value: 40 }, + { month: 'Mar', value: 72 }, + { month: 'May', value: 60 }, + { month: 'Jul', value: 84 }, + { month: 'Sep', value: 68 }, + { month: 'Nov', value: 92 }, + ] + const maxActivityValue = Math.max(...activityData.map((item) => item.value)) + const graphPoints = activityData + .map((item, index) => { + const x = 50 + index * 90 + const y = 120 - (item.value / maxActivityValue) * 100 + return `${x},${y}` + }) + .join(' ') + + return ( +
+
+

+ Transaction History +

+

Monitor your venue's revenue and transactions

+
+
+
+

This Month

+

$28.4K

+

Revenue this month

+
+
+

This Year

+

$196.8K

+

Revenue this year

+
+
+

Total Bookings

+

412

+

Bookings completed

+
+
+

Repeat Guests

+

78%

+

Returning customers

+
+
+ +
+
+
+

Booking activity

+

Transactions by month

+
+
Latest update: 2 hours ago
+
+ + +
+
+ + ) +} + +export { RevenueStats } \ No newline at end of file diff --git a/Frontend/bookmyvenue/components/review.tsx b/Frontend/bookmyvenue/components/review.tsx new file mode 100644 index 000000000..3227a407d --- /dev/null +++ b/Frontend/bookmyvenue/components/review.tsx @@ -0,0 +1,69 @@ +'use client' +import React, { useState } from 'react' +import { Button } from "@/components/ui/button" +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" +import { IconLocationCheck, IconStarFilled, IconWriting, IconX } from '@tabler/icons-react' +import { Input } from './ui/input' + +function Review() { + const [rating , setRating] = useState(0) + return ( + +
+ + + + + + Drop your review here + + + Please share your experience with us. + +
+
Rate your experience:
+
+ {Array.from({ length: 5 }, (_, index) => { + const starValue = index + 1 + return ( + + ) + })} +
+ +
+ +
+
+ + + + + + + +
+ +
+
+ ) +} + +export {Review} \ No newline at end of file diff --git a/Frontend/bookmyvenue/components/seasonal.tsx b/Frontend/bookmyvenue/components/seasonal.tsx new file mode 100644 index 000000000..320171ef0 --- /dev/null +++ b/Frontend/bookmyvenue/components/seasonal.tsx @@ -0,0 +1,77 @@ +import React from 'react' +import { Button } from "@/components/ui/button" +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" +import { IconCalendarCheck, IconClock, IconPlus, IconUpload, IconX } from '@tabler/icons-react' +import { InputGroup, InputGroupAddon, InputGroupInput } from './ui/input-group' +import { GroupDatePicker } from './groupDatePicker' + +function Seasonal() { + return ( + +
+ + + + + + + Add Seasonal Pay + + + Set special pricing and boost your revenue. + +
+
+
+

Seasonal Package Name

+ {/* 22-05-2026 to 05-06-2026 */} +
+ + + + + + +
+ +
+
+

Select the Dates

+ {/* 22-05-2026 to 05-06-2026 */} +
+ + +
+ + + + + + + +
+ + + + + + + +
+
+
+ ) +} + +export { Seasonal } \ No newline at end of file diff --git a/Frontend/bookmyvenue/components/theme-provider.tsx b/Frontend/bookmyvenue/components/theme-provider.tsx new file mode 100644 index 000000000..3d44f4815 --- /dev/null +++ b/Frontend/bookmyvenue/components/theme-provider.tsx @@ -0,0 +1,71 @@ +"use client" + +import * as React from "react" +import { ThemeProvider as NextThemesProvider, useTheme } from "next-themes" + +function ThemeProvider({ + children, + ...props +}: React.ComponentProps) { + return ( + + + {children} + + ) +} + +function isTypingTarget(target: EventTarget | null) { + if (!(target instanceof HTMLElement)) { + return false + } + + return ( + target.isContentEditable || + target.tagName === "INPUT" || + target.tagName === "TEXTAREA" || + target.tagName === "SELECT" + ) +} + +function ThemeHotkey() { + const { resolvedTheme, setTheme } = useTheme() + + React.useEffect(() => { + function onKeyDown(event: KeyboardEvent) { + if (event.defaultPrevented || event.repeat) { + return + } + + if (event.metaKey || event.ctrlKey || event.altKey) { + return + } + + if (event.key.toLowerCase() !== "d") { + return + } + + if (isTypingTarget(event.target)) { + return + } + + setTheme(resolvedTheme === "dark" ? "light" : "dark") + } + + window.addEventListener("keydown", onKeyDown) + + return () => { + window.removeEventListener("keydown", onKeyDown) + } + }, [resolvedTheme, setTheme]) + + return null +} + +export { ThemeProvider } diff --git a/Frontend/bookmyvenue/components/topRatedVenues.tsx b/Frontend/bookmyvenue/components/topRatedVenues.tsx new file mode 100644 index 000000000..b59ead33c --- /dev/null +++ b/Frontend/bookmyvenue/components/topRatedVenues.tsx @@ -0,0 +1,57 @@ +import React from 'react' +import { Card, CardContent } from "@/components/ui/card" +import { + Carousel, + CarouselContent, + CarouselItem, +} from "@/components/ui/carousel" +import Image from 'next/image' + +const CarousalData = [ + { + id: 1, + imgURl: "/1.png", + }, + { + id: 2, + imgURl: "/2.png", + }, + { + id: 3, + imgURl: "/3.png", + }, +] + +interface TopRatedVenuesProps { + CarousalData: string[] +} + +function TopRatedVenues({ CarousalData }: TopRatedVenuesProps) { + return ( + + + {CarousalData.map((venue, index) => ( + +
+ + + Venue + + +
+
+ ))} +
+
+ { + CarousalData.map((venue ,index) => ( +
+
+ )) + } +
+
+ ) +} + +export { TopRatedVenues } \ No newline at end of file diff --git a/Frontend/bookmyvenue/components/ui/alert.tsx b/Frontend/bookmyvenue/components/ui/alert.tsx new file mode 100644 index 000000000..1fe3176d2 --- /dev/null +++ b/Frontend/bookmyvenue/components/ui/alert.tsx @@ -0,0 +1,76 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const alertVariants = cva( + "group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4", + { + variants: { + variant: { + default: "bg-card text-card-foreground", + destructive: + "bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +function Alert({ + className, + variant, + ...props +}: React.ComponentProps<"div"> & VariantProps) { + return ( +
+ ) +} + +function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground", + className + )} + {...props} + /> + ) +} + +function AlertDescription({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function AlertAction({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +export { Alert, AlertTitle, AlertDescription, AlertAction } diff --git a/Frontend/bookmyvenue/components/ui/badge.tsx b/Frontend/bookmyvenue/components/ui/badge.tsx new file mode 100644 index 000000000..cacff11dc --- /dev/null +++ b/Frontend/bookmyvenue/components/ui/badge.tsx @@ -0,0 +1,49 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { Slot } from "radix-ui" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80", + secondary: + "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80", + destructive: + "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20", + outline: + "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground", + ghost: + "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50", + link: "text-primary underline-offset-4 hover:underline", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +function Badge({ + className, + variant = "default", + asChild = false, + ...props +}: React.ComponentProps<"span"> & + VariantProps & { asChild?: boolean }) { + const Comp = asChild ? Slot.Root : "span" + + return ( + + ) +} + +export { Badge, badgeVariants } diff --git a/Frontend/bookmyvenue/components/ui/button.tsx b/Frontend/bookmyvenue/components/ui/button.tsx new file mode 100644 index 000000000..75b8c3df3 --- /dev/null +++ b/Frontend/bookmyvenue/components/ui/button.tsx @@ -0,0 +1,67 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { Slot } from "radix-ui" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/80", + outline: + "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50", + secondary: + "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground", + ghost: + "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50", + destructive: + "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: + "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", + xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3", + sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5", + lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", + icon: "size-8", + "icon-xs": + "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3", + "icon-sm": + "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg", + "icon-lg": "size-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +function Button({ + className, + variant = "default", + size = "default", + asChild = false, + ...props +}: React.ComponentProps<"button"> & + VariantProps & { + asChild?: boolean + }) { + const Comp = asChild ? Slot.Root : "button" + + return ( + + ) +} + +export { Button, buttonVariants } diff --git a/Frontend/bookmyvenue/components/ui/calendar.tsx b/Frontend/bookmyvenue/components/ui/calendar.tsx new file mode 100644 index 000000000..2e820e2b6 --- /dev/null +++ b/Frontend/bookmyvenue/components/ui/calendar.tsx @@ -0,0 +1,222 @@ +"use client" + +import * as React from "react" +import { + DayPicker, + getDefaultClassNames, + type DayButton, + type Locale, +} from "react-day-picker" + +import { cn } from "@/lib/utils" +import { Button, buttonVariants } from "@/components/ui/button" +import { IconChevronLeft, IconChevronRight, IconChevronDown } from "@tabler/icons-react" + +function Calendar({ + className, + classNames, + showOutsideDays = true, + captionLayout = "label", + buttonVariant = "ghost", + locale, + formatters, + components, + ...props +}: React.ComponentProps & { + buttonVariant?: React.ComponentProps["variant"] +}) { + const defaultClassNames = getDefaultClassNames() + + return ( + svg]:rotate-180`, + String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`, + className + )} + captionLayout={captionLayout} + locale={locale} + formatters={{ + formatMonthDropdown: (date) => + date.toLocaleString(locale?.code, { month: "short" }), + ...formatters, + }} + classNames={{ + root: cn("w-fit", defaultClassNames.root), + months: cn( + "relative flex flex-col gap-4 md:flex-row", + defaultClassNames.months + ), + month: cn("flex w-full flex-col gap-4", defaultClassNames.month), + nav: cn( + "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1", + defaultClassNames.nav + ), + button_previous: cn( + buttonVariants({ variant: buttonVariant }), + "size-(--cell-size) p-0 select-none aria-disabled:opacity-50", + defaultClassNames.button_previous + ), + button_next: cn( + buttonVariants({ variant: buttonVariant }), + "size-(--cell-size) p-0 select-none aria-disabled:opacity-50", + defaultClassNames.button_next + ), + month_caption: cn( + "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)", + defaultClassNames.month_caption + ), + dropdowns: cn( + "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium", + defaultClassNames.dropdowns + ), + dropdown_root: cn( + "relative rounded-(--cell-radius)", + defaultClassNames.dropdown_root + ), + dropdown: cn( + "absolute inset-0 bg-popover opacity-0", + defaultClassNames.dropdown + ), + caption_label: cn( + "font-medium select-none", + captionLayout === "label" + ? "text-sm" + : "flex items-center gap-1 rounded-(--cell-radius) text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground", + defaultClassNames.caption_label + ), + table: "w-full border-collapse", + weekdays: cn("flex", defaultClassNames.weekdays), + weekday: cn( + "flex-1 rounded-(--cell-radius) text-[0.8rem] font-normal text-muted-foreground select-none", + defaultClassNames.weekday + ), + week: cn("mt-2 flex w-full", defaultClassNames.week), + week_number_header: cn( + "w-(--cell-size) select-none", + defaultClassNames.week_number_header + ), + week_number: cn( + "text-[0.8rem] text-muted-foreground select-none", + defaultClassNames.week_number + ), + day: cn( + "group/day relative aspect-square h-full w-full rounded-(--cell-radius) p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius)", + props.showWeekNumber + ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)" + : "[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)", + defaultClassNames.day + ), + range_start: cn( + "relative isolate z-0 rounded-l-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:right-0 after:w-4 after:bg-muted", + defaultClassNames.range_start + ), + range_middle: cn("rounded-none", defaultClassNames.range_middle), + range_end: cn( + "relative isolate z-0 rounded-r-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:left-0 after:w-4 after:bg-muted", + defaultClassNames.range_end + ), + today: cn( + "rounded-(--cell-radius) bg-muted text-foreground data-[selected=true]:rounded-none", + defaultClassNames.today + ), + outside: cn( + "text-muted-foreground aria-selected:text-muted-foreground", + defaultClassNames.outside + ), + disabled: cn( + "text-muted-foreground opacity-50", + defaultClassNames.disabled + ), + hidden: cn("invisible", defaultClassNames.hidden), + ...classNames, + }} + components={{ + Root: ({ className, rootRef, ...props }) => { + return ( +
+ ) + }, + Chevron: ({ className, orientation, ...props }) => { + if (orientation === "left") { + return ( + + ) + } + + if (orientation === "right") { + return ( + + ) + } + + return ( + + ) + }, + DayButton: ({ ...props }) => ( + + ), + WeekNumber: ({ children, ...props }) => { + return ( + +
+ {children} +
+ + ) + }, + ...components, + }} + {...props} + /> + ) +} + +function CalendarDayButton({ + className, + day, + modifiers, + locale, + ...props +}: React.ComponentProps & { locale?: Partial }) { + const defaultClassNames = getDefaultClassNames() + + const ref = React.useRef(null) + React.useEffect(() => { + if (modifiers.focused) ref.current?.focus() + }, [modifiers.focused]) + + return ( + + ) +} + +function CarouselNext({ + className, + variant = "outline", + size = "icon-sm", + ...props +}: React.ComponentProps) { + const { orientation, scrollNext, canScrollNext } = useCarousel() + + return ( + + ) +} + +export { + type CarouselApi, + Carousel, + CarouselContent, + CarouselItem, + useCarousel, +} diff --git a/Frontend/bookmyvenue/components/ui/chart.tsx b/Frontend/bookmyvenue/components/ui/chart.tsx new file mode 100644 index 000000000..7c2dc8472 --- /dev/null +++ b/Frontend/bookmyvenue/components/ui/chart.tsx @@ -0,0 +1,373 @@ +"use client" + +import * as React from "react" +import * as RechartsPrimitive from "recharts" +import type { TooltipValueType } from "recharts" + +import { cn } from "@/lib/utils" + +// Format: { THEME_NAME: CSS_SELECTOR } +const THEMES = { light: "", dark: ".dark" } as const + +const INITIAL_DIMENSION = { width: 320, height: 200 } as const +type TooltipNameType = number | string + +export type ChartConfig = Record< + string, + { + label?: React.ReactNode + icon?: React.ComponentType + } & ( + | { color?: string; theme?: never } + | { color?: never; theme: Record } + ) +> + +type ChartContextProps = { + config: ChartConfig +} + +const ChartContext = React.createContext(null) + +function useChart() { + const context = React.useContext(ChartContext) + + if (!context) { + throw new Error("useChart must be used within a ") + } + + return context +} + +function ChartContainer({ + id, + className, + children, + config, + initialDimension = INITIAL_DIMENSION, + ...props +}: React.ComponentProps<"div"> & { + config: ChartConfig + children: React.ComponentProps< + typeof RechartsPrimitive.ResponsiveContainer + >["children"] + initialDimension?: { + width: number + height: number + } +}) { + const uniqueId = React.useId() + const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}` + + return ( + +
+ + + {children} + +
+
+ ) +} + +const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { + const colorConfig = Object.entries(config).filter( + ([, config]) => config.theme ?? config.color + ) + + if (!colorConfig.length) { + return null + } + + return ( +